Я работаю над проектом, который включает в себя десятки файлов, каждый файл имеет сотни точек, и каждый файл представляет собой строку в matplotlib, эти файлы будут автоматически обновляться другим программным обеспечением, моя цель - постоянно составлять графики содержимое их, первый тип файла имеет этот формат:
"Convergence history of Static Temperature on p14 (in SI units)"
"Iteration" "Vertex Average Static Temperature"
10 358.3162536621094
20 369.484375
30 375.3867797851562
40 378.8209228515625
50 380.5880432128906
60 381.4667663574219
70 381.8531494140625
80 381.9440307617188
...
Первое число представляет "X"
ось, а второе "Y"
, это ".out"
, их легко анализировать и даже анимировать.
Файл другого типа со следующим форматом содержит 5 строк для построения на matplotlib, который имеет следующий формат:
1 {{continuity 1.0000e+00} {x-velocity 0.0000e+00} {y-velocity 4.3827e-02} {z-velocity 1.9319e-03} {energy 1.2276e-07} }
2 {{continuity 1.0000e+00} {x-velocity 7.8061e-04} {y-velocity 1.6308e+01} {z-velocity 1.0320e-03} {energy 2.9296e-06} }
3 {{continuity 2.3509e-01} {x-velocity 1.2848e-03} {y-velocity 1.2352e-02} {z-velocity 1.0337e-02} {energy 2.2715e-06} }
4 {{continuity 8.0945e-02} {x-velocity 1.6650e-03} {y-velocity 1.3073e-02} {z-velocity 1.0491e-02} {energy 3.2993e-07} }
Первое число представляет ось "X"
, и каждая строка / имя между фигурными скобками "{}"
имеет значение "Y "
, расширение их ".res"
, и я использую регулярное выражение для анализа их данных.
Ожидаемое поведение
Код должен читать все файлы, сортировать их по категориям, затем я буду вызывать функцию animate для каждой категории, функция animate будет читать каждый файл в категории и выводить ее на график matplotlib, каждый x количество времени.
Проблема
Код сейчас работает частично, потому что он действительно неэффективен, он даже не завершает чтение всех файлов, которые нужно построить, до того, как функция animate хочет выполнить снова, я считаю, что регулярное выражение это большая проблема, так как он медленнее и мне нужно найти способ прочитать только самую новую точку, а не перепланировать все файлы.
Код:
Функция, которая находит файлы для печати.
def find_plot_files(self, file_path, n):
project_name = file_path.split("/")[-1] # Erase everything before the last slash: /ab/bc/tu.out > tu.out
project_name = project_name[:project_name.find(".")]
current_project = self.controller.project_list.create_project(project_name, file_path)
file_path = os.path.dirname(file_path)
for file in os.listdir(file_path):
graph_name = file[file.find(".") + 1:file.rfind(".")]
if file.endswith(".out"):
if project_name in file:
current_file = open(file_path + "/" + file, 'r').read()
if 'Temperature' in current_file:
current_project.insert_graph('Temperature', graph_name, file_path+"/"+file)
elif 'Pressure' in current_file:
current_project.insert_graph('Pressure', graph_name, file_path+"/"+file)
elif 'Velocity' in current_file:
current_project.insert_graph('Velocity', graph_name, file_path+"/"+file)
elif file.endswith(".res"):
if project_name in file:
current_project.insert_graph('Residuals', graph_name, file_path+"/"+file)
#Here every "graph" represents a category, and i will create a figure and plot every line into it.
for graph in self.controller.project_list.get_project(project_name).get_graphs():
f = Figure(figsize=(5, 5), dpi=100)
a = f.add_subplot(111)
canvas = FigureCanvasTkAgg(f, self)
f.suptitle(graph)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.animated_graph.append(animation.FuncAnimation(f, self.animate, fargs=(a, project_name, graph),
interval=3000))
Функция анимации
def animate(self, i, target_graph, project_name, graph):
target_graph.clear()
for graph in self.controller.project_list.get_project(project_name).get_graphs()[graph]:
file_path = graph.file_path
pull_data = open(file_path, 'r').read()
data_array = pull_data.split('\n')
xar = []
# THIS PLOTS THE SECOND CASE THAT I COPIED IN THE QUESTION
if graph.file_path[-3:] == 'res':
lines_list = {}
for each_line in data_array:
if len(each_line) > 0:
xar.append(each_line[0:each_line.find(" ")])
each_line = each_line[each_line.find(" ")+2: -1]
for data_point in re.findall("\{(.*?)\}", each_line):
data_point = data_point.split()
if data_point[0] in lines_list:
lines_list[data_point[0]].append(data_point[1])
else:
lines_list[data_point[0]] = [data_point[1]]
for key in lines_list:
target_graph.plot(xar, lines_list[key], label=key)
else:
# THIS PLOTS THE FIRST CASE THAT I COPIED IN THE QUESTION
yar = []
for each_line in data_array:
try:
if len(each_line.split()) == 2:
x, y = each_line.split()
xar.append(float(x))
yar.append(float(y))
except TypeError:
pass
target_graph.plot(xar, yar)
Я действительно новичок в использовании функций matplotlib и animate, поэтому любая помощь будет очень полезна!
Заранее спасибо!