


import tempfile

import torch

from diffusers import (
    DEISMultistepScheduler,
    DPMSolverMultistepScheduler,
    DPMSolverSinglestepScheduler,
    UniPCMultistepScheduler,
)

from .test_schedulers import SchedulerCommonTest






class _lowerCamelCase(						_a   ):
       lowercase_ :	Tuple     =			(UniPCMultistepScheduler,)
       lowercase_ :	Dict     =			(("""num_inference_steps""", 25),)
       def 			UpperCamelCase     (					self,      **lowerCamelCase)       ->   Optional[int]:




           """simple docstring"""

           _lowercase       :							Tuple      		=		{
               'num_train_timesteps': 10_00,
               'beta_start': 0.0_0_0_1,
               'beta_end': 0.0_2,
               'beta_schedule': 'linear',
               'solver_order': 2,
               'solver_type': 'bh2',
           }

           config.update(**lowerCamelCase)
           return config
       def 			UpperCamelCase     (					self,      lowerCamelCase=0,      **lowerCamelCase)       ->   Union[str, Any]:




           """simple docstring"""

           _lowercase       :							List[str]      		=		dict(self.forward_default_kwargs)
           _lowercase       :							int      		=		kwargs.pop('num_inference_steps',      lowerCamelCase)
           _lowercase       :							Union[str, Any]      		=		self.dummy_sample
           _lowercase       :							Optional[Any]      		=		0.1 * sample
           _lowercase       :							Any      		=		[residual + 0.2, residual + 0.1_5, residual + 0.1_0]

           for scheduler_class in self.scheduler_classes:
               _lowercase       :							Optional[Any]      		=		self.get_scheduler_config(**lowerCamelCase)
               _lowercase       :							Tuple      		=		scheduler_class(**lowerCamelCase)
               scheduler.set_timesteps(lowerCamelCase)
               # copy over dummy past residuals
               _lowercase       :							Tuple      		=		dummy_past_residuals[: scheduler.config.solver_order]

               with tempfile.TemporaryDirectory() as tmpdirname:
                   scheduler.save_config(lowerCamelCase)
                   _lowercase       :							Dict      		=		scheduler_class.from_pretrained(lowerCamelCase)
                   new_scheduler.set_timesteps(lowerCamelCase)
                   # copy over dummy past residuals
                   _lowercase       :							Optional[int]      		=		dummy_past_residuals[: new_scheduler.config.solver_order]

               _lowercase		,				_lowercase       :							Any      		=		sample, sample
               for t in range(lowerCamelCase,      time_step + scheduler.config.solver_order + 1):
                   _lowercase       :							Optional[int]      		=		scheduler.step(lowerCamelCase,      lowerCamelCase,      lowerCamelCase,      **lowerCamelCase).prev_sample
                   _lowercase       :							Optional[Any]      		=		new_scheduler.step(lowerCamelCase,      lowerCamelCase,      lowerCamelCase,      **lowerCamelCase).prev_sample

                   assert torch.sum(torch.abs(output - new_output)) < 1E-5, "Scheduler outputs are not identical"
       def 			UpperCamelCase     (					self,      lowerCamelCase=0,      **lowerCamelCase)       ->   List[str]:




           """simple docstring"""

           _lowercase       :							List[Any]      		=		dict(self.forward_default_kwargs)
           _lowercase       :							Union[str, Any]      		=		kwargs.pop('num_inference_steps',      lowerCamelCase)
           _lowercase       :							int      		=		self.dummy_sample
           _lowercase       :							Tuple      		=		0.1 * sample
           _lowercase       :							List[Any]      		=		[residual + 0.2, residual + 0.1_5, residual + 0.1_0]

           for scheduler_class in self.scheduler_classes:
               _lowercase       :							Tuple      		=		self.get_scheduler_config()
               _lowercase       :							int      		=		scheduler_class(**lowerCamelCase)
               scheduler.set_timesteps(lowerCamelCase)

               # copy over dummy past residuals (must be after setting timesteps)
               _lowercase       :							Optional[int]      		=		dummy_past_residuals[: scheduler.config.solver_order]

               with tempfile.TemporaryDirectory() as tmpdirname:
                   scheduler.save_config(lowerCamelCase)
                   _lowercase       :							Union[str, Any]      		=		scheduler_class.from_pretrained(lowerCamelCase)
                   # copy over dummy past residuals
                   new_scheduler.set_timesteps(lowerCamelCase)

                   # copy over dummy past residual (must be after setting timesteps)
                   _lowercase       :							List[str]      		=		dummy_past_residuals[: new_scheduler.config.solver_order]

               _lowercase       :							str      		=		scheduler.step(lowerCamelCase,      lowerCamelCase,      lowerCamelCase,      **lowerCamelCase).prev_sample
               _lowercase       :							List[str]      		=		new_scheduler.step(lowerCamelCase,      lowerCamelCase,      lowerCamelCase,      **lowerCamelCase).prev_sample

               assert torch.sum(torch.abs(output - new_output)) < 1E-5, "Scheduler outputs are not identical"
       def 			UpperCamelCase     (					self,      lowerCamelCase=None,      **lowerCamelCase)       ->   Any:




           """simple docstring"""

           if scheduler is None:
               _lowercase       :							Optional[Any]      		=		self.scheduler_classes[0]
               _lowercase       :							str      		=		self.get_scheduler_config(**lowerCamelCase)
               _lowercase       :							List[str]      		=		scheduler_class(**lowerCamelCase)

           _lowercase       :							str      		=		self.scheduler_classes[0]
           _lowercase       :							Tuple      		=		self.get_scheduler_config(**lowerCamelCase)
           _lowercase       :							str      		=		scheduler_class(**lowerCamelCase)

           _lowercase       :							Dict      		=		10
           _lowercase       :							Any      		=		self.dummy_model()
           _lowercase       :							List[str]      		=		self.dummy_sample_deter
           scheduler.set_timesteps(lowerCamelCase)

           for i, t in enumerate(scheduler.timesteps):
               _lowercase       :							Optional[Any]      		=		model(lowerCamelCase,      lowerCamelCase)
               _lowercase       :							Optional[Any]      		=		scheduler.step(lowerCamelCase,      lowerCamelCase,      lowerCamelCase).prev_sample

           return sample
       def 			UpperCamelCase     (					self)       ->   List[str]:




           """simple docstring"""

           _lowercase       :							List[Any]      		=		dict(self.forward_default_kwargs)

           _lowercase       :							Optional[int]      		=		kwargs.pop('num_inference_steps',      lowerCamelCase)

           for scheduler_class in self.scheduler_classes:
               _lowercase       :							Any      		=		self.get_scheduler_config()
               _lowercase       :							int      		=		scheduler_class(**lowerCamelCase)

               _lowercase       :							Optional[Any]      		=		self.dummy_sample
               _lowercase       :							List[Any]      		=		0.1 * sample

               if num_inference_steps is not None and hasattr(lowerCamelCase,      'set_timesteps'):
                   scheduler.set_timesteps(lowerCamelCase)
               elif num_inference_steps is not None and not hasattr(lowerCamelCase,      'set_timesteps'):
                   _lowercase       :							Optional[Any]      		=		num_inference_steps

               # copy over dummy past residuals (must be done after set_timesteps)
               _lowercase       :							Tuple      		=		[residual + 0.2, residual + 0.1_5, residual + 0.1_0]
               _lowercase       :							Optional[int]      		=		dummy_past_residuals[: scheduler.config.solver_order]

               _lowercase       :							List[str]      		=		scheduler.timesteps[5]
               _lowercase       :							Any      		=		scheduler.timesteps[6]

               _lowercase       :							int      		=		scheduler.step(lowerCamelCase,      lowerCamelCase,      lowerCamelCase,      **lowerCamelCase).prev_sample
               _lowercase       :							Tuple      		=		scheduler.step(lowerCamelCase,      lowerCamelCase,      lowerCamelCase,      **lowerCamelCase).prev_sample

               self.assertEqual(output_a.shape,      sample.shape)
               self.assertEqual(output_a.shape,      output_a.shape)
       def 			UpperCamelCase     (					self)       ->   str:




           """simple docstring"""

           _lowercase       :							Dict      		=		UniPCMultistepScheduler(**self.get_scheduler_config())
           _lowercase       :							int      		=		self.full_loop(scheduler=lowerCamelCase)
           _lowercase       :							int      		=		torch.mean(torch.abs(lowerCamelCase))

           assert abs(result_mean.item() - 0.2_4_6_4) < 1E-3

           _lowercase       :							Tuple      		=		DPMSolverSinglestepScheduler.from_config(scheduler.config)
           _lowercase       :							Optional[Any]      		=		DEISMultistepScheduler.from_config(scheduler.config)
           _lowercase       :							str      		=		DPMSolverMultistepScheduler.from_config(scheduler.config)
           _lowercase       :							Tuple      		=		UniPCMultistepScheduler.from_config(scheduler.config)

           _lowercase       :							List[Any]      		=		self.full_loop(scheduler=lowerCamelCase)
           _lowercase       :							Optional[int]      		=		torch.mean(torch.abs(lowerCamelCase))

           assert abs(result_mean.item() - 0.2_4_6_4) < 1E-3
       def 			UpperCamelCase     (					self)       ->   int:




           """simple docstring"""

           for timesteps in [25, 50, 1_00, 9_99, 10_00]:
               self.check_over_configs(num_train_timesteps=lowerCamelCase)
       def 			UpperCamelCase     (					self)       ->   int:




           """simple docstring"""

           self.check_over_configs(thresholding=lowerCamelCase)
           for order in [1, 2, 3]:
               for solver_type in ["bh1", "bh2"]:
                   for threshold in [0.5, 1.0, 2.0]:
                       for prediction_type in ["epsilon", "sample"]:
                           self.check_over_configs(
                               thresholding=lowerCamelCase,      prediction_type=lowerCamelCase,      sample_max_value=lowerCamelCase,      solver_order=lowerCamelCase,      solver_type=lowerCamelCase,      )
       def 			UpperCamelCase     (					self)       ->   int:




           """simple docstring"""

           for prediction_type in ["epsilon", "v_prediction"]:
               self.check_over_configs(prediction_type=lowerCamelCase)
       def 			UpperCamelCase     (					self)       ->   Optional[int]:




           """simple docstring"""

           for solver_type in ["bh1", "bh2"]:
               for order in [1, 2, 3]:
                   for prediction_type in ["epsilon", "sample"]:
                       self.check_over_configs(
                           solver_order=lowerCamelCase,      solver_type=lowerCamelCase,      prediction_type=lowerCamelCase,      )
                       _lowercase       :							Any      		=		self.full_loop(
                           solver_order=lowerCamelCase,      solver_type=lowerCamelCase,      prediction_type=lowerCamelCase,      )
                       assert not torch.isnan(lowerCamelCase).any(), "Samples have nan numbers"
       def 			UpperCamelCase     (					self)       ->   str:




           """simple docstring"""

           self.check_over_configs(lower_order_final=lowerCamelCase)
           self.check_over_configs(lower_order_final=lowerCamelCase)
       def 			UpperCamelCase     (					self)       ->   Optional[int]:




           """simple docstring"""

           for num_inference_steps in [1, 2, 3, 5, 10, 50, 1_00, 9_99, 10_00]:
               self.check_over_forward(num_inference_steps=lowerCamelCase,      time_step=0)
       def 			UpperCamelCase     (					self)       ->   str:




           """simple docstring"""

           _lowercase       :							str      		=		self.full_loop()
           _lowercase       :							Tuple      		=		torch.mean(torch.abs(lowerCamelCase))

           assert abs(result_mean.item() - 0.2_4_6_4) < 1E-3
       def 			UpperCamelCase     (					self)       ->   int:




           """simple docstring"""

           _lowercase       :							List[Any]      		=		self.full_loop(prediction_type='v_prediction')
           _lowercase       :							str      		=		torch.mean(torch.abs(lowerCamelCase))

           assert abs(result_mean.item() - 0.1_0_1_4) < 1E-3
       def 			UpperCamelCase     (					self)       ->   Any:




           """simple docstring"""

           _lowercase       :							str      		=		self.scheduler_classes[0]
           _lowercase       :							Any      		=		self.get_scheduler_config(thresholding=lowerCamelCase,      dynamic_thresholding_ratio=0)
           _lowercase       :							List[Any]      		=		scheduler_class(**lowerCamelCase)

           _lowercase       :							str      		=		10
           _lowercase       :							Union[str, Any]      		=		self.dummy_model()
           _lowercase       :							Any      		=		self.dummy_sample_deter.half()
           scheduler.set_timesteps(lowerCamelCase)

           for i, t in enumerate(scheduler.timesteps):
               _lowercase       :							str      		=		model(lowerCamelCase,      lowerCamelCase)
               _lowercase       :							int      		=		scheduler.step(lowerCamelCase,      lowerCamelCase,      lowerCamelCase).prev_sample

           assert sample.dtype == torch.floataa




       def 			UpperCamelCase     (					self,      **lowerCamelCase)       ->   Any:




           """simple docstring"""

           for scheduler_class in self.scheduler_classes:
               _lowercase       :							Dict      		=		self.get_scheduler_config(**lowerCamelCase)
               _lowercase       :							Optional[Any]      		=		scheduler_class(**lowerCamelCase)

               scheduler.set_timesteps(scheduler.config.num_train_timesteps)
               assert len(scheduler.timesteps.unique()) == scheduler.num_inference_steps






