diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 57a21a0..7569299 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -38,5 +38,6 @@ jobs:
poetry run flake8 src --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
- # pip install pytest
poetry run pytest
+ - name: Upload coverage reports to Codecov
+ uses: codecov/codecov-action@v3
diff --git a/.gitignore b/.gitignore
index 96bb478..826ad19 100644
--- a/.gitignore
+++ b/.gitignore
@@ -105,3 +105,6 @@ dmypy.json
# Ignore demo-output dir
demo-output/
+
+# Ignore dir containing verification artifacts
+alto2txt-verify/
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index ac4197d..bc73ec6 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,7 +2,7 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.3.0
+ rev: v4.4.0
hooks:
- id: trailing-whitespace
# Leave demo-files unaltered after download from BL website.
@@ -12,20 +12,20 @@ repos:
- id: check-xml
- id: check-added-large-files
- repo: https://github.com/python-poetry/poetry
- rev: '1.3.2'
+ rev: '1.3.0'
hooks:
- id: poetry-check
- id: poetry-lock
- repo: https://github.com/psf/black
- rev: 22.6.0
+ rev: 23.1.0
hooks:
- id: black
- repo: https://github.com/pre-commit/mirrors-autopep8
- rev: v1.6.0 # Use the sha / tag you want to point at
+ rev: v2.0.1 # Use the sha / tag you want to point at
hooks:
- id: autopep8
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v0.971 # Use the sha / tag you want to point at
+ rev: v1.0.1 # Use the sha / tag you want to point at
hooks:
- id: mypy
- repo: https://github.com/pre-commit/mirrors-isort
@@ -33,7 +33,7 @@ repos:
hooks:
- id: isort
- repo: https://github.com/hadialqattan/pycln
- rev: v1.2.5
+ rev: v2.1.3
hooks:
- id: pycln
args: [--config=pyproject.toml]
diff --git a/README.md b/README.md
index 47358b4..ca5bb2e 100644
--- a/README.md
+++ b/README.md
@@ -1,62 +1,64 @@
-# `alto2txt`: Extract plain text from newspapers
+# `alto2txt`: Extract plain text from digital newspaper OCR scans
-![GitHub](https://img.shields.io/github/license/Living-with-Machines/alto2txt) ![PyPI](https://img.shields.io/pypi/v/alto2txt) [![DOI](https://zenodo.org/badge/259340615.svg)](https://zenodo.org/badge/latestdoi/259340615)
+![GitHub](https://img.shields.io/github/license/Living-with-Machines/alto2txt) ![PyPI](https://img.shields.io/pypi/v/alto2txt) [![DOI](https://zenodo.org/badge/259340615.svg)](https://zenodo.org/badge/latestdoi/259340615) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
+*Version extract_text 0.3.4*
+`alto2txt` converts `XML` `ALTO`/`METS` Optical Character Recognition (OCR) scans into plaintext files with minimal metadata.
-Converts `XML` (in `METS` `1.8`/`ALTO` `1.4`, `METS` `1.3`/`ALTO` `1.4`, `BLN` or `UKP` format) publications to plaintext articles and generates minimal metadata.
-
+**`XML` compatibility: `METS 1.8`/`ALTO 1.4`, `METS 1.3`/`ALTO 1.4`, `BLN`, or `UKP` format**
## [Full documentation and demo instructions.](https://living-with-machines.github.io/alto2txt/#/)
+`ALTO` and `METS` are industry standards maintained by the [US Library of Congress](https://www.loc.gov/librarians/standards) targeting newspaper digitization used by hundreds of modern, large-scale newspaper digitization projects. One text file is output per article, each complemented by one `XML` metadata file[^1] .
-## Installation
-
-### Installation using an Anaconda environment
-
-We recommend installation via Anaconda:
+[`METS` (Metadata Encoding and Transmission Standard)](http://www.loc.gov/standards/mets/) is a standard for encoding descriptive, administrative, and structural metadata regarding objects within a digital library, expressed in `XML`. [`ALTO` (Analyzed Layout and Text Objects)](https://www.loc.gov/standards/alto/) is an [`XML schema`](https://en.wikipedia.org/wiki/XML_schema) for technical metadata describing the layout and content of text resources such as book or newspaper pages. `ALTO` is often used in combination with `METS` but can also be used independently. Details of the `ALTO` schema are avilable at https://github.com/altoxml/schema.
-* Refer to the [Anaconda website and follow the instructions](https://docs.anaconda.com/anaconda/install/).
-* Create a new environment for `alto2txt`
+## Quick Install
-```bash
-conda create -n py37alto python=3.7
-```
+### `pip`
-* Activate the environment:
+As of verion `v0.3.4` `alto2txt` is available on [`PyPI`](https://pypi.org/project/alto2txt/) and can be installed via
-```bash
-conda activate py37alto
+```console
+$ pip install alto2txt
```
-### Installation using pip, outside an Anaconda environment
+### `conda`
-Note, the use of ``alto2txt`` outside a conda environment has not been as extensively tested as within a conda environment. Whilst we believe that this should work, please use with caution.
+If you are comfortable with the command line, git, and already have Python & Anaconda installed, you can install `alto2txt` by navigating to an empty directory in the terminal and run the following commands:
-```bash
-pip install alto2txt
+```console
+$ git clone https://github.com/Living-with-machines/alto2txt.git
+$ cd alto2txt
+$ conda create -n py37alto python=3.7
+$ conda activate py37alto
+$ pip install pyproject.toml
```
### Installation of a test release
-If you need (or want) to install a test release of `alto2txt` you will likely be advised of the specific version number to install. This examaple command will install `v0.3.1-alpha.20`:
+If you need (or want) to install a test release of `alto2txt` you will likely be advised of the specific version number to install. This command will install `v0.3.1-alpha.20`:
```bash
-pip install -i https://test.pypi.org/simple/ alto2txt==0.3.1a20
+$ pip install -i https://test.pypi.org/simple/ alto2txt==0.3.1a20
```
-## Usage
-
-Downsampling can be used to convert only every Nth issue of each newspaper. One text file is output per article, each complemented by one `XML` metadata file.
-
+[Click here](https://living-with-machines.github.io/alto2txt/#Demo.md) for more in-depth installation instructions using demo files.
+## Usage
+> *Note*: the formatting below is altered for readability
```
-usage: alto2txt [-h] [-p [PROCESS_TYPE]] [-l [LOG_FILE]] [-d [DOWNSAMPLE]] [-n [NUM_CORES]]
+$ alto2txt -h
+
+usage: alto2txt [-h]
+ [-p [PROCESS_TYPE]]
+ [-l [LOG_FILE]]
+ [-d [DOWNSAMPLE]]
+ [-n [NUM_CORES]]
xml_in_dir txt_out_dir
-alto2txt [-h] [-p [PROCESS_TYPE]] [-l [LOG_FILE]] [-d [DOWNSAMPLE]] [-n [NUM_CORES]]
- xml_in_dir txt_out_dir
Converts XML publications to plaintext articles
@@ -75,91 +77,92 @@ optional arguments:
-n [NUM_CORES], --num-cores [NUM_CORES]
Number of cores (Spark only). Default 1")
```
+To read about downsampling, logs, and using spark see [Advanced Information](https://living-with-machines.github.io/alto2txt/#/advanced).
-`xml_in_dir` is expected to hold `XML` for multiple publications, in the following structure:
-
-```
-xml_in_dir
-|-- publication
-| |-- year
-| | |-- issue
-| | | |-- xml_content
-| |-- year
-|-- publication
-```
-
-However, if `-p|--process-type single` is provided then `xml_in_dir` is expected to hold `XML` for a single publication, in the following structure:
-
-```
-xml_in_dir
-|-- year
-| |-- issue
-| | |-- xml_content
-|-- year
-```
-
-`txt_out_dir` is created with an analogous structure to `xml_in_dir`.
+## Process Types
-`PROCESS_TYPE` can be one of:
+`-p | -process-type` can be one of:
* `single`: Process single publication.
* `serial`: Process publications serially.
* `multi`: Process publications using multiprocessing (default).
* `spark`: Process publications using Spark.
-`DOWNSAMPLE` must be a positive integer, default 1.
+### Process Multiple Publications
-The following `XSLT` files need to be in an `extract_text.xslts` module:
+For default settings, (`multi`) multiprocessing assumes the following directory structure for multiple publications in `xml_in_dir`:
-* `extract_text_mets18.xslt`: `METS 1.8 XSL` file.
-* `extract_text_mets13.xslt`: `METS 1.3 XSL` file.
-* `extract_text_bln.xslt`: `BLN XSL` file.
-* `extract_text_ukp.xslt`: `UKP XSL` file.
-
-## Process publications
+```
+xml_in_dir/
+ ├── publication
+ │ ├── year
+ │ │ └── issue
+ │ │ └── xml_content
+ │ └── year
+ └── publication
+```
+Assuming `xml_in_dir` follows this structure, run alto2txt with the following in the terminal:
-Assume folder `BNA` exists and matches the structure above.
+```console
+$ alto2txt xml_in_dir txt_out_dir
+```
-Extract text from every publication:
+To downsample and only process every 100th edition:
-```bash
-alto2txt BNA txt
+```console
+$ alto2txt xml_in_dir txt_out_dir -d 100
```
-Extract text from every 100th issue of every publication:
-```bash
-alto2txt BNA txt -d 100
-```
+### Process Single Publication
-## Process a single publication
+[A demo for processing a single publication is available here.](https://living-with-machines.github.io/alto2txt/#/?id=process-single-publication)
-Extract text from every issue of a single publication:
+If `-p|--process-type single` is provided then `xml_in_dir` is expected to hold `XML` for a single publication, in the following structure:
-```bash
-alto2txt -p single BNA/0000151 txt
+```
+xml_in_dir/
+ ├── year
+ │ └── issue
+ │ └── xml_content
+ └── year
```
-Extract text from every 100th issue of a single publication:
+Assuming `xml_in_dir` follows this structure, run `alto2txt` with the following in the terminal in the folder `xml_in_dir` is stored in:
-```bash
-alto2txt -p single BNA/0000151 txt -d 100
+```console
+$ alto2txt -p single xml_in_dir txt_out_dir
```
+To downsample and only process every 100th edition from the one publication:
+
+```console
+$ alto2txt -p single xml_in_dir txt_out_dir -d 100
+```
+
+### Plain Text Files Output
+
+`txt_out_dir` is created with an analogous structure to `xml_in_dir`.
+One `.txt` file and one metadata `.xml` file are produced per article.
+
+
## Configure logging
By default, logs are put in `out.log`.
To specify an alternative location for logs, use the `-l` flag e.g.
-```bash
-alto2txt -l mylog.txt BNA txt -d 100 2> err.log
+```console
+$ alto2txt -l mylog.txt single xml_in_dir txt_out_dir -d 100 2> err.log
```
## Process publications via Spark
-[Information on running on spark.](spark_instructions.md)
+[Information on running on spark.](https://living-with-machines.github.io/alto2txt/#/advanced?id=using-spark)
+## Contributing
+
+Suggestions, code, tests, further documentation and features – especially to cover various OCR output formats – are needed and welcome. For details and examples see the [Contributing](https://living-with-machines.github.io/alto2txt/#/contributing) section.
## Future work
@@ -191,3 +194,6 @@ This data is "CC0 1.0 Universal Public Domain" - [No Copyright - Other Known Leg
This software has been developed as part of the [Living with Machines](https://livingwithmachines.ac.uk) project.
This project, funded by the UK Research and Innovation (UKRI) Strategic Priority Fund, is a multidisciplinary collaboration delivered by the Arts and Humanities Research Council (AHRC), with The Alan Turing Institute, the British Library and the Universities of Cambridge, East Anglia, Exeter, and Queen Mary University of London. Grant reference: AH/S01179X/1
+
+> Last updated 2023-02-21
+[^1]: For a more detailed description see: https://www.coloradohistoricnewspapers.org/forum/what-is-metsalto/
diff --git a/alto2txt-verify.sh b/alto2txt-verify.sh
new file mode 100755
index 0000000..977cbec
--- /dev/null
+++ b/alto2txt-verify.sh
@@ -0,0 +1,111 @@
+#!/usr/bin/env bash
+#
+# Verification checks to run after processing newspapers with alto2txt.
+#
+# Call this script with two command line arguments:
+# 1. the directory path containing the input data processed by alto2txt
+# 2. the directory path containing the output data generated by alto2txt
+#
+# Both input & output directories should have identical subdirectory
+# structure of the following form: title_code/YYYY/MMDD/
+#
+# This script checks that the directory structures are identical.
+# It does not check the validity of the alto2txt text or metadata files.
+
+input_dir=$1
+output_dir=$2
+
+if [[ ! -e $1 ]]; then
+ echo "Error: Input directory $1 does not exist."
+ exit
+fi
+if [[ ! -e $2 ]]; then
+ echo "Error: Output directory $2 does not exist."
+ exit
+fi
+echo ">>> alto2txt verification <<<"
+echo "Input directory: '$input_dir'"
+echo "Output directory: '$output_dir'"
+
+# Create subdirectories to store temporary files and results.
+subdir="alto2txt-verify"
+if [[ -e $subdir ]]; then
+ echo "Error: $subdir subdirectory already exists."
+ exit
+fi
+mkdir $subdir
+
+input_subdir="$subdir/input"
+if [[ ! -e $input_subdir ]]; then
+ mkdir $input_subdir
+fi
+output_subdir="$subdir/output"
+if [[ ! -e $output_subdir ]]; then
+ mkdir $output_subdir
+fi
+
+# Loop over the title_code/YYYY subdirectories in the input
+# directory and get a list of MMDD subdirectories for each.
+sep="-"
+for yyyy_dir in $(find $input_dir -mindepth 2 -maxdepth 2 -not -path '*/.*' -type d); do
+ yyyy="${yyyy_dir##*/}"
+ title_dir="${yyyy_dir:0:(${#yyyy_dir}-5)}"
+ title="${title_dir##*/}"
+ txtfile="$input_subdir/$title$sep$yyyy.txt"
+ (cd $input_dir && find "$title/$yyyy" -mindepth 1 -maxdepth 1 -not -path '*/.*' -type d) > $txtfile
+done
+
+# Repeat for the output subdirectories.
+for yyyy_dir in $(find $output_dir -mindepth 2 -maxdepth 2 -not -path '*/.*' -type d); do
+ yyyy="${yyyy_dir##*/}"
+ title_dir="${yyyy_dir:0:(${#yyyy_dir}-5)}"
+ title="${title_dir##*/}"
+ txtfile="$output_subdir/$title$sep$yyyy.txt"
+ (cd $output_dir && find "$title/$yyyy" -mindepth 1 -maxdepth 1 -not -path '*/.*' -type d) > $txtfile
+done
+
+# Compare the results.
+success=true
+titleyearcheck="$subdir/missing-title-years.txt"
+mmddcheck="$subdir/missing-mmdd-directories"
+affectedtitles="$subdir/affected-titles.txt"
+first=true
+first_cmp=true
+for filename in $(ls $input_subdir); do
+ title="${filename%$sep*}"
+ if [[ ! -e $output_subdir/$filename ]]; then
+ # Make a list of any .txt files in $input_subdir that aren't found in $output_subdir
+ success=false
+ echo "$title" >> $affectedtitles
+ if [ "$first" = true ]; then
+ echo "WARNING: Missing title-years detected in alto2txt output"
+ echo "Missing title-years are listed in: $titleyearcheck"
+ first=false
+ fi
+ echo "$filename" >> $titleyearcheck
+ else
+ # Compare .txt files that are found in both subdirs
+ if (! cmp -s "$input_subdir/$filename" "$output_subdir/$filename"); then
+ success=false
+ echo "$title" >> $affectedtitles
+ if [ "$first_cmp" = true ]; then
+ echo "WARNING: Missing MMDD directories detected in alto2txt output"
+ echo "Missing MMDD directories are are listed in subdirectory: $mmddcheck"
+ if [[ ! -e $mmddcheck ]]; then
+ mkdir $mmddcheck
+ fi
+ first_cmp=false
+ fi
+ comm -23 <(sort $input_subdir/$filename) <(sort $output_subdir/$filename) > $mmddcheck/$filename
+ fi
+ fi
+done
+
+if [[ -e $affectedtitles ]]; then
+ sort -u $affectedtitles -o $affectedtitles
+ echo ">>> All affected titles are listed in: $affectedtitles"
+fi
+
+if [ "$success" = true ]; then
+ echo "SUCCESS: alto2txt verification checks passed."
+fi
diff --git a/docs/Demo.md b/docs/Demo.md
index d801c52..5c7176d 100644
--- a/docs/Demo.md
+++ b/docs/Demo.md
@@ -12,24 +12,30 @@ If you are comfortable with the command line, git, and already have Python & Ana
Navigate to an empty directory in the terminal and run the following commands:
+```console
+$ git clone https://github.com/Living-with-machines/alto2txt.git
+$ cd alto2txt
+$ conda create -n py37alto python=3.7
+$ conda activate py37alto
```
-> git clone https://github.com/Living-with-machines/alto2txt.git
-> cd alto2txt
-> conda create -n py37alto python=3.7
-> conda activate py37alto
-```
+
To install that checkout you can
-```
-> pip install pyproject.toml
+
+```console
+$ pip install pyproject.toml
```
You can simply install the latest release (but this may not be up to date with the GitHub `main` branch)
+
+```console
+$ pip install alto2txt
```
-> pip install alto2txt
-```
+
regardless this should make the following command run
+
+```console
+$ alto2txt -p single demo-files demo-output
```
-> alto2txt -p single demo-files demo-output
-```
+
and the resulting plain text files of the articles will be in `alto2txt/demo-output/`.
Read on for a more in-depth explanation.
@@ -59,21 +65,21 @@ cd ~myFolder/alto2txt
Create a new [Conda environment](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html) with Python 3.7. The environment name can be whatever you choose, here it is `py37alto`:
-```
-conda create -n py37alto python=3.7
+```console
+$ conda create -n py37alto python=3.7
```
After creating the environment, activate it:
-```
-conda activate py37alto
+```console
+$ conda activate py37alto
```
#### Install Required Packages
Install the required packages which are outlined in `pyproject.toml`:
-```
-pip install pyproject.toml
+```console
+$ pip install pyproject.toml
```
Follow the instructions to download and install the packages. You should now have all the required Python packages within your conda environment to run `alto2txt`.
@@ -84,7 +90,7 @@ Follow the instructions to download and install the packages. You should now hav
Make sure you have navigated to the `alto2txt` directory in your terminal or Anaconda prompt. For this demo, we are using a single edition for a single publication. The output files will be created in `/demo-output` which you can check is currently empty.
```
-alto2txt -p single demo-files demo-output
+$ alto2txt -p single demo-files demo-output
```
Here we use the positional argument `-p` to determine which process type, in this case `single`. The script can be run on many publications and years by default, but in this case we only have one publication. [Click here](/#process-types) to read more about different process types.
@@ -178,26 +184,26 @@ Running these steps for your own files works in the same way. Your source and/or
#### Run on a single publication, multiple years, multiple editions
-```
-alto2txt -p single input-directory output-directory
+```console
+$ alto2txt -p single input-directory output-directory
```
#### Run on multiple publications, multiple years, multiple editions
-```
-alto2txt input-directory output-directory
+```console
+$ alto2txt input-directory output-directory
```
#### Extract every 100th edition from every publication
-```
-alto2txt input-directory output-directory -d 100
+```console
+$ alto2txt input-directory output-directory -d 100
```
Where `-d` determines the downsample value.
#### Extract every 100th edition from one publication
-```
-alto2txt -p single input-directory output-directory -d 100
+```console
+$ alto2txt -p single input-directory output-directory -d 100
```
diff --git a/docs/README.md b/docs/README.md
index d539874..773caf3 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,14 +1,42 @@
-# `alto2txt`: Extract plain text from digitised newspapers
+# `alto2txt`: Extract plain text from digital newspaper OCR scans
-*Version extract_text 0.3.0*
+*Version extract_text 0.3.4*
-`alto2txt` converts `XML` publications to plaintext articles with minimal metadata.
-ALTO and METS are the current industry standards for newspaper digitisation used by hundreds of modern, large-scale newspaper digitisation projects.
-One text file is output per article, each complemented by one `XML` metadata file.
+![GitHub](https://img.shields.io/github/license/Living-with-Machines/alto2txt) ![PyPI](https://img.shields.io/pypi/v/alto2txt) [![DOI](https://zenodo.org/badge/259340615.svg)](https://zenodo.org/badge/latestdoi/259340615) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
-[METS (Metadata Encoding and Transmission Standard)](http://www.loc.gov/standards/mets/) is a standard for encoding descriptive, administrative, and structural metadata regarding objects within a digital library, expressed in XML. [ALTO (Analyzed Layout and Text Objects](http://www.loc.gov/standards/alto/) is an 'XML Schema that details technical metadata for describing the layout and content of physical text resources, such as pages of a book or a newspaper'. ALTO extends METS but can also be used independently.
-**`XML` compatibility: METS 1.8/ALTO 1.4, METS 1.3/ALTO 1.4, BLN, or UKP format**
+`alto2txt` converts `XML` `ALTO`/`METS` Optical Character Recognition (OCR) scans into plaintext files with minimal metadata.
+
+**`XML` compatibility: `METS 1.8`/`ALTO 1.4`, `METS 1.3`/`ALTO 1.4`, `BLN`, or `UKP` format**
+
+`ALTO` and `METS` are industry standards maintained by the [US Library of Congress](https://www.loc.gov/librarians/standards) targeting newspaper digitization used by hundreds of modern, large-scale newspaper digitization projects. One text file is output per article, each complemented by one `XML` metadata file[^1] .
+
+[`METS` (Metadata Encoding and Transmission Standard)](http://www.loc.gov/standards/mets/) is a standard for encoding descriptive, administrative, and structural metadata regarding objects within a digital library, expressed in `XML`. [`ALTO` (Analyzed Layout and Text Objects)](https://www.loc.gov/standards/alto/) is an [`XML schema`](https://en.wikipedia.org/wiki/XML_schema) for technical metadata describing the layout and content of text resources such as book or newspaper pages. `ALTO` is often used in combination with `METS` but can also be used independently. Details of the `ALTO` schema are avilable at https://github.com/altoxml/schema.
+
+
+## Quick Install
+
+### `pip`
+
+As of verion `v0.3.4` `alto2txt` is available on [`PyPI`](https://pypi.org/project/alto2txt/) and can be installed via
+
+```bash
+pip install alto2txt
+```
+
+### `conda`
+
+If you are comfortable with the command line, git, and already have Python & Anaconda installed, you can install `alto2txt` by navigating to an empty directory in the terminal and run the following commands:
+
+```bash
+git clone https://github.com/Living-with-machines/alto2txt.git
+cd alto2txt
+conda create -n py37alto python=3.7
+conda activate py37alto
+pip install pyproject.toml
+```
+
+[Click here](/Demo.md) for more in-depth installation instructions using demo files.
## Usage
@@ -40,22 +68,6 @@ optional arguments:
```
To read about downsampling, logs, and using spark see [Advanced Information](advanced.md).
-
-## Quick Install
-
-If you are comfortable with the command line, git, and already have Python & Anaconda installed, you can install `alto2txt` by navigating to an empty directory in the terminal and run the following commands:
-
-```
-> git clone https://github.com/Living-with-machines/alto2txt.git
-> cd alto2txt
-> conda create -n py37alto python=3.7
-> conda activate py37alto
-> pip install pyproject.toml
-```
-
-[Click here](/Demo.md) for more in-depth installation instructions using demo files.
-
-
## Process Types
@@ -81,14 +93,14 @@ xml_in_dir/
```
Assuming `xml_in_dir` follows this structure, run alto2txt with the following in the terminal:
-```bash
-alto2txt xml_in_dir txt_out_dir
+```console
+$ alto2txt xml_in_dir txt_out_dir
```
To downsample and only process every 100th edition:
-```bash
-alto2txt xml_in_dir txt_out_dir -d 100
+```console
+$ alto2txt xml_in_dir txt_out_dir -d 100
```
@@ -108,14 +120,14 @@ xml_in_dir/
Assuming `xml_in_dir` follows this structure, run `alto2txt` with the following in the terminal in the folder `xml_in_dir` is stored in:
-```bash
-alto2txt -p single xml_in_dir txt_out_dir
+```console
+$ alto2txt -p single xml_in_dir txt_out_dir
```
To downsample and only process every 100th edition from the one publication:
-```bash
-alto2txt -p single xml_in_dir txt_out_dir -d 100
+```console
+$ alto2txt -p single xml_in_dir txt_out_dir -d 100
```
## Plain Text Files Output
@@ -135,8 +147,9 @@ Quality assurance is performed to check for:
## Future work
-* Export more metadata from ALTO, probably by parsing METS first.
+* Export more metadata from `ALTO`, probably by parsing `METS` first.
* Check and ensure that articles that span multiple pages are pulled into a single article file.
* Smarter handling of articles spanning multiple pages.
-> Last updated 2022-11-10
+> Last updated 2023-02-22
+[^1]: For a more detailed description see: https://www.coloradohistoricnewspapers.org/forum/what-is-metsalto/
diff --git a/docs/_coverpage.md b/docs/_coverpage.md
index c793c4f..c168ca1 100644
--- a/docs/_coverpage.md
+++ b/docs/_coverpage.md
@@ -1,7 +1,7 @@
-# Alto2Txt
+# alto2txt
-> Extract text from digitised newspapers articles
+> Extract plain text from newspaper OCR scans
@@ -11,4 +11,4 @@
- Made with docsify
+Made with docsify.
diff --git a/docs/_sidebar.md b/docs/_sidebar.md
index 35b2994..c92fa4d 100644
--- a/docs/_sidebar.md
+++ b/docs/_sidebar.md
@@ -1,4 +1,5 @@
-* [Alto2Txt](/)
+* [`alto2txt`](/)
* [Demo](Demo.md)
* [Advanced](advanced.md)
+* [Contributing](contributing.md)
diff --git a/docs/advanced.md b/docs/advanced.md
index 7eb19c3..3091d49 100644
--- a/docs/advanced.md
+++ b/docs/advanced.md
@@ -1,5 +1,4 @@
-# Further Information
-
+# Advanced features and utilities
## `XSTL`: `XML` Stylesheet
@@ -42,8 +41,8 @@ By default, logs are put in `out.log`.
To specify an alternative location for logs, use the `-l` flag e.g.
-```bash
-alto2txt -l mylog.txt ~/xml_in_dir ~/txt_out_dir -d 100 2> err.log
+```console
+$ alto2txt -l mylog.txt ~/xml_in_dir ~/txt_out_dir -d 100 2> err.log
```
## Using Spark
@@ -56,16 +55,16 @@ When running via Spark ensure that:
For example, the code can be run on Urika requesting as follows...
-Install the code as a package:
+Install the code as a package with the `spark` option:
-```bash
-python setup.py install
+```console
+poetry install --with spark
```
Run `spark-submit`:
-```bash
-spark-submit ./extract_publications_text.py \
+```console
+$ spark-submit ./extract_publications_text.py \
-p spark \
-n 144 \
-l /mnt/lustre/at003/at003//log.out \
@@ -83,22 +82,16 @@ this would request 144/36 = 4 workers/executors and nodes.
To update the version number:
-1. Edit `README.md`:
-
-```
-# Extract plain text from newspapers (extract_text 0.3.0)
-```
-
-2. Edit `setup.py`:
+1. Edit `pyproject.toml`:
```
-version="0.3.0",
+version = "0.3.4"
```
-3. Exit `extract_text/xslts/extract_text_common.xslt`:
+2. Edit `extract_text/xslts/extract_text_common.xslt`:
```
-0.3.0
+0.3.4
```
## Documentation with Docsify
diff --git a/docs/contributing.md b/docs/contributing.md
new file mode 100644
index 0000000..2104891
--- /dev/null
+++ b/docs/contributing.md
@@ -0,0 +1,165 @@
+# Contributing
+
+Contributions via [GitHub issues](https://github.com/Living-with-machines/alto2txt/issues) and [pull requests](https://github.com/Living-with-machines/alto2txt/pulls) very welcome. To install locally for contribtuions we recommend using [`poetry`](https://python-poetry.org/).
+
+## Local checkout
+
+1. Install [`poetry`](https://python-poetry.org/docs/#installation)
+2. `$ git checkout https://github.com/Living-with-machines/alto2txt.git`
+3. `$ cd alto2txt`
+4. `$ poetry install`
+
+## [`pre-commit`](https://pre-commit.com/) local changes
+
+Whatever contribution you make, be it code or documentation, your changes will need to pass our [`pre-commit`](https://pre-commit.com/) [configuration](https://github.com/Living-with-machines/alto2txt/blob/main/.pre-commit-config.yaml). To prepare that:
+
+1. Follow [installation instructions](https://pre-commit.com/#install)
+2. Add `pre-commit` [git commit hooks](https://pre-commit.com/#3-install-the-git-hook-scripts)
+
+```console
+$ cd path/to/alto2txt
+$ pre-commit install
+```
+
+3. Make your local commit and see if any `pre-commit` changes are added. See a [best practice guide](https://www.conventionalcommits.org/en/v1.0.0/#examples) for writing these:
+
+```console
+$ git commit -m "docs: add docs/contributing.py and enable in sidebar"
+```
+
+This *should* then run `pre-commit` checks that print messages like this to the screen (this is simplifed as an example):
+
+```console
+[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
+[INFO] Initializing environment for https://github.com/psf/black.
+[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
+[INFO] Installing environment for https://github.com/pre-commit/mirrors-autopep8.
+[INFO] Installing environment for https://github.com/pre-commit/mirrors-mypy.
+[INFO] This may take a few minutes...
+trim trailing whitespace.................................................Failed
+- hook id: trailing-whitespace
+- exit code: 1
+- files were modified by this hook
+
+Fixing docs/contributing.md
+
+fix end of files.........................................................Passed
+Check Yaml...............................................................Passed
+Fix End of Files.........................................................Passed
+check yaml...............................................................Passed
+check xml............................................(no files to check)Skipped
+check for added large files..............................................Passed
+poetry-check.........................................(no files to check)Skipped
+poetry-lock..............................................................Passed
+black................................................(no files to check)Skipped
+autopep8.............................................(no files to check)Skipped
+mypy.................................................(no files to check)Skipped
+isort................................................(no files to check)Skipped
+pycln................................................(no files to check)Skipped
+```
+
+In this simple case, adding the new changes generated by `pre-commit` (trimming trailing whitespace in `docs/contributing.md`) should then pass and complete the commit:j
+
+```console
+$ git add docs/contributing.md
+$ git commit -m "docs: add docs/contributing.py and enable in sidebar"
+
+trim trailing whitespace.................................................Passed
+fix end of files.........................................................Passed
+check yaml...............................................................Passed
+check xml............................................(no files to check)Skipped
+check for added large files..............................................Passed
+poetry-check.........................................(no files to check)Skipped
+poetry-lock..............................................................Passed
+black................................................(no files to check)Skipped
+autopep8.............................................(no files to check)Skipped
+mypy.................................................(no files to check)Skipped
+isort................................................(no files to check)Skipped
+pycln................................................(no files to check)Skipped
+[doc-copy-edits 18be46e] fix: update extract_text_common.xslt version
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+```
+
+## Running tests
+
+If you make changes to the code, please add a test (and/or modify current tests) within the `tests/` folder to help ensure your contribution produces correct results. It also makes it much easier (and quicker) to review contributions and either accept or suggest additional changes. Tests are run via
+
+```console
+$ poetry run pytest
+```
+
+See `pytest` [examples](https://docs.pytest.org/en/7.1.x/getting-started.html#create-your-first-test) for advice on writing tests and using [`fixtures`](https://docs.pytest.org/en/7.1.x/reference/fixtures.html#fixture-availability). Fixtures for our tests are are `tests/conftest.py`.
+
+If you need to debug changes and/or tests, you can run
+
+```console
+$ poetry run pytest --pdb
+```
+
+to drop into [`ipython`](https://ipython.readthedocs.io/en/stable/) to interactively debug how a test failed.
+
+Once tests have finished running, it will print out a summary of how much code was covered by the tests via [coverage](https://coverage.readthedocs.io/en/7.1.0/) package. For example:
+
+```console
+================================= test session starts =================================
+platform darwin -- Python 3.10.10, pytest-7.2.1, pluggy-1.0.0
+rootdir: /Users/you-user-name/path-to-git-checkouts/alto2txt, configfile: pyproject.toml
+plugins: cov-4.0.0
+collected 8 items
+
+tests/test_e2e.py ...s.ss [ 87%]
+tests/test_import.py . [100%]
+
+--------- coverage: platform darwin, python 3.10.10-final-0 ----------
+Name Stmts Miss Cover
+---------------------------------------------------------------
+src/alto2txt/extract_publications_text.py 21 1 95%
+src/alto2txt/spark_xml_to_text.py 29 29 0%
+src/alto2txt/xml_to_text.py 111 42 62%
+src/alto2txt/xml_to_text_entry.py 38 6 84%
+---------------------------------------------------------------
+TOTAL 320 78 76%
+
+5 files skipped due to complete coverage.
+```
+
+*Generally* higher coverage is better. In the example above, any contributions to testing `spark_xml_to_text.py` would be very appreciated.
+
+## Documentation with Docsify
+
+Documentation is a collection of [`markdown`](https://www.markdownguide.org/basic-syntax/) files rendered by [`docsify`](https://docsify.js.org/
+) and staticly hosted on [GitHub Pages](https://pages.github.com/). To contribute:
+
+1. Edit the `.md` files within `docs/`.
+2. Add any extra pages to `_sidebar.md` or reorder them
+3. Generate an [issue](https://github.com/Living-with-machines/alto2txt/issues) describing what you've added
+4. Make a [pull request](https://github.com/Living-with-machines/alto2txt/pulls)
+
+To preview locally from the terminal:
+
+1. Navigate to your `alto2txt` repository (and follow installation instructions above if needed).
+3. `$ poetry shell` to activate your local `python` environment
+4. `$ cd docs && python -m http.server 3000` to render the `docs`
+5. Navigate to `http://localhost:3000` in a browser to render changes as you make them
+
+## Update Version
+
+Once you've made a contribution, you may need to update the `alto2txt` version number. If requested, here's an example of following that process
+
+1. Edit `README.md`:
+
+```md
+# Extract plain text from newspapers (extract_text 0.3.4)
+```
+
+2. Edit `pyproject.toml`:
+
+```toml
+version = "0.3.4"
+```
+
+3. Exit `extract_text/xslts/extract_text_common.xslt`:
+
+```xml
+0.3.4
+```
diff --git a/docs/index.html b/docs/index.html
index 12fa727..d578e19 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -12,7 +12,7 @@
+