import argparse
import pathlib
from pathlib import Path
from tempfile import TemporaryDirectory

import esm as esm_module
import torch
from esm.esmfold.va.misc import batch_encode_sequences as esmfold_encode_sequences
from esm.esmfold.va.pretrained import esmfold_va

from transformers.models.esm.configuration_esm import EsmConfig, EsmFoldConfig
from transformers.models.esm.modeling_esm import (
    EsmForMaskedLM,
    EsmForSequenceClassification,
    EsmIntermediate,
    EsmLayer,
    EsmOutput,
    EsmSelfAttention,
    EsmSelfOutput,
)
from transformers.models.esm.modeling_esmfold import EsmForProteinFolding
from transformers.models.esm.tokenization_esm import EsmTokenizer
from transformers.utils import logging


logging.set_verbosity_info()
_SCREAMING_SNAKE_CASE   		=			logging.get_logger(__name__)

_SCREAMING_SNAKE_CASE   		=			[
    (
        """protein1""",
        """MNGTEGPNFYVPFSNATGVVRSPFEYPQYYLAEPWQFSMLAAYMFLLIVLGFPINFLTLYVTVQHKKLRTPLNYILLNLAVADLFMVLGGFTSTLYTSLHGYFVFGPTGCNLEGFFATLGGEIALWSLVVLAIERYVVVCKPMSNFRFGENHAIMGVAFTWVMALACAAPPLAGWSRYIPEGLQCSCGIDYYTLKPEVNNESFVIYMFVVHFTIPMIIIFFCYGQLVFTVKEAAAQQQESATTQKAEKEVTRMVIIMVIAFLICWVPYASVAFYIFTHQGSNFGPIFMTIPAFFAKSAAIYNPVIYIMMNKQFRNCMLTTICCGKNPLGDDEASATVSKTETSQVAPA""",
    ),
    ("""protein2""", """MKTVRQERLKSIVRILERSKEPVSGAQLAEELSVSRQVIVQDIAYLRSLGYNIVATPRGYVLA"""),
    ("""protein3""", """MKTVRQERLKSI<mask>RILERSKEPVSGAQLAEELS<mask>SRQVIVQDIAYLRSLGYN<mask>VATPRGYVLAGG"""),
    ("""protein4""", """MKTVRQERLKSI<mask>RILERSKEPVSGAQLAEELS<mask>SRQVIVQDIAYLRSLGYN<mask>VATPRGYVLA"""),
]

_SCREAMING_SNAKE_CASE   		=			{
    """esm1b_t33_650M_UR50S""": esm_module.pretrained.esm1b_t33_650M_UR50S,
    """esm1v_t33_650M_UR90S_1""": esm_module.pretrained.esm1v_t33_650M_UR90S_1,
    """esm1v_t33_650M_UR90S_2""": esm_module.pretrained.esm1v_t33_650M_UR90S_2,
    """esm1v_t33_650M_UR90S_3""": esm_module.pretrained.esm1v_t33_650M_UR90S_3,
    """esm1v_t33_650M_UR90S_4""": esm_module.pretrained.esm1v_t33_650M_UR90S_4,
    """esm1v_t33_650M_UR90S_5""": esm_module.pretrained.esm1v_t33_650M_UR90S_5,
    """esm2_t48_15B_UR50D""": esm_module.pretrained.esm2_t48_15B_UR50D,
    """esm2_t36_3B_UR50D""": esm_module.pretrained.esm2_t36_3B_UR50D,
    """esm2_t33_650M_UR50D""": esm_module.pretrained.esm2_t33_650M_UR50D,
    """esm2_t30_150M_UR50D""": esm_module.pretrained.esm2_t30_150M_UR50D,
    """esm2_t12_35M_UR50D""": esm_module.pretrained.esm2_t12_35M_UR50D,
    """esm2_t6_8M_UR50D""": esm_module.pretrained.esm2_t6_8M_UR50D,
    """esmfold_v1""": esmfold_va,
}

_SCREAMING_SNAKE_CASE   		=			list("""ARNDCQEGHILKMFPSTWYV""")

_SCREAMING_SNAKE_CASE   		=			restypes + ["""X"""]
_SCREAMING_SNAKE_CASE   		=			restypes_with_x + ["""<pad>""", """<mask>""", """<cls>""", """<sep>""", """<eos>"""]





