Skip to content

Commit

Permalink
Merge pull request 'Release v24.05' (#4) from release_24.05 into master
Browse files Browse the repository at this point in the history
  • Loading branch information
janvonde committed Jun 10, 2024
2 parents a3895cf + c84c965 commit 043a97b
Show file tree
Hide file tree
Showing 12 changed files with 855 additions and 45 deletions.
50 changes: 50 additions & 0 deletions install/cope/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

# COPE scripts

## EIP extraction

The script `eip_prepare_for_cope.py` extracts EIP files in a source directory to a target directory. It renames a specific subdirectory (`CaptureOne/Settings153` to `CaptureOne/Settings131`) and moves the EIP files into the `_raw` image directory.

## Usage

```
usage: eip_prepare_for_cope.py [-h] -s SOURCE -t TARGET
options:
-h, --help show this help message and exit
-s SOURCE, --source SOURCE
Source directory
-t TARGET, --target TARGET
Target directory
```

in Goobi workflow this can be integrated in a script step like this:

```shell
/opt/digiverso/goobi/scripts/eip_prepare_for_cope.py -s {origpath} -t {origpath}
```

## COPE conversion

The script `cope_folder.py` converts IIQ files from the source directory and uses COPE to convert them to tiff files located in the target directory. Optionally the given resolution value will be used.

## Usage

```
usage: cope_folder.py [-h] -s SOURCE -t TARGET [-r RESOLUTION]
options:
-h, --help show this help message and exit
-s SOURCE, --source SOURCE
-t TARGET, --target TARGET
-r RESOLUTION, --resolution RESOLUTION
```

The path to the cope binary can be given by an environment variable named `COPE_PATH`.

In Goobi workflow a script step in the external queue can be used to run the script on a Windows workernode like this:

```CMD
C:\Windows\py.exe D:\intranda\cope_folder.py -s "//mediaSMB-isilonArchive/GoobiMetadata/{s3_origpath}" -t "//mediaSMB-isilonArchive/GoobiMetadata/{s3_origpath}" -r "{process.File Resolution}"
```

104 changes: 104 additions & 0 deletions install/cope/cope_folder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env python3

import logging
import os
import shutil
import subprocess
from argparse import ArgumentParser
from pathlib import Path

loglevel = (os.environ.get('PYTHON_LOGLEVEL') or "DEBUG").upper()
numeric_level = getattr(logging, loglevel.upper(), None)
logging.basicConfig(
format='%(asctime)s %(levelname)-8s %(message)s', level=numeric_level)

file_name_pattern = "*.IIQ"
path_cope = (os.environ.get('COPE_PATH') or Path(
"C:/cope.Win.13.1.15-name_cope131/COPE/Bin/COPE.exe"))

cope_options = ["-bits=8"]


def find_files(root_dir: Path, file_name_pattern: str) -> list[list]:
"""find files matching file_name_pattern in direct subdirectories of root_dir
Args:
root_dir (Path): top level directory to perform search in
file_name_pattern (str): globbing expression to match for
Returns:
list[list]: a list of lists with the filename and the parent directory basename of matching files
"""
found_files = []
for file in Path(root_dir).glob("*/"+file_name_pattern):
found_files.append([file, file.parent.stem])
return (found_files)


def get_parser():
"""provides argument parser"""
parser = ArgumentParser()
parser.add_argument("-s", "--source", dest="source",
required=True, type=str)
parser.add_argument("-t", "--target", dest="target",
required=True, type=str)
parser.add_argument("-r", "--resolution", dest="resolution",
required=False, type=int)
return parser


if __name__ == "__main__":
parser = get_parser()
args = parser.parse_args()

sourcedir = Path(args.source)
targetdir = Path(args.target)
resolution = args.resolution

logging.debug(f"path to cope: {path_cope}")
logging.debug(f"source directory: {sourcedir}")
logging.debug(f"target directory: {targetdir}")

if resolution:
logging.debug(f"resolution: {resolution}")
cope_options.append(f"-resolution={resolution}")

if not os.path.isdir(sourcedir):
logging.error("source directory does not exist")
exit(1)

if not os.path.isdir(targetdir):
os.mkdir(targetdir)
logging.info("target directory created, as it did not exist")

logging.info("start processing...")
files = find_files(sourcedir, file_name_pattern)

if not files:
logging.info("no matching files found in source directory")

for file, base in files:
target = Path(targetdir) / (base + ".tif")
logging.info(f"processing {file}")

cope_command = [Path(path_cope), file, target] + cope_options

logging.debug(f"running {cope_command}")

# execute cope
try:
subprocess.run(cope_command, check=True)
except FileNotFoundError:
logging.error(f"cope executable was not found: {path_cope}")
exit(1)
except Exception as err:
logging.error(f"Unexpected {err=}, {type(err)=}")
raise

# cope does not appear to make much use of exit codes, thus we check the existence of the expected tiff file here
if not target.is_file():
logging.error(f"tiff file expected but not found: {target}")
exit(1)
else:
logging.debug(f"removing source package {target.with_suffix('')}")
shutil.rmtree(target.with_suffix(''))
65 changes: 65 additions & 0 deletions install/cope/eip_prepare_for_cope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3

# This script extracts eip files in a source directory to a target directory, renames a specific subdirectory and moves the original eip files

import os
import shutil
from argparse import ArgumentParser
from pathlib import Path


def extract_and_rename_eip(source_dir, target_dir):
# Check if source directory exists
if not os.path.isdir(source_dir):
print("Source directory does not exist")
exit(1)

# Create target directory if it does not exist
os.makedirs(target_dir, exist_ok=True)

if source_dir.name.endswith("_master"):
raw_directory = Path.joinpath(
source_dir.parent, source_dir.name.replace("_master", "_raw"))
os.makedirs(raw_directory, exist_ok=True)

for filename in os.listdir(source_dir):
if filename.endswith(".eip"):
file_path = os.path.join(source_dir, filename)
if os.path.isfile(file_path):
# Unzip eip to target directory
unzip_dir = os.path.join(
target_dir, os.path.splitext(filename)[0])
shutil.unpack_archive(filename=file_path,
extract_dir=unzip_dir, format="zip")

capture_one_dir = os.path.join(unzip_dir, "CaptureOne")
settings_old = os.path.join(capture_one_dir, "Settings153")
settings_new = os.path.join(capture_one_dir, "Settings131")

# Check if CaptureOne directory exists
if not os.path.isdir(capture_one_dir):
print(f"{capture_one_dir} does not exist")
exit(1)

# Rename setting directory to matching version for cope
if os.path.isdir(settings_old):
os.rename(settings_old, settings_new)

os.rename(file_path, Path.joinpath(raw_directory, filename))


def get_parser():
"""provides argument parser"""
parser = ArgumentParser()
parser.add_argument("-s", "--source", dest="source",
required=True, type=str, help="Source directory")
parser.add_argument("-t", "--target", dest="target",
required=True, type=str, help="Target directory")
return parser


if __name__ == "__main__":
parser = get_parser()
args = parser.parse_args()

extract_and_rename_eip(Path(args.source), Path(args.target))
62 changes: 39 additions & 23 deletions install/plugin_intranda_export_adm_bsme.xml
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
<config_plugin>

<!-- directories where to export to -->
<targetDirectoryMagazines>/opt/digiverso/viewer/hotfolderMagazines/</targetDirectoryMagazines>
<targetDirectoryNewspapers>/opt/digiverso/viewer/hotfolderNewspapers/</targetDirectoryNewspapers>
<targetDirectoryNewspapers>/opt/digiverso/export/bsme/mnt/export/Newspapers/</targetDirectoryNewspapers>
<targetDirectoryMagazines>/opt/digiverso/export/bsme/mnt/export/Magazines/</targetDirectoryMagazines>
<targetDirectoryPositives>/opt/digiverso/export/bsme/mnt/export/Positives/</targetDirectoryPositives>
<targetDirectoryNegatives>/opt/digiverso/export/bsme/mnt/export/Negatives/</targetDirectoryNegatives>
<targetDirectorySlides>/opt/digiverso/export/bsme/mnt/export/Slides/</targetDirectorySlides>
<targetDirectoryGeneric>/opt/digiverso/export/bsme/mnt/export/Generic/</targetDirectoryGeneric>

<!-- additional PDF copy directory, leave empty if not needed -->
<pdfCopyNewspapers>/opt/digiverso/export/bsme/mnt/pdf/Newspapers/</pdfCopyNewspapers>
<pdfCopyMagazines>/opt/digiverso/export/bsme/mnt/pdf/Magazines/</pdfCopyMagazines>

<!-- main viewer url -->
<viewerUrl>https://adm.goobi.cloud/viewer/</viewerUrl>>

<!-- configured values to be used inside of the export xml,
can use variable replacer expressions here like e.g.:
- $(meta.CatalogIDDigital)
- $(meta.topstruct.TitleDocMain)
<viewerUrl>https://adm.goobi.cloud/viewer/</viewerUrl>

<!-- configured values to be used inside of the export xml, can use variable
replacer expressions here like e.g.: - $(meta.CatalogIDDigital) - $(meta.topstruct.TitleDocMain)
- $(process.Template) -->
<rightsToUse>$(template.Rights to Use)</rightsToUse>
<rightsDetails>$(template.Rights Details)</rightsDetails>
<source>Goobi</source>
<mediaType>$(template.Media Type)</mediaType>
<mediaGroup>$(template.Media Group)</mediaGroup>
<sourceOrganisation>$(template.Source Organization)</sourceOrganisation>
<frequency>$(template.Issue Frequency)</frequency>

<rightsToUse>$(template.Rights to Use)</rightsToUse>
<rightsDetails>$(template.Rights Details)</rightsDetails>
<source>Goobi</source>
<mediaType>$(template.Media Type)</mediaType>
<mediaGroup>$(template.Media Group)</mediaGroup>
<sourceOrganisation>$(template.Source Organization)</sourceOrganisation>
<frequency>$(template.Issue Frequency)</frequency>
<eventName>$(template.Event Name)</eventName>
<eventDate>$(template.Event Date)</eventDate>
<subject>$(template.Subject)</subject>
<photographer>$(template.Photographer)</photographer>
<personsInImage>$(template.Persons in Image)</personsInImage>
<locations>$(template.Locations)</locations>
<description>$(template.Description)</description>
<editorInChief>$(template.Editor in Chief)</editorInChief>
<format>$(template.Format)</format>

<!-- mets parameter -->
<!-- if a field is empty or missing, project configuration is used -->
<metsUrl addFileExtension="true">https://adm.goobi.cloud/viewer/sourcefile?id=</metsUrl>
<resolverUrl>https://adm.goobi.cloud/viewer/piresolver?id=</resolverUrl>
<metsUrl addFileExtension="true">https://adm.goobi.cloud/viewer/sourcefile?id=
</metsUrl>
<resolverUrl>https://adm.goobi.cloud/viewer/piresolver?id=
</resolverUrl>
<metsPointerPath>https://adm.goobi.cloud/viewer/sourcefile?id=$(meta.topstruct.CatalogIDDigital).xml
</metsPointerPath>
<metsPointerPathAnchor>https://adm.goobi.cloud/viewer/sourcefile?id=$(meta.CatalogIDDigital).xml
Expand Down Expand Up @@ -65,11 +81,11 @@
<anchorId>AnchorID</anchorId>
<anchorTitle>AnchorTitle</anchorTitle>
<accessConditionUse>AccessConditionUse</accessConditionUse>
<accessConditionDetails>AccessConditionDetails</accessConditionDetails>
<accessConditionDetails>AccessConditionDetails
</accessConditionDetails>
<frequency>Frequency</frequency>

</metadata>

<docstruct>
<newspaper>Newspaper</newspaper>
<year>Year</year>
Expand All @@ -78,5 +94,5 @@
<issue>NewspaperIssue</issue>
<newspaperStub>NewspaperStub</newspaperStub>
</docstruct>
</config_plugin>

</config_plugin>
2 changes: 1 addition & 1 deletion module-base/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<parent>
<groupId>io.goobi.workflow.plugin</groupId>
<artifactId>plugin-export-adm-bsme</artifactId>
<version>24.04.30</version>
<version>24.05</version>
</parent>
<artifactId>plugin-export-adm-bsme-base</artifactId>
<packaging>jar</packaging>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
Expand Down Expand Up @@ -95,16 +97,54 @@ public static String getLanguageFullname(DocStruct ds, String field) {
String lang = getMetdata(ds, field);
switch (lang) {
case "Arabic":
return "عربي Arabic";
return "عربي - Arabic";
case "ara":
return "عربي Arabic";
return "عربي - Arabic";
case "English":
return "انجليزي English";
return "انجليزي - English";
case "eng":
return "انجليزي English";
return "انجليزي - English";
case "ger":
return "German";
}
return lang;
}

/**
* convert the date from dd-mm-yyyy to format yyyy-mm-dd and give it back
*
* @param inputDate
* @return
*/
public static String convertDateFormatToDayMonthYear(String inputDate) {
return convertDateFormat(inputDate, "yyyy-MM-dd", "dd-MM-yyyy");
}

/**
* convert the date from yyyy-mm-dd to format dd-mm-yyyy and give it back
*
* @param inputDate
* @return
*/
public static String convertDateFormatToYearMonthDay(String inputDate) {
return convertDateFormat(inputDate, "dd-MM-yyyy", "yyyy-MM-dd");
}

/**
* convert the date from one format to the other
*
* @param inputDate
* @return
*/
private static String convertDateFormat(String inputDate, String inFormat, String outFormat) {
SimpleDateFormat inputFormatter = new SimpleDateFormat(inFormat);
SimpleDateFormat outputFormatter = new SimpleDateFormat(outFormat);

try {
Date date = inputFormatter.parse(inputDate);
return outputFormatter.format(date);
} catch (Exception e) {
return inputDate;
}
}
}
Loading

0 comments on commit 043a97b

Please sign in to comment.