ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English
GakuNin RDMのAPIを使って、ファイルのアップロードなどを行う

GakuNin RDMのAPIを使って、ファイルのアップロードなどを行う

背景 GakuNin RDMのAPIを使って、ファイルのアップロードなどを行う方法の備忘録です。 参考 以下でPAT(パーソナルアクセストークン)の取得方法などを説明しています。 また以下では、OAuth (Open Authorization)を使った方法を紹介しています。Webアプリなどから使用される場合には、こちらが参考になりましたら幸いです。 方法 nbdevを使って、以下のリポジトリを作成しました。 https://github.com/nakamura196/grdm-tools 以下でドキュメントを確認できます。 https://nakamura196.github.io/grdm-tools/ プロバイダ(osfstorage)とフォルダのID(6735a92e6dc8e1001062ac08)は変更する必要がありますが、以下のようなスクリプトにより、特定のフォルダにファイルをアップロードできます。 from grdm_tools.api import GrdmClient import os client = GrdmClient( token=os.environ.get('GRDM_TOKEN') ) project_id = "ys86g" file_path = "./sample.png" url = f"https://files.rdm.nii.ac.jp/v1/resources/{project_id}/providers/osfstorage/6735a92e6dc8e1001062ac08/?kind=file" client.upload_file(file_path, url) ソースコードは以下からご確認いただけます。 https://nakamura196.github.io/grdm-tools/api.html#grdmclient.upload_file まとめ GakuNin RDMのAPI利用にあたり、参考になりましたら幸いです。

ArchivematicaのMETSファイルの内容を可視化するPythonライブラリ

ArchivematicaのMETSファイルの内容を可視化するPythonライブラリ

概要 ArchivematicaのMETSファイルの内容を可視化するPythonライブラリを作成しました。 例えば以下のように、AIPの作成過程で行われた処理(premis:event)の集計結果などを可視化します。 背景 以下の記事で、ArchivematicaのMETSファイルを人間に優しい方法で探索するためのウェブアプリケーションであるMETSFlaskを紹介しました。 今回作成したものは、このMETSFlaskで提供されている機能を、Flask以外からも利用しやすいようにライブラリ化したものです。 リポジトリ 以下で公開しています。README.mdファイルに使用方法を記載しています。 https://github.com/nakamura196/mets_tools GitHub Pagesでもドキュメントを公開しています。 https://nakamura196.github.io/mets_tools/ まとめ ArchivematicaおよびAIPの利用にあたり、参考になりましたら幸いです。

画像ファイルに対してGoogle Cloud Visionを適用して、IIIFマニフェストおよびTEI/XMLファイルを作成する

画像ファイルに対してGoogle Cloud Visionを適用して、IIIFマニフェストおよびTEI/XMLファイルを作成する

