"""simple docstring"""







import dataclasses
import re
import string
from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Tuple

import numpy as np

from . import residue_constants


__SCREAMING_SNAKE_CASE    	=Mapping[str, np.ndarray]
__SCREAMING_SNAKE_CASE    	=Mapping[str, Any]  # Is a nested dict.
__SCREAMING_SNAKE_CASE    	=0.01







@dataclasses.dataclass(frozen=lowercase_  )
class        UpperCamelCase		:
   lowercase							=  42  # [num_res, num_atom_type, 3]

   # Amino-acid type for each residue represented as an integer between 0 and
   # 20, where 20 is 'X'.
   lowercase							=  42  # [num_res]

   # Binary float mask to indicate presence of a particular atom. 1.0 if an atom
   # is present and 0.0 if not. This should be used for loss masking.
   lowercase							=  42  # [num_res, num_atom_type]

   # Residue index as used in PDB. It is not necessarily continuous or 0-indexed.
   lowercase							=  42  # [num_res]

   # B-factors, or temperature factors, of each residue (in sq. angstroms units),
   # representing the displacement of the residue from its ground truth mean
   # value.
   lowercase							=  42  # [num_res, num_atom_type]

   # Chain indices for multi-chain predictions
   lowercase							=  None

   # Optional remark about the protein. Included as a comment in output PDB
   # files
   lowercase							=  None

   # Templates used to generate this protein (prediction-only)
   lowercase							=  None

   # Chain corresponding to each parent
   lowercase							=  None