def  lowercase(  )		->  Any:







 '''simple docstring'''
 with TemporaryDirectory() as tempdir:
  UpperCamelCase      =			"""\n""".join(UpperCamelCase_					)
  UpperCamelCase      =			Path(UpperCamelCase_					) / """vocab.txt"""
  vocab_file.write_text(UpperCamelCase_					)
  UpperCamelCase      =			EsmTokenizer(vocab_file=str(UpperCamelCase_					)					)
 UpperCamelCase      =			0  # Overlaps with 'A' but that seems to be what they want
 return hf_tokenizer





def  lowercase(  UpperCamelCase_       ,				UpperCamelCase_					)		->  int:







 '''simple docstring'''
 UpperCamelCase      =			our_module.load_state_dict(original_module.state_dict()					)
 if status.missing_keys:
  raise ValueError(f"""Missing keys: {status.missing_keys}"""					)
 if status.unexpected_keys:
  raise ValueError(f"""Unexpected keys: {status.unexpected_keys}"""					)





def  lowercase(  UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_					)		->  List[str]:







 '''simple docstring'''
 if model.startswith("""esmfold"""					):
  UpperCamelCase      =			MODEL_MAPPING[model]()
 else:
  UpperCamelCase     ,    UpperCamelCase      =			MODEL_MAPPING[model]()
 esm.eval()  # disable dropout

 if model.startswith("""esmfold"""					):
  UpperCamelCase      =			esm.esm.embed_dim
  UpperCamelCase      =			esm.esm.num_layers
  UpperCamelCase      =			esm.esm.attention_heads
  UpperCamelCase      =			4 * embed_dim
  UpperCamelCase      =			esm.esm.token_dropout
  UpperCamelCase      =			False  # This code path does not exist in ESM-2
  UpperCamelCase      =			"""rotary"""
  UpperCamelCase      =			True
  UpperCamelCase      =			EsmFoldConfig()
  for key, val in esm.cfg.items():
   if hasattr(UpperCamelCase_       ,				UpperCamelCase_					) and key != "trunk":
    setattr(UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_					)
  for key, val in esm.cfg.trunk.items():
   if hasattr(esmfold_config.trunk       ,				UpperCamelCase_					) and key != "structure_module":
    setattr(esmfold_config.trunk       ,				UpperCamelCase_       ,				UpperCamelCase_					)
  for key, val in esm.cfg.trunk.structure_module.items():
   if hasattr(esmfold_config.trunk.structure_module       ,				UpperCamelCase_					):
    setattr(esmfold_config.trunk.structure_module       ,				UpperCamelCase_       ,				UpperCamelCase_					)
 elif hasattr(UpperCamelCase_       ,				"""args"""					):
  # Indicates an ESM-1b or ESM-1v model
  UpperCamelCase      =			esm.args.embed_dim
  UpperCamelCase      =			esm.args.layers
  UpperCamelCase      =			esm.args.attention_heads
  UpperCamelCase      =			esm.args.ffn_embed_dim
  UpperCamelCase      =			esm.args.token_dropout
  UpperCamelCase      =			True if esm.emb_layer_norm_before else False
  UpperCamelCase      =			"""absolute"""
  UpperCamelCase      =			False
  UpperCamelCase      =			None
 else:
  # Indicates an ESM-2 model
  UpperCamelCase      =			esm.embed_dim
  UpperCamelCase      =			esm.num_layers
  UpperCamelCase      =			esm.attention_heads
  UpperCamelCase      =			4 * embed_dim  # This is hardcoded in ESM-2
  UpperCamelCase      =			esm.token_dropout
  UpperCamelCase      =			False  # This code path does not exist in ESM-2
  UpperCamelCase      =			"""rotary"""
  UpperCamelCase      =			False
  UpperCamelCase      =			None

 if is_folding_model:
  UpperCamelCase      =			esm.esm.alphabet
 UpperCamelCase      =			tuple(alphabet.all_toks					)
 UpperCamelCase      =			alphabet.mask_idx
 UpperCamelCase      =			alphabet.padding_idx

 if is_folding_model:
  UpperCamelCase      =			esm.esm
 else:
  UpperCamelCase      =			esm

 UpperCamelCase      =			EsmConfig(
     vocab_size=original_esm_model.embed_tokens.num_embeddings       ,				mask_token_id=UpperCamelCase_       ,				hidden_size=UpperCamelCase_       ,				num_hidden_layers=UpperCamelCase_       ,				num_attention_heads=UpperCamelCase_       ,				intermediate_size=UpperCamelCase_       ,				max_position_embeddings=1026       ,				layer_norm_eps=1E-5       ,				attention_probs_dropout_prob=0.0       ,				hidden_dropout_prob=0.0       ,				pad_token_id=UpperCamelCase_       ,				emb_layer_norm_before=UpperCamelCase_       ,				token_dropout=UpperCamelCase_       ,				position_embedding_type=UpperCamelCase_       ,				is_folding_model=UpperCamelCase_       ,				esmfold_config=UpperCamelCase_       ,				vocab_list=UpperCamelCase_       ,				)
 if classification_head:
  UpperCamelCase      =			esm.classification_heads["""mnli"""].out_proj.weight.shape[0]
 print("""Our ESM config:"""       ,				UpperCamelCase_					)

 if model.startswith("""esmfold"""					):
  UpperCamelCase      =			EsmForProteinFolding
 elif classification_head:
  UpperCamelCase      =			EsmForSequenceClassification
 else:
  UpperCamelCase      =			EsmForMaskedLM
 UpperCamelCase      =			model_class(UpperCamelCase_					)
 model.eval()

 # Now let's copy all the weights.
 # Embeddings
 UpperCamelCase      =			original_esm_model.embed_tokens.weight
 if position_embedding_type == "absolute":
  UpperCamelCase      =			original_esm_model.embed_positions.weight

 if config.emb_layer_norm_before:
  UpperCamelCase      =			original_esm_model.emb_layer_norm_before.weight
  UpperCamelCase      =			original_esm_model.emb_layer_norm_before.bias

 UpperCamelCase      =			original_esm_model.emb_layer_norm_after.weight
 UpperCamelCase      =			original_esm_model.emb_layer_norm_after.bias

 for i in range(config.num_hidden_layers					):
  # Encoder: start of layer
  UpperCamelCase      =			model.esm.encoder.layer[i]
  # esm_layer: TransformerSentenceEncoderLayer = original_esm_model.layers[i]
  UpperCamelCase      =			original_esm_model.layers[i]

  # self attention
  UpperCamelCase      =			layer.attention.self
  assert (
      esm_layer.self_attn.k_proj.weight.data.shape
      == esm_layer.self_attn.q_proj.weight.data.shape
      == esm_layer.self_attn.v_proj.weight.data.shape
      == torch.Size((config.hidden_size, config.hidden_size)					)
  )

  UpperCamelCase      =			esm_layer.self_attn.q_proj.weight
  UpperCamelCase      =			esm_layer.self_attn.q_proj.bias
  UpperCamelCase      =			esm_layer.self_attn.k_proj.weight
  UpperCamelCase      =			esm_layer.self_attn.k_proj.bias
  UpperCamelCase      =			esm_layer.self_attn.v_proj.weight
  UpperCamelCase      =			esm_layer.self_attn.v_proj.bias

  if getattr(esm_layer.self_attn       ,				"""rot_emb"""       ,				UpperCamelCase_					) is not None:
   # Matt: Although inv_freq is not a trainable weight, it is computed at model init and cached.
   # During the training of ESM-2 the model was converted to float16 precision, which also converts
   # the inv_freq tensor, and the loss of precision remains even if the model is loaded later as float32.
   # If we recompute inv_freq without this loss of precision then we will get subtly different rotary
   # embeddings, which are enough to cause significant discrepancies in model outputs. To avoid this,
   # we make sure the new model copies the data from the old inv_freq.
   UpperCamelCase      =			esm_layer.self_attn.rot_emb.inv_freq

  # LayerNorm changes for pre-activation
  UpperCamelCase      =			esm_layer.self_attn_layer_norm.weight
  UpperCamelCase      =			esm_layer.self_attn_layer_norm.bias
  UpperCamelCase      =			esm_layer.final_layer_norm.weight
  UpperCamelCase      =			esm_layer.final_layer_norm.bias

  # self-attention output
  UpperCamelCase      =			layer.attention.output
  assert self_output.dense.weight.shape == esm_layer.self_attn.out_proj.weight.shape
  UpperCamelCase      =			esm_layer.self_attn.out_proj.weight
  UpperCamelCase      =			esm_layer.self_attn.out_proj.bias

  # intermediate
  UpperCamelCase      =			layer.intermediate
  assert intermediate.dense.weight.shape == esm_layer.fca.weight.shape
  UpperCamelCase      =			esm_layer.fca.weight
  UpperCamelCase      =			esm_layer.fca.bias

  # output
  UpperCamelCase      =			layer.output
  assert bert_output.dense.weight.shape == esm_layer.fca.weight.shape
  UpperCamelCase      =			esm_layer.fca.weight
  UpperCamelCase      =			esm_layer.fca.bias
  # end of layer

 if is_folding_model:
  UpperCamelCase      =			esm.esm_s_combine.data
  UpperCamelCase      =			esm.afa_to_esm.data
  transfer_and_check_weights(esm.embedding       ,				model.embedding					)
  transfer_and_check_weights(esm.esm_s_mlp       ,				model.esm_s_mlp					)
  transfer_and_check_weights(esm.trunk       ,				model.trunk					)
  transfer_and_check_weights(esm.distogram_head       ,				model.distogram_head					)
  transfer_and_check_weights(esm.ptm_head       ,				model.ptm_head					)
  transfer_and_check_weights(esm.lm_head       ,				model.lm_head					)
  transfer_and_check_weights(esm.lddt_head       ,				model.lddt_head					)

 elif classification_head:
  UpperCamelCase      =			esm.esm.classification_heads["""mnli"""].dense.weight
  UpperCamelCase      =			esm.classification_heads["""mnli"""].dense.bias
  UpperCamelCase      =			esm.classification_heads["""mnli"""].out_proj.weight
  UpperCamelCase      =			esm.classification_heads["""mnli"""].out_proj.bias
 else:
  # LM Head
  UpperCamelCase      =			esm.lm_head.dense.weight
  UpperCamelCase      =			esm.lm_head.dense.bias
  UpperCamelCase      =			esm.lm_head.layer_norm.weight
  UpperCamelCase      =			esm.lm_head.layer_norm.bias
  UpperCamelCase      =			esm.lm_head.weight
  UpperCamelCase      =			esm.lm_head.bias

 # Contact prediction head
 transfer_and_check_weights(esm.contact_head       ,				model.esm.contact_head					)

 # Prepare data (first 2 sequences from ESMStructuralSplitDataset superfamily / 4)
 if is_folding_model:
  # Folding models aren't trained on masked inputs and don't like mask tokens.
  UpperCamelCase      =			SAMPLE_DATA[:2]
 else:
  UpperCamelCase      =			SAMPLE_DATA

 if is_folding_model:
  UpperCamelCase      =			get_esmfold_tokenizer()
  UpperCamelCase      =			hf_tokenizer(
      [row[1] for row in sample_data]       ,				return_tensors="""pt"""       ,				padding=UpperCamelCase_       ,				add_special_tokens=UpperCamelCase_					)
  UpperCamelCase     ,    UpperCamelCase     ,    UpperCamelCase     ,    UpperCamelCase     ,    UpperCamelCase      =			esmfold_encode_sequences([row[1] for row in sample_data]					)
  UpperCamelCase      =			torch.all(hf_tokens["""input_ids"""] == esmfold_aas					) and torch.all(
      hf_tokens["""attention_mask"""] == esmfold_mask					)
 else:
  # Let's check that we get the same results.
  UpperCamelCase      =			alphabet.get_batch_converter()
  UpperCamelCase     ,    UpperCamelCase     ,    UpperCamelCase      =			batch_converter(UpperCamelCase_					)
  # Prepare tokenizer and make sure it matches
  with TemporaryDirectory() as tempdir:
   UpperCamelCase      =			"""\n""".join(alphabet.all_toks					)
   UpperCamelCase      =			Path(UpperCamelCase_					) / """vocab.txt"""
   vocab_file.write_text(UpperCamelCase_					)
   UpperCamelCase      =			EsmTokenizer(vocab_file=str(UpperCamelCase_					)					)

  UpperCamelCase      =			hf_tokenizer([row[1] for row in sample_data]       ,				return_tensors="""pt"""       ,				padding=UpperCamelCase_					)
  UpperCamelCase      =			torch.all(hf_tokens["""input_ids"""] == batch_tokens					)

 print("""Do both models tokenizers output the same tokens?"""       ,				"""🔥""" if success else """💩"""					)
 if not success:
  raise Exception("""Tokenization does not match!"""					)

 with torch.no_grad():
  if is_folding_model:
   # Let's test the model in parts
   # ESMFold always converts the ESM stem to float16, which requires float16 ops
   # that don't exist on CPU. Therefore, to test it we need to run it on GPU. However,
   # ESMFold is what we in the community call a "big boy" and so we desperately avoid putting both the
   # original and the converted model on the GPU at the same time.
   UpperCamelCase      =			esm.cuda().infer([row[1] for row in sample_data]					)
   UpperCamelCase      =			model.cuda()(
       input_ids=hf_tokens["""input_ids"""].cuda()       ,				attention_mask=hf_tokens["""attention_mask"""].cuda()					)
  else:
   UpperCamelCase      =			model(**UpperCamelCase_       ,				output_hidden_states=UpperCamelCase_					)
   UpperCamelCase      =			our_output["""logits"""]
   if classification_head:
    UpperCamelCase      =			esm.model.classification_heads["""mnli"""](esm.extract_features(UpperCamelCase_					)					)
   else:
    UpperCamelCase      =			esm(hf_tokens["""input_ids"""]       ,				repr_layers=list(range(999					)					)					)
    UpperCamelCase      =			their_output["""logits"""]

  if is_folding_model:
   UpperCamelCase      =			torch.max(torch.abs(our_output["""positions"""] - their_output["""positions"""]					)					).item()
   UpperCamelCase      =			torch.allclose(our_output["""positions"""]       ,				their_output["""positions"""]       ,				atol=1E-5					)
  else:
   UpperCamelCase      =			torch.max(torch.abs(our_output - their_output					)					).item()
   UpperCamelCase      =			torch.allclose(UpperCamelCase_       ,				UpperCamelCase_       ,				atol=1E-5					)

  print(f"""max_absolute_diff = {max_absolute_diff}"""					)  # ~ 1e-5
  print("""Do both models output the same tensors?"""       ,				"""🔥""" if success else """💩"""					)

  if not success:
   raise Exception("""Something went wRoNg"""					)

  if not is_folding_model:
   # Let's check contact prediction too
   UpperCamelCase      =			model.predict_contacts(hf_tokens["""input_ids"""]       ,				hf_tokens["""attention_mask"""]					)
   UpperCamelCase      =			esm.predict_contacts(hf_tokens["""input_ids"""]					)
   UpperCamelCase      =			torch.max(torch.abs(our_output - their_output					)					).item()
   UpperCamelCase      =			torch.allclose(UpperCamelCase_       ,				UpperCamelCase_       ,				atol=1E-5					)

   print("""Contact prediction testing:"""					)
   print(f"""max_absolute_diff = {max_absolute_diff}"""					)  # ~ 1e-5
   print("""Do both models output the same tensors?"""       ,				"""🔥""" if success else """💩"""					)

   if not success:
    raise Exception("""Something went wRoNg"""					)

  pathlib.Path(UpperCamelCase_					).mkdir(parents=UpperCamelCase_       ,				exist_ok=UpperCamelCase_					)
  print(f"""Saving model to {pytorch_dump_folder_path}"""					)
  model.save_pretrained(UpperCamelCase_					)

  del esm  # Free up some memory before continuing

 print(f"""Saving tokenizer to {pytorch_dump_folder_path}"""					)
 hf_tokenizer.save_pretrained(UpperCamelCase_					)

 if push_to_repo:
  model.push_to_hub(repo_id=UpperCamelCase_       ,				use_auth_token=UpperCamelCase_					)
  hf_tokenizer.push_to_hub(repo_id=UpperCamelCase_       ,				use_auth_token=UpperCamelCase_					)


