In [1]:
from __future__ import absolute_import, division, print_function
import dic
from cycler import cycler
from IPython.display import HTML
from base64 import b64encode
import matplotlib.pyplot as plt
import numpy as np
import os
import warnings
rc_dict = {'font.size': 14,
'font.family': 'sans-serif',
'font.sans-serif': ['Arial'],
'axes.titlesize':'large',
'lines.linewidth': 2,
'axes.prop_cycle': cycler('color', ('#2196F3', # blue
'#F44336', # red
'#4CAF50', # green
'#9C27B0', # purple
'#FFB300', # amber
'#795548', # brown
'#607D8B' # blue grey
))
}
plt.rcParams.update(rc_dict)
%matplotlib notebook
In [2]:
# path to the .mat files exported by VIC software:
dic_directory = "/home/ryan/Desktop/sample_006_mat/"
# path to the raw image file and their extension:
image_directory = "/home/ryan/Desktop/sample_006_dic/"
image_extension = ".tif"
# CSV file saved by VIC software during analysis:
csv_filename = "/home/ryan/BTSync/dic_load/FCC_2x2x1_sample-006.csv"
# column in the CSV file that contains the load data in volts
csv_load_column = 9
# full scale load from MTS card / 10 V
newtons_per_volt = 4448 / 10.0
# sample area is needed to calculate stress from load data
lattice_parameter = 30.0
sample_area = (2 * lattice_parameter)**2
This loads the DIC files (with .MAT extension), image files and MTS data file.
I assume the left camera was used as the reference images. If you used the right camera, simply change the reference_camera_filenames
variable to right_camera_filenames
.
Warnings will be issued if a possible error is detected when loading the data.
In [3]:
dic_filenames = dic.get_filenames(dic_directory, ".mat", prepend_directory=True)
left_camera_filenames, right_camera_filenames = dic.get_image_filenames(image_directory, image_extension,
prepend_directory=True)
# set this to the camera filenames used for the reference during the correlation:
reference_camera_filenames = left_camera_filenames
print("Found {:d} DIC files at {}".format(len(dic_filenames), dic_directory))
print("Found {:d} image files at {}".format(len(reference_camera_filenames), image_directory))
if len(dic_filenames) != len(reference_camera_filenames):
warnings.warn("The number of camera images must equal the number of DIC files.")
if os.path.exists(csv_filename):
print("Found CSV file {}".format(csv_filename))
mts_load = dic.load_csv_data(csv_filename, csv_load_column, scale=newtons_per_volt)
print("MTS load data imported from CSV file.")
else:
warnings.warn("Unable to find CSV file: {}".format(csv_filename))
In [4]:
extensometers = dic.place_extensometers(reference_camera_filenames[0], dic_filenames[0])
In [5]:
stress, strain = dic.stress_strain(dic_filenames, mts_load, area=sample_area, extensometers=extensometers)
In [6]:
smoothed_stress = dic.smooth(stress, window_len=10)
axes_options = {
"xlabel": "Compressive strain, $\\epsilon_{1}$",
"ylabel": "Compressive stress, $\\sigma_{1}$ (MPa)",
"xlim" : (0, 0.06),
"xticks": np.arange(0, 0.08, 0.02),
"ylim" : (0, 0.6),
"yticks": np.arange(0, 0.8, 0.2)
}
fig, ax = dic.plot_xy(-strain, -stress, axes_options=axes_options, plot_options={"label": "Raw data"})
dic.plot_xy(-strain, -smoothed_stress, ax=ax, plot_options={"label": "Smoothed"})
plt.legend()
plt.show()
A frame creator is an object that when called with a frame number i
will return a matplotlib.figure.Figure
corresponding to the current frame. The frame creator's __len__
attribute must return the number frames the creator intends to create (usually the number of DIC files/images). Those are the only two requirements when creating a custom frame creator. Often the frame creator will have to be created for your specific use case. I've created one that will plot a contour overlay and an (x, y)
plot.
In [7]:
xy_axes_options = {
"xlabel": "Compressive strain, $\\epsilon_{1}$",
"ylabel": "Compressive stress, $\\sigma_{1}$ (MPa)",
"xlim" : (0, 0.06),
"xticks": np.arange(0, 0.08, 0.02),
"ylim" : (0, 0.9),
"yticks": np.arange(0, 1.2, 0.3)
}
xy_plot_options = {
"color" : (0., 0., 0., 0.7),
"linewidth": 1.5
}
point_plot_options = {
"markersize": 6,
"color": plt.get_cmap("viridis")(0.5)
}
vmin = -0.04
vmax = -vmin
step = 0.02
levels = 32
overlay_contour_options = {
"levels": np.linspace(vmin, vmax, levels)
}
colorbar_options = {
"title": "$\\epsilon_{\\mathsf{min}}$",
"ticks": np.arange(vmin, vmax+step, step)
}
plt.close("all")
frame_creator = dic.OverlayWithStressStrainFrameCreator(reference_camera_filenames, dic_filenames, "e2",
(-strain, -smoothed_stress), figure_width=11, fractional_padding=0.5,
overlay_contour_options=overlay_contour_options,
xy_axes_options=xy_axes_options, xy_plot_options=xy_plot_options,
colorbar_options=colorbar_options, point_plot_options=point_plot_options)
fig = frame_creator(90)
plt.show()
In [8]:
savefig_options = {
"dpi" : 300,
"bbox_inches": "tight"
}
dic.export_frames(frame_creator, output_directory="example/image_sequence/",
output_filename="frame.jpg", savefig_options=savefig_options)
In [9]:
input_template = "example/image_sequence/frame_%3d.jpg"
output_filename = "example/movie.mp4"
dic.image_sequence_to_video(input_template, output_filename, crf=23, scale=(720, -1))
In [11]:
video = open(output_filename, "rb").read()
video_encoded = b64encode(video)
video_tag = \
"""
<video alt="example video" controls>
<source src="data:video/mp4;base64,{0}" type="video/mp4"/>
</video>
""".format(video_encoded.decode('ascii'))
HTML(data=video_tag)
Out[11]: