paths.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import pathlib as pl
  2. from itertools import product
  3. def check_for_existing_dbb1(data_dir_path, dbb1, extension, animal_tag):
  4. dbb1 = str(dbb1).replace("\\", "/") # dbb1 for settings files generated in windows can contain "\\"
  5. without_ORline_value_trailing = "_".join(animal_tag.split("_")[:-1])
  6. possible_paths = [data_dir_path / dbb1,
  7. data_dir_path / f"{dbb1}{extension}",
  8. data_dir_path / animal_tag / dbb1,
  9. data_dir_path / animal_tag / f"{dbb1}{extension}",
  10. data_dir_path / f"{animal_tag}{extension}" / f"{dbb1}{extension}",
  11. # for till vision setups, structure could be
  12. # {STG_Datapath} / {STG_ReportTag} / {STG_ReportTag}.pst / {dbb1}.pst
  13. data_dir_path / animal_tag / f"{animal_tag}{extension}" / dbb1,
  14. data_dir_path / animal_tag / f"{animal_tag}{extension}" / f"{dbb1}{extension}",
  15. data_dir_path / without_ORline_value_trailing / dbb1,
  16. data_dir_path / without_ORline_value_trailing / f"{dbb1}{extension}",
  17. data_dir_path / without_ORline_value_trailing / f"{animal_tag}{extension}" / dbb1,
  18. data_dir_path / without_ORline_value_trailing / f"{animal_tag}{extension}" / f"{dbb1}{extension}"
  19. ]
  20. # resolution required for cross OS compatibility, i.e., for example, when settings files was generated in Windows
  21. # and used on linux/mac
  22. existences = [x.resolve(strict=False).is_file() for x in possible_paths]
  23. if any(existences):
  24. existing_path = possible_paths[existences.index(True)]
  25. return str(existing_path)
  26. else:
  27. return None
  28. def get_existing_raw_data_filename(flags, dbb, extensions):
  29. possible_filenames = []
  30. # check if dbb1 is absolute and file
  31. dbb1_path = pl.Path(dbb)
  32. if dbb1_path.is_absolute() and dbb1_path.is_file():
  33. possible_filenames.append(str(dbb))
  34. if not flags.is_flag_state_default("STG_ReportTag"):
  35. animal_tag = flags["STG_ReportTag"]
  36. if not flags.is_flag_state_default("STG_Datapath"):
  37. data_dir_path = pl.Path(flags["STG_Datapath"])
  38. for extension in extensions:
  39. # check if dbb1 can be interpreted relative to data directory
  40. possible_existing_filename = check_for_existing_dbb1(
  41. data_dir_path=data_dir_path, dbb1=dbb, extension=extension, animal_tag=animal_tag)
  42. possible_filenames.append(possible_existing_filename)
  43. if not flags.is_flag_state_default("STG_MotherOfAllFolders"):
  44. for extension in extensions:
  45. # check if dbb1 can be interpreted relative to mother of all folders directory
  46. moaf = pl.Path(flags["STG_MotherOfAllFolders"])
  47. possible_existing_filename = check_for_existing_dbb1(data_dir_path=moaf, dbb1=dbb, extension=extension,
  48. animal_tag=animal_tag)
  49. possible_filenames.append(possible_existing_filename)
  50. hits = [x is not None for x in possible_filenames]
  51. if any(hits):
  52. return possible_filenames[hits.index(True)]
  53. else:
  54. raise FileNotFoundError(f"Could not find raw file with dbb1={dbb} in {flags['STG_Datapath']}")
  55. def convert_to_path_for_current_os(path_str):
  56. """
  57. If path_str is absolute and exists, returns a path object initialized with it. Raises an error if it is absolute
  58. but for the wrong operating system. If it is not absolute, returns the relative path with the separators of the
  59. current operating system
  60. :param path_str: pathlib.Path
  61. :return:
  62. """
  63. possible_posix_path = pl.PurePosixPath(path_str)
  64. possible_win_path = pl.PureWindowsPath(path_str)
  65. if possible_posix_path.is_absolute() or possible_win_path.is_absolute():
  66. possible_path = pl.Path(path_str)
  67. # if it exists
  68. if possible_path.exists():
  69. return possible_path
  70. else:
  71. raise OSError(f"Either the specified path {path_str} does not exist or "
  72. f"cannot be interpreted for the current operating system")
  73. else:
  74. # PureWindowsPath interprets paths with only posix separators, only windows separators or a mix of the two
  75. return pl.Path(possible_win_path)
  76. def check_get_file_existence_in_folder(folder, stems, possible_extensions):
  77. """
  78. Checks if the file folder / {stem}{ext} exists for all combinations of stem in <stems> and ext in
  79. <possible_extensions>. If any exist, returns the one at the top of the hierarchy, where the order of elements
  80. decides the hierarchy within <stems> and <possible_extensions> and <stems> having higher precedence than
  81. <possible_extensions>.
  82. :param folder: str, full path of the folder
  83. :param stems: iterable of strings
  84. :param possible_extensions: iterable of strings, including "."
  85. :return: full file path of an existing file or None, if none exist
  86. """
  87. folder_path = pl.Path(folder)
  88. paths = [folder_path / f"{stem}{ext}" for stem, ext in product(stems, possible_extensions)]
  89. existences = [x.is_file() for x in paths]
  90. if any(existences):
  91. return str(paths[existences.index(True)])
  92. else:
  93. return None