class_docstr: Multiview Transformer Encoder.
  
  Attributes:
    view_configs: Model configs for each view (e.g., num_heads, mlp_dim, etc).
    cross_view_fusion: Cross view fusion config.
    dropout_rate: Dropout rate.
    attention_dropout_rate: Dropout for attention heads.
    stochastic_depth: probability of dropping a layer linearly grows from 0 to
      the provided value. Our implementation of stochastic depth follows the
      timm library, which does per-example layer dropping and uses independent
      dropping patterns for each skip-connection.
    dtype: Any of activations.
docstr: Builds the encoder with bottlenecks.
docstr_tok: ["Builds","the","encoder","with","bottlenecks","."]
code: def _build_with_bottleneck(
      self,
      xs: List[jnp.ndarray],
      bottleneck: jnp.ndarray,
      fusion_layers: Sequence[int],
      max_num_layers: int,
      train: bool,
      dtype: Any,
  ) -> List[jnp.ndarray]:
      """Builds the encoder with bottlenecks."""
      view_indices = list(range(len(self.view_configs)))
      if self.cross_view_fusion.get("fuse_in_descending_order", True):
          view_indices.reverse()
      for lyr in range(max_num_layers):
          for view_idx in view_indices:
              view_config = self.view_configs[view_idx]
              if lyr >= view_config["num_layers"]:
                  continue
              if lyr in fusion_layers:
                  if xs[view_idx].shape[-1] != bottleneck.shape[-1]:
                      bottleneck = nn.Dense(
                          xs[view_idx].shape[-1],
                          kernel_init=nn.initializers.xavier_uniform(),
                          name=f"bottleneck_linear_{lyr}_view{view_idx}",
                      )(bottleneck)
                  xs[view_idx] = jnp.concatenate(
                      [xs[view_idx], bottleneck], axis=1
                  )
  
              xs[view_idx] = vit.Encoder1DBlock(
                  mlp_dim=view_config["mlp_dim"],
                  num_heads=view_config["num_heads"],
                  dropout_rate=self.dropout_rate,
                  attention_dropout_rate=self.attention_dropout_rate,
                  stochastic_depth=(
                      lyr / max(view_config["num_layers"] - 1, 1)
                  )
                  * self.stochastic_depth,
                  name=f"encoderblock_{lyr}_view{view_idx}",
                  dtype=self.dtype,
              )(xs[view_idx], deterministic=not train)
              if lyr in fusion_layers:
                  (
                      xs[view_idx],
                      bottleneck,
                  ) = self._split_tokens_and_bottleneck(xs[view_idx])
      return xs
  
imports: import functools
  from typing import Any, List, Sequence, Tuple, Union
  import flax.linen
  import jax
  import jax.numpy
  import ml_collections
  from scenic.model_lib.layers import attention_layers
  from scenic.model_lib.layers import nn_layers
  from scenic.projects.baselines import vit
  from scenic.projects.mtv import model_utils
  from scenic.projects.vivit import model
  from scenic.train_lib import train_utils
label_desc: Use image node_id 3 for calling the MultiviewEncoder obj's underlying member method code with example usage: obj._build_with_bottleneck(xs, bottleneck, fusion_layers, max_num_layers, train, dtype) and returns: xs