import gc
import random
import unittest

import numpy as np
import torch
from PIL import Image
from transformers import XLMRobertaTokenizerFast

from diffusers import DDIMScheduler, KandinskyImgaImgPipeline, KandinskyPriorPipeline, UNetaDConditionModel, VQModel
from diffusers.pipelines.kandinsky.text_encoder import MCLIPConfig, MultilingualCLIP
from diffusers.utils import floats_tensor, load_image, load_numpy, slow, torch_device
from diffusers.utils.testing_utils import enable_full_determinism, require_torch_gpu

from ..test_pipelines_common import PipelineTesterMixin, assert_mean_pixel_difference


enable_full_determinism()






class _lowerCamelCase(						_a, unittest.TestCase   ):
       lowercase_ :	Any     =			KandinskyImgaImgPipeline
       lowercase_ :	Union[str, Any]     =			["""prompt""", """image_embeds""", """negative_image_embeds""", """image"""]
       lowercase_ :	Any     =			[
           """prompt""",
           """negative_prompt""",
           """image_embeds""",
           """negative_image_embeds""",
           """image""",
       ]
       lowercase_ :	List[Any]     =			[
           """generator""",
           """height""",
           """width""",
           """strength""",
           """guidance_scale""",
           """negative_prompt""",
           """num_inference_steps""",
           """return_dict""",
           """guidance_scale""",
           """num_images_per_prompt""",
           """output_type""",
           """return_dict""",
       ]
       lowercase_ :	Union[str, Any]     =			False
       @property
       def 			UpperCamelCase     (					self)       ->   str:




           """simple docstring"""

           return 32
       @property
       def 			UpperCamelCase     (					self)       ->   int:




           """simple docstring"""

           return 32
       @property
       def 			UpperCamelCase     (					self)       ->   Tuple:




           """simple docstring"""

           return self.time_input_dim
       @property
       def 			UpperCamelCase     (					self)       ->   Optional[Any]:




           """simple docstring"""

           return self.time_input_dim * 4
       @property
       def 			UpperCamelCase     (					self)       ->   List[str]:




           """simple docstring"""

           return 1_00
       @property
       def 			UpperCamelCase     (					self)       ->   str:




           """simple docstring"""

           _lowercase       :							str      		=		XLMRobertaTokenizerFast.from_pretrained('YiYiXu/tiny-random-mclip-base')
           return tokenizer
       @property
       def 			UpperCamelCase     (					self)       ->   int:




           """simple docstring"""

           torch.manual_seed(0)
           _lowercase       :							Optional[int]      		=		MCLIPConfig(
               numDims=self.cross_attention_dim,      transformerDimensions=self.text_embedder_hidden_size,      hidden_size=self.text_embedder_hidden_size,      intermediate_size=37,      num_attention_heads=4,      num_hidden_layers=5,      vocab_size=10_05,      )

           _lowercase       :							Optional[int]      		=		MultilingualCLIP(lowerCamelCase)
           _lowercase       :							List[str]      		=		text_encoder.eval()

           return text_encoder
       @property
       def 			UpperCamelCase     (					self)       ->   List[str]:




           """simple docstring"""

           torch.manual_seed(0)

           _lowercase       :							Union[str, Any]      		=		{
               'in_channels': 4,
               # Out channels is double in channels because predicts mean and variance
               'out_channels': 8,
               'addition_embed_type': 'text_image',
               'down_block_types': ('ResnetDownsampleBlock2D', 'SimpleCrossAttnDownBlock2D'),
               'up_block_types': ('SimpleCrossAttnUpBlock2D', 'ResnetUpsampleBlock2D'),
               'mid_block_type': 'UNetMidBlock2DSimpleCrossAttn',
               'block_out_channels': (self.block_out_channels_a, self.block_out_channels_a * 2),
               'layers_per_block': 1,
               'encoder_hid_dim': self.text_embedder_hidden_size,
               'encoder_hid_dim_type': 'text_image_proj',
               'cross_attention_dim': self.cross_attention_dim,
               'attention_head_dim': 4,
               'resnet_time_scale_shift': 'scale_shift',
               'class_embed_type': None,
           }

           _lowercase       :							Optional[Any]      		=		UNetaDConditionModel(**lowerCamelCase)
           return model
       @property
       def 			UpperCamelCase     (					self)       ->   str:




           """simple docstring"""

           return {
               "block_out_channels": [32, 64],
               "down_block_types": ["DownEncoderBlock2D", "AttnDownEncoderBlock2D"],
               "in_channels": 3,
               "latent_channels": 4,
               "layers_per_block": 1,
               "norm_num_groups": 8,
               "norm_type": "spatial",
               "num_vq_embeddings": 12,
               "out_channels": 3,
               "up_block_types": [
                   "AttnUpDecoderBlock2D",
                   "UpDecoderBlock2D",
               ],
               "vq_embed_dim": 4,
           }
       @property
       def 			UpperCamelCase     (					self)       ->   List[str]:




           """simple docstring"""

           torch.manual_seed(0)
           _lowercase       :							Dict      		=		VQModel(**self.dummy_movq_kwargs)
           return model
       def 			UpperCamelCase     (					self)       ->   List[str]:




           """simple docstring"""

           _lowercase       :							Any      		=		self.dummy_text_encoder
           _lowercase       :							List[Any]      		=		self.dummy_tokenizer
           _lowercase       :							int      		=		self.dummy_unet
           _lowercase       :							int      		=		self.dummy_movq

           _lowercase       :							Optional[int]      		=		{
               'num_train_timesteps': 10_00,
               'beta_schedule': 'linear',
               'beta_start': 0.0_0_0_8_5,
               'beta_end': 0.0_1_2,
               'clip_sample': False,
               'set_alpha_to_one': False,
               'steps_offset': 0,
               'prediction_type': 'epsilon',
               'thresholding': False,
           }

           _lowercase       :							List[Any]      		=		DDIMScheduler(**lowerCamelCase)

           _lowercase       :							List[Any]      		=		{
               'text_encoder': text_encoder,
               'tokenizer': tokenizer,
               'unet': unet,
               'scheduler': scheduler,
               'movq': movq,
           }

           return components
       def 			UpperCamelCase     (					self,      lowerCamelCase,      lowerCamelCase=0)       ->   Dict:




           """simple docstring"""

           _lowercase       :							List[str]      		=		floats_tensor((1, self.cross_attention_dim),      rng=random.Random(lowerCamelCase)).to(lowerCamelCase)
           _lowercase       :							Optional[Any]      		=		floats_tensor((1, self.cross_attention_dim),      rng=random.Random(seed + 1)).to(lowerCamelCase)
           # create init_image
           _lowercase       :							Tuple      		=		floats_tensor((1, 3, 64, 64),      rng=random.Random(lowerCamelCase)).to(lowerCamelCase)
           _lowercase       :							Optional[int]      		=		image.cpu().permute(0,      2,      3,      1)[0]
           _lowercase       :							Tuple      		=		Image.fromarray(np.uinta(lowerCamelCase)).convert('RGB').resize((2_56, 2_56))

           if str(lowerCamelCase).startswith('mps'):
               _lowercase       :							List[str]      		=		torch.manual_seed(lowerCamelCase)
           else:
               _lowercase       :							Optional[Any]      		=		torch.Generator(device=lowerCamelCase).manual_seed(lowerCamelCase)
           _lowercase       :							Tuple      		=		{
               'prompt': 'horse',
               'image': init_image,
               'image_embeds': image_embeds,
               'negative_image_embeds': negative_image_embeds,
               'generator': generator,
               'height': 64,
               'width': 64,
               'num_inference_steps': 10,
               'guidance_scale': 7.0,
               'strength': 0.2,
               'output_type': 'np',
           }
           return inputs




       def 			UpperCamelCase     (					self)       ->   Tuple:




           """simple docstring"""

           _lowercase       :							Dict      		=		'cpu'

           _lowercase       :							Tuple      		=		self.get_dummy_components()

           _lowercase       :							str      		=		self.pipeline_class(**lowerCamelCase)
           _lowercase       :							str      		=		pipe.to(lowerCamelCase)

           pipe.set_progress_bar_config(disable=lowerCamelCase)

           _lowercase       :							List[str]      		=		pipe(**self.get_dummy_inputs(lowerCamelCase))
           _lowercase       :							Optional[int]      		=		output.images

           _lowercase       :							List[Any]      		=		pipe(
               **self.get_dummy_inputs(lowerCamelCase),      return_dict=lowerCamelCase,      )[0]

           _lowercase       :							List[str]      		=		image[0, -3:, -3:, -1]
           _lowercase       :							List[Any]      		=		image_from_tuple[0, -3:, -3:, -1]

           assert image.shape == (1, 64, 64, 3)

           _lowercase       :							Tuple      		=		np.array(
               [0.6_1_4_7_4_9_4_3, 0.6_0_7_3_5_3_9, 0.4_3_3_0_8_5_4_4, 0.5_9_2_8_2_6_9, 0.4_7_4_9_3_5_9_5, 0.4_6_7_5_5_9_7_3, 0.4_6_1_3_8_3_8, 0.4_5_3_6_8_7_9_7, 0.5_0_1_1_9_2_3_3])
           assert (
               np.abs(image_slice.flatten() - expected_slice).max() < 1E-2
           ), F''' expected_slice {expected_slice}, but got {image_slice.flatten()}'''
           assert (
               np.abs(image_from_tuple_slice.flatten() - expected_slice).max() < 1E-2
           ), F''' expected_slice {expected_slice}, but got {image_from_tuple_slice.flatten()}'''






