[D0013] 伝達関数CSVファイルの作成

 

伝達関数のCSVファイルを作成する。

#from jmag.designer import designer
import designer

import csv
import traceback
import glob
import re

app = designer.GetApplication()

title_ja = u'伝達関数CSVファイルの作成'
title_en = u'Create transfer function csv file'

def show_message(title_en, title_jp, message_en, message_jp):
	msgdlg = app.CreateDialogBox()

	msgdlg.SetTranslation(title_en, title_jp)
	msgdlg.SetTranslation(message_en, message_jp)

	msgdlg.SetCancelButtonVisible(False)
	msgdlg.SetTitle(title_en)
	msgdlg.AddLabel(message_en)
	msgdlg.Show()


def show_error_message(message_en, message_jp):
	title_en = "Error"
	title_jp = "エラー"
	show_message(title_en, title_jp, message_en, message_jp)


class ForcePointData:
	def __init__(self):
		self.study_title = ""
		self.probe_name = ""
		self.type = ""
		self.case_row = list()
		self.case_group_row = list()
		self.data_header_row = list()
		self.freq = list()
		self.val6d = list()
		self.probe_names = list()
		self.component_names = list()
		self.num_observation_points = ""
		
	def read_csv(self, csvreader, component_header):
		row = next(csvreader)
		self.study_title = row[0][row[0].find(":") + 1:]
		row = next(csvreader)
		self.probe_name = row[0]
		row = next(csvreader)
		self.type = row[0]
		row = next(csvreader)
		self.case_row = row
		row = next(csvreader)
		self.case_group_row = row
		for row in csvreader:
			if row[0].startswith('Frequency'):
				break
		if not row[0].startswith('Frequency'):
			show_error_message(
				f"The line beginning with \"Frequency\" was not found in the CSV.",
				f"CSVファイルに Frequency で始まる行が見つかりませんでした。",
			)
			return False
		self.data_header_row = row
		items = [item.split(" (")[0] for item in self.data_header_row]
		num_points = len(set(items)) - 1
		self.num_observation_points = num_points
		probe_namestmp = []
		component_namestmp = []
		NUM_VALUES_WRITTEN_PER_POINT = 12
		for op in range(num_points):
			pos_read = 7 + op * NUM_VALUES_WRITTEN_PER_POINT
			probe_namestmp.extend(items[pos_read:pos_read+6])
			component_namestmp.extend(component_header)
		self.probe_names.append(probe_namestmp)
		self.component_names.append(component_namestmp)
		for row in csvreader:
			self.freq.append(row[0])
			val6dtmp = []
			for op in range(num_points):
				pos_read = 7 + op * NUM_VALUES_WRITTEN_PER_POINT
				val6dtmp.extend(row[pos_read:pos_read+6])
			self.val6d.append(val6dtmp)
		
		return True
	
	def reference_unit(self):
		if self.type == "Velocity":
			return "m/s"
		elif self.type == "Acceleration":
			return "m/s^2"
		elif self.type == "Displacement":
			return "m"

def read_files(fileList, component_header):
	forcePoints = list()
	for filePath in fileList:
		try:
			with open(filePath, "r", encoding="utf-8-sig") as f:
				csvreader = csv.reader(f)
				fp = ForcePointData()
				success = fp.read_csv(csvreader, component_header)
				if not success:
					return None
				forcePoints.append(fp)
		except Exception as e:
			(e)
			show_error_message(
				f"Error occurred while reading the CSV file.\n {filePath}\n\n{traceback.format_exc()}",
				f"CSVファイル読み込み中にエラーが発生しました。\n {filePath}\n\n{traceback.format_exc()}",
			)
			return None
	if not forcePoints:
		show_error_message(
			"No Force Points.",
			"有効な加振点がありません。",
		)

	return forcePoints

def force_point_label(fp:ForcePointData, index:int):
	dir_label = ("X","Y","Z")
	return  f"tooth:{index//3+1}:{dir_label[index%3]}"

