(機械翻訳)The TEI Archive

以下の「The TEI Archive」ページの機械翻訳結果です。 https://tei-c.org/Vault/ テキスト・エンコーディング・イニシアティブ (TEI) TEIアーカイブ 目次 ポキプシー原則 スポンサー団体 1. TEI委員会ドキュメント 1987-1998 TEI諮問委員会 分析解釈委員会 編集論文 メタ言語と構文問題委員会 指導委員会 技術審査委員会 テキスト文書化委員会 テキスト表現委員会 2. ガイドラインの以前のバージョン 3. 番号なしの報告書、記事、発表等 4. 歌、写真、その他のエフェメラ TEI Titeドキュメント 活動を終了したワーキンググループ エレクトロニック・テキスト・エディティングの予備稿(MLA、2006年) 利用可能なすべてのP5リリース このページには、テキスト・エンコーディング・イニシアティブからのアーカイブ資料が含まれています。1988年のポキプシー会議から1999年にTEIコンソーシアムの設立プロセスが始まるまでの初期10年間にわたり、さまざまなサーバーや個人のコレクションから断片的に集められたものですが、その大部分はウェンディ・プロトキンがシカゴで維持していた優れたリストサーブ・アーカイブから派生しています。 ここに保存されている資料が何らかの形で完全であると主張するものではありませんが、TEIの歴史を構成する主要な資料を追跡し、ここに保存する努力をしています。ここで利用できないオリジナルのTEI文書をお持ちの方や、お持ちの方を知っている場合は、ご連絡ください: webmaster AT tei-c DOT org。 1987年から1998年のアーカイブ部分は、TEIのオリジナルのワーキング委員会構造を反映しています。文書はTEI文書番号でリストされており、これはマイケル・スパーグ・マックイーンによって初期に考案された索引方式で、文書を起源(委員会またはワーキンググループを示す2〜3文字のコード)とタイプ(Mは議事録、Wは作業文書、Pは提案等)によってグループ分けします。番号は(通常)各プレフィックス内で時系列に割り当てられます。 現在制作中または現在活動中の文書はここには含まれておらず、TEIホームページからリンクされています。 注: このエリアは以前「TEI Vault」と呼ばれていたため、URLがそうなっています。他の場所でVaultに言及しているのを見かけた場合、それはこのアーカイブスペースを指しています。 TEIホーム | フィードバック

2024年5月5日 · 1 分 · Nakamura

デジタルアーカイブ関連ツールの試作: 主にIIIFの利用支援

概要 「デジタルアーカイブ関連ツール」を作成しました。主にIIIF(International Image Interoperability Framework)の利用に関する支援機能を提供します。 https://nakamura196.github.io/viewer/ 機能1: Mirador 3 による画像比較 https://nakamura196.github.io/viewer/input 以下のように、比較したいマニフェストファイルのURLとカンバスのIDを指定します。 結果、以下のように画像を比較することができます。 機能2: コマ数の指定ツール ! IIIF Presentation APIのVersion 2にのみ対応しています。 https://nakamura196.github.io/viewer/canvas いくつかのIIIF対応のビューアでは、manifest引数にマニフェストファイルのURL、canvas引数にカンバスのIDを指定することで、表示するコマ数を指定することができます。 ただし、このカンバスのIDを知るにはマニフェストファイルの中身を確認する必要があり、面倒なことがあります。そこで本機能では、コマ数を指定することで、このカンバスIDを自動的に補完する機能を提供します。 コマ数を指定して「URLを生成」を押すと、カンバスIDが指定されたURLが表示されます。 すべてのビューアに対応していない点に注意が必要ですが、同様のことでお困りの方の参考になりましたら幸いです。 まとめ 参考になりましたら幸いです。

2024年5月2日 · 1 分 · Nakamura

Input value "page" contains a non-scalar value.への対処

