
      i'G                         d Z ddlZddlZddlZddlZddlmZ ddlm	Z	 ddl
m
Z
 ddlZddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ  G d d      Zd Zy)ah  
Pipeline

Usage:
  pyannote-pipeline train [options] [(--forever | --iterations=<iterations>)] <experiment_dir> <database.task.protocol>
  pyannote-pipeline best [options] <experiment_dir> <database.task.protocol>
  pyannote-pipeline apply [options] <train_dir> <database.task.protocol>
  pyannote-pipeline -h | --help
  pyannote-pipeline --version

Common options:
  <database.task.protocol>   Experimental protocol (e.g. "Etape.SpeakerDiarization.TV")
  --registry=<db.yml>        Path to, comma-separated, database configuration files.
                             [default: ~/.pyannote/db.yml]
  --subset=<subset>          Set subset. Defaults to 'development' in "train"
                             mode, and to 'test' in "apply" mode.

"train" mode:
  <experiment_dir>           Set experiment root directory. This script expects
                             a configuration file called "config.yml" to live
                             in this directory. See "Configuration file"
                             section below for more details.
  --iterations=<iterations>  Number of iterations. [default: 1]
  --forever                  Iterate forever.
  --sampler=<sampler>        Choose sampler between RandomSampler or TPESampler
                             [default: TPESampler].
  --pruner=<pruner>          Choose pruner between MedianPruner or
                             SuccessiveHalvingPruner. Defaults to no pruning.
  --pretrained=<train_dir>   Use parameters in existing training directory to
                             bootstrap the optimization process. In practice,
                             this will simply run a first trial with this set
                             of parameters.
  --average-case             Optimize for average case instead of worst case.

"apply" mode:
  <train_dir>                Path to the directory containing trained hyper-
                             parameters (i.e. the output of "train" mode).

  --use-filter               Apply pipeline only to files that pass the filter.

Configuration file:
    The configuration of each experiment is described in a file called
    <experiment_dir>/config.yml that describes the pipeline.

    ................... <experiment_dir>/config.yml ...................
    pipeline:
       name: Yin2018
       params:
          sad: tutorials/pipeline/sad
          scd: tutorials/pipeline/scd
          emb: tutorials/pipeline/emb
          metric: angular

    # preprocessors can be used to automatically add keys into
    # each (dict) file obtained from pyannote.database protocols.
    preprocessors:
       audio: ~/.pyannote/db.yml   # load template from YAML file
       video: ~/videos/{uri}.mp4   # define template directly

    # filters can be used to filter out some files from the protocol
    # (e.g. to only keep files with a specific number of speakers)
    filters:
        pyannote.audio.utils.protocol.FilterByNumberOfSpeakers:
            num_speakers: 2

    # one can freeze some hyper-parameters if needed (e.g. when
    # only part of the pipeline needs to be updated)
    freeze:
       speech_turn_segmentation:
          speech_activity_detection:
              onset: 0.5
              offset: 0.5

    # pyannote.audio pipelines will run on CPU by default.
    # use `device` key to send it to GPU.
    device: cuda
    ...................................................................

"train" mode:
    Tune the pipeline hyper-parameters
        <experiment_dir>/<database.task.protocol>.<subset>.yml

"best" mode:
    Display current best loss and corresponding hyper-paramters.

"apply" mode
    Apply the pipeline (with best set of hyper-parameters)

    N)Optional)Path)docopt)tqdm)datetime)
FileFinder)registry)get_annotated)get_class_by_name   )	Optimizerc                        e Zd ZdZdZdZdZeddede	dd fd       Z
dd	ede	f fd
Z	 	 	 	 	 	 ddedee   dee   dedee   dee   de	fdZddedefdZ	 	 ddededee   de	fdZ xZS )
ExperimentzPipeline experiment

    Parameters
    ----------
    experiment_dir : `Path`
        Experiment root directory.
    training : `bool`, optional
        Switch to training mode
    z{experiment_dir}/config.ymlz*{experiment_dir}/train/{protocol}.{subset}z{train_dir}/apply/{date}	train_dirtrainingreturnc                     |j                   d   } | ||      }|dz  }t        j                  t        j                  j                  |            |_        |j                  j                  |       |S )a6  Load pipeline from train directory

        Parameters
        ----------
        train_dir : `Path`
            Path to train directory
        training : `bool`, optional
            Switch to training mode.

        Returns
        -------
        xp : `Experiment`
            Pipeline experiment.
        r   r   
params.yml)	parentsr   fromtimestampospathgetmtimemtime_	pipeline_load_params)clsr   r   experiment_dirxp
params_ymls         q/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/pyannote/pipeline/experiment.pyfrom_train_dirzExperiment.from_train_dir   sb      #**1-(3-
**277+;+;J+GH	
  ,	    r   c           	         t         |           || _        | j                  j	                  | j                        }t        |d      5 }t        j                  |t        j                        | _	        d d d        i }| j                  j                  di       j                         D ]Q  \  }}t        |t              r,t        |d   d      } |di |j                  di       ||<   B	 t        |	      ||<   S || _        g | j                  j                  d