def write_file(forcePoints, filePath):
	try:
		with open(filePath, "w", encoding="utf-8-sig", newline="") as f:
			csvwriter = csv.writer(f)
			csvwriter.writerow(["CSV Version","1.1.0"])
			csvwriter.writerow(["Number of Force Points",str(len(forcePoints))])
			observation_points_number = len(set(forcePoints[0].probe_names[0]))
			csvwriter.writerow(["Number of Observation Points", observation_points_number])
			csvwriter.writerow(["Number of Frequencies", len(forcePoints[0].freq)])
			csvwriter.writerow(["Frequency Unit", "Hz"])
			csvwriter.writerow(["Reference Unit", forcePoints[0].reference_unit()])
			csvwriter.writerow(["Force Unit", "N"])
			csvwriter.writerow(["Transfer Function Matrix"])
			for i in range(len(forcePoints)):
				fp: ForcePointData = forcePoints[i]
				csvwriter.writerow(["Force Point Label", force_point_label(fp, i)])
				probe_names = ['Observation Point Names'] + fp.probe_names[0]
				csvwriter.writerow(probe_names)
				component_names = ['Frequency'] + fp.component_names[0]
				csvwriter.writerow(component_names)
				for j in range(len(fp.freq)):
					row = [fp.freq[j]]
					row.extend(fp.val6d[j])
					csvwriter.writerow(row)
	except Exception as e:
		(e)
		show_error_message(
			f"Error occurred while writing the CSV file.\n {filePath}\n\n{traceback.format_exc()}",
			f"CSVファイル書き出し中にエラーが発生しました。\n {filePath}\n\n{traceback.format_exc()}",
		)
		return False
	
	return True

def write_transfer_function_files(input_files, output_file_path, component_header):
	force_points = read_files(input_files, component_header)
	if not force_points:
		return False
	success = write_file(force_points, output_file_path)
	return success

def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    return [ atoi(c) for c in re.split(r'(\d+)', text) ]

def main():

	xyz_component_header = ["x(real)", "x(imag)", "y(real)", "y(imag)", "z(real)", "z(imag)"]
	rtz_component_header = ["r(real)", "r(imag)", "t(real)", "t(imag)", "z(real)", "z(imag)"]

	label_study_csv_output_dir_ja = u'入力CSVファイルのフォルダ:'
	label_study_csv_output_dir_en = u'Folder with Input CSV Files:'

	label_explanation_ja = u'入力ファイルのフォルダに次のファイルが出力されます。'
	label_explanation_en = u'The following files will be output in the folder.'

	dialog = app.CreateDialogBox()
	
	dialog.SetTranslation(title_en, title_ja)
	dialog.SetTranslation(label_study_csv_output_dir_en, label_study_csv_output_dir_ja)
	dialog.SetTranslation(label_explanation_en, label_explanation_ja)

	dialog.SetTitle(title_en)
	dialog.SetModal(True)
	dialog.AddLabel(label_study_csv_output_dir_en, 0, 1)
	dialog.AddDirectoryPath("study_csv_output_dir", "", "", 1, 2)
	dialog.AddLabel("", 0, 1)
	dialog.AddLabel(label_explanation_en, 1, 2)
	dialog.AddLabel("", 0, 1)
	dialog.AddLabel("transfer_function-xyz.csv", 1, 2)
	dialog.AddLabel("", 0, 1)
	dialog.AddLabel("transfer_function-rtz.csv", 1, 2)

	ret = dialog.Show()
	if ret==0:
		return False

	study_csv_output_dir = dialog.GetValue("study_csv_output_dir").decode(encoding='utf-8')
	if study_csv_output_dir == "":
		show_error_message("Folder with Input CSV Files is not specified.", "入力CSVファイルのフォルダが指定されていません。")
		return False

	XYZInputFiles = glob.glob(study_csv_output_dir+'/'+'*_probe_ObservationPoint-xyz(*).csv')
	RTZInputFiles = glob.glob(study_csv_output_dir+'/'+'*_probe_ObservationPoint-rtz(*).csv')
	
	XYZInputFiles = sorted(XYZInputFiles, key=natural_keys)
	RTZInputFiles = sorted(RTZInputFiles, key=natural_keys)	
	
	success = write_transfer_function_files(XYZInputFiles, study_csv_output_dir+'/'+'transfer_function-xyz.csv', xyz_component_header)
	if not success:
		return False;
	success = write_transfer_function_files(RTZInputFiles, study_csv_output_dir+'/'+'transfer_function-rtz.csv', rtz_component_header)
	if not success:
		return False;

	message_finished_ja = u"伝達関数CSVファイルの作成が終了しました。"
	message_finished_en = u"Creation of transfer function csv file has been completed,"
	show_message(title_en, title_ja, message_finished_en, message_finished_ja)


main()

Download Python source code

ファイルご利用の注意点

JMAGスクリプトライブラリをご利用されるに際し、以下の利用規約をよくお読みいただき、ご同意の上ご利用下さるようお願い申し上げます。