Olive XML importer
Olive Custom classes
This module contains the definition of the Olive importer classes.
The classes define newspaper Issues and Pages objects which convert OCR data in the Olive XML format to a unified canoncial format.
- class text_importer.importers.olive.classes.OliveNewspaperIssue(issue_dir: IssueDir, image_dirs: str, temp_dir: str)
Newspaper Issue in Olive format.
- Upon object initialization the following things happen:
The Zip archive containing the issue is uncompressed.
The ToC file is parsed to determine the logical structure of the issue.
Page objects (instances of
OliveNewspaperPage
) are initialized.
- Parameters:
issue_dir (IssueDir) – Identifying information about the issue.
image_dirs (str) – Path to the directory with the page images. Multiple paths should be separated by comma (“,”).
temp_dir (str) – Temporary directory to unpack ZipArchive objects.
- id
Canonical Issue ID (e.g.
GDL-1900-01-02-a
).- Type:
str
- edition
Lower case letter ordering issues of the same day.
- Type:
str
- journal
Newspaper unique identifier or name.
- Type:
str
- path
Path to directory containing the issue’s OCR data.
- Type:
str
- date
Publication date of issue.
- Type:
datetime.date
- issue_data
Issue data according to canonical format.
- Type:
dict[str, Any]
- pages
list of
NewspaperPage
instances from this issue.- Type:
list
- rights
Access rights applicable to this issue.
- Type:
str
- image_dirs
Path to the directory with the page images. Multiple paths should be separated by comma (“,”).
- Type:
str
- archive
ZipArchive for this issue.
- Type:
ZipArchive
- toc_data
Table of contents (ToC) data for this issue.
- Type:
dict
- content_elements
All content elements detected.
- Type:
list[dict[str, Any]]
- content_items
Issue’s recomposed content items.
- Type:
list[dict[str, Any]]
- clusters
Inverted index of legacy ids; values are clusters of articles, each indexed by one member.
- Type:
dict[str, list[str]]
- class text_importer.importers.olive.classes.OliveNewspaperPage(_id: str, number: int, toc_data: dict, image_info: dict, page_xml: str)
Newspaper page in Olive format.
- Parameters:
_id (str) – Canonical page ID.
number (int) – Page number.
toc_data (dict) – Metadata about content items in the newspaper issue.
page_info (dict) – Metadata about the page image.
page_xml (str) – Path to the Olive XML file of the page.
- id
Canonical Page ID (e.g.
GDL-1900-01-02-a-p0004
).- Type:
str
- number
Page number.
- Type:
int
- page_data
Page data according to canonical format.
- Type:
dict[str, Any]
- issue
Issue this page is from.
- Type:
NewspaperIssue | None
- toc_data
Metadata about content items in the newspaper issue.
- Type:
dict
- image_info
Metadata about the page image.
- Type:
dict
- page_xml
Path to the Olive XML file of the page.
- Type:
str
- archive
Archive of the issue this page is from.
- Type:
ZipArchive
- add_issue(issue: NewspaperIssue) None
Add to a page object its parent, i.e. the newspaper issue.
This allows each page to preserve contextual information coming from the newspaper issue.
- Parameters:
issue (NewspaperIssue) – Newspaper issue containing this page.
- parse() None
Process the page XML file and transform into canonical Page format.
Note
This lazy behavior means that the page contents are not processed upon creation of the page object, but only once the
parse()
method is called.- Raises:
ValueError – No Newspaper issue has been added to this page.
Olive Detect functions
This module contains functions to detect Olive OCR data to be imported.
- text_importer.importers.olive.detect.OliveIssueDir
A light-weight data structure to represent a newspaper issue.
This named tuple contains basic metadata about a newspaper issue. They can then be used to locate the relevant data in the filesystem or to create canonical identifiers for the issue and its pages.
Note
In case of newspaper published multiple times per day, a lowercase letter is used to indicate the edition number: ‘a’ for the first, ‘b’ for the second, etc.
- Parameters:
journal (str) – Newspaper ID.
date (datetime.date) – Publication date or issue.
edition (str) – Edition of the newspaper issue (‘a’, ‘b’, ‘c’, etc.).
path (str) – Path to the directory containing the issue’s OCR data.
rights (str) – Access rights on the data (open, closed, etc.).
>>> from datetime import date >>> i = OliveIssueDir('GDL', date(1900,1,1), 'a', './GDL-1900-01-01/', 'open')
- text_importer.importers.olive.detect.dir2olivedir(issue_dir: IssueDir, access_rights: dict[str, dict[str, str]]) OliveIssueDirectory
Helper function that injects access rights info into an
IssueDir
.Note
This function is called internally by
olive_detect_issues()
.- Parameters:
issue_dir (IssueDir) – Input
IssueDir
object.access_rights (dict[str, dict[str, str]]) – Access rights information.
- Returns:
New
OliveIssueDir
object.- Return type:
OliveIssueDir
- text_importer.importers.olive.detect.olive_detect_issues(base_dir: str, access_rights: str, journal_filter: set | None = None, exclude: bool = False) list[OliveIssueDirectory]
Detect newspaper issues to import within the filesystem.
This function expects the directory structure that RERO used to organize the dump of Olive OCR data.
- Parameters:
base_dir (str) – Path to the base directory of newspaper data.
access_rights (str) – Path to
access_rights.json
file.journal_filter (set | None, optional) – IDs of newspapers to consider. Defaults to None.
exclude (bool, optional) – Whether
journal_filter
should determine exclusion. Defaults to False.
- Returns:
List of OliveIssueDir instances, to be imported.
- Return type:
list[OliveIssueDir]
- text_importer.importers.olive.detect.olive_select_issues(base_dir: str, config: dict[str, Any], access_rights: str) list[OliveIssueDirectory]
Detect selectively newspaper issues to import.
The behavior is very similar to
olive_detect_issues()
with the only difference thatconfig
specifies some rules to filter the data to import. See this section for further details on how to configure filtering.- Parameters:
base_dir (str) – Path to the base directory of newspaper data.
config (dict[str, Any]) – Config dictionary for filtering.
access_rights (str) – Path to
access_rights.json
file.
- Returns:
List of OliveIssueDir instances, to be imported.
- Return type:
list[OliveIssueDir]
Olive parsers
Functions to parse Olive XML data.
- text_importer.importers.olive.parsers.olive_image_parser(text: bytes) dict[str, str | list] | None
Parse the Olive XML file containing image metadata.
- Parameters:
text (bytes) – Content of the XML file to parse.
- Returns:
Dictionary of image metadata.
- Return type:
dict[str, str | list] | None
- text_importer.importers.olive.parsers.olive_parser(text: str) dict[str, dict | list]
Parse an Olive XML file (e.g. from Le Temps corpus).
The main logic implemented here was derived from <https://github.com/dhlab-epfl/LeTemps-preprocessing/>. Each XML file corresponds to one article, as detected by Olive. The final dictionary has keys
meta
,r
,stats
andlegacy
, each mapping to dictionaries or lists with the file’s parsed contents.- Parameters:
text (str) – Contents of the xml file to parse.
- Returns:
Dictionary with parsed contents.
- Return type:
dict[str, dict | list]
- text_importer.importers.olive.parsers.olive_toc_parser(toc_path: str, issue_dir: IssueDir, encoding: str = 'windows-1252') dict[int, dict[str, dict]]
Parse the TOC.xml file (Olive format).
For each page, the a dict containing page data is created; mapping content item legacy IDs to their metadata.
- Parameters:
toc_path (str) – Path to the ToC XML file.
issue_dir (IssueDir) – Corresponding
IssueDir
object.encoding (str, optional) – File’s encoding. Defaults to “windows-1252”.
- Returns:
- Dictionary where keys are page numbers and
values the corresponding page data dictionary.
- Return type:
dict[int, dict[str, dict]]
- text_importer.importers.olive.parsers.parse_styles(text: str) list[dict[str, Any]]
Turn Olive styleGallery.txt file into a dictionary.
Style IDs may be referred to within the
s
property of token elements as defined in the impresso JSON schema for newspaper pages (see documentation). Each style has ID, font, font size, color (rgb).- Parameters:
text (str) – textual content of file styleGallery.txt.
- Returns:
List of styles according to the impresso schema.
- Return type:
list[dict[str, Any]]
Olive Helper methods
Helper functions used by the Olive Importer.
These functions are mainly used within (i.e. called by) the classes
OliveNewspaperIssue
and OliveNewspaperPage
.
- text_importer.importers.olive.helpers.combine_article_parts(article_parts: list[dict[str, Any]]) dict[str, Any]
Merge article parts into a single element.
Olive format splits an article into multiple components whenever it spans over multiple pages. Thus, it is necessary to recompose multiple parts.
- Parameters:
article_parts (list[dict[str, Any]]) – One or more article parts.
- Returns:
Dict with keys meta, fulltext, stats,`legacy`.
- Return type:
dict[str, Any]
- text_importer.importers.olive.helpers.convert_box(coords: list[int], scale_factor: float) list[int]
Rescale iiif box coordinates relative to given scale factor.
- Parameters:
coords (list[int]) – Original box coordinates.
scale_factor (float) – Scale factor based on image conversion necessary.
- Returns:
Rescaled box coordinates.
- Return type:
list[int]
- text_importer.importers.olive.helpers.convert_image_coordinates(image: dict[str, Any], page_xml: str, page_image_name: str, zip_archive: ZipArchive, box_strategy: str, issue: IssueDir) dict[str, Any]
Convert coordinates of an Olive image element.
Note
This conversion is necessary since the coordinates recorded in the XML file were computed on a different image than the one used for display in the impresso interface.
- Parameters:
image (dict[str, Any]) – Image metadata.
page_xml (str) – Content of Olive page XML.
page_image_name (str) – Name of page image file.
zip_archive (ZipArchive) – Olive Zip archive.
box_strategy (str) – Conversion strategy to apply.
issue (IssueDir) – IssueDie of the newspaper issue the page belongs to.
- Returns:
Updated image metadata based on the conversion.
- Return type:
dict[str, Any]
- text_importer.importers.olive.helpers.convert_page_coordinates(page: dict[str, Any], page_xml: str, page_image_name: str, zip_archive: ZipArchive, box_strategy: str, issue: NewspaperIssue) bool
Convert coordinates of all elements in a page that have coordinates.
Note
This conversion is necessary since the coordinates recorded in the XML file were computed on a different image than the one used for display in the impresso interface.
- Parameters:
page (dict[str, Any]) – Page data where coordinates should be converted.
page_xml (str) – Content of Olive page XML.
page_image_name (str) – Name of page image file.
zip_archive (ZipArchive) – Olive Zip archive.
box_strategy (str) – Conversion strategy to apply.
issue (NewspaperIssue) – Newspaper issue the page belongs to.
- Returns:
Whether the coordinate conversion was successful or not.
- Return type:
bool
- text_importer.importers.olive.helpers.get_clusters(articles: list[dict[str, Any]]) dict[str, list[str]]
Created inverted index of legacy ids to article clusters.
Each cluster of articles is indexed by the legacy id of one its members. If a cluster contains only one element, the its id will be in the keys.
- Parameters:
articles (list[dict[str, Any]]) – Articles to cluster by legacy ids.
- Returns:
Article clusters dictionary.
- Return type:
dict[str, list[str]]
- text_importer.importers.olive.helpers.keep_title(title: str) bool
Whether an element’s title should be kept.
The title should not be kept if it is one of “untitled article”, “untitled ad”, and “untitled picture”.
- Parameters:
title (str) – Title to verify
- Returns:
False if given title is in the black list, True otherwise.
- Return type:
bool
- text_importer.importers.olive.helpers.merge_pseudo_tokens(line: dict[str, list[Any]]) dict[str, list[Any]]
Remove pseudo tokens from a line by merging them.
- Parameters:
line (dict[str, list[Any]]) – A line of OCR in JSON format.
- Returns:
A new line object (with some merged tokens).
- Return type:
dict[str, list[Any]]
- text_importer.importers.olive.helpers.merge_tokens(tokens: list[dict[str, Any]], line: str) dict[str, Any]
Merge two or more tokens for the same line into one.
The resulting (merged) token will have new coordinates corresponding to the combination of coordinates of the input tokens.
- Parameters:
tokens (list[dict[str, Any]]) – Tokens to merge.
line (str) – The line of text to which the input tokens belong.
- Returns:
The new (merged) token.
- Return type:
dict[str, Any]
- text_importer.importers.olive.helpers.normalize_hyphenation(line: dict[str, list[Any]]) dict[str, list[Any]]
Normalize end-of-line hyphenated words.
- Parameters:
line (dict[str, list[Any]]) – A line of OCR.
- Returns:
A new line element.
- Return type:
dict[str, list[Any]]
- text_importer.importers.olive.helpers.normalize_language(language: str) str
Normalize the language’s string representation.
- Parameters:
language (str) – Language to normalize.
- Returns:
Normalized language, one of “fr”, “en” and “de”.
- Return type:
str
- text_importer.importers.olive.helpers.normalize_line(line: dict[str, list[Any]], lang: str) dict[str, list[Any]]
Apply normalization rules to a line of OCR.
The normalization rules that are applied depend on the language in which the text is written. This normalization is necessary because Olive, unlike e.g. Mets, does not encode explicitly the presence/absence of whitespaces.
- Parameters:
line (dict[str, list[Any]]) – A line of OCR text.
lang (str) – Language of the text.
- Returns:
The new normalized line of text.
- Return type:
dict[str, list[Any]]
- text_importer.importers.olive.helpers.recompose_ToC(original_toc_data: dict[int, dict[str, dict]], articles: list[dict[str, Any]], images: list[dict[str, str]]) list[dict[str, Any]]
Recompose the ToC of a newspaper issue.
Function used by
OliveNewspaperIssue
.- Parameters:
original_toc_data (dict[int, dict[str, dict]]) – ToC data.
articles (list[dict[str, Any]]) – List of articles in the issue.
images (list[dict[str, str]]) – List of images in the issue.
- Returns:
List of final content items in the issue.
- Return type:
list[dict[str, Any]]
- text_importer.importers.olive.helpers.recompose_page(page_id: str, info_from_toc: dict[str, dict], page_elements: dict[str, dict], clusters: dict[str, list[str]]) dict[str, Any]
Merge a list of page elements into a single one.
Note
It is here that an
n
attribute is assigned to each region/paragraph/line/token.- Parameters:
page_id (str) – Page canonical id.
info_from_toc (dict[str, dict]) – Dictionary with page element IDs (articles, ads.) as keys, and dictionaries as values.
page_elements (dict[str, dict]) – Page’s articles or advertisements.
clusters (dict[str, list[str]]) – Inverted index of legacy ids; values are clusters of articles, each indexed by one member.
- Returns:
Page data according to impresso canonical format.
- Return type:
dict[str, Any]