概要 画像ファイルに対してGoogle Cloud Visionを適用して、IIIFマニフェストおよびTEI/XMLファイルを作成するライブラリを作成しました。 https://github.com/nakamura196/iiif_tei_py 本ライブラリの使用方法を説明します。 使用方法 以下で使い方などを確認できます。 https://nakamura196.github.io/iiif_tei_py/ ライブラリのインストール GitHubのリポジトリから、ライブラリをインストールします。 pip install https://github.com/nakamura196/iiif_tei_py GCのサービスアカウントの作成 以下の記事などを参考に、GC(Google Cloud)のサービスアカウントキー(JSONファイル)をダウンロードします。 https://book.st-hakky.com/data-science/data-science-gcp-vision-api-setting/ そして、以下のような.envファイルを作成します。 GOOGLE_APPLICATION_CREDENTIALS=your-google-credentials.json 実行 入力サンプル画像として、IIIF Cookbookでも使用されている以下の画像を使用します。 https://iiif.io/api/presentation/2.1/example/fixtures/resources/page1-full.png 以下のようなファイルを作成して実行します。 from iiif_tei_py.core import CoreClient cred_path = CoreClient.load_env() url = "https://iiif.io/api/presentation/2.1/example/fixtures/resources/page1-full.png" output_tei_xml_file_path = "./tmp/01/output.xml" CoreClient.create_tei_xml_with_gocr(url, output_tei_xml_file_path, cred_path, title="Sample") 上記の例では、IIIFマニフェストファイルが./tmp/01/output.jsonに、TEI/XMLファイルが./tmp/01/output.xmlに作成されます。 結果の確認 IIIF IIIFマニフェストファイルをMiradorで表示した例が以下です。 JSONファイルの内容は以下です。 { "@context": "http://iiif.io/api/presentation/3/context.json", "id": "http://example.org/iiif/abc/manifest", "label": { "none": [ "Sample" ] }, "type": "Manifest", "items": [ { "id": "http://example.org/iiif/abc/canvas/p1", "type": "Canvas", "label": { "none": [ "[1]" ] }, "height": 1800, "width": 1200, "items": [ { "id": "http://example.org/iiif/abc/annotation/p0001-image", "type": "AnnotationPage", "items": [ { "body": { "id": "https://iiif.io/api/presentation/2.1/example/fixtures/resources/page1-full.png", "type": "Image", "format": "image/jpeg", "height": 1800, "width": 1200 }, "id": "http://example.org/iiif/abc/annotation/p0001-image/anno", "type": "Annotation", "motivation": "painting", "target": "http://example.org/iiif/abc/canvas/p1" } ] } ], "annotations": [ { "id": "http://example.org/iiif/abc/canvas/p1/curation", "type": "AnnotationPage", "items": [ { "body": { "type": "TextualBody", "value": "[00001] Top", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=245/69/94/52", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=245,69,94,52" }, { "body": { "type": "TextualBody", "value": "[00002] of", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=355/69/49/52", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=355,69,49,52" }, { "body": { "type": "TextualBody", "value": "[00003] First", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=420/69/112/54", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=420,69,112,54" }, { "body": { "type": "TextualBody", "value": "[00004] Page", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=547/70/134/53", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=547,70,134,53" }, { "body": { "type": "TextualBody", "value": "[00005] to", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=697/71/50/52", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=697,71,50,52" }, { "body": { "type": "TextualBody", "value": "[00006] Display", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=763/71/189/54", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=763,71,189,54" }, { "body": { "type": "TextualBody", "value": "[00007] Middle", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=296/593/163/164", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=296,593,163,164" }, { "body": { "type": "TextualBody", "value": "[00008] of", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=433/733/76/76", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=433,733,76,76" }, { "body": { "type": "TextualBody", "value": "[00009] First", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=484/786/123/124", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=484,786,123,124" }, { "body": { "type": "TextualBody", "value": "[00010] Page", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=584/889/128/129", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=584,889,128,129" }, { "body": { "type": "TextualBody", "value": "[00011] on", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=691/998/80/80", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=691,998,80,80" }, { "body": { "type": "TextualBody", "value": "[00012] Angle", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=749/1057/148/149", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=749,1057,148,149" }, { "body": { "type": "TextualBody", "value": "[00013] Bottom", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=203/1686/175/55", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=203,1686,175,55" }, { "body": { "type": "TextualBody", "value": "[00014] of", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=398/1689/51/53", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=398,1689,51,53" }, { "body": { "type": "TextualBody", "value": "[00015] First", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=466/1689/109/54", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=466,1689,109,54" }, { "body": { "type": "TextualBody", "value": "[00016] Page", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=593/1690/130/54", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=593,1690,130,54" }, { "body": { "type": "TextualBody", "value": "[00017] to", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=740/1692/51/54", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=740,1692,51,54" }, { "body": { "type": "TextualBody", "value": "[00018] Display", "format": "text/plain" }, "id": "http://example.org/iiif/abc/canvas/p1#xywh=808/1693/190/54", "type": "Annotation", "motivation": "commenting", "target": "http://example.org/iiif/abc/canvas/p1#xywh=808,1693,190,54" } ] } ] } ] } TEI また、TEI/XMLファイルをOxygen XML Editorで表示した例が以下です。 ...

concurrent.futures.process.BrokenProcessPoolへの対処

concurrent.futures.process.BrokenProcessPoolへの対処

概要 nbdevで、nbdev_prepareを実行した際、以下のエラーが発生しました。 concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending. 対処法 以下を事前に実行することで、エラーを回避できました。 export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES まとめ 同様の事象でお困りの方の参考になりましたら幸いです。

macOSでnbdev使用時のエラー対応

macOSでnbdev使用時のエラー対応

概要 macOSでnbdevを使用した際、以下のエラーが発生しました。 nbdev_prepare objc[48348]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called. objc[48348]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug. Traceback (most recent call last): ... concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending. このエラーへの対応に関する備忘録です。 ...

PyPIでtwo factor auth enabled...への対応

PyPIでtwo factor auth enabled...への対応