概要 以下の記事で、同エラーへの対応を行いました。 ただし、上記の対応を行なっても、エラーを解決することができないケースがありましたので、追加の対応を記載します。 エラーの内容 エラーの内容は以下です。特に、jsonapi_search_api_facetsを有効化した際に発生しました。 { "jsonapi": { "version": "1.0", "meta": { "links": { "self": { "href": "http://jsonapi.org/format/1.0/" } } } }, "errors": [ { "title": "Bad Request", "status": "400", "detail": "Input value \"page\" contains a non-scalar value.", "links": { "via": { "href": "http://localhost:61117/web/jsonapi/index/document?page%5Blimit%5D=24&sort=field_id" }, "info": { "href": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1" } }, "source": { "file": "/app/vendor/symfony/http-kernel/HttpKernel.php", "line": 83 }, "meta": { "exception": "Symfony\\Component\\HttpFoundation\\Exception\\BadRequestException: Input value \"page\" contains a non-scalar value. in /app/vendor/symfony/http-foundation/InputBag.php:38\nStack trace:\n#0 /app/web/modules/contrib/facets/src/Plugin/facets/url_processor/QueryString.php(92): Symfony\\Component\\HttpFoundation\\InputBag->get('page')\n#1 /app/web/modules/contrib/facets/src/Plugin/facets/processor/UrlProcessorHandler.php(76): Drupal\\facets\\Plugin\\facets\\url_processor\\QueryString->buildUrls(Object(Drupal\\facets\\Entity\\Facet), Array)\n#2 /app/web/modules/contrib/facets/src/FacetManager/DefaultFacetManager.php(339): ... 対応 そこで、上記で言及されている以下のファイルについて、buildUrlsを修正しました。 <?php namespace Drupal\facets\Plugin\facets\url_processor; use Drupal\Core\Cache\UnchangingCacheableDependencyTrait; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\EventSubscriber\MainContentViewSubscriber; use Drupal\facets\Event\ActiveFiltersParsed; use Drupal\facets\Event\QueryStringCreated; use Drupal\facets\Event\UrlCreated; use Drupal\facets\FacetInterface; use Drupal\facets\UrlProcessor\UrlProcessorPluginBase; use Drupal\facets\Utility\FacetsUrlGenerator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Drupal\jsonapi\Query\OffsetPage; // 追加 /** * Query string URL processor. * * @FacetsUrlProcessor( * id = "query_string", * label = @Translation("Query string"), * description = @Translation("Query string is the default Facets URL processor, and uses GET parameters, for example ?f[0]=brand:drupal&f[1]=color:blue") * ) */ class QueryString extends UrlProcessorPluginBase { ... /** * {@inheritdoc} */ public function buildUrls(FacetInterface $facet, array $results) { // No results are found for this facet, so don't try to create urls. if (empty($results)) { return []; } // First get the current list of get parameters. $get_params = $this->request->query; // When adding/removing a filter the number of pages may have changed, // possibly resulting in an invalid page parameter. /* // コメントアウト if ($get_params->has('page')) { $current_page = $get_params->get('page'); $get_params->remove('page'); } */ // 追加 if ($get_params->has(OffsetPage::KEY_NAME)) { $page_params = $get_params->all(OffsetPage::KEY_NAME); unset($page_params[OffsetPage::OFFSET_KEY]); $get_params->set(OffsetPage::KEY_NAME, $page_params); } 上記の修正は、以下のファイルを参考に、Drupal\jsonapi\Query\OffsetPageを追加して、pageの処理を修正しました。 ...

2024年4月30日 · 2 分 · Nakamura

AWS CLIを使用したS3バケットの一括削除

AWS CLIを使用してS3バケットの一覧を取得し、特定のパターンに基づいてバケットを削除するには、以下の手順を実行できます。ここでは、wbyという文字列で始まるバケットを削除する方法について説明します。 必要なもの AWS CLIがインストールされていること。 適切なAWSの認証情報とアクセス権限が設定されていること。 ステップ 1: バケットの一覧を取得 まず、インストールされているAWS CLIを使用して、すべてのS3バケットの一覧を取得します。 aws s3 ls ステップ 2: 条件に一致するバケットの削除 wbyで始まるバケットを削除するには、シェルスクリプトを利用して条件に一致するバケットをフィルタリングし、それらを削除します。 以下のスクリプトは、wbyで始まるバケット名を検索し、各バケットを削除します。注意:このスクリプトはバケットとその中のすべてのオブジェクトを削除します。実行前にデータのバックアップを確認してください。 aws s3 ls | awk '{print $3}' | grep '^wby' | while read bucket do echo "Deleting bucket $bucket..." aws s3 rb s3://$bucket --force done このスクリプトは次のことを行います: aws s3 lsでバケット一覧を取得。 awk '{print $3}'でバケット名のみを抽出。 grep '^wby'でwbyで始まるバケット名をフィルタリング。 while read bucketループで各バケットを削除。 注意 バケットを削除する前に、必要なデータがバックアップされていることを確認してください。 バケットが空でない場合、aws s3 rb --forceオプションを使用してバケットとその中のすべてのオブジェクトを削除します。 実行する前に、削除されるバケット名を確認するために、実際に削除するコマンドを実行する前にechoステートメントを挟むことをお勧めします。

2024年4月26日 · 1 分 · Nakamura

NDLTSR (NDL Table Structure Recognition)を試す

概要 NDLTSR (NDL Table Structure Recognition)は以下のように説明されています。 資料画像に含まれる表の構造を認識するプログラムを公開しています。 座標付きのOCRテキストデータと組み合わせることで表中に含まれるテキストデータを構造化する用途に利用できます。 参考(外部リンク):次世代デジタルライブラリーへの新機能(表の構造化)の追加及び新機能のソースコード及びデータセットの公開について 本プログラムにより、国立国会図書館が公開しているNDLTableSetを学習した機械学習モデルによる表構造の推論を行えるほか、LORE-TSR(外部リンク)と同様の方法により別途利用者が用意したデータセットによる再学習を行うことが可能です。 ノートブック 以下のノートブックを用意しました。 https://colab.research.google.com/github/nakamura196/000_tools/blob/main/NDLTSR.ipynb 以下のように、「ランタイム」 > 「すべてのセルを実行」 からお試しいただけます。 結果 以下のような認識結果が出力されます。 参考 台湾総督府農業試験所 編『台湾総督府農業試験所彙報』第197号 甘藷の生育、収量並に品質に及ぼす懽漑の影響,台湾総督府農業試験所,昭和15-19. 国立国会図書館デジタルコレクション https://dl.ndl.go.jp/pid/1046122 (参照 2024-04-26) https://dl.ndl.go.jp/pid/1046122/1/1 注意 以下のように公式の説明がありますが、本プログラムで得られるのは表の構造情報のみである点にご注意ください。 本プログラムが推論できるのは、表の構造情報(各セルの矩形座標及びセル間の関係性を表す数値情報)であるので、プログラム単体でOCR処理プログラムとして利用することはできません。 次世代デジタルライブラリーの機能と同様の処理を行うためには、別途座標付きテキストデータを出力するOCR処理プログラムが必要です。 まとめ NDLTSR (NDL Table Structure Recognition)の試行にあたり、参考になりましたら幸いです。

2024年4月26日 · 1 分 · Nakamura

「SAT大蔵経DB 2018」で公開されているテキストの分析例

概要 「SAT大蔵経DB 2018」は以下のように説明されています。 https://21dzk.l.u-tokyo.ac.jp/SAT2018/master30.php このサイトは、SAT大蔵経テキストデータベース研究会が提供するデジタル研究環境の2018年版です。 SAT大蔵経テキストデータベース研究会は、2008年4月より、大正新脩大藏経テキスト部分85巻の全文検索サービスを提供するとともに、各地のWebサービスとの連携機能を提供することにより、利便性を高めるとともに、Webにおける人文学研究環境の可能性を追求してきました。 2018年版となるSAT2018では、近年広まりつつある機械学習の技術と、IIIFによる高精細画像との連携、高校生でもわかる現代日本語訳の公開及び本文との連携、といった新たなサービスに取り組んでみました。また、本文の漢字をUnicode10.0に対応させるとともに、すでに公開していたSAT大正蔵図像DBの機能の大部分も統合いたしました。ただし、今回は、コラボレーションを含む仕組みの提供という側面もあり、今後は、この輪組に沿ってデータを増やし、より利便性を高めていくことになります。 当研究会が提供するWebサービスは、さまざまな関係者が提供するサービスや支援に依拠しています。SAT2018で新たに盛り込んだサービスでは、機械学習及びIIIF対応に関しては一般財団法人人文情報学研究所、現代日本語訳の作成に関しては公益財団法人全日本仏教会の支援と全国の仏教研究者の方々のご協力をいただいております。 SAT2018が、仏教研究者のみなさまだけでなく、仏典に関心を持つ様々な方々のお役に立つことを願っております。さらに、ここで提示されている文化資料への技術の適用の仕方が、人文学研究における一つのモデルになることがあれば、なお幸いです。 今回は、上記のDBが公開するテキストデータを対象として、簡単な分析を試みます。 説明 以下の「T0220 大般若波羅蜜多經」のテキストを対象にします。 方法 テキストデータの取得 ネットワークを確認したところ、以下のようなURLでテキストデータを取得することができました。 https://21dzk.l.u-tokyo.ac.jp/SAT2018/satdb2018pre.php?mode=detail&ob=1&mode2=2&useid=0220_,05,0001 0220_,05,0001の部分について、05を06に変えると6巻のデータが取得できました。また、末尾の0001を0011に変更すると、0011の前後を含むテキストが取得できました。 この傾向を踏まえて、以下のようなプログラムを実行しました。 import os import requests import time from bs4 import BeautifulSoup def fetch_soup(url): """Fetches and parses HTML content from the given URL.""" time.sleep(1) # Sleep for 1 second before making a request response = requests.get(url) return BeautifulSoup(response.text, "html.parser") def write_html(soup, filepath): """Writes the prettified HTML content to a file.""" with open(filepath, "w") as file: file.write(soup.prettify()) def read_html(filepath): """Reads HTML content from a file and returns its parsed content.""" with open(filepath, "r") as file: return BeautifulSoup(file.read(), "html.parser") def process_volume(vol): """Processes each volume by iterating over pages until no new page is found.""" page_str = "0001" while True: url = f"https://21dzk.l.u-tokyo.ac.jp/SAT2018/satdb2018pre.php?mode=detail&ob=1&mode2=2&useid=0220_{vol}_{page_str}" id = url.split("useid=")[1] opath = f"html/{id}.html" if os.path.exists(opath): soup = read_html(opath) else: soup = fetch_soup(url) write_html(soup, opath) new_page_str = get_last_page_id(soup) if new_page_str == page_str: break page_str = new_page_str def get_last_page_id(soup): """Extracts the last page ID from the soup object.""" spans = soup.find_all("span", class_="ln") if spans: last_id = spans[-1].text return last_id.split(".")[-1][0:4] return None def main(): vols = ["05", "06", "07"] for vol in vols: process_volume(vol) if __name__ == "__main__": main() 上記の処理により、HTMLファイルをダウンロードすることができます。 ...

2024年4月25日 · 3 分 · Nakamura

Node.jsでXML文字列をパースする

概要 Node.jsでXML文字列を解析し、その中から情報を抽出するための関数を完成させるには、xmldom ライブラリの使用をお勧めします。これにより、ブラウザでDOMを操作するような方法でXMLを扱うことができます。以下に、xmldom を使ってXMLを解析し、“PAGE” タグに焦点を当てて要素を抽出するための関数の設定方法を示します。 xmldom ライブラリをインストールする: まず、XML文字列を解析するために必要な xmldom をインストールしてください。 npm install xmldom xmldom を使用してXMLを解析し、必要な要素を抽出します。 const { DOMParser } = require('xmldom'); const xmlString = "..."; // DOMParserを使用してXML文字列を解析 const parser = new DOMParser(); const xmlDoc = parser.parseFromString(xmlString, 'text/xml'); // 全てのPAGE要素を取得 const pages = xmlDoc.getElementsByTagName('PAGE'); // 発見されたPAGE要素の数をログに記録(例) console.log('PAGE要素の数:', pages.length); この例では、XML文字列をログに記録し、文書に解析し、各 “PAGE” 要素を繰り返し処理して属性や内容をログに記録する基本的な関数を設定します。ループ内の処理は、各ページから特定の詳細を抽出するなど、具体的な要件に基づいてカスタマイズできます。

2024年4月24日 · 1 分 · Nakamura

researchmapで論文等にリンクを貼る

概要 researchmapで論文等にリンクを貼る方法です。 それぞれのアイテムの編集画面において、「より詳しい情報の入力」リンクをクリックします。 以下のようにURLなどの入力フォームが追加で表示されます。 researchmapの利用にあたり、参考になりましたら幸いです。

2024年4月24日 · 1 分 · Nakamura

LlamaIndex+GPT4+gradio

概要 LlamaIndexとGPT4、gradioを組み合わせて使う機会がありましたので、備忘録です。 使用したテキストのサイズが小さいので、結果もそれなりですが、渋沢栄一のチャットボットを試作しました。 背景 以下の記事を参考にしました。 https://qiita.com/DeepTama/items/1a44ddf6325c2b2cd030 上記をもとに、2024年4月20日時点のライブラリで動作するように修正しています。ノートブックを以下で公開しています。 https://github.com/nakamura196/000_tools/blob/main/LlamaIndex%2BGPT4%2Bgradio.ipynb 以下のデータを使用しています。 TEIを用いた『渋沢栄一伝記資料』テキストデータの再構築と活用 まとめ 参考になりましたら幸いです。

2024年4月20日 · 1 分 · Nakamura

Editor.jsでインラインのマーカーツールで作成する

概要 Editor.jsでインラインのマーカーツールを作成する方法の備忘録です。 参考 以下のページが参考になりました。 https://editorjs.io/creating-an-inline-tool/ https://note.com/eveningmoon_lab/n/n638b9541c47c TypeScriptでの記述にあたっては、以下が参考になりました。 https://github.com/codex-team/editor.js/issues/900 実装 Nuxtで実装します。以下のmarker.tsを作成します。 import type { API } from "@editorjs/editorjs"; class MarkerTool { button: null | HTMLButtonElement; state: boolean; api: API; tag: string; class: string; // 静的メソッドで許可されるHTMLタグと属性を指定 static get sanitize() { return { mark: { class: "cdx-marker", }, }; } // インラインツールとしての振る舞いを定義 static get isInline() { return true; } constructor({ api }: { api: API }) { this.api = api; this.button = null; this.state = false; this.tag = "MARK"; this.class = "cdx-marker"; } // ボタン要素を作成し、SVGアイコンを設定 render() { this.button = document.createElement("button"); this.button.type = "button"; this.button.innerHTML = '<svg width="20" height="18"><path d="M10.458 12.04l2.919 1.686-.781 1.417-.984-.03-.974 1.687H8.674l1.49-2.583-.508-.775.802-1.401zm.546-.952l3.624-6.327a1.597 1.597 0 0 1 2.182-.59 1.632 1.632 0 0 1 .615 2.201l-3.519 6.391-2.902-1.675zm-7.73 3.467h3.465a1.123 1.123 0 1 1 0 2.247H3.273a1.123 1.123 0 1 1 0-2.247z"/></svg>'; this.button.classList.add(this.api.styles.inlineToolButton); return this.button; } // 選択されたテキストを <mark> タグで囲む surround(range: Range) { if (this.state) { this.unwrap(range); return; } this.wrap(range); } // テキストを <mark> タグでラップ wrap(range: Range) { const selectedText = range.extractContents(); const mark = document.createElement(this.tag); mark.className = this.class; // class 属性の追加 mark.appendChild(selectedText); range.insertNode(mark); this.api.selection.expandToTag(mark); } // <mark> タグを解除 unwrap(range: Range) { const mark = this.api.selection.findParentTag(this.tag); const text = range.extractContents(); mark?.remove(); range.insertNode(text); } // ツールの状態をチェック checkState() { const mark = this.api.selection.findParentTag(this.tag, this.class); this.state = !!mark; if (this.state) { this.button?.classList.add("cdx-marker--active"); } else { this.button?.classList.remove("cdx-marker--active"); } } } export default MarkerTool; 上記を以下のように呼び出します。 ...

2024年4月19日 · 2 分 · Nakamura

Editor.jsのmax-widthを変更する

概要 Editor.jsを使用する際、デフォルトでは左右に大きなマージンができます。これを解決する方法を紹介します。 方法 以下が参考になりました。 https://github.com/codex-team/editor.js/issues/1328 具体的には、以下を追加します。 .ce-block__content, .ce-toolbar__content { max-width: calc(100% - 80px) !important; } .cdx-block { max-width: 100% !important; } ソースコード全体は以下です。 <script setup lang="ts"> import EditorJS from "@editorjs/editorjs"; import type { OutputData } from "@editorjs/editorjs"; const blocks = ref<OutputData>({ time: new Date().getTime(), blocks: [ { type: "paragraph", data: { text: "大明副使蒋 承奉すらく 、 欽差督察総制提督浙江等処軍務各衙門 、近年以来、日本各島小民、仮るに買売を以て名と為し 、 しばしば中国辺境を犯し、居民を刼掠するを因となし、旨を奉じて 、 浙江等処承宣布政使司 に議行し、本職に転行して 、 親しく貴国に詣り面議せしめん等の因あり。", }, }, ], }); const editor = () => { new EditorJS({ holder: "editorjs", data: blocks.value, onChange: async (api) => { blocks.value = await api.saver.save(); }, }); }; editor(); </script> <template> <div style="background-color: aliceblue"> <div id="editorjs"></div> <hljson :content="blocks" /> </div> </template> <style> .ce-block__content, .ce-toolbar__content { max-width: calc(100% - 80px) !important; } .cdx-block { max-width: 100% !important; } pre { background-color: #f4f4f4; border: 1px solid #ccc; padding: 10px; } </style> 結果、以下のように、左右のマージンが小さくなりました。 ...

2024年4月18日 · 1 分 · Nakamura

Linuxシステムで特定のグループに所属しているユーザーを確認する

概要 ! ChatGPT 4による回答です。 Linuxシステムで特定のグループに所属しているユーザーを確認するには、いくつかの方法があります。ここでは、コマンドラインを使用して、特定のグループ(この場合は「group1」と「group2」)に所属するユーザーをリストする方法を説明します。 方法1: /etc/group ファイルを確認する Linuxでは、/etc/group ファイルにシステム上のすべてのグループとそれに所属するユーザーの情報が格納されています。このファイルを確認することで、特定のグループに含まれるユーザーを確認することができます。 コマンド: grep '^group1:' /etc/group grep '^group2:' /etc/group これらのコマンドは、group1 と group2 グループについての情報を /etc/group ファイルから検索し、出力します。出力例は以下のようになります: group1:x:1001:user1,user2 group2:x:1002:user3,user4 ここで、user1 と user2 は group1 グループのメンバーで、user3 と user4 は group2 グループのメンバーです。 方法2: getent コマンドを使用する getent コマンドを使用しても、グループに所属するユーザーを調べることができます。このコマンドは /etc/group ファイルから直接情報を取得します。 コマンド: getent group group1 getent group group2 出力は /etc/group を grep した時と同様のフォーマットです。 方法3: members コマンドを使用する members コマンドは、特定のグループに属するすべてのユーザーの名前をリストアップするために使われます。ただし、このコマンドはすべてのLinuxディストリビューションにはデフォルトでインストールされていないため、インストールが必要な場合があります。 コマンド: sudo apt install members # Debian系の場合 members group1 members group2 これらの方法を使用して、group1 および group2 グループに含まれるユーザーを確認できます。どの方法を選択するかは、使用しているシステムやインストールされているプログラムによります。 ...

2024年4月18日 · 1 分 · Nakamura

Bootstrap 5を用いたOmeka Sのテーマver 4.0.2をリリースしました。

概要 Bootstrap 5を用いたOmeka Sのテーマを更新しました。今回の更新で追加した機能などについて紹介します。 https://github.com/ldasjp8/Omeka-S-theme-Bootstrap5/releases/tag/4.0.2 新機能 詳細検索ボタンのリンク設定 テーマの設定画面に「Advanced Search URL」という項目を追加しました。 上記の例では、「page/advanced」というページに遷移する設定を行っています。 具体的には、以下の「詳細検索」のボタンをクリックした際に、ここで設定したURLに遷移します。(未設定の場合は、Omekaの通常の詳細検索のページに遷移します。) 以下の記事で、独自の検索ページを作成する方法を紹介しました。こちらと組み合わせて使用することで、独自の検索ページとの画面遷移を実現できます。 不具合の修正 ソート 以下のように、ソート項目が表示されない不具合がありました。 以下のように、$sortByとして使用していたものを、$sortConfigに変更する必要がありました。 https://github.com/ldasjp8/Omeka-S-theme-Bootstrap5/commit/5928a37fc4af1cb26ac0b6df13c25cf4f57eb66e#diff-2388527aaa944d338d7a5144cb4e49aa659702c2d628d12103e090f7cd6ed3bc Advanced Search Advanced Searchモジュールと組み合わせて使用した際、レイアウトが崩れる箇所がありました。まだ統一感が取れていない点がありますが、改善しました。 まとめ Omeka Sの利用にあたり、お役に立ちましたら幸いです。

2024年4月17日 · 1 分 · Nakamura

Omeka SのAdvanced Searchモジュールでの部分一致検索

概要 Advanced Searchモジュールを使って、追加したフィルタで部分一致検索を行う方法について説明します。 上記では、「とる」という文字列をクエリとして、タイトルが「abc タイトル」のアイテムがヒットしています。 背景 Advanced Searchモジュールを使用すると、検索条件やファセットなどを柔軟に設定することができます。 https://omeka.org/s/modules/AdvancedSearch/ 特に、「Reference」モジュールと組み合わせることで、以下のようなファセット検索を実現できます。 フィルタの追加もできます。ただし、フィルタを用いた部分一致検索を行う場合には、設定が必要です。 上記の例では、「とる」という文字列をクエリとした際、タイトルが「abc タイトル」のアイテムがヒットしていません。 設定方法 フィルタの追加は、以下の設定画面のFiltersで行います。(slugの部分は必要に応じて読み替えてください。) /admin/search-manager/config/1/configure 上記の例では、titleとsubjectをフィルタとして以下のように追加しています。 title = Title subject = Subject advanced = Filters = Advanced = このままでは、titleおよびsubjectに対する完全一致になります。 これに対して、以下のように、Textを追加します。 title = Title = Text subject = Subject advanced = Filters = Advanced = これにより、titleについては部分一致、subjectについては完全一致、を実現することができます。 まとめ Omeka SのAdvanced Searchモジュールの利用にあたり、参考になりましたら幸いです。

2024年4月17日 · 1 分 · Nakamura

Omeka Sの検索結果に表示する項目を指定する

概要 以下のように、検索結果に表示する項目を指定する方法について説明します。 設定 デフォルトの設定では、以下のように、「見出し」にタイトル(dcterms:title)、「Body」に説明文(dcterms:description)が表示されます。 これに対して、サイトごとの設定画面の以下の箇所を変更することにより、「見出し」「Body」それぞれに表示する項目を設定することができます。 Advanced Searchの場合 Advanced Searchモジュールを使用している場合でも、この設定は引き継がれます。 以下でソースコードを確認できます。 https://github.com/Daniel-KM/Omeka-S-module-AdvancedSearch/blob/master/view/search/resource-list.phtml browse_heading_property_termとbrowse_body_property_termの設定に基づき、表示項目が指定されています。 <?php ... $headingTerm = $setting('browse_heading_property_term'); $bodyTerm = $setting('browse_body_property_term'); ... ?> <?php if ($title): ?> <h3><?= $escape($title) ?></h3> <?php endif; ?> <ul class="resource-list search-results-list<?= $gridListMode === 'list_only' ? ' list' : ($gridListMode === 'grid_only' ? ' grid' : '') ?>"> <?php /** @var \Omeka\Api\Representation\AbstractResourceEntityRepresentation $resource */ foreach ($resources as $resource): ... $heading = $headingTerm ? $resource->value($headingTerm, ['lang' => $langValue]) : null; $heading = $heading ? $heading->asHtml() : $escape($resource->displayTitle($untitled, $lang)); $body = $bodyTerm ? $resource->value($bodyTerm, ['lang' => $langValue]) : null; $body = $body ? $body->asHtml() : $escape($resource->displayDescription(null, $lang)); ?> <li class="resource <?= $resourceType ?>"> <div class="resource-thumbnail"> <?= $hyperlink->raw($resourceThumbnail, $resourceUrl, ['class' => 'resource-link']) ?> </div> <div class="resource-metadata"> <h4><?= $resource->linkRaw($heading) ?></h4> <div class="description"> <?= $body ?> </div> </div> </li> <?php endforeach; ?> </ul> まとめ Omeka Sの検索結果に表示する項目の指定にあたり、参考になりましたら幸いです。 ...

2024年4月17日 · 1 分 · Nakamura

Omeka Sで独自の検索ページを作成する

概要 Omeka Sで以下のような独自の検索ページを作成する方法について紹介します。 背景 Omeka Sでの検索ページの作成にあたり、詳細検索画面で絞り込み項目を限定する方法を紹介しました。 一方、概要で紹介したように、指定した項目だけを列挙した検索画面を作成したい場合もあります。このような検索ページの作成にあたり、「Advanced Search」モジュールを使うことができます。 https://omeka.org/s/modules/AdvancedSearch/ 以下のページで使い方を説明しています。以下ではApache Solrとの連携を行っていますが、Referenceモジュールなどと組み合わせて、Omeka S単体で使用することもできます。 ただし、「Advanced Search」モジュールは機能が豊富なゆえに、使いこなすのが難しい面があります。そこで、今回は簡単に上記のようなカスタム検索ページを作成する方法について紹介します。 作成方法 具体的には、検索用の独自ページを作成します。 以下のように、特定のサイトで、ページを作成します。 「HTML」ブロックを追加します。 「ソース」ボタンをクリックして、以下のHTMLをコピペします。 <div id="dynamic-fields"></div> <button id="submit" class="btn btn-primary">検索</button> <script> const params = [ { label: "キーワード検索", type: "in", placeholder: "すべてのフィールドに対して検索します。", help: "部分一致", }, { label: "タイトル", property: 1, type: "in", help: "部分一致" }, { label: "資料番号", property: 10, type: "eq", help: "完全一致" }, { label: "主題", property: 3, type: "in", help: "部分一致" }, ]; // 以下はそのまま document.addEventListener("DOMContentLoaded", () => { initializeSearchForm(); setupFormSubmission(); }); function initializeSearchForm() { const container = document.getElementById("dynamic-fields"); params.forEach((param, index) => { container.appendChild(createFormGroup(param, index)); }); } function createFormGroup(param, index) { const formGroup = document.createElement("div"); formGroup.className = "form-group mb-4"; formGroup.appendChild(createLabel(param.label)); formGroup.appendChild( createInput( `property[${index}][text]`, "form-control", param.placeholder ) ); formGroup.appendChild(createHelpText(param.help)); formGroup.appendChild( createHiddenInput(`property[${index}][type]`, param.type) ); if (param.property) { formGroup.appendChild( createHiddenInput(`property[${index}][property][]`, param.property) ); } formGroup.appendChild( createHiddenInput(`property[${index}][joiner]`, "and") ); return formGroup; } function createLabel(text) { const label = document.createElement("label"); label.className = "mb-1"; label.textContent = text; return label; } function createInput(name, className, placeholder) { const input = document.createElement("input"); input.type = "text"; input.name = name; input.className = className; input.placeholder = placeholder || ""; // set value const urlParams = new URLSearchParams(window.location.search); const value = urlParams.get(name); if (value) { input.value = value; } return input; } function createHelpText(text) { const small = document.createElement("small"); small.className = "form-text text-muted"; small.textContent = text; return small; } function createHiddenInput(name, value) { const input = document.createElement("input"); input.type = "hidden"; input.name = name; input.value = value; return input; } function setupFormSubmission() { document.getElementById("submit").addEventListener("click", () => { const form = document.createElement("form"); form.method = "GET"; form.action = "../item"; form.style.display = "none"; Array.from( document.querySelectorAll("#dynamic-fields input") ).forEach((input) => { form.appendChild(input.cloneNode(true)); }); document.body.appendChild(form); form.submit(); }); } </script> 結果、以下のように、ボタンのみが表示されます。 ...

2024年4月17日 · 2 分 · Nakamura

学習指導要領コード推薦アプリのAPIを使用する

概要 以下の記事で、学習指導要領コードの推薦アプリについて紹介しました。 今回は、GradioのAPIを使って、上記の推薦アプリを使用する方法について紹介します。 使い方 ライブラリをインストールします。 pip install gradio_client 例えば、以下のデータを使用してみます。 テキスト 学校種別 空気鉄砲や水鉄砲、ペットボトルロケットなどのしくみを調べ、空気はおし縮められ体積が小さくなるにつれて反発する力が大きくなるが、水はおし縮められないことに気づく。 小学校 JSONデータは実行結果の配列の2つ目の要素に格納されているため、result[1]で取得します。 from gradio_client import Client client = Client("nakamura196/jp-cos") result = client.predict( text="空気鉄砲や水鉄砲、ペットボトルロケットなどのしくみを調べ、空気はおし縮められ体積が小さくなるにつれて反発する力が大きくなるが、水はおし縮められないことに気づく。", courseOfStudy=["小学校"], api_name="/predict" ) json_data = result[1] 結果、以下のようなJSONデータが得られます。 [{'dcterms:identifier': '8260243111200000', 'jp-cos:courseOfStudy': '小学校', 'jp-cos:subjectArea': '理科', 'score': 0.215, 'jp-cos:sectionText': '閉じ込めた空気は圧《お》し縮められるが,水は圧《お》し縮められないこと。'}, {'dcterms:identifier': '8260243111100000', 'jp-cos:courseOfStudy': '小学校', 'jp-cos:subjectArea': '理科', 'score': 0.236, 'jp-cos:sectionText': '閉じ込めた空気を圧《お》すと,体積は小さくなるが,圧《お》し返す力は大きくなること。'}, {'dcterms:identifier': '8260243112000000', 'jp-cos:courseOfStudy': '小学校', 'jp-cos:subjectArea': '理科', 'score': 0.246, 'jp-cos:sectionText': '空気と水の性質について追究する中で,既習の内容や生活経験を基に,空気と水の体積や圧《お》し返す力の変化と圧《お》す力との関係について,根拠のある予想や仮説を発想し,表現すること。'}, {'dcterms:identifier': '8260243110000000', 'jp-cos:courseOfStudy': '小学校', 'jp-cos:subjectArea': '理科', 'score': 0.255, 'jp-cos:sectionText': '空気と水の性質 空気と水の性質について,体積や圧《お》し返す力の変化に着目して,それらと圧《お》す力とを関係付けて調べる活動を通して,次の事項を身に付けることができるよう指導する。'}] 発展 より詳細な使用方法について、フッター部分の「Use via API」から確認することができます。 パラメータや返却される値について説明されています。 まとめ 参考になりましたら幸いです。

2024年4月16日 · 1 分 · Nakamura

学習指導要領コードの推薦アプリの試作

概要 学習指導要領コードの推薦アプリを作成しましたので、その紹介です。以下のhuggingfaceのspaceでお試しいただけます。学習指導要領LODを利用しました。 https://huggingface.co/spaces/nakamura196/jp-cos 使い方 テキストフォームに任意のテキストを入力します。「学校種別」は任意項目です。 結果が画面右側に表示されます。 サンプルも用意していますので、お試しください。NHK for Schoolの情報を利用しています。 仕組み 以下の記事を参考に、学習指導要領のテキストをベクトル化し、同様にベクトル化した質問文と類似する学習指導要領を返却します。 https://zenn.dev/yumefuku/articles/llm-langchain-rag 上記の記事の通り、ベクトル検索ライブラリには「FAISS」、埋め込みモデルには「multilingual-e5-large」を使用しています。 https://huggingface.co/intfloat/multilingual-e5-large 推論部分のソースコードは以下でご確認いただけます。 https://huggingface.co/spaces/nakamura196/jp-cos/blob/main/app.py 工夫点 「学校種別」などを用いたフィルタリング 「学校種別」が指定された場合、langchainのFAISS.similarity_search_with_scoreによる類似度検索において、フィルタリングを行っています。 具体的には、以下のfilterを用いています。 metadata = {} if grade: metadata["学校種別"] = grade try: docs_and_scores = index.similarity_search_with_score(input_text, filter=metadata) except Exception as e: print(f"Error during search: {e}") return [] 今後 「教科等」による絞り込み 「学校種別」による絞り込みに加えて、「教科等(理科、社会、数学など)」も追加予定です。 推薦精度の評価 学習指導要領コードがすでに付与されているNHK for Schoolのコンテンツを対象に、推薦精度の評価を行う予定です。 「学校種別」の追加 現在は、以下の7つの学校種別のみを使用しています。他の学習指導要領も今後追加予定です。 UpperSecondary/2018 UpperSecondaryDeptSNES/2019 Elementary/2017 ElementaryAndLowerSecondaryDeptSNES/2017 LowerSecondary/2017 Kindergarten/2017 KindergartenDeptSNES/2017 まとめ 学習指導要領LODの開発者の方々に感謝いたします。 ...

2024年4月16日 · 1 分 · Nakamura

researchmapのapiを使う

概要 researchmapのapiを使って、業績リストを作成する機会がありましたので、備忘録です。 researchmapのapiに対するクエリ例 researchmapのapiに対するクエリ例をいくつか紹介します。 論文の一覧を取得する https://api.researchmap.jp/nakamura.satoru/published_papers 上限を指定する(limitの使用) https://api.researchmap.jp/nakamura.satoru/published_papers?limit=5 x件以降の結果を取得する(startの使用) https://api.researchmap.jp/nakamura.satoru/published_papers?limit=5&start=6 出版年月日を指定する(from_dateとto_date) https://api.researchmap.jp/nakamura.satoru/published_papers?from_date=2023-04-01&to_date=2024-03-31 Pythonでの使用例 指定したユーザと出版年月日に基づき、published_papersとpresentationsをExcelに書き出します。 #| export import requests import pandas as pd import os class Client: def __init__(self, slug, date_start, date_end): self.slug = slug self.date_start = date_start self.date_end = date_end self.output_dir = f"data/{self.slug}/{self.date_start}_{self.date_end}" os.makedirs(self.output_dir, exist_ok=True) @staticmethod def main(slug, date_start, date_end): client = Client(slug, date_start, date_end) client.process_data() def process_data(self): self.df_paper = self.fetch_data('published_papers', self.paper_processing_logic) self.df_presentation = self.fetch_data('presentations', self.presentation_processing_logic) self.write_to_excel() def fetch_data(self, data_type, processing_function): url = f"https://api.researchmap.jp/{self.slug}/{data_type}" params = { "limit": 100, "start": 0, "from_date": self.date_start, "to_date": self.date_end, } response = requests.get(url, params=params) if response.status_code == 200: data = response.json().get("items", []) return processing_function(data) else: raise Exception(f"Error fetching {data_type}: {response.status_code}") def paper_processing_logic(self, papers): rows = [] for item in papers: rows.append(self.process_paper_item(item)) return pd.DataFrame(rows) def process_paper_item(self, item): author_list = [auth["name"] for auth in item.get('authors', {}).get("ja", [])] c1 = '''1.掲載論文のDOI (デジタルオブジェクト識別子)''' c2 = '''2.著者名''' c3 = '''3.論文標題''' c4 = '''4.雑誌名''' c5 = '''5.巻 (半角数字)''' c6 = '''6.発行年 (半角数字)''' c7 = '''7.最初と最後の頁 (半角数字)''' c8 = '''8.査読の有無 (1:有 0:無)''' c9 = '''9.国際共著 (1:有 0:無)''' c10 = '''10.オープンアクセス (1:有 0:無)''' return { c1: item.get('identifiers', {}).get('doi', [None])[0], c2: ", ".join(author_list), c3: item.get('paper_title', {}).get('ja', ''), c4: item.get('publication_name', {}).get('ja', ''), c5: item.get('volume', None), c6: item['publication_date'][:4], c7: f"{item.get('starting_page', '')}-{item.get('ending_page', '')}", c8: 1 if item.get('referee', False) else 0, c9: 1 if item.get('is_international_collaboration', False) else 0, c10: 1 if item.get('rm:is_open_access', False) else 0 } def presentation_processing_logic(self, presentations): rows = [] for item in presentations: rows.append(self.process_presentation_item(item)) return pd.DataFrame(rows) def process_presentation_item(self, item): author_list = [auth["name"] for auth in item.get('presenters', {}).get("ja", [])] c1 = '''1.発表者名''' c2 = "2.発表標題" c3 = "3.学会等名" c4 = '''4.発表年(開始) (半角数字)''' c5 = '''5.発表年(終了) (半角数字)''' c6 = '''6.招待講演 (1:有 0:無)''' c7 = '''7.国際学会 (1:有 0:無)''' return { c1: ", ".join(author_list), c2: item.get('presentation_title', {}).get('ja', ''), c3: item.get('event', {}).get('ja', ''), c4: item['publication_date'][:4], c5: item['publication_date'][:4], c6: 1 if item.get('invited', False) else 0, c7: 1 if item.get('is_international_presentation', False) else 0 } def write_to_excel(self): with pd.ExcelWriter(f'{self.output_dir}/merged.xlsx', engine='openpyxl') as writer: self.df_paper.to_excel(writer, sheet_name='Papers', index=False) self.df_presentation.to_excel(writer, sheet_name='Presentations', index=False) self.df_paper.to_csv(f"{self.output_dir}/papers.csv", index=False) self.df_presentation.to_csv(f"{self.output_dir}/presentations.csv", index=False) 使用例は以下です。dataフォルダにcsvやexcelが出力されます。 ...

2024年4月15日 · 2 分 · Nakamura

学習指導要領LODを使う

概要 学習指導要領LODは以下のように説明されています。 学習指導要領LODは、文部科学省が公開している学習指導要領と教育要領の内容・コードおよび関連する情報をLinked Open Data (LOD) として公開します。LOD化の対象は、現在公開されている全ての学校種別の新旧学習指導要領と教育要領(一部改正を含む)コード表の最新版です。 https://jp-cos.github.io/ このデータセットを使う機会がありましたので、使い方に関する備忘録です。 SPARQLエンドポイントの構築 今回は、DYDRAを使用します。 https://dydra.com/ 以下が登録した結果です。 https://dydra.com/ut-digital-archives/jp-cos/ Snorqlの作成 SPARQLエンドポイントを使いやすくするため、Snorqlを用意しました。 https://sukilam-educational-metadata.github.io/etc/jp-cos/ 検索例 以下のクエリにより、「学習指導要領(jp-cos:CourseOfStudy)」毎の「細目(jp-cos:Item)」の数を把握することができます。 https://sukilam-educational-metadata.github.io/etc/jp-cos/?query=PREFIX+rdf%3A+<http%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23> PREFIX+jp-cos%3A+<https%3A%2F%2Fw3id.org%2Fjp-cos%2F> SELECT+%3FcourseOfStudy+(count(distinct+%3Fs)+as+%3Fcount)++WHERE+{ ++%3FcourseOfStudy+rdf%3Atype+<https%3A%2F%2Fw3id.org%2Fjp-cos%2FCourseOfStudy>+.+ ++%3Fs+jp-cos%3AcourseOfStudy+%3FcourseOfStudy+.+ }+ GROUP+BY+%3FcourseOfStudy ORDER+BY+desc(%3Fcount) Yasguiで可視化する 以下がYasuiでの可視化例です。UpperSecondary(高等学校, jp-cos:school/UpperSecondary)の細目が多いようです。 https://api.triplydb.com/s/Vhi86jwiH まとめ 学習指導要領LODの作成者の方々に感謝いたします。 学習指導要領LODの利用にあたり、参考になりましたら幸いです。

2024年4月15日 · 1 分 · Nakamura