i       j                         D ]'  \  }}t        |      }j%                   |di |       ) dt&        ffd}|| _        | j                  d   d   }t        |d      } |di | j                  d   j                  di       | _        d| j                  v r*| j                  d   }| j*                  j-                  |       d| j                  v r>dd l}|j1                  | j                  d         }| j*                  j3                  |       y y # 1 sw Y   xY w# t         $ r}	|}
|
||<   Y d }	~	d }	~	ww xY w)N)r   rLoaderpreprocessorsnamezpyannote.pipeline)default_module_nameparams)database_ymlfiltersr   c                 .     t         fdD              S )Nc              3   .   K   | ]  } |        y w)N ).0fis     r"   	<genexpr>z;Experiment.__init__.<locals>.all_filters.<locals>.<genexpr>   s     -WqtWs   )all)r4   r.   s   `r"   all_filtersz(Experiment.__init__.<locals>.all_filters   s    -W---r$   pipelinezpyannote.pipeline.blocksfreezedevicer   r1   )super__init__r   
CONFIG_YMLformatopenyamlload
SafeLoaderconfig_getitems
isinstancedictr   r   FileNotFoundErrorpreprocessors_appendboolfilters_r   r9   torchr:   to)selfr   r   
config_ymlfpr)   keypreprocessorKlassetemplater,   r7   pipeline_namerM   r:   r.   	__class__s                   @r"   r<   zExperiment.__init__   s8   , __++4;N;N+O
*c"b99R@DL # !%!1!1/2!F!L!L!NC ,-) (>Q &+%L\-=-=h-K%Lc"	. &0\%Jc"# "O2 , <<++Ir:@@BKC%c*ENN5?6?+ C	.d 	. $ Z08!/I
 Lj!9!=!=h!KL t||#\\(+FNN!!&) t||#\\$,,x"89FNNf%	 $q #"0 % . (%-c"	.s$   
+H;,I;I	I#II#protocol_namesubset
pretrainedn_iterationssamplerpruneraverage_casec           
         t        | j                  j                  | j                  ||            }|j	                  dd       t        j                  || j                        }	d}
t        | j                  |dz  |
|||      }| j                  j                         dk(  rd	nd
}|dz  }t        ddd      }|j                  d       |j                  d       |rF|dz  }t        |d      5 }t        j                   |t        j"                        }ddd       d   }nd}t%        t'        | j(                   t+        |	|                         }|j-                  ||d      }	 |j.                  }|dk  rt7        j8                         n
t;        |      }t=        ||      D ]g  \  }}|d   }||z  ||z  k  r%|d   }|}| j                  j?                  |||       dd|z  dd}|j                  |       |j                  d	       i y# 1 sw Y   xY w# t0        $ r}|t2        j4                  z  }Y d}~d}~ww xY w)ay  Train pipeline

        Parameters
        ----------
        protocol_name : `str`
            Name of pyannote.database protocol to use.
        subset : `str`, optional
            Use this subset for training. Defaults to 'development'.
        pretrained : Path, optional
            Use parameters in "pretrained" training directory to bootstrap the
            optimization process. In practice this will simply run a first trial
            with this set of parameters.
        n_iterations : `int`, optional
            Number of iterations. Defaults to 1.
        sampler : `str`, optional
            Choose sampler between RandomSampler and TPESampler
        pruner : `str`, optional
            Choose between MedianPruner or SuccessiveHalvingPruner.
        average_case : `bool`, optional
            Optimise for average case. Defaults to False (i.e. worst case).
        r   protocolrZ   Tr   exist_okr)   defaulttrials.journal)db
study_namer]   r^   r_   minimizer   r   trialr   )unitpositionleavezFirst trial in progressr&   moder'   Nr,   )
warm_startshow_progressloss)r,   rt   zBest trial: d   g%)desc) r   	TRAIN_DIRr>   r   mkdirr	   get_protocolrI   r   r   get_directionr   set_descriptionupdater?   r@   rA   rB   listfilterrL   getattr	tune_iter	best_loss
ValueErrornpinf	itertoolscountrangezipdump_params)rO   rY   rZ   r[   r\   r]   r^   r_   r   rb   ri   	optimizer	directionr!   progress_barpre_params_ymlrQ   
pre_paramsrr   inputs
iterationsr   rU   r   r4   statusrt   best_paramsrx   s                                r"   trainzExperiment.train   sH   > NN!!#22& " 
	 	t4(()<)<
 
NN++!%
	 557:EA2	-
1DA$$%>?A',6Nn3/2!YYr$//B
 0#H-J JfT]],EGHf,E,GHI((z ) 

	+!++I &2A%5	!5;NUJ/IAv&>D4)i"77$X. 	**{ + 
 "#	/!!4A6D((d(3" 0' 0/  	+!BFF*I	+s$   0&H)H H	I%H==Ic                 ~   t        | j                  j                  | j                  ||            }d}t	        | j
                  |dz  |      }	 |j                  }|j                  }t        dd|z  d	d
       t        j                  |d      }	t        |	       y# t        $ r}t        d       Y d}~yd}~ww xY w)a  Print current best pipeline

        Parameters
        ----------
        protocol_name : `str`
            Name of pyannote.database protocol used for training.
        subset : `str`, optional
            Subset used for training. Defaults to 'development'.
        ra   rf   rg   )rh   ri   z4Still waiting for at least one iteration to succeed.NzLoss = ru   rv   z&% with the following hyper-parameters:F)default_flow_style)r   ry   r>   r   r   r   r   r   printr   r@   dump)
