예제 #1
0
def phase_pb_file(file_path: str) -> Union[MSGraph, None]:
    """
    Parse pb file to graph

    Args:
        file_path (str): The file path of pb file.

    Returns:
        MSGraph, if load pb file and build graph success, will return the graph, else return None.
    """
    if not CONFIG.VERBOSE:
        logger.setLevel(logging.ERROR)
    logger.info("Start to load graph from pb file, file path: %s.", file_path)
    model_proto = anf_ir_pb2.ModelProto()
    try:
        model_proto.ParseFromString(FileHandler(file_path).read())
    except ParseError:
        logger.warning("The given file is not a valid pb file, file path: %s.",
                       file_path)
        return None

    graph = MSGraph()

    try:
        graph.build_graph(model_proto.graph)
    except Exception as ex:
        logger.error("Build graph failed, file path: %s.", file_path)
        logger.exception(ex)
        raise UnknownError(str(ex))

    logger.info("Build graph success, file path: %s.", file_path)
    return graph
예제 #2
0
 def _load_data_in_thread(self):
     """Log (but not swallow) exceptions in thread to help debugging."""
     try:
         self._load_data()
     except Exception as exc:
         logger.exception(exc)
         raise UnknownError('Load data thread error.')
예제 #3
0
    def _load_single_file(self, file_handler):
        """
        Load a log file data.

        Args:
            file_handler (FileHandler): A file handler.
        """
        logger.debug("Load single summary file, file path: %s.", file_handler.file_path)
        while True:
            start_offset = file_handler.offset
            try:
                event_str = self._event_load(file_handler)
                if event_str is None:
                    file_handler.reset_offset(start_offset)
                    break

                event = summary_pb2.Event.FromString(event_str)
                self._event_parse(event)
            except exceptions.CRCFailedError:
                file_handler.reset_offset(start_offset)
                logger.warning("Check crc faild and ignore this file, file_path=%s, "
                               "offset=%s.", file_handler.file_path, file_handler.offset)
                break
            except (OSError, DecodeError, exceptions.MindInsightException) as ex:
                logger.warning("Parse log file fail, and ignore this file, detail: %r,"
                               "file path: %s.", str(ex), file_handler.file_path)
                break
            except Exception as ex:
                logger.exception(ex)
                raise UnknownError(str(ex))
예제 #4
0
    def _load_single_file(self, file_handler, executor):
        """
        Load a log file data.

        Args:
            file_handler (FileHandler): A file handler.
            executor (Executor): The executor instance.

        Returns:
            bool, True if the summary file is finished loading.
        """
        while True:
            start_offset = file_handler.offset
            try:
                event_str = self._event_load(file_handler)
                if event_str is None:
                    file_handler.reset_offset(start_offset)
                    return True
                if len(event_str) > MAX_EVENT_STRING:
                    logger.warning("file_path: %s, event string: %d exceeds %d and drop it.",
                                   file_handler.file_path, len(event_str), MAX_EVENT_STRING)
                    continue

                future = executor.submit(self._event_parse, event_str, self._latest_filename)

                def _add_tensor_event_callback(future_value):
                    try:
                        tensor_values = future_value.result()
                        for tensor_value in tensor_values:
                            if tensor_value.plugin_name == PluginNameEnum.GRAPH.value:
                                try:
                                    graph_tags = self._events_data.list_tags_by_plugin(PluginNameEnum.GRAPH.value)
                                except KeyError:
                                    graph_tags = []

                                summary_tags = self.filter_files(graph_tags)
                                for tag in summary_tags:
                                    self._events_data.delete_tensor_event(tag)

                            self._events_data.add_tensor_event(tensor_value)
                    except Exception as exc:
                        # Log exception for debugging.
                        logger.exception(exc)
                        raise

                future.add_done_callback(_add_tensor_event_callback)
                return False
            except exceptions.CRCFailedError:
                file_handler.reset_offset(start_offset)
                logger.warning("Check crc faild and ignore this file, file_path=%s, "
                               "offset=%s.", file_handler.file_path, file_handler.offset)
                return True
            except (OSError, DecodeError, exceptions.MindInsightException) as ex:
                logger.warning("Parse log file fail, and ignore this file, detail: %r,"
                               "file path: %s.", str(ex), file_handler.file_path)
                return True
            except Exception as ex:
                logger.exception(ex)
                raise UnknownError(str(ex))
