"""
tkfilterモジュール
データフィルタリング機能を提供するクラスを定義します。
プラグインとしてロードされたモジュールを通じて、データの読み込み、検索、操作を行います。
:doc:`tkfilter_usage`
"""
import re
from tklib.tkobject import tkObject
from tklib.tkutils import pint, pfloat, print_line, print_data
[ドキュメント]
class tkFilter(tkObject):
"""
データフィルタリングとデータ操作のための基底クラスです。
プラグインとしてロードされたモジュールを用いて、ファイルの読み込み、
データ配列の検索、ハッシュ変換、出力などの機能を提供します。
"""
def __init__(self, app, cparams, plugin_dir, module_file, target = "read_data", is_print = False, **args):
"""
tkFilterクラスのコンストラクタです。
フィルタリングモジュールの初期設定とロードを行います。
:param app: object: アプリケーションオブジェクト。モジュールのロードに使用されます。
:param cparams: dict: 設定パラメータの辞書。モジュールに渡されます。
:param plugin_dir: str: プラグインモジュールが格納されているディレクトリのパス。
:param module_file: str: ロードするモジュールファイルの名前またはパターン。
:param target: str: (オプション) モジュール内で呼び出すターゲット関数の名前。デフォルトは "read_data"。
:param is_print: bool: (オプション) 処理の詳細をコンソールに出力するかどうか。デフォルトは False。
:param args: dict: その他のキーワード引数。`update` メソッドに渡されます。
"""
super().__init__()
self.app = app
self.cparams = cparams
self._plugin_dir = plugin_dir
self._module_file = module_file
self.target = target
self.is_print = is_print
self.module_names = None
self.modules = None
self.iregion = None
self.label = None
self.data = None
self.ispectrum = None
self.inf = None
self.update(**args)
def __del__(self):
"""
デストラクタです。
現在は特別な終了処理を行いません。
"""
pass
def __str__(self):
"""
オブジェクトの文字列表現を返します。
クラスの完全なパスを返します。
:returns: str: クラスの完全なパス。
"""
return self.ClassPath()
[ドキュメント]
def load(self, target = None, is_print = None):
"""
フィルタリングモジュールをロードします。
指定されたプラグインディレクトリから、`_module_file` にマッチするモジュールをロードします。
各モジュールの入出力タイプを表示することもできます。
:param target: str: (オプション) ロードするモジュールのターゲット関数名。指定されない場合は初期設定を使用します。
:param is_print: bool: (オプション) ロード処理の詳細をコンソールに出力するかどうか。指定されない場合は初期設定を使用します。
:returns: tuple[list[str], list[object]]: ロードされたモジュール名 (`module_names`) のリストと、モジュールオブジェクト (`modules`) のリストのタプル。
"""
if target is not None:
self.target = target
if is_print is not None:
self.is_print = is_print
self.module_names, self.modules \
= self.app.load_modules(plugin_dir = self._plugin_dir, fmask = self._module_file,
target = self.target, is_print = self.is_print)
for m in self.modules:
input_type = m.get_input_type(app = self.app, cparams = self.cparams)
output_type = m.get_output_type(app = self.app, cparams = self.cparams)
if is_print:
print(f" {m.name}: input_type={input_type} output_type={output_type}")
return self.module_names, self.modules
[ドキュメント]
def read_datalist(self, idata = None, imodule = 0, infile = None, target = '',
app = None, cparams = None, is_print = False):
"""
指定された複数のデータインデックスに基づいて、データリストを読み込みます。
まずモジュールをロードし、指定されたインデックス (`idata`) に基づいて、
各データポイントのラベルとデータ配列を検索してリストとして返します。
:param idata: list | tuple: 読み込むデータのインデックスのリストまたはタプル。整数、文字列(正規表現)、または (int, int) / (str, int) のタプルが可能です。
:param imodule: int: (オプション) データを読み込むモジュールのインデックス。デフォルトは 0。
:param infile: str: (オプション) 読み込む入力ファイルのパス。
:param target: str: (オプション) ロードするモジュールのターゲット関数名。
:param app: object: (オプション) アプリケーションオブジェクト。指定されない場合は、インスタンスの `app` を使用します。
:param cparams: dict: (オプション) 設定パラメータの辞書。指定されない場合は、インスタンスの `cparams` を使用します。
:param is_print: bool: (オプション) 処理の詳細をコンソールに出力するかどうか。デフォルトは False。
:returns: tuple[list[str], list[Any], dict]: 読み込んだラベルのリスト、データ配列のリスト、および読み込んだデータの詳細情報 (`self.inf`) のタプル。
"""
self.load(target = target, is_print = is_print)
self.inf = self.modules[imodule].read_data(infile, app = app, cparams = cparams, is_print = is_print)
labels = []
data_list = []
for idx in idata:
if type(idx) is int:
label, data = self.find_data_array(0, idx)
elif type(idx) is str:
label, data = self.find_data_array(idx)
elif type(idx) is list or type(idx) is tuple:
label, data = self.find_data_array(idx[0], idx[1])
else:
print(f"\nError in tkfilter.read_datalist(): Invalid idata [{idata}]")
exit()
labels.append(label)
data_list.append(data)
return labels, data_list, self.inf
[ドキュメント]
def read_data(self, imodule = 0, infile = None, idata = None, target = '',
app = None, cparams = None, is_print = False):
"""
データを読み込みます。
`idata` がリストまたはタプルの場合は `read_datalist` を呼び出して複数のデータを読み込みます。
それ以外の場合は、指定されたモジュールから単一のデータセットを読み込みます。
:param imodule: int: (オプション) データを読み込むモジュールのインデックス。デフォルトは 0。
:param infile: str: (オプション) 読み込む入力ファイルのパス。
:param idata: int | str | list | tuple: (オプション) 読み込むデータのインデックス。整数、文字列(正規表現)、またはそれらのリスト/タプル。
リストまたはタプルの場合、`read_datalist` が呼び出されます。
:param target: str: (オプション) ロードするモジュールのターゲット関数名。
:param app: object: (オプション) アプリケーションオブジェクト。指定されない場合は、インスタンスの `app` を使用します。
:param cparams: dict: (オプション) 設定パラメータの辞書。指定されない場合は、インスタンスの `cparams` を使用します。
:param is_print: bool: (オプション) 処理の詳細をコンソールに出力するかどうか。デフォルトは False。
:returns: Any: 読み込んだデータまたは情報の辞書。`idata` がリストまたはタプルの場合は `read_datalist` の戻り値、
それ以外の場合はモジュールの `read_data` メソッドの戻り値。
"""
if type(idata) is list or type(idata) is tuple:
return self.read_datalist(idata = idata, imodule = imodule, infile = infile, target = target,
app = app, cparams = cparams, is_print = is_print)
self.inf = self.modules[imodule].read_data(infile, app = app, cparams = cparams, is_print = is_print)
return self.inf
[ドキュメント]
def print_line(self, data_list, format = '{:^10}'):
"""
データリストの行を整形して出力します。
`tklib.tkutils.print_line` 関数を呼び出します。
:param data_list: list: 出力するデータ要素のリスト。
:param format: str: (オプション) 各データ要素を整形するためのフォーマット文字列。デフォルトは '{:^10}'。
:returns: None
"""
print_line(data_list, format)
[ドキュメント]
def print_data(self, labels = None, data_list = None, label_format = '{:^10}', data_format = '{:>10}', header = None, print_level = 0):
"""
ラベルとデータリストを整形して出力します。
`tklib.tkutils.print_data` 関数を呼び出します。
:param labels: list[str]: (オプション) 各データ行に対応するラベルのリスト。
:param data_list: list[list[Any]]: (オプション) 出力するデータのリストのリスト。
:param label_format: str: (オプション) ラベルを整形するためのフォーマット文字列。デフォルトは '{:^10}'。
:param data_format: str: (オプション) データ要素を整形するためのフォーマット文字列。デフォルトは '{:>10}'。
:param header: str: (オプション) 出力するデータのヘッダー文字列。
:param print_level: int: (オプション) 出力の詳細レベル。
:returns: None
"""
print_data(labels = labels, data_list = data_list, label_format = label_format, data_format = data_format, header = header, print_level = print_level)
[ドキュメント]
def get_hash_data(self, idx, inf = None):
"""
ロードされたデータから、ラベルとデータ配列のマッピングをハッシュ(辞書)形式で取得します。
`inf` に含まれるラベルと `data_list` を使用して、ラベルをキー、対応するデータ配列を値とする辞書を作成します。
:param idx: Any: (このメソッドでは使用されませんが、シグネチャに含まれています)
:param inf: dict: (オプション) データの詳細情報を含む辞書。指定されない場合は、インスタンスの `self.inf` を使用します。
:returns: dict[str, Any]: ラベルをキー、データ配列を値とする辞書。
"""
if inf is None:
inf = self.inf
labels = inf["labels"]
hash = {}
for iregion, ls in enumerate(labels):
for ispectrum, l in enumerate(ls):
hash[l] = inf["data_list"][iregion][ispectrum]
return hash
[ドキュメント]
def find_label_index(self, regexp, flag = '', inf = None):
"""
指定された正規表現またはインデックスに一致するラベルのインデックスを検索します。
まず `regexp` が整数であれば、直接領域インデックス0と `regexp` をスペクトルインデックスとして返します。
次に `regexp` を整数に変換可能であれば、同様に返します。
それ以外の場合は、`inf` に含まれるラベルのリストを走査し、正規表現 `regexp` に一致するラベルの
領域インデックスとスペクトルインデックスを返します。
:param regexp: str | int: 検索対象の正規表現文字列またはインデックス値。
:param flag: str | int: (オプション) 正規表現検索フラグ (例: `re.IGNORECASE`)。またはスペクトルインデックスとしての整数値。
:param inf: dict: (オプション) データの詳細情報を含む辞書。指定されない場合は、インスタンスの `self.inf` を使用します。
:returns: tuple[int | None, int | None]: 見つかった領域インデックスとスペクトルインデックスのタプル。見つからない場合は (None, None)。
"""
if inf is None:
inf = self.inf
labels = inf["labels"]
if type(regexp) is int:
return 0, regexp
else:
idx = pint(regexp, defval = None)
if idx is not None:
return 0, idx
for iregion, ls in enumerate(labels):
for ispectrum, l in enumerate(ls):
if flag == '':
ret = re.search(regexp, l)
else:
ret = re.search(regexp, l, flag)
if ret:
return iregion, ispectrum
return None, None
[ドキュメント]
def find_data_array(self, regexp, flag = '', inf = None):
"""
指定された正規表現またはインデックスに一致するラベルとデータ配列を検索します。
まず `regexp` と `flag` が両方とも整数の場合、それらを直接領域インデックスとスペクトルインデックスとして使用します。
それ以外の場合は `find_label_index` を呼び出してインデックスを取得します。
取得したインデックスに基づいて、対応するラベルとデータ配列を `inf` から取得し、インスタンス変数に設定します。
:param regexp: str | int: 検索対象の正規表現文字列または領域インデックス。
:param flag: str | int: (オプション) 正規表現検索フラグ (例: `re.IGNORECASE`)、またはスペクトルインデックス。デフォルトは空文字列。
:param inf: dict: (オプション) データの詳細情報を含む辞書。指定されない場合は、インスタンスの `self.inf` を使用します。
:returns: tuple[str | None, Any | None]: 見つかったラベルとデータ配列のタプル。見つからない場合は (None, None)。
"""
if inf is None:
inf = self.inf
if type(regexp) is int and type(flag) is int:
self.iregion = regexp
self.ispectrum = flag
else:
self.iregion, self.ispectrum = self.find_label_index(regexp, flag, inf = inf)
if self.iregion is None:
return None, None
self.label = inf["labels"][self.iregion][self.ispectrum]
self.data = inf["data_list"][self.iregion][self.ispectrum]
return self.label, self.data