rO   rY   rZ   r   ri   r   r   rU   r   contents
             r"   bestzExperiment.bestX  s     NN!!#22& " 
	 
NNy+;;

		!++I
  ++i**PQR))KEBg  	HI	s   B 	B<'B77B<
output_dir
use_filterc                 H   t        j                  || j                        }	 | j                  j	                         }|j                  dd       |r"|| d| d| j                  j                   z  }n!|| d| d| j                  j                   z  }t        |d      5 }	t         t        ||                   }
|rt        | j                  |
      }
d	| d
| d}t        |
|d      D ]^  }| j                  |      }| j                  j                  |	|       |j                  dd      }|d}|It!        |      } ||||      }` 	 ddd       |j"                  dz  }|j%                         r|j'                          |j)                  |       |d| d}t+        |       y|r|| d| dz  }n|| d| dz  }t        |d      5 }	|	j                  t-        |             ddd       y# t
        $ r}d}Y d}~d}~ww xY w# 1 sw Y   xY w# 1 sw Y   yxY w)zApply current best pipeline

        Parameters
        ----------
        protocol_name : `str`
            Name of pyannote.database protocol to process.
        subset : `str`, optional
            Subset to process. Defaults to 'test'
        re   NTrc   .z_INCOMPLETE.wrp   zProcessing z ()file)iterablerx   rm   
annotation)uemlatestzWFor some (possibly good) reason, the output of this pipeline could not be evaluated on z_INCOMPLETE.evalz.eval)r	   r{   rI   r   
get_metricNotImplementedErrorrz   write_formatr?   r   r   r   rL   r   writerD   r
   parentexistsunlink
symlink_tor   str)rO   rY   r   rZ   r   rb   metricrU   
output_extrQ   filesrx   current_fileoutput	referencer   _r   msgoutput_evals                       r"   applyzExperiment.apply}  sK   $ (()<)<

	^^..0F 	5"O1VHL9T9T8UVW  axq9T9T8UVV  *3'226245Et}}e4 r&;D $e$V L5$$R0 ),,\4@	$!F >#L19f#6 !M (0 ""X-==?MMO*% >66C_AG  #J$-&AQ'RRK$-&'GGK+s#rHHS[! $#s # 	F	 ('V $#s0   G3 "B+HH3	H	<HH	HH!)F)developmentNr   NNF)r   )testF)__name__
__module____qualname____doc__r=   ry   	APPLY_DIRclassmethodr   rK   r#   r<   r   r   intr   r   r   __classcell__)rX   s   @r"   r   r      s    /J<I*It t   ,C&t C&t C&P !.%)!% $"`#`# `# TN	`#
 `# #`# `# `#D## #s #R !' S"S" S" 	S"
 S"r$   r   c            	         t        t        d      } | d   j                  d      D ]  }t        j                  |        | d   }| d   }| d   r|d}| d	   rd
}nt        | d         }| d   }| d   }| d   }|r)t        |      j                         j                  d      }| d   }t        | d         }	|	j                         j                  d      }	t        |	d      }
|
j                  |||||||       | d   rR|d}t        | d         }	|	j                         j                  d      }	t        |	d      }
|
j                  ||       | d   r|d}| d   }t        | d         }|j                         j                  d      }t        j                  |d      }
t        |
j                  j                  ||
j                  j!                  d                  }|
j#                  ||||       y y )NzTunable pipelines)versionz
--registry,z<database.task.protocol>z--subsetr   r   z	--foreverrk   z--iterationsz	--samplerz--prunerz--pretrainedT)strictz--average-casez<experiment_dir>r   )rZ   r\   r[   r]   r^   r_   r   F)rZ   r   r   z--use-filterz<train_dir>z%Y%m%d-%H%M%S)r   date)rZ   r   )r   r   splitr	   load_databaser   r   
expanduserresolver   r   r   r#   r   r>   r   strftimer   )	argumentsr-   rY   rZ   r   r]   r^   r[   r_   r   
experimentr   r   r   s                 r"   mainr     s=   w(;<I!,/55c:|, ; 89Mz"F>"F[!JY~67JK(:&~.
j)446>>d>KJ !12i(:;<'224<<D<I>
#!% 	 	
 >"Fi(:;<'224<<D<I?
f5>F~.
=12	((*22$2?	..y5.I
  ''#**;*;*D*D_*U ( 

 	:f 	 	
! r$   )r   r   os.pathr@   numpyr   typingr   pathlibr   r   r   r   r   pyannote.databaser   r	   r
   pyannote.core.utils.helperr   r   r   r   r   r1   r$   r"   <module>r      sN   :Xt 
          ( & + 8  E" E"P
E
r$   