예제 #5
0
 def wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except (PathNotDirectoryError, FileNotFoundError) as err:
         # except PathNotDirectoryError and FileNotFoundError as they are on warning level
         logger.warning(str(err))
     except Exception as exc:
         logger.exception(exc)
         raise UnknownError(str(exc))
예제 #6
0
def handle_unknown_error(ex):
    """Handle unknown error."""
    logger.error('%r %r detail: %r', request.method, quote(request.path),
                 str(ex))
    logger.exception(ex)
    if isinstance(ex, PermissionError):
        error = FileSystemPermissionError('File System Permission Error')
    else:
        error = UnknownError('System error.')
    res_body = dict(error_code=error.error_code, error_msg=error.message)
    return jsonify(res_body), error.http_code
예제 #7
0
def handle_http_exception_error(ex):
    """Handle http exception error."""
    logger.warning('%r %r, detail: %r', request.method, quote(request.path),
                   str(ex))
    if isinstance(ex, NotFound):
        error = RestfulApiNotExist()
    elif isinstance(ex, MethodNotAllowed):
        error = RequestMethodNotAllowed()
    else:
        logger.exception(ex)
        error = UnknownError('System error or http error.')
    res_body = {"error_code": error.error_code, "error_msg": error.message}
    return jsonify(res_body), error.http_code
예제 #8
0
 def _make_summary_base_dir(self, summary_base_dir):
     """Check and make summary_base_dir."""
     if not os.path.exists(summary_base_dir):
         permissions = os.R_OK | os.W_OK | os.X_OK
         os.umask(permissions << 3 | permissions)
         mode = permissions << 6
         try:
             logger.info(
                 "The summary_base_dir is generated automatically, path is %s.",
                 summary_base_dir)
             os.makedirs(summary_base_dir, mode=mode, exist_ok=True)
         except OSError as exc:
             raise UnknownError(
                 "Can not make the summary base directory. Detail: %s." %
                 str(exc))
예제 #9
0
    def _validate_config(self, config_path):
        """Check config_path."""
        config_path = self._normalize_path("config_path", config_path)
        try:
            with open(config_path, "r") as file:
                config_info = yaml.safe_load(file)
        except PermissionError as exc:
            raise FileSystemPermissionError(
                "Can not open config file. Detail: %s." % str(exc))
        except Exception as exc:
            raise UnknownError("Detail: %s." % str(exc))

        self._validate_config_schema(config_info)
        config_info['summary_base_dir'] = self._normalize_path(
            "summary_base_dir", config_info.get('summary_base_dir'))
        self._make_summary_base_dir(config_info['summary_base_dir'])
        return config_info
예제 #10
0
    def _parse_pb_file(summary_dir, filename):
        """
        Parse pb file and write content to `EventsData`.

        Args:
            filename (str): The file path of pb file.

        Returns:
            TensorEvent, if load pb file and build graph success, will return tensor event, else return None.
        """
        file_path = FileHandler.join(summary_dir, filename)
        logger.info("Start to load graph from pb file, file path: %s.",
                    file_path)
        filehandler = FileHandler(file_path)
        model_proto = anf_ir_pb2.ModelProto()
        try:
            model_proto.ParseFromString(filehandler.read())
        except ParseError:
            logger.warning(
                "The given file is not a valid pb file, file path: %s.",
                file_path)
            return None

        graph = MSGraph()

        try:
            graph.build_graph(model_proto.graph)
        except Exception as ex:
            # Normally, there are no exceptions, and it is only possible for users on the MindSpore side
            # to dump other non-default graphs.
            logger.error("Build graph failed, file path: %s.", file_path)
            logger.exception(ex)
            raise UnknownError(str(ex))

        tensor_event = TensorEvent(
            wall_time=FileHandler.file_stat(file_path).mtime,
            step=0,
            tag=filename,
            plugin_name=PluginNameEnum.GRAPH.value,
            value=graph,
            filename=filename)

        logger.info("Build graph success, file path: %s.", file_path)
        return tensor_event