def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     str      ):
     lowercase_	:				List[Any]													=	R'(\[[A-Z]+\]\n)'
     lowercase_	:				Dict													=	[tag.strip() for tag in re.split(lowerCAmelCase_     ,			lowerCAmelCase_      ) if len(lowerCAmelCase_      ) > 0]
     lowercase_	:				Dict													=	zip(tags[0::2]     ,			[l.split('\n'      ) for l in tags[1::2]]      )

     lowercase_	:				str													=	['N', 'CA', 'C']
     lowercase_	:				List[str]													=	None
     lowercase_	:				str													=	None
     lowercase_	:				int													=	None
     for g in groups:
          if "[PRIMARY]" == g[0]:
               lowercase_	:				Dict													=	g[1][0].strip()
               for i in range(len(lowerCAmelCase_      )      ):
                    if seq[i] not in residue_constants.restypes:
                         lowercase_	:				Dict													=	'X'  # FIXME: strings are immutable
               lowercase_	:				Optional[Any]													=	np.array(
                   [residue_constants.restype_order.get(lowerCAmelCase_     ,			residue_constants.restype_num      ) for res_symbol in seq]      )
          elif "[TERTIARY]" == g[0]:
               lowercase_	:				Any													=	[]
               for axis in range(3      ):
                    tertiary.append(list(map(lowerCAmelCase_     ,			g[1][axis].split()      )      )      )
               lowercase_	:				Optional[int]													=	np.array(lowerCAmelCase_      )
               lowercase_	:				Dict													=	np.zeros((len(tertiary[0]      ) // 3, residue_constants.atom_type_num, 3)      ).astype(np.floataa      )
               for i, atom in enumerate(lowerCAmelCase_      ):
                    lowercase_	:				Optional[int]													=	np.transpose(tertiary_np[:, i::3]      )
               atom_positions *= PICO_TO_ANGSTROM
          elif "[MASK]" == g[0]:
               lowercase_	:				int													=	np.array(list(map({'-': 0, '+': 1}.get     ,			g[1][0].strip()      )      )      )
               lowercase_	:				Optional[Any]													=	np.zeros(
                   (
                       len(lowerCAmelCase_      ),
                       residue_constants.atom_type_num,
                   )      ).astype(np.floataa      )
               for i, atom in enumerate(lowerCAmelCase_      ):
                    lowercase_	:				str													=	1
               atom_mask *= mask[..., None]

     assert aatype is not None

     return Protein(
         atom_positions=lowerCAmelCase_     ,			atom_mask=lowerCAmelCase_     ,			aatype=lowerCAmelCase_     ,			residue_index=np.arange(len(lowerCAmelCase_      )      )     ,			b_factors=lowerCAmelCase_     ,			)



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     List[Any]     ,			__SCREAMING_SNAKE_CASE							:     Dict = 0      ):
     lowercase_	:				List[str]													=	[]

     lowercase_	:				List[Any]													=	prot.remark
     if remark is not None:
          pdb_headers.append(F'''REMARK {remark}'''      )

     lowercase_	:				Any													=	prot.parents
     lowercase_	:				List[Any]													=	prot.parents_chain_index
     if parents is not None and parents_chain_index is not None:
          lowercase_	:				Tuple													=	[p for i, p in zip(lowerCAmelCase_     ,			lowerCAmelCase_      ) if i == chain_id]

     if parents is None or len(lowerCAmelCase_      ) == 0:
          lowercase_	:				Tuple													=	['N/A']

     pdb_headers.append(F'''PARENT {" ".join(lowerCAmelCase_      )}'''      )

     return pdb_headers



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     Dict     ,			__SCREAMING_SNAKE_CASE							:     int      ):
     lowercase_	:				int													=	[]
     lowercase_	:				str													=	pdb_str.split('\n'      )

     lowercase_	:				Optional[int]													=	prot.remark
     if remark is not None:
          out_pdb_lines.append(F'''REMARK {remark}'''      )

     lowercase_	:				int													=	42
     if prot.parents is not None and len(prot.parents      ) > 0:
          lowercase_	:				Dict													=	[]
          if prot.parents_chain_index is not None:
               lowercase_	:				Tuple													=	{}
               for p, i in zip(prot.parents     ,			prot.parents_chain_index      ):
                    parent_dict.setdefault(str(lowerCAmelCase_      )     ,			[]      )
                    parent_dict[str(lowerCAmelCase_      )].append(lowerCAmelCase_      )

               lowercase_	:				Union[str, Any]													=	max([int(lowerCAmelCase_      ) for chain_idx in parent_dict]      )
               for i in range(max_idx + 1      ):
                    lowercase_	:				Any													=	parent_dict.get(str(lowerCAmelCase_      )     ,			['N/A']      )
                    parents_per_chain.append(lowerCAmelCase_      )
          else:
               parents_per_chain.append(list(prot.parents      )      )
     else:
          lowercase_	:				List[Any]													=	[['N/A']]

     def make_parent_line(__SCREAMING_SNAKE_CASE							:     List[str]      ) -> str:
          return F'''PARENT {" ".join(lowerCAmelCase_      )}'''

     out_pdb_lines.append(make_parent_line(parents_per_chain[0]      )      )

     lowercase_	:				Optional[int]													=	0
     for i, l in enumerate(lowerCAmelCase_      ):
          if "PARENT" not in l and "REMARK" not in l:
               out_pdb_lines.append(lowerCAmelCase_      )
          if "TER" in l and "END" not in lines[i + 1]:
               chain_counter += 1
               if not chain_counter >= len(lowerCAmelCase_      ):
                    lowercase_	:				List[Any]													=	parents_per_chain[chain_counter]
               else:
                    lowercase_	:				List[Any]													=	['N/A']

               out_pdb_lines.append(make_parent_line(lowerCAmelCase_      )      )

     return "\n".join(lowerCAmelCase_      )



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     Optional[int]      ):
     lowercase_	:				Any													=	residue_constants.restypes + ['X']

     def res_atoa(__SCREAMING_SNAKE_CASE							:     List[str]      ) -> str:
          return residue_constants.restype_atoa.get(restypes[r]     ,			'UNK'      )

     lowercase_	:				List[str]													=	residue_constants.atom_types

     lowercase_	:				Any													=	[]

     lowercase_	:				str													=	prot.atom_mask
     lowercase_	:				Any													=	prot.aatype
     lowercase_	:				Dict													=	prot.atom_positions
     lowercase_	:				Optional[int]													=	prot.residue_index.astype(np.intaa      )
     lowercase_	:				str													=	prot.b_factors
     lowercase_	:				Tuple													=	prot.chain_index

     if np.any(aatype > residue_constants.restype_num      ):
          raise ValueError('Invalid aatypes.'      )

     lowercase_	:				List[str]													=	get_pdb_headers(lowerCAmelCase_      )
     if len(lowerCAmelCase_      ) > 0:
          pdb_lines.extend(lowerCAmelCase_      )

     lowercase_	:				List[Any]													=	aatype.shape[0]
     lowercase_	:				Dict													=	1
     lowercase_	:				List[Any]													=	0
     lowercase_	:				Union[str, Any]													=	string.ascii_uppercase
     lowercase_	:				List[Any]													=	None
     # Add all atom sites.
     for i in range(lowerCAmelCase_      ):
          lowercase_	:				Dict													=	res_atoa(aatype[i]      )
          for atom_name, pos, mask, b_factor in zip(lowerCAmelCase_     ,			atom_positions[i]     ,			atom_mask[i]     ,			b_factors[i]      ):
               if mask < 0.5:
                    continue

               lowercase_	:				Optional[int]													=	'ATOM'
               lowercase_	:				Any													=	atom_name if len(lowerCAmelCase_      ) == 4 else F''' {atom_name}'''
               lowercase_	:				List[Any]													=	''
               lowercase_	:				Tuple													=	''
               lowercase_	:				Union[str, Any]													=	1.00
               lowercase_	:				Tuple													=	atom_name[0]  # Protein supports only C, N, O, S, this works.
               lowercase_	:				str													=	''

               lowercase_	:				Union[str, Any]													=	'A'
               if chain_index is not None:
                    lowercase_	:				Any													=	chain_tags[chain_index[i]]

               # PDB is a columnar format, every space matters here!
               lowercase_	:				Tuple													=	(
                   F'''{record_type:<6}{atom_index:>5} {name:<4}{alt_loc:>1}'''
                   F'''{res_name_a:>3} {chain_tag:>1}'''
                   F'''{residue_index[i]:>4}{insertion_code:>1}   '''
                   F'''{pos[0]:>8.3f}{pos[1]:>8.3f}{pos[2]:>8.3f}'''
                   F'''{occupancy:>6.2f}{b_factor:>6.2f}          '''
                   F'''{element:>2}{charge:>2}'''
               )
               pdb_lines.append(lowerCAmelCase_      )
               atom_index += 1

          lowercase_	:				Union[str, Any]													=	i == n - 1
          if chain_index is not None:
               if i != n - 1 and chain_index[i + 1] != prev_chain_index:
                    lowercase_	:				str													=	True
                    lowercase_	:				Tuple													=	chain_index[i + 1]

          if should_terminate:
               # Close the chain.
               lowercase_	:				Union[str, Any]													=	'TER'
               lowercase_	:				Union[str, Any]													=	(
                   F'''{chain_end:<6}{atom_index:>5}      {res_atoa(aatype[i]      ):>3} {chain_tag:>1}{residue_index[i]:>4}'''
               )
               pdb_lines.append(lowerCAmelCase_      )
               atom_index += 1

               if i != n - 1:
                    # "prev" is a misnomer here. This happens at the beginning of
                    # each new chain.
                    pdb_lines.extend(get_pdb_headers(lowerCAmelCase_     ,			lowerCAmelCase_      )      )

     pdb_lines.append('END'      )
     pdb_lines.append(''      )
     return "\n".join(lowerCAmelCase_      )



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     Any      ):
     return residue_constants.STANDARD_ATOM_MASK[prot.aatype]







