
    +hi                     r   S SK r S SKJrJrJrJrJrJr  S SKr	S SK
r
S SKJrJr  SSKJrJr  SSKJr  SSKJrJr  SSKJr  SS	KJrJrJrJr  SS
KJr  SSKJ r   SSK!J"r"  SSK#J$r$  \" 5       (       a  S SK%J&s  J'r(  Sr)OSr)\RT                  " \+5      r,\" 5       (       a  S SK-r-Sr.S r/S r0S r1 " S S\"\5      r2g)    N)AnyCallableDictListOptionalUnion)AutoTokenizerUMT5EncoderModel   )MultiPipelineCallbacksPipelineCallback)SkyReelsV2LoraLoaderMixin)AutoencoderKLWanSkyReelsV2Transformer3DModel)UniPCMultistepScheduler)is_ftfy_availableis_torch_xla_availableloggingreplace_example_docstring)randn_tensor)VideoProcessor   )DiffusionPipeline   )SkyReelsV2PipelineOutputTFas      Examples:
        ```py
        >>> import torch
        >>> from diffusers import (
        ...     SkyReelsV2Pipeline,
        ...     UniPCMultistepScheduler,
        ...     AutoencoderKLWan,
        ... )
        >>> from diffusers.utils import export_to_video

        >>> # Load the pipeline
        >>> # Available models:
        >>> # - Skywork/SkyReels-V2-T2V-14B-540P-Diffusers
        >>> # - Skywork/SkyReels-V2-T2V-14B-720P-Diffusers
        >>> vae = AutoencoderKLWan.from_pretrained(
        ...     "Skywork/SkyReels-V2-T2V-14B-720P-Diffusers",
        ...     subfolder="vae",
        ...     torch_dtype=torch.float32,
        ... )
        >>> pipe = SkyReelsV2Pipeline.from_pretrained(
        ...     "Skywork/SkyReels-V2-T2V-14B-720P-Diffusers",
        ...     vae=vae,
        ...     torch_dtype=torch.bfloat16,
        ... )
        >>> flow_shift = 8.0  # 8.0 for T2V, 5.0 for I2V
        >>> pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config, flow_shift=flow_shift)
        >>> pipe = pipe.to("cuda")

        >>> prompt = "A cat and a dog baking a cake together in a kitchen. The cat is carefully measuring flour, while the dog is stirring the batter with a wooden spoon. The kitchen is cozy, with sunlight streaming through the window."

        >>> output = pipe(
        ...     prompt=prompt,
        ...     num_inference_steps=50,
        ...     height=544,
        ...     width=960,
        ...     guidance_scale=6.0,  # 6.0 for T2V, 5.0 for I2V
        ...     num_frames=97,
        ... ).frames[0]
        >>> export_to_video(output, "video.mp4", fps=24, quality=8)
        ```