예제 #11
0
    def _get_hoc_image(self, image_path, train_id):
        """Get hoc image for image data demonstration in UI."""

        sample_id, label, layer = image_path.strip(".jpg").split("_")
        layer = int(layer)
        job = self.job_manager.get_job(train_id)
        samples = job.samples
        label_idx = job.labels.index(label)

        chosen_sample = samples[int(sample_id)]
        original_path_image = chosen_sample['image']
        abs_image_path = os.path.join(self.job_manager.summary_base_dir,
                                      _clean_train_id_b4_join(train_id),
                                      original_path_image)
        if self._is_forbidden(abs_image_path):
            raise FileSystemPermissionError("Forbidden.")

        image_type = ImageQueryTypes.OUTCOME.value
        try:
            image = Image.open(abs_image_path)
        except FileNotFoundError:
            raise ImageNotExistError(
                f"train_id:{train_id} path:{image_path} type:{image_type}")
        except PermissionError:
            raise FileSystemPermissionError(
                f"train_id:{train_id} path:{image_path} type:{image_type}")
        except OSError:
            raise UnknownError(
                f"Invalid image file: train_id:{train_id} path:{image_path} type:{image_type}"
            )

        edit_steps = []
        boxes = chosen_sample["hierarchical_occlusion"][label_idx][
            "hoc_layers"][layer]["boxes"]
        mask = chosen_sample["hierarchical_occlusion"][label_idx]["mask"]

        for box in boxes:
            edit_steps.append(EditStep(layer, *box))
        image_cp = pil_apply_edit_steps(image, mask, edit_steps)
        buffer = io.BytesIO()
        image_cp.save(buffer, format=_PNG_FORMAT)

        return buffer.getvalue()
예제 #12
0
    def run(self, args):
        """
        Execute for start command.

        Args:
            args (Namespace): Parsed arguments to hold customized parameters.
        """
        try:
            date_time = datetime.datetime.now().strftime(
                'output_%Y%m%d_%H%M%S_%f')
            output_path = os.path.join(args.output, date_time)

            summary_dir = args.summary_dir
            if not self._check_dirpath(summary_dir):
                return

            summary_parser = _SummaryParser(summary_dir)
            summary_files = summary_parser.filter_files(
                os.listdir(summary_dir))

            if not summary_files:
                parse_summary_logger.error('Path %s has no summary file.',
                                           summary_dir)
                return

            summary_files = summary_parser.sort_files(summary_files)
            filename = summary_files[-1]

            summary_file = FileHandler.join(summary_dir, filename)

            if not (self._check_filepath(summary_file)
                    and self._check_create_filepath(output_path)
                    and self._check_create_filepath(
                        FileHandler.join(output_path, 'image'))):
                return

            eventparser = EventParser(summary_file, output_path)
            eventparser.parse()

        except Exception as ex:
            parse_summary_logger.error(
                "Parse summary file failed, detail: %r.", str(ex))
            raise UnknownError(str(ex))
예제 #13
0
    def _load_data(self):
        """
        Prepare loaders in cache and start loading the data from summaries.

        Only a limited number of loaders will be cached in terms of updated_time or query_time. The size of cache
        pool is determined by _MAX_LOADERS_NUM. When the manager start loading data, only the latest _MAX_LOADER_NUM
        summaries will be loaded in cache. If a cached loader if queries by 'get_job', the query_time of the loader
        will be updated as well as the the loader moved to the end of cache. If an uncached summary is queried,
        a new loader instance will be generated and put to the end cache.
        """
        try:
            with self._load_data_mutex:
                if self.status == _ExplainManagerStatus.LOADING.value:
                    logger.info(
                        'Current status is %s, will ignore to load data.',
                        self.status)
                    return

                logger.info('Start to load data, and status change to %s.',
                            _ExplainManagerStatus.LOADING.value)
                self.status = _ExplainManagerStatus.LOADING.value
                self._cache_loaders()

                if self.status == _ExplainManagerStatus.STOPPING.value:
                    logger.info(
                        'The manager status has been %s, will not execute loading.',
                        self.status)
                    return
                self._execute_loading()

                logger.info(
                    'Load event data end, current status: %s, next status: %s, loader pool size: %d.',
                    self.status, _ExplainManagerStatus.DONE.value,
                    len(self._loader_pool))

        except Exception as ex:
            logger.exception(ex)
            raise UnknownError(str(ex))
        finally:
            self.status = _ExplainManagerStatus.DONE.value
