code: from pathlib import Path
  from collections import defaultdict
  import math
  import json
  
  import pandas as pd
  import cv2
  import duckdb
  import matplotlib.pyplot as plt
  import numpy as np
  import yaml
  from tqdm import tqdm
  from ultralytics.utils import LOGGER, colorstr
  from ultralytics.utils.plotting import Annotator, colors
  from torch import Tensor
  import lancedb
  import pyarrow as pa
  from lancedb.embeddings import with_embeddings
  from sklearn.decomposition import PCA
  
  from yoloexplorer.dataset import get_dataset_info, Dataset
  from yoloexplorer.frontend import launch
  from yoloexplorer.config import TEMP_CONFIG_PATH
  
  import torch
  import torchvision.models as models
  from torchvision import datasets, transforms
  from PIL import Image
  import sys
  
  SCHEMA = [
      "id",
      # "img", # Make this optional; disabled by default. Not feasible unless we can have row_id/primary key to index
      "path",
      "cls",
      "labels",
      "bboxes",
      "segments",
      "keypoints",
      "meta",
  ]  # + "vector" with embeddings
  
  
  def encode(img_path):
      img = cv2.imread(img_path)
      ext = Path(img_path).suffix
      img_encoded = cv2.imencode(ext, img)[1].tobytes()
  
      return img_encoded
  
  
  def decode(img_encoded):
      nparr = np.frombuffer(img_encoded, np.byte)
      img = cv2.imdecode(nparr, cv2.IMREAD_ANYCOLOR)
  
      return img
  
  
  class Explorer:
      """
      Dataset explorer
      """
  
      def __init__(self, data, device="", model="resnet18", batch_size=64, project="run") -> None:
          """
          Args:
              data (str, optional): path to dataset file
              table (str, optional): path to LanceDB table to load embeddings Table from.
              model (str, optional): path to model. Defaults to None.
              device (str, optional): device to use. Defaults to ''. If empty, uses the default device.
              project (str, optional): path to project. Defaults to "runs/dataset".
          """
          self.data = data
          self.table = None
          self.model = model
          self.device = device
          self.batch_size = batch_size
          self.project = project
          self.dataset_info = None
          self.predictor = None
          self.trainset = None
          self.removed_img_count = 0
          self.verbose = False  # For embedding function
          self._sim_index = None
          self.version = None
  
          self.table_name = Path(data).name
          self.temp_table_name = self.table_name + "_temp"
  
          self.model_arch_supported = [
              "resnet18",
              "resnet50",
              "efficientnet_b0",
              "efficientnet_v2_s",
              "googlenet",
              "mobilenet_v3_small",
          ]
  
          if model:
              self.predictor = self._setup_predictor(model, device)
          if data:
              self.dataset_info = get_dataset_info(self.data)
  
          self.transform = transforms.Compose(
              [
                  transforms.Resize((224, 224)),
                  transforms.ToTensor(),
              ]
          )
  
      def build_embeddings(self, verbose=False, force=False, store_imgs=False):
          """
          Builds the dataset in LanceDB table format
  
          Args:
              batch (int, optional): batch size. Defaults to 1000.
              verbose (bool, optional): verbose. Defaults to False.
              force (bool, optional): force rebuild. Defaults to False.
          """
          trainset = self.dataset_info["train"]
          trainset = trainset if isinstance(trainset, list) else [trainset]
          self.trainset = trainset
          self.verbose = verbose
  
          dataset = Dataset(img_path=trainset, data=self.dataset_info, augment=False, cache=False)
          batch_size = self.batch_size  # TODO: fix this hardcoding
          db = self._connect()
          if not force and self.table_name in db.table_names():
              LOGGER.info("LanceDB embedding space already exists. Attempting to reuse it. Use force=True to overwrite.")
              self.table = self._open_table(self.table_name)
              self.version = self.table.version
              if len(self.table) == dataset.ni:
                  return
              else:
                  self.table = None
                  LOGGER.info("Table length does not match the number of images in the dataset. Building embeddings...")
  
          table_data = defaultdict(list)
          for idx, batch in enumerate(dataset):
              batch["id"] = idx
              batch["cls"] = batch["cls"].flatten().int().tolist()
              box_cls_pair = sorted(zip(batch["bboxes"].tolist(), batch["cls"]), key=lambda x: x[1])
              batch["bboxes"] = [box for box, _ in box_cls_pair]
              batch["cls"] = [cls for _, cls in box_cls_pair]
              batch["labels"] = [self.dataset_info["names"][i] for i in batch["cls"]]
              batch["path"] = batch["im_file"]
              # batch["cls"] = batch["cls"].tolist()
              keys = (key for key in SCHEMA if key in batch)
              for key in keys:
                  val = batch[key]
                  if isinstance(val, Tensor):
                      val = val.tolist()
                  table_data[key].append(val)
  
              table_data["img"].append(encode(batch["im_file"])) if store_imgs else None
  
              if len(table_data[key]) == batch_size or idx == dataset.ni - 1:
                  df = pd.DataFrame(table_data)
                  df = with_embeddings(self._embedding_func, df, "path", batch_size=batch_size)
                  if self.table:
                      self.table.add(df)
                  else:
                      self.table = self._create_table(self.table_name, data=df, mode="overwrite")
                  self.version = self.table.version
                  table_data = defaultdict(list)
  
          LOGGER.info(f'{colorstr("LanceDB:")} Embedding space built successfully.')
  
      def plot_embeddings(self):
          """
          Projects the embedding space to 2D using PCA
  
          Args:
              n_components (int, optional): number of components. Defaults to 2.
          """
          if self.table is None:
              LOGGER.error("No embedding space found. Please build the embedding space first.")
              return None
          pca = PCA(n_components=2)
          embeddings = np.array(self.table.to_arrow()["vector"].to_pylist())
          embeddings = pca.fit_transform(embeddings)
          plt.scatter(embeddings[:, 0], embeddings[:, 1])
          plt.show()
  
      def get_similar_imgs(self, img, n=10):
          """
          Returns the n most similar images to the given image
  
          Args:
              img (int, str, Path): index of image in the table, or path to image
              n (int, optional): number of similar images to return. Defaults to 10.
  
          Returns:
              tuple: (list of paths, list of ids)
          """
          embeddings = None
          if self.table is None:
              LOGGER.error("No embedding space found. Please build the embedding space first.")
              return None
          if isinstance(img, int):
              embeddings = self.table.to_pandas()["vector"][img]
          elif isinstance(img, (str, Path)):
              img = img
          elif isinstance(img, bytes):
              img = decode(img)
          elif isinstance(img, list):  # exceptional case for batch search from dash
              df = self.table.to_pandas().set_index("path")
              array = None
              try:
                  array = df.loc[img]["vector"].to_list()
                  embeddings = np.array(array)
              except KeyError:
                  pass
          else:
              LOGGER.error("img should be index from the table(int), path of an image (str or Path), or bytes")
              return
  
          if embeddings is None:
              if isinstance(img, list):
                  embeddings = np.array(
                      [self.predictor(self._image_encode(i)).squeeze().cpu().detach().numpy() for i in img]
                  )
              else:
                  embeddings = self.predictor(self._image_encode(img)).squeeze().cpu().detach().numpy()
  
          if len(embeddings.shape) > 1:
              embeddings = np.mean(embeddings, axis=0)
  
          sim = self.table.search(embeddings).limit(n).to_df()
          return sim["path"].to_list(), sim["id"].to_list()
  
      def plot_similar_imgs(self, img, n=10):
          """
          Plots the n most similar images to the given image
  
          Args:
              img (int, str, Path): index of image in the table, or path to image.
              n (int, optional): number of similar images to return. Defaults to 10.
          """
          _, ids = self.get_similar_imgs(img, n)
          self.plot_imgs(ids)
  
      def plot_imgs(self, ids=None, query=None, labels=True):
          if ids is None and query is None:
              ValueError("ids or query must be provided")
  
          # Resize the images to the minimum and maximum width and height
          resized_images = []
          df = self.sql(query) if query else self.table.to_pandas().iloc[ids]
          for _, row in df.iterrows():
              img = cv2.imread(row["path"])
              img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
              if labels:
                  ann = Annotator(img)
                  for box, label, cls in zip(row["bboxes"], row["labels"], row["cls"]):
                      ann.box_label(box, label, color=colors(cls, True))
  
                  img = ann.result()
              resized_images.append(img)
  
          if not resized_images:
              LOGGER.error("No images found")
              return
          # Create a grid of the images
  
          cols = 10 if len(resized_images) > 10 else max(2, len(resized_images))
          rows = max(1, math.ceil(len(resized_images) / cols))
          fig, axes = plt.subplots(nrows=rows, ncols=cols)
          fig.subplots_adjust(hspace=0, wspace=0)
          for i, ax in enumerate(axes.ravel()):
              if i < len(resized_images):
                  ax.imshow(resized_images[i])
              ax.axis("off")
          # Display the grid of images
          plt.show()
  
      def get_similarity_index(self, top_k=0.01, sim_thres=0.90, reduce=False, sorted=False):
          """
  
          Args:
              sim_thres (float, optional): Similarity threshold to set the minimum similarity. Defaults to 0.9.
              top_k (float, optional): Top k fraction of the similar embeddings to apply the threshold on. Default 0.1.
              dim (int, optional): Dimension of the reduced embedding space. Defaults to 256.
              sorted (bool, optional): Sort the embeddings by similarity. Defaults to False.
          Returns:
              np.array: Similarity index
          """
          if self.table is None:
              LOGGER.error("No embedding space found. Please build the embedding space first.")
              return None
          if top_k > 1.0:
              LOGGER.warning("top_k should be between 0 and 1. Setting top_k to 1.0")
              top_k = 1.0
          if top_k < 0.0:
              LOGGER.warning("top_k should be between 0 and 1. Setting top_k to 0.0")
              top_k = 0.0
          if sim_thres is not None:
              if sim_thres > 1.0:
                  LOGGER.warning("sim_thres should be between 0 and 1. Setting sim_thres to 1.0")
                  sim_thres = 1.0
              if sim_thres < 0.0:
                  LOGGER.warning("sim_thres should be between 0 and 1. Setting sim_thres to 0.0")
                  sim_thres = 0.0
          embs = np.array(self.table.to_arrow()["vector"].to_pylist())
          self._sim_index = np.zeros(len(embs))
          limit = max(int(len(embs) * top_k), 1)
  
          # create a new table with reduced dimensionality to speedup the search
          self._search_table = self.table
          if reduce:
              dim = min(256, embs.shape[1])  # TODO: make this configurable
              pca = PCA(n_components=min(dim, len(embs)))
              embs = pca.fit_transform(embs)
              dim = embs.shape[1]
              values = pa.array(embs.reshape(-1), type=pa.float32())
              table_data = pa.FixedSizeListArray.from_arrays(values, dim)
              table = pa.table([table_data, self.table.to_arrow()["id"]], names=["vector", "id"])
              self._search_table = self._create_table("reduced_embs", data=table, mode="overwrite")
  
          # with multiprocessing.Pool() as pool: # multiprocessing doesn't do much. Need to revisit
          #    list(tqdm(pool.imap(build_index, iterable)))
  
          for _, emb in enumerate(tqdm(embs)):
              df = self._search_table.search(emb).metric("cosine").limit(limit).to_df()
              if sim_thres is not None:
                  df = df.query(f"_distance >= {1.0 - sim_thres}")
              for idx in df["id"][1:]:
                  self._sim_index[idx] += 1
          self._drop_table("reduced_embs") if reduce else None
  
          return self._sim_index if not sorted else np.sort(self._sim_index)
  
      def plot_similarity_index(self, sim_thres=0.90, top_k=0.01, reduce=False, sorted=False):
          """
          Plots the similarity index
  
          Args:
              threshold (float, optional): Similarity threshold to set the minimum similarity. Defaults to 0.9.
              top_k (float, optional): Top k fraction of the similar embeddings to apply the threshold on. Default 0.1.
              dim (int, optional): Dimension of the reduced embedding space. Defaults to 256.
              sorted (bool, optional): Whether to sort the index or not. Defaults to False.
          """
          index = self.get_similarity_index(top_k, sim_thres, reduce)
          if sorted:
              index = np.sort(index)
          plt.bar([i for i in range(len(index))], index)
          plt.xlabel("idx")
          plt.ylabel("similarity count")
          plt.show()
  
      def remove_imgs(self, idxs):
          """
          Works on temporary table. To apply the changes to the main table, call `persist()`
  
          Args:
              idxs (int or list): Index of the image to remove from the dataset.
          """
          if isinstance(idxs, int):
              idxs = [idxs]
  
          pa_table = self.table.to_arrow()
          mask = [True for _ in range(len(pa_table))]
          for idx in idxs:
              mask[idx] = False
  
          self.removed_img_count += len(idxs)
  
          table = pa_table.filter(mask)
          ids = [i for i in range(len(table))]
          table = table.set_column(0, "id", [ids])  # TODO: Revisit this. This is a hack to fix the ids==dix
          self.table = self._create_table(self.temp_table_name, data=table, mode="overwrite")  # work on a temporary table
  
          self.log_status()
  
      def add_imgs(self, exp, idxs):
          """
          Works on temporary table. To apply the changes to the main table, call `persist()`
  
          Args:
              data (pd.DataFrame or pa.Table): Table rows to add to the dataset.
          """
          table_df = self.table.to_pandas()
          data = exp.table.to_pandas().iloc[idxs]
          assert len(table_df["vector"].iloc[0]) == len(data["vector"].iloc[0]), "Vector dimension mismatch"
          table_df = pd.concat([table_df, data], ignore_index=True)
          ids = [i for i in range(len(table_df))]
          table_df["id"] = ids
          self.table = self._create_table(
              self.temp_table_name, data=table_df, mode="overwrite"
          )  # work on a temporary table
          self.log_status()
  
      def reset(self):
          """
          Resets the dataset table to its original state or to the last persisted state.
          """
          if self.table is None:
              LOGGER.info("No changes made to the dataset.")
              return
  
          db = self._connect()
          if self.temp_table_name in db.table_names():
              self._drop_table(self.temp_table_name)
  
          self.table = self._open_table(self.table_name)
          self.removed_img_count = 0
          # self._sim_index = None # Not sure if we should reset this as computing the index is expensive
          LOGGER.info("Dataset reset to original state.")
  
      def persist(self, name=None):
          """
          Persists the changes made to the dataset. Available only if data is provided in the constructor.
  
          Args:
              name (str, optional): Name of the new dataset. Defaults to `data_updated.yaml`.
          """
          db = self._connect()
          if self.table is None or self.temp_table_name not in db.table_names():
              LOGGER.info("No changes made to the dataset.")
              return
  
          LOGGER.info("Persisting changes to the dataset...")
          self.log_status()
  
          if not name:
              name = self.data.split(".")[0] + "_updated"
          datafile_name = name + ".yaml"
          train_txt = "train_updated.txt"
  
          path = Path(name).resolve()  # add new train.txt file in the dataset parent path
          path.mkdir(parents=True, exist_ok=True)
          if (path / train_txt).exists():
              (path / train_txt).unlink()  # remove existing
  
          for img in tqdm(self.table.to_pandas()["path"].to_list()):
              with open(path / train_txt, "a") as f:
                  f.write(f"{img}" + "\n")  # add image to txt file
  
          new_dataset_info = self.dataset_info.copy()
          new_dataset_info.pop("yaml_file")
          new_dataset_info.pop("path")  # relative paths will get messed up when merging datasets
          new_dataset_info.pop("download")  # Assume all files are present offline, there is no way to store metadata yet
          new_dataset_info["train"] = (path / train_txt).resolve().as_posix()
          for key, value in new_dataset_info.items():
              if isinstance(value, Path):
                  new_dataset_info[key] = value.as_posix()
  
          yaml.dump(new_dataset_info, open(path / datafile_name, "w"))  # update dataset.yaml file
  
          # TODO: not sure if this should be called data_final to prevent overwriting the original data?
          self.table = self._create_table(datafile_name, data=self.table.to_arrow(), mode="overwrite")
          db.drop_table(self.temp_table_name)
  
          LOGGER.info("Changes persisted to the dataset.")
          log = self._log_training_cmd(Path(path / datafile_name).relative_to(Path.cwd()).as_posix())
  
          return log
  
      def log_status(self):
          # TODO: Pretty print log status
          LOGGER.info("\n|-----------------------------------------------|")
          LOGGER.info(f"\t Number of images: {len(self.table.to_arrow())}")
          LOGGER.info("|------------------------------------------------|")
  
      def sql(self, query: str):
          """
          Executes a SQL query on the dataset table.
  
          Args:
              query (str): SQL query to execute.
          """
          if self.table is None:
              LOGGER.info("No table found. Please provide a dataset to work on.")
              return
  
          table = self.table.to_arrow()  # noqa
          result = duckdb.sql(query).to_df()
  
          return result
  
      def dash(self, exps=None, analysis=False):
          """
          Launches a dashboard to visualize the dataset.
          """
          config = {}
          Path(TEMP_CONFIG_PATH).parent.mkdir(exist_ok=True, parents=True)
          with open(TEMP_CONFIG_PATH, "w+") as file:
              config_exp = [self.config]
              if exps:
                  for exp in exps:
                      config_exp.append(exp.config)
              config["exps"] = config_exp
              config["analysis"] = analysis
  
              json.dump(config, file)
  
          launch()
  
      @property
      def config(self):
          return {"project": self.project, "model": self.model, "device": self.device, "data": self.data}
  
      def _log_training_cmd(self, data_path):
          success_log = (
              f'{colorstr("LanceDB: ") }New dataset created successfully! Run the following command to train a model:'
          )
          train_cmd = f"yolo train  model={self.model} data={data_path} epochs=10"
          success_log = success_log + "\n" + train_cmd
          LOGGER.info(success_log)
  
          return train_cmd
  
      def _connect(self):
          db = lancedb.connect(self.project)
  
          return db
  
      def _create_table(self, name, data=None, mode="overwrite"):
          db = lancedb.connect(self.project)
          table = db.create_table(name, data=data, mode=mode)
  
          return table
  
      def _open_table(self, name):
          db = lancedb.connect(self.project)
          table = db.open_table(name) if name in db.table_names() else None
          if table is None:
              raise ValueError(f'{colorstr("LanceDB: ") }Table not found.')
          return table
  
      def _drop_table(self, name):
          db = lancedb.connect(self.project)
          if name in db.table_names():
              db.drop_table(name)
              return True
  
          return False
  
      def _copy_table_to_project(self, table_path):
          if not table_path.endswith(".lance"):
              raise ValueError(f"{colorstr('LanceDB: ')} Table must be a .lance file")
  
          LOGGER.info(f"Copying table from {table_path}")
          path = Path(table_path).parent
          name = Path(table_path).stem  # lancedb doesn't need .lance extension
          db = lancedb.connect(path)
          table = db.open_table(name)
          return self._create_table(self.table_name, data=table.to_arrow(), mode="overwrite")
  
      def _image_encode(self, img):
          image = Image.open(img)
          n_channels = np.array(image).ndim
          if n_channels == 2:
              image = image.convert(mode="RGB")
  
          img_tensor = self.transform(image)
          trans_img = img_tensor.unsqueeze(0)
          return trans_img
  
      def _embedding_func(self, imgs):
          embeddings = []
          for img in tqdm(imgs):
              encod_img = self._image_encode(img)
              embeddings.append(self.predictor(encod_img).squeeze().cpu().detach().numpy())
  
          return embeddings
  
      def _setup_predictor(self, model_arch, device=""):
          if model_arch in self.model_arch_supported:
              load_model = getattr(models, model_arch)
              model = load_model(pretrained=True)
              predictor = torch.nn.Sequential(*list(model.children())[:-1])
              return predictor
  
          else:
              LOGGER.error(f"Supported for {model_arch} is not added yet")
              sys.exit(1)
  
      def create_index(self):
          # TODO: create index
          pass
  