@slow
@require_torch_gpu
class _lowerCamelCase(						unittest.TestCase   ):
       def 			UpperCamelCase     (					self)       ->   Tuple:




           """simple docstring"""

           super().tearDown()
           gc.collect()
           torch.cuda.empty_cache()




       def 			UpperCamelCase     (					self)       ->   Union[str, Any]:




           """simple docstring"""

           _lowercase       :							int      		=		load_numpy(
               'https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main'
               '/kandinsky/kandinsky_img2img_frog.npy')

           _lowercase       :							str      		=		load_image(
               'https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main' '/kandinsky/cat.png')
           _lowercase       :							Optional[int]      		=		'A red cartoon frog, 4k'

           _lowercase       :							Union[str, Any]      		=		KandinskyPriorPipeline.from_pretrained(
               'kandinsky-community/kandinsky-2-1-prior',      torch_dtype=torch.floataa)
           pipe_prior.to(lowerCamelCase)

           _lowercase       :							Optional[Any]      		=		KandinskyImgaImgPipeline.from_pretrained(
               'kandinsky-community/kandinsky-2-1',      torch_dtype=torch.floataa)
           _lowercase       :							List[Any]      		=		pipeline.to(lowerCamelCase)

           pipeline.set_progress_bar_config(disable=lowerCamelCase)

           _lowercase       :							str      		=		torch.Generator(device='cpu').manual_seed(0)
           _lowercase		,				_lowercase       :							List[Any]      		=		pipe_prior(
               lowerCamelCase,      generator=lowerCamelCase,      num_inference_steps=5,      negative_prompt='',      ).to_tuple()

           _lowercase       :							Union[str, Any]      		=		pipeline(
               lowerCamelCase,      image=lowerCamelCase,      image_embeds=lowerCamelCase,      negative_image_embeds=lowerCamelCase,      generator=lowerCamelCase,      num_inference_steps=1_00,      height=7_68,      width=7_68,      strength=0.2,      output_type='np',      )

           _lowercase       :							Dict      		=		output.images[0]

           assert image.shape == (7_68, 7_68, 3)

           assert_mean_pixel_difference(lowerCamelCase,      lowerCamelCase)