예제 #14
0
 def wrapper(*args, **kwargs):
     try:
         func(*args, **kwargs)
     except Exception as exc:
         logger.exception(exc)
         raise UnknownError(str(exc))
예제 #15
0
    def list_events(self, filenames):
        """
        Load summary file and parse file content.

        Args:
            filenames (list[str]): File name list.

        Returns:
            tuple, the elements of the tuple are:

                - file_changed (bool): True if the latest file is changed.
                - is_end (bool): True if all the summary files are finished loading.
                - event_data (dict): Event data where keys are explanation field.
        """
        summary_files = self.sort_files(filenames)

        is_end = False
        file_changed = False
        event_data = {}
        filename = summary_files[-1]

        file_path = FileHandler.join(self._summary_dir, filename)
        if filename != self._latest_filename:
            self._summary_file_handler = FileHandler(file_path, 'rb')
            self._latest_filename = filename
            self._latest_offset = 0
            file_changed = True

        new_size = FileHandler.file_stat(file_path).size
        if new_size == self._latest_offset:
            is_end = True
            return file_changed, is_end, event_data

        while True:
            start_offset = self._summary_file_handler.offset
            try:
                event_str = self.event_load(self._summary_file_handler)
                if event_str is None:
                    self._summary_file_handler.reset_offset(start_offset)
                    is_end = True
                    return file_changed, is_end, event_data
                if len(event_str) > MAX_EVENT_STRING:
                    logger.warning(
                        "file_path: %s, event string: %d exceeds %d and drop it.",
                        self._summary_file_handler.file_path, len(event_str),
                        MAX_EVENT_STRING)
                    continue

                field_list, tensor_value_list = self._event_decode(event_str)
                for field, tensor_value in zip(field_list, tensor_value_list):
                    event_data[field] = tensor_value

                logger.debug("Parse summary file offset %d, file path: %s.",
                             self._summary_file_handler.offset, file_path)
                return file_changed, is_end, event_data
            except exceptions.CRCLengthFailedError as ex:
                self._summary_file_handler.reset_offset(start_offset)
                is_end = True
                logger.warning(
                    "Check crc failed and reset offset, file_path=%s, offset=%s. Detail: %r.",
                    self._summary_file_handler.file_path,
                    self._summary_file_handler.offset, str(ex))
                return file_changed, is_end, event_data
            except Exception as ex:
                # Note: If an unknown error occurs, we will set the offset to the end of this file,
                # which is equivalent to stopping parsing this file. We do not delete the current job
                # and retain the data that has been successfully parsed.
                self._summary_file_handler.reset_offset(new_size)

                # Notice: If the current job is the latest one in the loader pool and the job is deleted,
                # the job goes into an infinite cycle of load-fail-delete-reload-load-fail-delete.
                # We need to prevent this infinite loop.
                logger.error(
                    "Parse summary file failed, will set offset to the file end. file_path: %s, "
                    "offset: %d, detail: %s.", file_path,
                    self._summary_file_handler.offset, str(ex))
                logger.exception(ex)
                raise UnknownError(str(ex))
            finally:
                self._latest_offset = self._summary_file_handler.offset