if __name__ == "__main__":
     _SCREAMING_SNAKE_CASE   		=			argparse.ArgumentParser()
     # Required parameters
     parser.add_argument(
         """--pytorch_dump_folder_path""", type=str, required=True, help="""Path to the output PyTorch model."""
     )
     parser.add_argument(
         """--classification_head""", action="""store_true""", help="""Whether to convert a final classification head."""
     )
     parser.add_argument("""--model""", default=None, type=str, required=True, help="""Name of model to convert.""")
     parser.add_argument("""--push_to_repo""", type=str, help="""Repo to upload to (including username!).""")
     parser.add_argument("""--auth_token""", type=str, help="""HuggingFace auth token.""")
     _SCREAMING_SNAKE_CASE   		=			parser.parse_args()
     convert_esm_checkpoint_to_pytorch(
         args.model, args.pytorch_dump_folder_path, args.classification_head, args.push_to_repo, args.auth_token
     )

import numpy as np





def  lowercase(  UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_					)		->  List[str]:







 '''simple docstring'''
 UpperCamelCase      =			n_draws * class_counts / class_counts.sum()
 # floored means we don't overshoot n_samples, but probably undershoot
 UpperCamelCase      =			np.floor(UpperCamelCase_					)
 # we add samples according to how much "left over" probability
 # they had, until we arrive at n_samples
 UpperCamelCase      =			int(n_draws - floored.sum()					)
 if need_to_add > 0:
  UpperCamelCase      =			continuous - floored
  UpperCamelCase      =			np.sort(np.unique(UpperCamelCase_					)					)[::-1]
  # add according to remainder, but break ties
  # randomly to avoid biases
  for value in values:
   ((UpperCamelCase)     ,    )      =			np.where(remainder == value					)
   # if we need_to_add less than what's in inds
   # we draw randomly from them.
   # if we need to add more, we add them all and
   # go to the next value
   UpperCamelCase      =			min(len(UpperCamelCase_					)       ,				UpperCamelCase_					)
   UpperCamelCase      =			rng.choice(UpperCamelCase_       ,				size=UpperCamelCase_       ,				replace=UpperCamelCase_					)
   floored[inds] += 1
   need_to_add -= add_now
   if need_to_add == 0:
    break
 return floored.astype(np.intaa					)





