def apply_autoencoder_pre_latent(
    transformer_layer: TransformerLayer,
    autoencoder: Autoencoder,
    resid: torch.Tensor,
    autoencoder_dst: DerivedScalarType,
    detach_layer_norm_scale: bool,
    latent_slice: slice = slice(None),
) -> torch.Tensor:
    """
    Given the residual stream activations preceding an autoencoder to be
    applied to a given DST, first compute the activations of the DST (`to_be_encoded`)
    and then apply the autoencoder to these activations (NOT INCLUDING the autoencoder nonlinearity),
    and return the result.
    """
    match autoencoder_dst:
        case DerivedScalarType.MLP_POST_ACT:
            to_be_encoded = apply_mlp_act(
                transformer_layer,
                resid,
                detach_layer_norm_scale=detach_layer_norm_scale,
            )
        case DerivedScalarType.RESID_DELTA_ATTN:
            to_be_encoded = apply_resid_delta_attn(
                transformer_layer,
                resid,
                detach_layer_norm_scale=detach_layer_norm_scale,
            )
        case DerivedScalarType.RESID_DELTA_MLP:
            to_be_encoded = apply_resid_delta_mlp(
                transformer_layer,
                resid,
                detach_layer_norm_scale=detach_layer_norm_scale,
            )
        case _:
            raise NotImplementedError(autoencoder_dst.node_type)
    return autoencoder.encode_pre_act(to_be_encoded, latent_slice=latent_slice)

    Given the residual stream activations preceding an autoencoder to be
    applied to a given DST, first compute the activations of the DST (`to_be_encoded`)
    and then apply the autoencoder to these activations (NOT INCLUDING the autoencoder nonlinearity),
    and return the result.
    
neuron_explainer/activations/derived_scalars/reconstituted.py