def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     Tuple     ,			__SCREAMING_SNAKE_CASE							:     Dict     ,			__SCREAMING_SNAKE_CASE							:     Dict = None     ,			__SCREAMING_SNAKE_CASE							:     Union[str, Any] = None     ,			__SCREAMING_SNAKE_CASE							:     str = None     ,			__SCREAMING_SNAKE_CASE							:     Dict = None     ,			__SCREAMING_SNAKE_CASE							:     str = None     ,			):
     return Protein(
         aatype=features['aatype']     ,			atom_positions=result['final_atom_positions']     ,			atom_mask=result['final_atom_mask']     ,			residue_index=features['residue_index'] + 1     ,			b_factors=b_factors if b_factors is not None else np.zeros_like(result['final_atom_mask']      )     ,			chain_index=lowerCAmelCase_     ,			remark=lowerCAmelCase_     ,			parents=lowerCAmelCase_     ,			parents_chain_index=lowerCAmelCase_     ,			)





"""simple docstring"""







import unittest

from transformers import is_torch_available
from transformers.testing_utils import require_torch


if is_torch_available():
		import torch

		from transformers.generation import DisjunctiveConstraint




@require_torch
class  UpperCamelCase_	( unittest.TestCase):

	"""simple docstring"""





	def   UpperCAmelCase_      ( self			:				Optional[int]   )       ->	List[str]:
						# For consistency across different places the DisjunctiveConstraint is called,
						# dc.token_ids is a list of integers. It is also initialized only by integers.

						__SCREAMING_SNAKE_CASE						   =				[[1, 2, 4], [1, 2, 3, 4]]
						__SCREAMING_SNAKE_CASE						   =				DisjunctiveConstraint(UpperCAmelCase__   )
						self.assertTrue(isinstance(dc.token_ids			,			UpperCAmelCase__   )   )

						with self.assertRaises(UpperCAmelCase__   ):
											DisjunctiveConstraint(torch.LongTensor([[1, 2, 4], [1, 2, 3]]   )   )

						with self.assertRaises(UpperCAmelCase__   ):
											DisjunctiveConstraint([torch.LongTensor([1, 2, 4]   ), torch.LongTensor([1, 2, 3, 4, 5]   )]   )




	def   UpperCAmelCase_      ( self			:				Any   )       ->	int:
						# We can't have constraints that are complete subsets of another. This leads to a preverse
						# interpretation of "constraint fulfillment": does generating [1,2,3] fulfill the constraint?
						# It would mean that it generated [1,2] which fulfills it, but it's in the middle of potentially
						# fulfilling [1,2,3,4]. If we believe that [1,2,3] does fulfill the constraint, then the algorithm
						# will necessarily never reach [1,2,3,4], giving users a false sense of control (better to just not allow it).
						__SCREAMING_SNAKE_CASE						   =				[[1, 2], [1, 2, 3, 4]]

						with self.assertRaises(UpperCAmelCase__   ):
											DisjunctiveConstraint(UpperCAmelCase__   )  # fails here




	def   UpperCAmelCase_      ( self			:				List[Any]   )       ->	Any:
						__SCREAMING_SNAKE_CASE						   =				[[1, 2, 3], [1, 2, 4]]

						__SCREAMING_SNAKE_CASE						   =				DisjunctiveConstraint(UpperCAmelCase__   )

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(1   )
						__SCREAMING_SNAKE_CASE						   =				stepped is True and completed is False and reset is False
						self.assertTrue(UpperCAmelCase__   )
						self.assertTrue(not dc.completed   )
						self.assertTrue(dc.current_seq == [1]   )

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(2   )
						__SCREAMING_SNAKE_CASE						   =				stepped is True and completed is False and reset is False
						self.assertTrue(UpperCAmelCase__   )
						self.assertTrue(not dc.completed   )
						self.assertTrue(dc.current_seq == [1, 2]   )

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(3   )
						__SCREAMING_SNAKE_CASE						   =				stepped is True and completed is True and reset is False
						self.assertTrue(UpperCAmelCase__   )
						self.assertTrue(dc.completed   )  # Completed!
						self.assertTrue(dc.current_seq == [1, 2, 3]   )




	def   UpperCAmelCase_      ( self			:				str   )       ->	List[str]:
						__SCREAMING_SNAKE_CASE						   =				[[1, 2, 3], [1, 2, 4, 5], [1, 2, 5]]

						__SCREAMING_SNAKE_CASE						   =				DisjunctiveConstraint(UpperCAmelCase__   )

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(1   )
						self.assertTrue(not dc.completed   )
						self.assertTrue(dc.current_seq == [1]   )

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(2   )
						self.assertTrue(not dc.completed   )
						self.assertTrue(dc.current_seq == [1, 2]   )

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(4   )
						self.assertTrue(not dc.completed   )
						self.assertTrue(dc.current_seq == [1, 2, 4]   )

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(5   )
						self.assertTrue(dc.completed   )  # Completed!
						self.assertTrue(dc.current_seq == [1, 2, 4, 5]   )

						dc.reset()

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(1   )
						self.assertTrue(not dc.completed   )
						self.assertTrue(dc.remaining() == 3   )
						self.assertTrue(dc.current_seq == [1]   )

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(2   )
						self.assertTrue(not dc.completed   )
						self.assertTrue(dc.remaining() == 2   )
						self.assertTrue(dc.current_seq == [1, 2]   )

						__SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE   ,  __SCREAMING_SNAKE_CASE						   =				dc.update(5   )
						self.assertTrue(dc.completed   )  # Completed!
						self.assertTrue(dc.remaining() == 0   )
						self.assertTrue(dc.current_seq == [1, 2, 5]   )
