Arulkumar03/Fox_Sheep_Detector_Computer_Vision_model
0
1# Copyright (c) Facebook, Inc. and its affiliates.2import atexit3import functools4import logging5import os6import sys7import time8from collections import Counter9import torch10from tabulate import tabulate11from termcolor import colored12 13from detectron2.utils.file_io import PathManager14 15__all__ = ["setup_logger", "log_first_n", "log_every_n", "log_every_n_seconds"]16 17D2_LOG_BUFFER_SIZE_KEY: str = "D2_LOG_BUFFER_SIZE"18 19DEFAULT_LOG_BUFFER_SIZE: int = 1024 * 1024 # 1MB20 21 22class _ColorfulFormatter(logging.Formatter):23 def __init__(self, *args, **kwargs):24 self._root_name = kwargs.pop("root_name") + "."25 self._abbrev_name = kwargs.pop("abbrev_name", "")26 if len(self._abbrev_name):27 self._abbrev_name = self._abbrev_name + "."28 super(_ColorfulFormatter, self).__init__(*args, **kwargs)29 30 def formatMessage(self, record):31 record.name = record.name.replace(self._root_name, self._abbrev_name)32 log = super(_ColorfulFormatter, self).formatMessage(record)33 if record.levelno == logging.WARNING:34 prefix = colored("WARNING", "red", attrs=["blink"])35 elif record.levelno == logging.ERROR or record.levelno == logging.CRITICAL:36 prefix = colored("ERROR", "red", attrs=["blink", "underline"])37 else:38 return log39 return prefix + " " + log40 41 42@functools.lru_cache() # so that calling setup_logger multiple times won't add many handlers43def setup_logger(44 output=None,45 distributed_rank=0,46 *,47 color=True,48 name="detectron2",49 abbrev_name=None,50 enable_propagation: bool = False,51 configure_stdout: bool = True52):53 """54 Initialize the detectron2 logger and set its verbosity level to "DEBUG".55 56 Args:57 output (str): a file name or a directory to save log. If None, will not save log file.58 If ends with ".txt" or ".log", assumed to be a file name.59 Otherwise, logs will be saved to `output/log.txt`.60 name (str): the root module name of this logger61 abbrev_name (str): an abbreviation of the module, to avoid long names in logs.62 Set to "" to not log the root module in logs.63 By default, will abbreviate "detectron2" to "d2" and leave other64 modules unchanged.65 enable_propagation (bool): whether to propagate logs to the parent logger.66 configure_stdout (bool): whether to configure logging to stdout.67 68 69 Returns:70 logging.Logger: a logger71 """72 logger = logging.getLogger(name)73 logger.setLevel(logging.DEBUG)74 logger.propagate = enable_propagation75 76 if abbrev_name is None:77 abbrev_name = "d2" if name == "detectron2" else name78 79 plain_formatter = logging.Formatter(80 "[%(asctime)s] %(name)s %(levelname)s: %(message)s", datefmt="%m/%d %H:%M:%S"81 )82 # stdout logging: master only83 if configure_stdout and distributed_rank == 0:84 ch = logging.StreamHandler(stream=sys.stdout)85 ch.setLevel(logging.DEBUG)86 if color:87 formatter = _ColorfulFormatter(88 colored("[%(asctime)s %(name)s]: ", "green") + "%(message)s",89 datefmt="%m/%d %H:%M:%S",90 root_name=name,91 abbrev_name=str(abbrev_name),92 )93 else:94 formatter = plain_formatter95 ch.setFormatter(formatter)96 logger.addHandler(ch)97 98 # file logging: all workers99 if output is not None:100 if output.endswith(".txt") or output.endswith(".log"):101 filename = output102 else:103 filename = os.path.join(output, "log.txt")104 if distributed_rank > 0:105 filename = filename + ".rank{}".format(distributed_rank)106 PathManager.mkdirs(os.path.dirname(filename))107 108 fh = logging.StreamHandler(_cached_log_stream(filename))109 fh.setLevel(logging.DEBUG)110 fh.setFormatter(plain_formatter)111 logger.addHandler(fh)112 113 return logger114 115 116# cache the opened file object, so that different calls to `setup_logger`117# with the same file name can safely write to the same file.118@functools.lru_cache(maxsize=None)119def _cached_log_stream(filename):120 # use 1K buffer if writing to cloud storage121 io = PathManager.open(filename, "a", buffering=_get_log_stream_buffer_size(filename))122 atexit.register(io.close)123 return io124 125 126def _get_log_stream_buffer_size(filename: str) -> int:127 if "://" not in filename:128 # Local file, no extra caching is necessary129 return -1130 # Remote file requires a larger cache to avoid many small writes.131 if D2_LOG_BUFFER_SIZE_KEY in os.environ:132 return int(os.environ[D2_LOG_BUFFER_SIZE_KEY])133 return DEFAULT_LOG_BUFFER_SIZE134 135 136"""137Below are some other convenient logging methods.138They are mainly adopted from139https://github.com/abseil/abseil-py/blob/master/absl/logging/__init__.py140"""141 142 143def _find_caller():144 """145 Returns:146 str: module name of the caller147 tuple: a hashable key to be used to identify different callers148 """149 frame = sys._getframe(2)150 while frame:151 code = frame.f_code152 if os.path.join("utils", "logger.") not in code.co_filename:153 mod_name = frame.f_globals["__name__"]154 if mod_name == "__main__":155 mod_name = "detectron2"156 return mod_name, (code.co_filename, frame.f_lineno, code.co_name)157 frame = frame.f_back158 159 160_LOG_COUNTER = Counter()161_LOG_TIMER = {}162 163 164def log_first_n(lvl, msg, n=1, *, name=None, key="caller"):165 """166 Log only for the first n times.167 168 Args:169 lvl (int): the logging level170 msg (str):171 n (int):172 name (str): name of the logger to use. Will use the caller's module by default.173 key (str or tuple[str]): the string(s) can be one of "caller" or174 "message", which defines how to identify duplicated logs.175 For example, if called with `n=1, key="caller"`, this function176 will only log the first call from the same caller, regardless of177 the message content.178 If called with `n=1, key="message"`, this function will log the179 same content only once, even if they are called from different places.180 If called with `n=1, key=("caller", "message")`, this function181 will not log only if the same caller has logged the same message before.182 """183 if isinstance(key, str):184 key = (key,)185 assert len(key) > 0186 187 caller_module, caller_key = _find_caller()188 hash_key = ()189 if "caller" in key:190 hash_key = hash_key + caller_key191 if "message" in key:192 hash_key = hash_key + (msg,)193 194 _LOG_COUNTER[hash_key] += 1195 if _LOG_COUNTER[hash_key] <= n:196 logging.getLogger(name or caller_module).log(lvl, msg)197 198 199def log_every_n(lvl, msg, n=1, *, name=None):200 """201 Log once per n times.202 203 Args:204 lvl (int): the logging level205 msg (str):206 n (int):207 name (str): name of the logger to use. Will use the caller's module by default.208 """209 caller_module, key = _find_caller()210 _LOG_COUNTER[key] += 1211 if n == 1 or _LOG_COUNTER[key] % n == 1:212 logging.getLogger(name or caller_module).log(lvl, msg)213 214 215def log_every_n_seconds(lvl, msg, n=1, *, name=None):216 """217 Log no more than once per n seconds.218 219 Args:220 lvl (int): the logging level221 msg (str):222 n (int):223 name (str): name of the logger to use. Will use the caller's module by default.224 """225 caller_module, key = _find_caller()226 last_logged = _LOG_TIMER.get(key, None)227 current_time = time.time()228 if last_logged is None or current_time - last_logged >= n:229 logging.getLogger(name or caller_module).log(lvl, msg)230 _LOG_TIMER[key] = current_time231 232 233def create_small_table(small_dict):234 """235 Create a small table using the keys of small_dict as headers. This is only236 suitable for small dictionaries.237 238 Args:239 small_dict (dict): a result dictionary of only a few items.240 241 Returns:242 str: the table as a string.243 """244 keys, values = tuple(zip(*small_dict.items()))245 table = tabulate(246 [values],247 headers=keys,248 tablefmt="pipe",249 floatfmt=".3f",250 stralign="center",251 numalign="center",252 )253 return table254 255 256def _log_api_usage(identifier: str):257 """258 Internal function used to log the usage of different detectron2 components259 inside facebook's infra.260 """261 torch._C._log_api_usage_once("detectron2." + identifier)262 