概要 PyPIで2要素認証が義務化されます。 https://blog.pypi.org/posts/2023-05-25-securing-pypi-with-2fa/ そのため2要素認証の設定を行った上でアップロードを試みたところ、以下のエラーが生じました。 Uploading xxxx.whl 100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 22.2/22.2 kB • 00:00 • 65.2 MB/s WARNING Error during upload. Retry with the --verbose option for more details. ERROR HTTPError: 401 Unauthorized from https://upload.pypi.org/legacy/ User <アカウント名> has two factor auth enabled, an API Token or Trusted Publisher must be used to upload in place of password. 対策 ~/.pypircを以下のように設定していました。 [pypi] username = <アカウント名> password = <パスワード> これを以下のように変更することでエラーが解消しました。APIトークンはPyPIのアカウント設定画面で作成することができました。 [pypi] username = __token__ password = <発行したAPIトークン> まとめ 私の場合、nbdevを使用していた際、以下で説明されている方法から変更する必要がありました。 https://nbdev.fast.ai/tutorials/tutorial.html#upload-to-pypi nbdevの利用に限らず、同様のことでお困りの方の参考になりましたら幸いです。 ...

nbdevを使用する際の備忘録

nbdevを使用する際の備忘録

概要 Pythonでパッケージを作成する際、nbdevを使用しています。 https://nbdev.fast.ai/ nbdevは以下のように説明されています。 Write, test, document, and distribute software packages and technical articles — all in one place, your notebook. (機械翻訳) ソフトウェア パッケージや技術記事の作成、テスト、文書化、配布をすべて 1 か所のノートブックで行います。 本記事では、nbdevを使用する際の備忘録です。 インストール 以下のチュートリアルのページが参考になります。 https://nbdev.fast.ai/tutorials/tutorial.html 以下、かいつまんで流れを説明します。 関連するツールをインストールした後、GitHubリポジトリを作成し、クローンした先で以下を実行します。 nbdev_new その後、以下も実行しておきます。 nbdev_install_hooks そしてnbsフォルダの中の00_core.ipynbなどを編集して、本ノートブックの最後のセルにある以下を実行します。 import nbdev; nbdev.nbdev_export() その結果、Pythonモジュールが自動的に作成されます。 パッケージをインストールする 同一フォルダ内 以下を実行します。 pip install -e '.[dev]' 別のフォルダから 一例ですが、絶対パスを指定してインストールします。 例: /Users/hogehoge/tei_xml_tools の場合 pip install -e /Users/hogehoge/tei_xml_tools -eオプションを付けることで、開発中にパッケージに加えられた変更をすぐに使用できます。 ライブラリの使用 以下のように%を使用することで、開発中の内容を反映することができました。 # %load_ext autoreload %reload_ext autoreload %autoreload 2 from tei_xml_tools.core import * まとめ その他、ドキュメントのプレビューやpypiにアップロードを行うためのコマンドも提供されています。機会があれば、nbdevの使い方全般についても記事にしたいと思います。

Omeka SのREST APIとやりとりするためのPythonパッケージ

Omeka SのREST APIとやりとりするためのPythonパッケージ

概要 Omeka SのREST APIをPythonから操作可能なパッケージが開発されています。 https://github.com/wragge/omeka_s_tools さらに、上記のリポジトリをベースとして、いくつかの機能追加を行なったリポジトリを作成しています。 https://github.com/nakamura196/omeka_s_tools2 本稿では、このリポジトリについて紹介します。 使い方 以下のページを参考にしてください。 https://nakamura196.github.io/omeka_s_tools2/ 本リポジトリはnbdevを用いて開発されており、パッケージの開発とドキュメンテーションを並行して行うことができ、便利な仕組みだと感じました。 追加開発した機能 IIIF画像URLの登録機能 Omeka SではIIIF画像URLの登録機能がありますが、本モジュールではこの登録機能が未実装でした。以下のように、IIIF画像URLの登録を行うメソッドを追加しました。 https://nakamura196.github.io/omeka_s_tools2/api.html#omekaapiclient.add_iiif_to_item アイテムセットの追加機能 本モジュールではアイテムセットの登録機能が未実装でした。以下のように、アイテムセットの登録を行うメソッドを追加しました。 https://nakamura196.github.io/omeka_s_tools2/api.html#adding-item-sets まとめ 今後追加開発していく機能については、いずれ本家のリポジトリに統合できればと考えています。 また今回開発した機能の使用例について、別の記事で紹介したいと思います。 具体的には、IIIFマニフェストファイルを入力データとして、そこに含まれる画像データを本モジュールを用いてOmeka Sに機械的に登録し、さらにScriptoを用いることで、それらの画像データに対する翻刻環境を作成する、といったことが可能になります。