code: def make_mvtec_3d_dataset(
      root: str | Path,
      split: str | Split | None = None,
      extensions: Sequence[str] | None = None,
  ) -> DataFrame:
      """Create MVTec 3D-AD samples by parsing the MVTec AD data file structure.
  
      The files are expected to follow the structure:
          path/to/dataset/split/category/image_filename.png
          path/to/dataset/ground_truth/category/mask_filename.png
  
      This function creates a dataframe to store the parsed information based on the following format:
      |---|---------------|-------|---------|---------------|---------------------------------------|-------------|
      |   | path          | split | label   | image_path    | mask_path                             | label_index |
      |---|---------------|-------|---------|---------------|---------------------------------------|-------------|
      | 0 | datasets/name |  test |  defect |  filename.png | ground_truth/defect/filename_mask.png | 1           |
      |---|---------------|-------|---------|---------------|---------------------------------------|-------------|
  
      Args:
          path (Path): Path to dataset
          split (str | Split | None, optional): Dataset split (ie., either train or test). Defaults to None.
          split_ratio (float, optional): Ratio to split normal training images and add to the
              test set in case test set doesn't contain any normal images.
              Defaults to 0.1.
          seed (int, optional): Random seed to ensure reproducibility when splitting. Defaults to 0.
          create_validation_set (bool, optional): Boolean to create a validation set from the test set.
              MVTec AD dataset does not contain a validation set. Those wanting to create a validation set
              could set this flag to ``True``.
  
      Examples:
          The following example shows how to get training samples from MVTec 3D-AD bagel category:
  
          >>> root = Path('./MVTec3D')
          >>> category = 'bagel'
          >>> path = root / category
          >>> path
          PosixPath('MVTec3D/bagel')
  
          >>> samples = make_mvtec_3d_dataset(path, split='train', split_ratio=0.1, seed=0)
          >>> samples.head()
             path         split label image_path                           mask_path
          0  MVTec3D/bagel train good MVTec3D/bagel/train/good/rgb/105.png MVTec3D/bagel/ground_truth/good/gt/105.png
          1  MVTec3D/bagel train good MVTec3D/bagel/train/good/rgb/017.png MVTec3D/bagel/ground_truth/good/gt/017.png
          2  MVTec3D/bagel train good MVTec3D/bagel/train/good/rgb/137.png MVTec3D/bagel/ground_truth/good/gt/137.png
          3  MVTec3D/bagel train good MVTec3D/bagel/train/good/rgb/152.png MVTec3D/bagel/ground_truth/good/gt/152.png
          4  MVTec3D/bagel train good MVTec3D/bagel/train/good/rgb/109.png MVTec3D/bagel/ground_truth/good/gt/109.png
             depth_path                                   label_index
             MVTec3D/bagel/ground_truth/good/xyz/105.tiff 0
             MVTec3D/bagel/ground_truth/good/xyz/017.tiff 0
             MVTec3D/bagel/ground_truth/good/xyz/137.tiff 0
             MVTec3D/bagel/ground_truth/good/xyz/152.tiff 0
             MVTec3D/bagel/ground_truth/good/xyz/109.tiff 0
  
      Returns:
          DataFrame: an output dataframe containing the samples of the dataset.
      """
      if extensions is None:
          extensions = IMG_EXTENSIONS
  
      root = Path(root)
      samples_list = [
          (str(root),) + f.parts[-4:]
          for f in root.glob(r"**/*")
          if f.suffix in extensions
      ]
      if not samples_list:
          raise RuntimeError(f"Found 0 images in {root}")
  
      samples = DataFrame(
          samples_list,
          columns=["path", "split", "label", "type", "file_name"],
      )
  
      # Modify image_path column by converting to absolute path
      samples.loc[(samples.type == "rgb"), "image_path"] = (
          samples.path
          + "/"
          + samples.split
          + "/"
          + samples.label
          + "/"
          + "rgb/"
          + samples.file_name
      )
      samples.loc[(samples.type == "rgb"), "depth_path"] = (
          samples.path
          + "/"
          + samples.split
          + "/"
          + samples.label
          + "/"
          + "xyz/"
          + samples.file_name.str.split(".").str[0]
          + ".tiff"
      )
  
      # Create label index for normal (0) and anomalous (1) images.
      samples.loc[
          (samples.label == "good"), "label_index"
      ] = LabelName.NORMAL
      samples.loc[
          (samples.label != "good"), "label_index"
      ] = LabelName.ABNORMAL
      samples.label_index = samples.label_index.astype(int)
  
      # separate masks from samples
      mask_samples = samples.loc[
          ((samples.split == "test") & (samples.type == "rgb"))
      ].sort_values(by="image_path", ignore_index=True)
      samples = samples.sort_values(by="image_path", ignore_index=True)
  
      # assign mask paths to all test images
      samples.loc[
          ((samples.split == "test") & (samples.type == "rgb")),
          "mask_path",
      ] = (
          mask_samples.path
          + "/"
          + samples.split
          + "/"
          + samples.label
          + "/"
          + "gt/"
          + samples.file_name
      )
      samples.dropna(subset=["image_path"], inplace=True)
      samples = samples.astype(
          {"image_path": "str", "mask_path": "str", "depth_path": "str"}
      )
  
      # assert that the right mask files are associated with the right test images
      assert (
          samples.loc[samples.label_index == LabelName.ABNORMAL]
          .apply(
              lambda x: Path(x.image_path).stem
              in Path(x.mask_path).stem,
              axis=1,
          )
          .all()
      ), "Mismatch between anomalous images and ground truth masks. Make sure the mask files in 'ground_truth' \
                folder follow the same naming convention as the anomalous images in the dataset (e.g. image: '000.png', \
                mask: '000.png' or '000_mask.png')."
  
      # assert that the right depth image files are associated with the right test images
      assert (
          samples.loc[samples.label_index == LabelName.ABNORMAL]
          .apply(
              lambda x: Path(x.image_path).stem
              in Path(x.depth_path).stem,
              axis=1,
          )
          .all()
      ), "Mismatch between anomalous images and depth images. Make sure the mask files in 'xyz' \
                folder follow the same naming convention as the anomalous images in the dataset (e.g. image: '000.png', \
                depth: '000.tiff')."
  
      if split:
          samples = samples[samples.split == split].reset_index(
              drop=True
          )
  
      return samples
  
file_path: anomalib/src/anomalib/data/mvtec_3d.py
imports: from __future__ import annotations
  import logging
  from pathlib import Path
  from typing import Sequence
  import albumentations
  from pandas import DataFrame
  from anomalib.data.base import AnomalibDataModule, AnomalibDepthDataset
  from anomalib.data.task_type import TaskType
  from anomalib.data.utils import DownloadInfo, InputNormalizationMethod, LabelName, Split, TestSplitMode, ValSplitMode, download_and_extract, get_transforms
label_desc: Use image node_id 1 for calling a global function with example usage: make_mvtec_3d_dataset(root, split, extensions) and returns: samples