def  lowercase(  UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_=10					)		->  Dict:







 '''simple docstring'''
 UpperCamelCase     ,    UpperCamelCase      =			np.unique(UpperCamelCase_       ,				return_inverse=UpperCamelCase_					)
 UpperCamelCase      =			classes.shape[0]
 UpperCamelCase      =			np.bincount(UpperCamelCase_					)
 if np.min(UpperCamelCase_					) < 2:
  raise ValueError("""Minimum class count error"""					)
 if n_train < n_classes:
  raise ValueError(
      """The train_size = %d should be greater or """ """equal to the number of classes = %d""" % (n_train, n_classes)					)
 if n_test < n_classes:
  raise ValueError(
      """The test_size = %d should be greater or """ """equal to the number of classes = %d""" % (n_test, n_classes)					)
 UpperCamelCase      =			np.split(np.argsort(UpperCamelCase_       ,				kind="""mergesort"""					)       ,				np.cumsum(UpperCamelCase_					)[:-1]					)
 for _ in range(UpperCamelCase_					):
  UpperCamelCase      =			approximate_mode(UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_					)
  UpperCamelCase      =			class_counts - n_i
  UpperCamelCase      =			approximate_mode(UpperCamelCase_       ,				UpperCamelCase_       ,				UpperCamelCase_					)

  UpperCamelCase      =			[]
  UpperCamelCase      =			[]

  for i in range(UpperCamelCase_					):
   UpperCamelCase      =			rng.permutation(class_counts[i]					)
   UpperCamelCase      =			class_indices[i].take(UpperCamelCase_       ,				mode="""clip"""					)
   train.extend(perm_indices_class_i[: n_i[i]]					)
   test.extend(perm_indices_class_i[n_i[i] : n_i[i] + t_i[i]]					)
  UpperCamelCase      =			rng.permutation(UpperCamelCase_					)
  UpperCamelCase      =			rng.permutation(UpperCamelCase_					)

  yield train, test