c                     [         R                  " U 5      n [        R                  " [        R                  " U 5      5      n U R	                  5       $ N)ftfyfix_texthtmlunescapestriptexts    n/home/james-whalen/.local/lib/python3.13/site-packages/diffusers/pipelines/skyreels_v2/pipeline_skyreels_v2.pybasic_cleanr&   Z   s3    ==D==t,-D::<    c                 V    [         R                  " SSU 5      n U R                  5       n U $ )Nz\s+ )resubr"   r#   s    r%   whitespace_cleanr,   `   s$    66&#t$D::<DKr'   c                 .    [        [        U 5      5      n U $ r   )r,   r&   r#   s    r%   prompt_cleanr.   f   s    K-.DKr'   c            (         ^  \ rS rSrSrSr/ SQrS\S\S\	S\
S	\4
U 4S
 jjr     S9S\\\\   4   S\S\S\\R&                     S\\R(                     4
S jjr        S:S\\\\   4   S\\\\\   4      S\S\S\\R.                     S\\R.                     S\S\\R&                     S\\R(                     4S jjr   S;S jr        S<S\S\S\S\S\S\\R(                     S\\R&                     S\\\R4                  \\R4                     4      S \\R.                     S!\R.                  4S" jjr\S# 5       r\S$ 5       r\S% 5       r\S& 5       r \S' 5       r!\S( 5       r"\RF                  " 5       \$" \%5      SSS)S*S+S,S-SSSSSS.SSSS /S/4S\\\\   4   S\\\\   4   S\S\S\S0\S1\&S\\   S\\\R4                  \\R4                     4      S \\R.                     S\\R.                     S\\R.                     S2\\   S3\S4\\'\\(4      S5\\\)\\\'/S4   \*\+4      S6\\   S\4$S7 jj5       5       r,S8r-U =r.$ )=SkyReelsV2Pipelinek   au  
Pipeline for Text-to-Video (t2v) generation using SkyReels-V2.

This model inherits from [`DiffusionPipeline`]. Check the superclass documentation for the generic methods
implemented for all pipelines (downloading, saving, running on a particular device, etc.).

Args:
    tokenizer ([`T5Tokenizer`]):
        Tokenizer from [T5](https://huggingface.co/docs/transformers/en/model_doc/t5#transformers.T5Tokenizer),
        specifically the [google/umt5-xxl](https://huggingface.co/google/umt5-xxl) variant.
    text_encoder ([`T5EncoderModel`]):
        [T5](https://huggingface.co/docs/transformers/en/model_doc/t5#transformers.T5EncoderModel), specifically
        the [google/umt5-xxl](https://huggingface.co/google/umt5-xxl) variant.
    transformer ([`SkyReelsV2Transformer3DModel`]):
        Conditional Transformer to denoise the input latents.
    scheduler ([`UniPCMultistepScheduler`]):
        A scheduler to be used in combination with `transformer` to denoise the encoded image latents.
    vae ([`AutoencoderKLWan`]):
        Variational Auto-Encoder (VAE) Model to encode and decode videos to and from latent representations.
ztext_encoder->transformer->vae)latentsprompt_embedsnegative_prompt_embeds	tokenizertext_encodertransformervae	schedulerc                 d  > [         TU ]  5         U R                  UUUUUS9  [        U SS 5      (       a"  S[	        U R
                  R                  5      -  OSU l        [        U SS 5      (       a"  S[        U R
                  R                  5      -  OSU l	        [        U R                  S9U l        g )N)r8   r6   r5   r7   r9   r8   r         )vae_scale_factor)super__init__register_modulesgetattrsumr8   temperal_downsamplevae_scale_factor_temporallenvae_scale_factor_spatialr   video_processor)selfr5   r6   r7   r8   r9   	__class__s         r%   r?   SkyReelsV2Pipeline.__init__   s     	%# 	 	
 T[[_afhlSmSmc$((2N2N.O)Ost&RYZ^`egkRlRlS1M1M-N(Nrs%-t?\?\]r'   Nr   promptnum_videos_per_promptmax_sequence_lengthdevicedtypec                    U=(       d    U R                   nU=(       d    U R                  R                  n[        U[        5      (       a  U/OUnU Vs/ s H  n[        U5      PM     nn[        U5      nU R                  USUSSSSS9nUR                  UR                  pU
R                  S5      R                  SS9R                  5       nU R                  U	R                  U5      U
R                  U5      5      R                  nUR                  XTS9n[        X5       VVs/ s H
  u  pmUS U PM     nnn[         R"                  " U Vs/ s HJ  n[         R$                  " XfR'                  X6R)                  S5      -
  UR)                  S5      5      /5      PML     snSS9nUR*                  u  pnUR-                  SUS5      nUR/                  Xr-  US	5      nU$ s  snf s  snnf s  snf )
N
max_lengthTpt)paddingrQ   
truncationadd_special_tokensreturn_attention_maskreturn_tensorsr   r   )dim)rO   rN   )_execution_devicer6   rO   
isinstancestrr.   rE   r5   	input_idsattention_maskgtrB   longtolast_hidden_stateziptorchstackcat	new_zerossizeshaperepeatview)rH   rK   rL   rM   rN   rO   u
batch_sizetext_inputstext_input_idsmaskseq_lensr3   v_seq_lens                   r%   _get_t5_prompt_embeds(SkyReelsV2Pipeline._get_t5_prompt_embeds   s    14110**00'44&&+126a,q/62[
nn *#"& % 
  +44k6P6P771:>>a>(--/)).*;*;F*CTWWV_Ugg%((u(D+.}+GH+G412A+GH^kl^kYZUYY;;':VVAY'Fq	RST^klrs

 &++A%,,Q0EqI%**:+MwXZ[7 3" Ils   G$G!AG'Tnegative_promptdo_classifier_free_guidancer3   r4   c
                 2   U=(       d    U R                   n[        U[        5      (       a  U/OUnUb  [        U5      n
OUR                  S   n
Uc  U R                  UUUUU	S9nU(       a  Uc  U=(       d    Sn[        U[        5      (       a  X/-  OUnUb;  [        U5      [        U5      La$  [        S[        U5       S[        U5       S35      eU
[        U5      :w  a!  [        SU S[        U5       S	U SU
 S
3	5      eU R                  UUUUU	S9nXV4$ )ab  
Encodes the prompt into text encoder hidden states.

Args:
    prompt (`str` or `List[str]`, *optional*):
        prompt to be encoded
    negative_prompt (`str` or `List[str]`, *optional*):
        The prompt or prompts not to guide the image generation. If not defined, one has to pass
        `negative_prompt_embeds` instead. Ignored when not using guidance (i.e., ignored if `guidance_scale` is
        less than `1`).
    do_classifier_free_guidance (`bool`, *optional*, defaults to `True`):
        Whether to use classifier free guidance or not.
    num_videos_per_prompt (`int`, *optional*, defaults to 1):
        Number of videos that should be generated per prompt. torch device to place the resulting embeddings on
    prompt_embeds (`torch.Tensor`, *optional*):
        Pre-generated text embeddings. Can be used to easily tweak text inputs, *e.g.* prompt weighting. If not
        provided, text embeddings will be generated from `prompt` input argument.
    negative_prompt_embeds (`torch.Tensor`, *optional*):
        Pre-generated negative text embeddings. Can be used to easily tweak text inputs, *e.g.* prompt
        weighting. If not provided, negative_prompt_embeds will be generated from `negative_prompt` input
        argument.
    device: (`torch.device`, *optional*):
        torch device
    dtype: (`torch.dtype`, *optional*):
        torch dtype
r   )rK   rL   rM   rN   rO    z?`negative_prompt` should be the same type to `prompt`, but got z != .z`negative_prompt`: z has batch size z, but `prompt`: zT. Please make sure that passed `negative_prompt` matches the batch size of `prompt`.)	rZ   r[   r\   rE   ri   ru   type	TypeError
ValueError)rH   rK   rw   rx   rL   r3   r4   rM   rN   rO   rm   s              r%   encode_prompt SkyReelsV2Pipeline.encode_prompt   sk   L 1411'44&&VJ&,,Q/J  66&;$7 7 M '+A+I-3O@J?\_@`@`j+<<fuO!d6l$:O&OUVZ[jVkUl mV~Q(  s?33 )/)::J3K_J` ax/
| <33  &*%?%?&&;$7 &@ &" 44r'   c           
        ^  US-  S:w  d	  US-  S:w  a  [        SU SU S35      eUbW  [        U 4S jU 5       5      (       d=  [        ST R                   SU Vs/ s H  oT R                  ;  d  M  UPM     sn 35      eUb  Ub  [        S	U S
U S35      eUb  Ub  [        SU SU S35      eUc  Uc  [        S5      eUbA  [        U[        5      (       d,  [        U[
        5      (       d  [        S[        U5       35      eUbC  [        U[        5      (       d-  [        U[
        5      (       d  [        S[        U5       35      eg g g s  snf )N   r   z8`height` and `width` have to be divisible by 16 but are z and r{   c              3   @   >#    U  H  oTR                   ;   v   M     g 7fr   )_callback_tensor_inputs).0krH   s     r%   	<genexpr>2SkyReelsV2Pipeline.check_inputs.<locals>.<genexpr>#  s      F
7Y!---7Ys   z2`callback_on_step_end_tensor_inputs` has to be in z, but found zCannot forward both `prompt`: z and `prompt_embeds`: z2. Please make sure to only forward one of the two.z'Cannot forward both `negative_prompt`: z and `negative_prompt_embeds`: zeProvide either `prompt` or `prompt_embeds`. Cannot leave both `prompt` and `prompt_embeds` undefined.z2`prompt` has to be of type `str` or `list` but is z;`negative_prompt` has to be of type `str` or `list` but is )r~   allr   r[   r\   listr|   )	rH   rK   rw   heightwidthr3   r4   "callback_on_step_end_tensor_inputsr   s	   `        r%   check_inputsSkyReelsV2Pipeline.check_inputs  s    B;!urzQWX^W__dejdkklmnn-9# F
7YF
 C
 C
 DTEaEaDbbn  |^  pH  |^vw  ko  kG  kG  bGpq  |^  pH  oI  J  -";08N}o ^0 0  (-C-O9/9JJi  kA  jB B0 0  ^ 5w  FC)@)@TZ\`IaIaQRVW]R^Q_`aa(?C00OUY9Z9ZZ[_`o[pZqrss :[0 )' pHs   E1Erm   num_channels_latentsr   r   
num_frames	generatorr2   returnc
                 L   U	b  U	R                  XvS9$ US-
  U R                  -  S-   n
UUU
[        U5      U R                  -  [        U5      U R                  -  4n[	        U[
        5      (       a*  [        U5      U:w  a  [        S[        U5       SU S35      e[        XXvS9n	U	$ )N)rN   rO   r   z/You have passed a list of generators of length z+, but requested an effective batch size of z@. Make sure the batch size matches the length of the generators.)r   rN   rO   )	ra   rD   intrF   r[   r   rE   r~   r   )rH   rm   r   r   r   r   rO   rN   r   r2   num_latent_framesri   s               r%   prepare_latents"SkyReelsV2Pipeline.prepare_latents@  s     ::V:99'!^0N0NNQRR K4888J$777
 i&&3y>Z+GA#i.AQ R&<'gi 
 u&Vr'   c                     U R                   $ r   _guidance_scalerH   s    r%   guidance_scale!SkyReelsV2Pipeline.guidance_scale`  s    ###r'   c                      U R                   S:  $ )N      ?r   r   s    r%   rx   .SkyReelsV2Pipeline.do_classifier_free_guidanced  s    ##c))r'   c                     U R                   $ r   )_num_timestepsr   s    r%   num_timesteps SkyReelsV2Pipeline.num_timestepsh  s    """r'   c                     U R                   $ r   )_current_timestepr   s    r%   current_timestep#SkyReelsV2Pipeline.current_timestepl      %%%r'   c                     U R                   $ r   )
_interruptr   s    r%   	interruptSkyReelsV2Pipeline.interruptp  s    r'   c                     U R                   $ r   )_attention_kwargsr   s    r%   attention_kwargs#SkyReelsV2Pipeline.attention_kwargst  r   r'   i   i  a   2   g      @npi   num_inference_stepsr   output_typereturn_dictr   callback_on_step_endr   c                    [        U[        [        45      (       a  UR                  nU R	                  UUUUUUU5        XPR
                  -  S:w  aA  [        R                  SU R
                   S35        XPR
                  -  U R
                  -  S-   n[        US5      nXpl	        Xl
        SU l        SU l        U R                  nUb  [        U[        5      (       a  SnO3Ub!  [        U[        5      (       a  [!        U5      nOUR"                  S   nU R%                  UUU R&                  UUUUUS9u  pU R(                  R*                  nUR-                  U5      nUb  UR-                  U5      nU R.                  R1                  UUS9  U R.                  R2                  nU R(                  R4                  R6                  nU R9                  UU-  UUUU[:        R<                  UU	U
5	      n
[!        U5      X`R.                  R>                  -  -
  n[!        U5      U l         U RC                  US	9 n[E        U5       GH  u  nnU RF                  (       a  M  UU l        U
R-                  U5      nURI                  U
R"                  S   5      nU R)                  UUUUSS
9S   nU R&                  (       a!  U R)                  UUUUSS
9S   nUUUU-
  -  -   nU R.                  RK                  UUU
SS9S   n
Ub\  0 n U H  n![M        5       U!   U U!'   M     U" U UUU 5      n"U"RO                  SU
5      n
U"RO                  SU5      nU"RO                  SU5      nU[!        U5      S-
  :X  d)  US-   U:  a0  US-   U R.                  R>                  -  S:X  a  URQ                  5         [R        (       d  GMo  [T        RV                  " 5         GM     SSS5        SU l        US:X  Gdz  U
R-                  U RX                  R*                  5      n
[:        RZ                  " U RX                  R4                  R\                  5      R_                  SU RX                  R4                  R`                  SSS5      R-                  U
Rb                  U
R*                  5      n#S[:        RZ                  " U RX                  R4                  Rd                  5      R_                  SU RX                  R4                  R`                  SSS5      R-                  U
Rb                  U
R*                  5      -  n$U
U$-  U#-   n
U RX                  Rg                  U
SS9S   n%U Rh                  Rk                  U%US9n%OU
n%U Rm                  5         U(       d  U%4$ [o        U%S9$ ! , (       d  f       GN= f)a  
The call function to the pipeline for generation.

Args:
    prompt (`str` or `List[str]`, *optional*):
        The prompt or prompts to guide the image generation. If not defined, one has to pass `prompt_embeds`.
        instead.
    height (`int`, defaults to `544`):
        The height in pixels of the generated image.
    width (`int`, defaults to `960`):
        The width in pixels of the generated image.
    num_frames (`int`, defaults to `97`):
        The number of frames in the generated video.
    num_inference_steps (`int`, defaults to `50`):
        The number of denoising steps. More denoising steps usually lead to a higher quality image at the
        expense of slower inference.
    guidance_scale (`float`, defaults to `6.0`):
        Guidance scale as defined in [Classifier-Free Diffusion Guidance](https://arxiv.org/abs/2207.12598).
        `guidance_scale` is defined as `w` of equation 2. of [Imagen
        Paper](https://arxiv.org/pdf/2205.11487.pdf). Guidance scale is enabled by setting `guidance_scale >
        1`. Higher guidance scale encourages to generate images that are closely linked to the text `prompt`,
        usually at the expense of lower image quality.
    num_videos_per_prompt (`int`, *optional*, defaults to 1):
        The number of images to generate per prompt.
    generator (`torch.Generator` or `List[torch.Generator]`, *optional*):
        A [`torch.Generator`](https://pytorch.org/docs/stable/generated/torch.Generator.html) to make
        generation deterministic.
    latents (`torch.Tensor`, *optional*):
        Pre-generated noisy latents sampled from a Gaussian distribution, to be used as inputs for image
        generation. Can be used to tweak the same generation with different prompts. If not provided, a latents
        tensor is generated by sampling using the supplied random `generator`.
    prompt_embeds (`torch.Tensor`, *optional*):
        Pre-generated text embeddings. Can be used to easily tweak text inputs (prompt weighting). If not
        provided, text embeddings are generated from the `prompt` input argument.
    output_type (`str`, *optional*, defaults to `"np"`):
        The output format of the generated image. Choose between `PIL.Image` or `np.array`.
    return_dict (`bool`, *optional*, defaults to `True`):
        Whether or not to return a [`SkyReelsV2PipelineOutput`] instead of a plain tuple.
    attention_kwargs (`dict`, *optional*):
        A kwargs dictionary that if specified is passed along to the `AttentionProcessor` as defined under
        `self.processor` in
        [diffusers.models.attention_processor](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention_processor.py).
    callback_on_step_end (`Callable`, `PipelineCallback`, `MultiPipelineCallbacks`, *optional*):
        A function or a subclass of `PipelineCallback` or `MultiPipelineCallbacks` that is called at the end of
        each denoising step during the inference. with the following arguments: `callback_on_step_end(self:
        DiffusionPipeline, step: int, timestep: int, callback_kwargs: Dict)`. `callback_kwargs` will include a
        list of all tensors as specified by `callback_on_step_end_tensor_inputs`.
    callback_on_step_end_tensor_inputs (`List`, *optional*):
        The list of tensor inputs for the `callback_on_step_end` function. The tensors specified in the list
        will be passed as `callback_kwargs` argument. You will only be able to include variables listed in the
        `._callback_tensor_inputs` attribute of your pipeline class.
    max_sequence_length (`int`, *optional*, defaults to `512`):
        The maximum sequence length for the text encoder.

Examples:

Returns:
    [`~SkyReelsV2PipelineOutput`] or `tuple`:
        If `return_dict` is `True`, [`SkyReelsV2PipelineOutput`] is returned, otherwise a `tuple` is returned
        where the first element is a list with the generated images and the second element is a list of `bool`s
        indicating whether the corresponding generated image contains "not-safe-for-work" (nsfw) content.
r   z(`num_frames - 1` has to be divisible by z!. Rounding to the nearest number.NFr   )rK   rw   rx   rL   r3   r4   rM   rN   )rN   )total)hidden_statestimestepencoder_hidden_statesr   r   )r   r2   r3   r4   latentr   )r   )frames)8r[   r   r   tensor_inputsr   rD   loggerwarningmaxr   r   r   r   rZ   r\   r   rE   ri   r   rx   r7   rO   ra   r9   set_timesteps	timestepsconfigin_channelsr   rd   float32orderr   progress_bar	enumerater   expandsteplocalspopupdateXLA_AVAILABLExm	mark_stepr8   tensorlatents_meanrk   z_dimrN   latents_stddecoderG   postprocess_videomaybe_free_model_hooksr   )&rH   rK   rw   r   r   r   r   r   rL   r   r2   r3   r4   r   r   r   r   r   rM   rN   rm   transformer_dtyper   r   num_warmup_stepsr   itlatent_model_inputr   
noise_prednoise_uncondcallback_kwargsr   callback_outputsr   r   videos&                                         r%   __call__SkyReelsV2Pipeline.__call__x  sZ   p *-=?U,VWW1E1S1S. 	".	
 666!;NN:4;Y;Y:ZZ{| $'E'EEHfHffijjJQ'
-!1!%'' *VS"9"9JJvt$<$<VJ&,,Q/J 150B0B+(,(H(H"7'#9 3 1C 	1
- !,,22%(():;!-%;%>%>?P%Q" 	$$%8$HNN,,	  $//66BB&&.. MM

 y>,?..BVBV,VV!)n%89\!),1>>)*&%,ZZ0A%B"88GMM!$45!--"4%*7%5 % .  
 33#'#3#3&8!).D)9$) $4 $ $L ".*|B[0\!\J ..--j!WRW-XYZ['3&(O?-3Xa[* @';D!Q'X$.229gFG$4$8$8-$XM-=-A-ABZ\r-s* I**A9I/IqSTuX\XfXfXlXlNlpqNq '') =LLNY - :^ "&h&jj0GTXX__99:a..1a8GNNGMM2 
 TXX__-H-H I N NqRVRZRZRaRaRgRgijlmop q t t! K +l:GHHOOGO?BE((::5k:ZEE 	##%8O'u55O :9s   ,E6U6'U66
V)r   r   r   r   r   rF   rD   rG   )Nr      NN)NTr   NNr   NN)NNN)r   i  i@  Q   NNNN)/__name__
__module____qualname____firstlineno____doc__model_cpu_offload_seqr   r	   r
   r   r   r   r?   r   r\   r   r   r   rd   rN   rO   ru   boolTensorr   r   	Generatorr   propertyr   rx   r   r   r   r   no_gradr   EXAMPLE_DOC_STRINGfloatr   r   r   r   r   r   __static_attributes____classcell__)rI   s   @r%   r0   r0   k   s   * =T^ ^ '^ 2	^
 ^ +^2 )-%&#&)-'+'c49n%'  #' !	'
 &' $'Z <@,0%&049=#&)-'+O5c49n%O5 "%T#Y"78O5 &*	O5
  #O5  -O5 !) 6O5 !O5 &O5 $O5n #+/'tZ %''+)-MQ*. " 	
   $ & E%//43H"HIJ %,,' 
@ $ $ * * # # & &   & & ]]_12 )-15#% #/0MQ*.049=%) 59 9B#&+h6c49n%h6 sDI~.h6 	h6
 h6 h6 !h6 h6  (}h6 E%//43H"HIJh6 %,,'h6  -h6 !) 6h6 c]h6 h6  #4S>2!h6" '(Cd+T124DF\\]
#h6( -1I)h6* !+h6 3 h6r'   r0   )3r    typingr   r   r   r   r   r   regexr*   rd   transformersr	   r
   	callbacksr   r   loadersr   modelsr   r   
schedulersr   utilsr   r   r   r   utils.torch_utilsr   rG   r   pipeline_utilsr   pipeline_outputr   torch_xla.core.xla_modelcore	xla_modelr   r   
get_loggerr   r   r   r   r&   r,   r.   r0    r'   r%   <module>r	     s     = =   8 A 0 D 1 b b - - . 5 ))MM			H	%) X
w6*,E w6r'   