apis: lancedb.embeddings.with_embeddings lancedb.connect
extract_api: [((1044, 1064), 'cv2.imread', 'cv2.imread', (['img_path'], {}), '(img_path)\n', (1054, 1064), False, 'import cv2\n'), ((1214, 1249), 'numpy.frombuffer', 'np.frombuffer', (['img_encoded', 'np.byte'], {}), '(img_encoded, np.byte)\n', (1227, 1249), True, 'import numpy as np\n'), ((1260, 1300), 'cv2.imdecode', 'cv2.imdecode', (['nparr', 'cv2.IMREAD_ANYCOLOR'], {}), '(nparr, cv2.IMREAD_ANYCOLOR)\n', (1272, 1300), False, 'import cv2\n'), ((1075, 1089), 'pathlib.Path', 'Path', (['img_path'], {}), '(img_path)\n', (1079, 1089), False, 'from pathlib import Path\n'), ((3544, 3622), 'yoloexplorer.dataset.Dataset', 'Dataset', ([], {'img_path': 'trainset', 'data': 'self.dataset_info', 'augment': '(False)', 'cache': '(False)'}), '(img_path=trainset, data=self.dataset_info, augment=False, cache=False)\n', (3551, 3622), False, 'from yoloexplorer.dataset import get_dataset_info, Dataset\n'), ((4267, 4284), 'collections.defaultdict', 'defaultdict', (['list'], {}), '(list)\n', (4278, 4284), False, 'from collections import defaultdict\n'), ((6116, 6135), 'sklearn.decomposition.PCA', 'PCA', ([], {'n_components': '(2)'}), '(n_components=2)\n', (6119, 6135), False, 'from sklearn.decomposition import PCA\n'), ((6270, 6317), 'matplotlib.pyplot.scatter', 'plt.scatter', (['embeddings[:, 0]', 'embeddings[:, 1]'], {}), '(embeddings[:, 0], embeddings[:, 1])\n', (6281, 6317), True, 'import matplotlib.pyplot as plt\n'), ((6326, 6336), 'matplotlib.pyplot.show', 'plt.show', ([], {}), '()\n', (6334, 6336), True, 'import matplotlib.pyplot as plt\n'), ((9593, 9629), 'matplotlib.pyplot.subplots', 'plt.subplots', ([], {'nrows': 'rows', 'ncols': 'cols'}), '(nrows=rows, ncols=cols)\n', (9605, 9629), True, 'import matplotlib.pyplot as plt\n'), ((9881, 9891), 'matplotlib.pyplot.show', 'plt.show', ([], {}), '()\n', (9889, 9891), True, 'import matplotlib.pyplot as plt\n'), ((13468, 13485), 'matplotlib.pyplot.xlabel', 'plt.xlabel', (['"""idx"""'], {}), "('idx')\n", (13478, 13485), True, 'import matplotlib.pyplot as plt\n'), ((13494, 13524), 'matplotlib.pyplot.ylabel', 'plt.ylabel', (['"""similarity count"""'], {}), "('similarity count')\n", (13504, 13524), True, 'import matplotlib.pyplot as plt\n'), ((13533, 13543), 'matplotlib.pyplot.show', 'plt.show', ([], {}), '()\n', (13541, 13543), True, 'import matplotlib.pyplot as plt\n'), ((14841, 14887), 'pandas.concat', 'pd.concat', (['[table_df, data]'], {'ignore_index': '(True)'}), '([table_df, data], ignore_index=True)\n', (14850, 14887), True, 'import pandas as pd\n'), ((15716, 15763), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""Dataset reset to original state."""'], {}), "('Dataset reset to original state.')\n", (15727, 15763), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((16230, 16281), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""Persisting changes to the dataset..."""'], {}), "('Persisting changes to the dataset...')\n", (16241, 16281), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((17779, 17827), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""Changes persisted to the dataset."""'], {}), "('Changes persisted to the dataset.')\n", (17790, 17827), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((18023, 18092), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""\n|-----------------------------------------------|"""'], {}), '("""\n|-----------------------------------------------|""")\n', (18034, 18092), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((18172, 18237), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""|------------------------------------------------|"""'], {}), "('|------------------------------------------------|')\n", (18183, 18237), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((19192, 19200), 'yoloexplorer.frontend.launch', 'launch', ([], {}), '()\n', (19198, 19200), False, 'from yoloexplorer.frontend import launch\n'), ((19680, 19704), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['success_log'], {}), '(success_log)\n', (19691, 19704), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((19769, 19798), 'lancedb.connect', 'lancedb.connect', (['self.project'], {}), '(self.project)\n', (19784, 19798), False, 'import lancedb\n'), ((19896, 19925), 'lancedb.connect', 'lancedb.connect', (['self.project'], {}), '(self.project)\n', (19911, 19925), False, 'import lancedb\n'), ((20055, 20084), 'lancedb.connect', 'lancedb.connect', (['self.project'], {}), '(self.project)\n', (20070, 20084), False, 'import lancedb\n'), ((20327, 20356), 'lancedb.connect', 'lancedb.connect', (['self.project'], {}), '(self.project)\n', (20342, 20356), False, 'import lancedb\n'), ((20663, 20710), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['f"""Copying table from {table_path}"""'], {}), "(f'Copying table from {table_path}')\n", (20674, 20710), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((20841, 20862), 'lancedb.connect', 'lancedb.connect', (['path'], {}), '(path)\n', (20856, 20862), False, 'import lancedb\n'), ((21042, 21057), 'PIL.Image.open', 'Image.open', (['img'], {}), '(img)\n', (21052, 21057), False, 'from PIL import Image\n'), ((21368, 21378), 'tqdm.tqdm', 'tqdm', (['imgs'], {}), '(imgs)\n', (21372, 21378), False, 'from tqdm import tqdm\n'), ((2346, 2356), 'pathlib.Path', 'Path', (['data'], {}), '(data)\n', (2350, 2356), False, 'from pathlib import Path\n'), ((2773, 2800), 'yoloexplorer.dataset.get_dataset_info', 'get_dataset_info', (['self.data'], {}), '(self.data)\n', (2789, 2800), False, 'from yoloexplorer.dataset import get_dataset_info, Dataset\n'), ((3792, 3909), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""LanceDB embedding space already exists. Attempting to reuse it. Use force=True to overwrite."""'], {}), "(\n    'LanceDB embedding space already exists. Attempting to reuse it. Use force=True to overwrite.'\n    )\n", (3803, 3909), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((5996, 6082), 'ultralytics.utils.LOGGER.error', 'LOGGER.error', (['"""No embedding space found. Please build the embedding space first."""'], {}), "(\n    'No embedding space found. Please build the embedding space first.')\n", (6008, 6082), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((6779, 6865), 'ultralytics.utils.LOGGER.error', 'LOGGER.error', (['"""No embedding space found. Please build the embedding space first."""'], {}), "(\n    'No embedding space found. Please build the embedding space first.')\n", (6791, 6865), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((8007, 8034), 'numpy.mean', 'np.mean', (['embeddings'], {'axis': '(0)'}), '(embeddings, axis=0)\n', (8014, 8034), True, 'import numpy as np\n'), ((8928, 8951), 'cv2.imread', 'cv2.imread', (["row['path']"], {}), "(row['path'])\n", (8938, 8951), False, 'import cv2\n'), ((8970, 9006), 'cv2.cvtColor', 'cv2.cvtColor', (['img', 'cv2.COLOR_BGR2RGB'], {}), '(img, cv2.COLOR_BGR2RGB)\n', (8982, 9006), False, 'import cv2\n'), ((9343, 9374), 'ultralytics.utils.LOGGER.error', 'LOGGER.error', (['"""No images found"""'], {}), "('No images found')\n", (9355, 9374), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((10534, 10620), 'ultralytics.utils.LOGGER.error', 'LOGGER.error', (['"""No embedding space found. Please build the embedding space first."""'], {}), "(\n    'No embedding space found. Please build the embedding space first.')\n", (10546, 10620), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((10676, 10747), 'ultralytics.utils.LOGGER.warning', 'LOGGER.warning', (['"""top_k should be between 0 and 1. Setting top_k to 1.0"""'], {}), "('top_k should be between 0 and 1. Setting top_k to 1.0')\n", (10690, 10747), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((10808, 10879), 'ultralytics.utils.LOGGER.warning', 'LOGGER.warning', (['"""top_k should be between 0 and 1. Setting top_k to 0.0"""'], {}), "('top_k should be between 0 and 1. Setting top_k to 0.0')\n", (10822, 10879), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((11856, 11902), 'pyarrow.FixedSizeListArray.from_arrays', 'pa.FixedSizeListArray.from_arrays', (['values', 'dim'], {}), '(values, dim)\n', (11889, 11902), True, 'import pyarrow as pa\n'), ((12287, 12297), 'tqdm.tqdm', 'tqdm', (['embs'], {}), '(embs)\n', (12291, 12297), False, 'from tqdm import tqdm\n'), ((12680, 12704), 'numpy.sort', 'np.sort', (['self._sim_index'], {}), '(self._sim_index)\n', (12687, 12704), True, 'import numpy as np\n'), ((13390, 13404), 'numpy.sort', 'np.sort', (['index'], {}), '(index)\n', (13397, 13404), True, 'import numpy as np\n'), ((15313, 15359), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""No changes made to the dataset."""'], {}), "('No changes made to the dataset.')\n", (15324, 15359), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((16155, 16201), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""No changes made to the dataset."""'], {}), "('No changes made to the dataset.')\n", (16166, 16201), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((18450, 18517), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""No table found. Please provide a dataset to work on."""'], {}), "('No table found. Please provide a dataset to work on.')\n", (18461, 18517), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((19159, 19182), 'json.dump', 'json.dump', (['config', 'file'], {}), '(config, file)\n', (19168, 19182), False, 'import json\n'), ((20726, 20742), 'pathlib.Path', 'Path', (['table_path'], {}), '(table_path)\n', (20730, 20742), False, 'from pathlib import Path\n'), ((20765, 20781), 'pathlib.Path', 'Path', (['table_path'], {}), '(table_path)\n', (20769, 20781), False, 'from pathlib import Path\n'), ((21079, 21094), 'numpy.array', 'np.array', (['image'], {}), '(image)\n', (21087, 21094), True, 'import numpy as np\n'), ((21884, 21944), 'ultralytics.utils.LOGGER.error', 'LOGGER.error', (['f"""Supported for {model_arch} is not added yet"""'], {}), "(f'Supported for {model_arch} is not added yet')\n", (21896, 21944), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((21957, 21968), 'sys.exit', 'sys.exit', (['(1)'], {}), '(1)\n', (21965, 21968), False, 'import sys\n'), ((1115, 1137), 'cv2.imencode', 'cv2.imencode', (['ext', 'img'], {}), '(ext, img)\n', (1127, 1137), False, 'import cv2\n'), ((2877, 2906), 'torchvision.transforms.Resize', 'transforms.Resize', (['(224, 224)'], {}), '((224, 224))\n', (2894, 2906), False, 'from torchvision import datasets, transforms\n'), ((2924, 2945), 'torchvision.transforms.ToTensor', 'transforms.ToTensor', ([], {}), '()\n', (2943, 2945), False, 'from torchvision import datasets, transforms\n'), ((4142, 4254), 'ultralytics.utils.LOGGER.info', 'LOGGER.info', (['"""Table length does not match the number of images in the dataset. Building embeddings..."""'], {}), "(\n    'Table length does not match the number of images in the dataset. Building embeddings...'\n    )\n", (4153, 4254), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((5262, 5286), 'pandas.DataFrame', 'pd.DataFrame', (['table_data'], {}), '(table_data)\n', (5274, 5286), True, 'import pandas as pd\n'), ((5308, 5380), 'lancedb.embeddings.with_embeddings', 'with_embeddings', (['self._embedding_func', 'df', '"""path"""'], {'batch_size': 'batch_size'}), "(self._embedding_func, df, 'path', batch_size=batch_size)\n", (5323, 5380), False, 'from lancedb.embeddings import with_embeddings\n'), ((5648, 5665), 'collections.defaultdict', 'defaultdict', (['list'], {}), '(list)\n', (5659, 5665), False, 'from collections import defaultdict\n'), ((9052, 9066), 'ultralytics.utils.plotting.Annotator', 'Annotator', (['img'], {}), '(img)\n', (9061, 9066), False, 'from ultralytics.utils.plotting import Annotator, colors\n'), ((10986, 11065), 'ultralytics.utils.LOGGER.warning', 'LOGGER.warning', (['"""sim_thres should be between 0 and 1. Setting sim_thres to 1.0"""'], {}), "('sim_thres should be between 0 and 1. Setting sim_thres to 1.0')\n", (11000, 11065), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((11146, 11225), 'ultralytics.utils.LOGGER.warning', 'LOGGER.warning', (['"""sim_thres should be between 0 and 1. Setting sim_thres to 0.0"""'], {}), "('sim_thres should be between 0 and 1. Setting sim_thres to 0.0')\n", (11160, 11225), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((16481, 16491), 'pathlib.Path', 'Path', (['name'], {}), '(name)\n', (16485, 16491), False, 'from pathlib import Path\n'), ((18601, 18618), 'duckdb.sql', 'duckdb.sql', (['query'], {}), '(query)\n', (18611, 18618), False, 'import duckdb\n'), ((19426, 19447), 'ultralytics.utils.colorstr', 'colorstr', (['"""LanceDB: """'], {}), "('LanceDB: ')\n", (19434, 19447), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((5690, 5710), 'ultralytics.utils.colorstr', 'colorstr', (['"""LanceDB:"""'], {}), "('LanceDB:')\n", (5698, 5710), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((11817, 11829), 'pyarrow.float32', 'pa.float32', ([], {}), '()\n', (11827, 11829), True, 'import pyarrow as pa\n'), ((18805, 18827), 'pathlib.Path', 'Path', (['TEMP_CONFIG_PATH'], {}), '(TEMP_CONFIG_PATH)\n', (18809, 18827), False, 'from pathlib import Path\n'), ((7473, 7580), 'ultralytics.utils.LOGGER.error', 'LOGGER.error', (['"""img should be index from the table(int), path of an image (str or Path), or bytes"""'], {}), "(\n    'img should be index from the table(int), path of an image (str or Path), or bytes'\n    )\n", (7485, 7580), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((17904, 17914), 'pathlib.Path.cwd', 'Path.cwd', ([], {}), '()\n', (17912, 17914), False, 'from pathlib import Path\n'), ((20217, 20238), 'ultralytics.utils.colorstr', 'colorstr', (['"""LanceDB: """'], {}), "('LanceDB: ')\n", (20225, 20238), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((20601, 20622), 'ultralytics.utils.colorstr', 'colorstr', (['"""LanceDB: """'], {}), "('LanceDB: ')\n", (20609, 20622), False, 'from ultralytics.utils import LOGGER, colorstr\n'), ((7381, 7396), 'numpy.array', 'np.array', (['array'], {}), '(array)\n', (7389, 7396), True, 'import numpy as np\n'), ((9205, 9222), 'ultralytics.utils.plotting.colors', 'colors', (['cls', '(True)'], {}), '(cls, True)\n', (9211, 9222), False, 'from ultralytics.utils.plotting import Annotator, colors\n'), ((17865, 17891), 'pathlib.Path', 'Path', (['(path / datafile_name)'], {}), '(path / datafile_name)\n', (17869, 17891), False, 'from pathlib import Path\n')]