<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def from_elan(cls: Type[CorpusT], org_dir: Path, tgt_dir: Path, feat_type: str = "fbank", label_type: str = "phonemes", utterance_filter: Callable[[Utterance], bool] = None, label_segmenter: Optional[LabelSegmenter] = None, speakers: List[str] = None, lazy: bool = True, """ Construct a `Corpus` from ELAN files. Args: org_dir: A path to the directory containing the unpreprocessed data. tgt_dir: A path to the directory where the preprocessed data will be stored. feat_type: A string describing the input speech features. For example, "fbank" for log Mel filterbank features. label_type: A string describing the transcription labels. For example, "phonemes" or "tones". utterance_filter: A function that returns False if an utterance should not be included in the corpus and True otherwise. This can be used to remove undesirable utterances for training, such as codeswitched utterances. label_segmenter: An object that has an attribute `segment_labels`, which is creates new `Utterance` instances from old ones, by segmenting the tokens in their `text` attribute. Note, `LabelSegmenter` might be better as a function, the only issue is it needs to carry with it a list of labels. This could potentially be a function attribute. speakers: A list of speakers to filter for. If `None`, utterances from all speakers are included. tier_prefixes: A collection of strings that prefix ELAN tiers to filter for. For example, if this is `("xv", "rf")`, then tiers named "xv", "xv@Mark", "rf@Rose" would be extracted if they existed. """

        # This currently bails out if label_segmenter is not provided
        if not label_segmenter:
            raise ValueError("A label segmenter must be provided via label_segmenter")

        # In case path is supplied as a string, make it a Path
        if isinstance(tgt_dir, str):
            tgt_dir = Path(tgt_dir)

        # Read utterances from org_dir.
        utterances = elan.utterances_from_dir(org_dir,
                                              tier_prefixes=tier_prefixes)

        # Filter utterances based on some criteria (such as codeswitching).
        if utterance_filter:
            utterances = [utter for utter in utterances if utterance_filter(utter)]
        utterances = utterance.remove_duplicates(utterances)

        # Segment the labels in the utterances appropriately
        if label_segmenter:
            utterances = [label_segmenter.segment_labels(utter) for utter in utterances]

        # Remove utterances without transcriptions.
        utterances = utterance.remove_empty_text(utterances)

        # Remove utterances with exceptionally short wav_files that are too
        # short for CTC to work.
        utterances = utterance.remove_too_short(utterances)

        tgt_dir.mkdir(parents=True, exist_ok=True)

        # TODO A lot of these methods aren't ELAN-specific. preprocess.elan was
        # only used to get the utterances. There could be another Corpus
        # factory method that takes Utterance objects. the fromElan and
        # fromPangloss constructors could call this.

        # Writes the transcriptions to the tgt_dir/label/ dir
        utterance.write_transcriptions(utterances, (tgt_dir / "label"),
                               label_type, lazy=lazy)
        # Extracts utterance level WAV information from the input file.
        wav.extract_wavs(utterances, (tgt_dir / "wav"), lazy=lazy)

        corpus = cls(feat_type, label_type, tgt_dir,
                     labels=label_segmenter.labels, speakers=speakers)
        corpus.utterances = utterances
        return corpus