예제 #16
0
    def parse_explain(self, filenames):
        """
        Load summary file and parse file content.

        Args:
            filenames (list[str]): File name list.
        Returns:
            bool, True if all the summary files are finished loading.
        """
        summary_files = self.sort_files(filenames)

        is_end = False
        is_clean = False
        event_data = {}
        filename = summary_files[-1]

        file_path = FileHandler.join(self._summary_dir, filename)
        if filename != self._latest_filename:
            self._summary_file_handler = FileHandler(file_path, 'rb')
            self._latest_filename = filename
            self._latest_file_size = 0
            is_clean = True

        new_size = FileHandler.file_stat(file_path).size
        if new_size == self._latest_file_size:
            is_end = True
            return is_clean, is_end, event_data

        while True:
            start_offset = self._summary_file_handler.offset
            try:
                event_str = self.event_load(self._summary_file_handler)
                if event_str is None:
                    self._summary_file_handler.reset_offset(start_offset)
                    is_end = True
                    return is_clean, is_end, event_data
                if len(event_str) > MAX_EVENT_STRING:
                    logger.warning(
                        "file_path: %s, event string: %d exceeds %d and drop it.",
                        self._summary_file_handler.file_path, len(event_str),
                        MAX_EVENT_STRING)
                    continue

                field_list, tensor_value_list = self._event_decode(event_str)
                for field, tensor_value in zip(field_list, tensor_value_list):
                    event_data[field] = tensor_value
                logger.info("Parse summary file offset %d, file path: %s.",
                            self._summary_file_handler.offset, file_path)
                return is_clean, is_end, event_data

            except (exceptions.CRCFailedError,
                    exceptions.CRCLengthFailedError) as ex:
                self._summary_file_handler.reset_offset(start_offset)
                is_end = True
                logger.warning(
                    "Check crc failed and ignore this file, file_path=%s, offset=%s. Detail: %r.",
                    self._summary_file_handler.file_path,
                    self._summary_file_handler.offset, str(ex))
                return is_clean, is_end, event_data
            except (OSError, DecodeError,
                    exceptions.MindInsightException) as ex:
                is_end = True
                logger.warning(
                    "Parse log file fail, and ignore this file, detail: %r,"
                    "file path: %s.", str(ex),
                    self._summary_file_handler.file_path)
                return is_clean, is_end, event_data
            except Exception as ex:
                logger.exception(ex)
                raise UnknownError(str(ex))
예제 #17
0
    def query_image_binary(self, train_id, image_path, image_type):
        """
        Query image binary content.

        Args:
            train_id (str): Job ID.
            image_path (str): Image path relative to explain job's summary directory.
            image_type (str): Image type, 'original' or 'overlay'.

        Returns:
            bytes, image binary.
        """

        abs_image_path = os.path.join(self.job_manager.summary_base_dir,
                                      _clean_train_id_b4_join(train_id),
                                      image_path)

        if self._is_forbidden(abs_image_path):
            raise FileSystemPermissionError("Forbidden.")

        try:

            if image_type != "overlay":
                # no need to convert
                with open(abs_image_path, "rb") as fp:
                    return fp.read()

            image = Image.open(abs_image_path)

            if image.mode == _RGBA_MODE:
                # It is RGBA already, do not convert.
                with open(abs_image_path, "rb") as fp:
                    return fp.read()

        except FileNotFoundError:
            raise ImageNotExistError(
                f"train_id:{train_id} path:{image_path} type:{image_type}")
        except PermissionError:
            raise FileSystemPermissionError(
                f"train_id:{train_id} path:{image_path} type:{image_type}")
        except OSError:
            raise UnknownError(
                f"Invalid image file: train_id:{train_id} path:{image_path} type:{image_type}"
            )

        if image.mode == _SINGLE_CHANNEL_MODE:
            saliency = np.asarray(image) / _UINT8_MAX
        elif image.mode == _RGB_MODE:
            saliency = np.asarray(image)
            saliency = saliency[:, :, 0] / _UINT8_MAX
        else:
            raise UnknownError(f"Invalid overlay image mode:{image.mode}.")

        saliency_stack = np.empty((saliency.shape[0], saliency.shape[1], 4))
        for c in range(3):
            saliency_stack[:, :, c] = saliency
        rgba = saliency_stack * _SALIENCY_CMAP_HI
        rgba += (1 - saliency_stack) * _SALIENCY_CMAP_LOW
        rgba[:, :, 3] = saliency * _UINT8_MAX

        overlay = Image.fromarray(np.uint8(rgba), mode=_RGBA_MODE)
        buffer = io.BytesIO()
        overlay.save(buffer, format=_PNG_FORMAT)

        return buffer.getvalue()