~gcg/constrain/trunk

« back to all changes in this revision

Viewing changes to conStrain.py

  • Committer: GCG at MSI
  • Date: 2021-02-16 18:56:47 UTC
  • Revision ID: gcg@msi-20210216185647-jundceapke4mtvbz
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
"""
 
3
Created on Thu Mar  5 01:50:10 2020
 
4
 
 
5
@author: Georg Ganzenmueller, Fraunhofer Ernst-Mach Institut, EMI
 
6
 
 
7
This code is performs true strain analysis for cylindric specimens based on the 
 
8
evaluation of shadow images.
 
9
The evolution of the minimal diameter is tracked. Triaxiality of stress is
 
10
evaluated using Bridgman's correction [1].
 
11
The algorithm works by determining the silhouette of the specimen gauge region
 
12
using Canny-edge detection. The minimum distance between the edges constitutes
 
13
the current cylindrical diameter. In the vicinity of the minimum location,
 
14
the local edge curvature is calculated, which is then used by the Bridgman
 
15
correctiion, providing a measure of stress triaxiality.
 
16
 
 
17
This file is the user interface. The actual silhouette detection is performed
 
18
in the class SilhouetteDiameter.
 
19
 
 
20
The user needs to provide a path to a folder containing the images to be analysed,
 
21
along with their file type suffix. The images need to be labeled with increasing numbers.
 
22
The specimen diameter should be resolved with at least 100 pixels in order to obtain accurate results
 
23
with strain errors < 1%.
 
24
 
 
25
Two parameters significantly affect the accuracy of the strain computation, and especially the accuracy
 
26
of the stress triaxiality factor: The amount of smoothing (nsmooth) applied to the specimen silhouette
 
27
detected by the Canny-edge filter, and the order of its spline representation. Good values
 
28
for nsmooth are 100 -- 1000, and order = 1 to 3.
 
29
 
 
30
 
 
31
 
 
32
[1] P. W. Bridgman, Studies in Large Plastic Flow and Fracture, McGraw-Hill, New York, (1952).
 
33
"""
 
34
 
 
35
import configparser, triaxiality
 
36
 
 
37
cfg = configparser.ConfigParser()
 
38
cfg.read("constrain.ini")
 
39
suffix = cfg.get("DEFAULT", "suffix")
 
40
nMax = cfg.getint("DEFAULT", "nMax")
 
41
transpose = cfg.getboolean("DEFAULT", "transpose") # rotate image? Specimen must be vertical in image
 
42
notched_specimen = cfg.getboolean("DEFAULT", "notched_specimen")
 
43
nueps = cfg.getfloat("DEFAULT", "nueps")
 
44
 
 
45
###############################################################################
 
46
# *********** Only edit lines above *************
 
47
###############################################################################
 
48
 
 
49
import numpy as np
 
50
import matplotlib.pyplot as plt
 
51
import glob
 
52
from Silhouette import Silhouette
 
53
 
 
54
def read_images():
 
55
    filenames = []
 
56
    for file in glob.glob(suffix):
 
57
        filenames.append(file)
 
58
        
 
59
    from natsort import natsorted
 
60
    filenames = natsorted(filenames)
 
61
        
 
62
    if nMax > 0:
 
63
        return filenames[:nMax]
 
64
    else:
 
65
        return filenames
 
66
 
 
67
filenames = read_images()
 
68
N = len(filenames)
 
69
 
 
70
diameters = np.zeros(N)
 
71
notch_radii = np.zeros(N)
 
72
valid_flag = np.zeros(N, dtype=bool)
 
73
 
 
74
for i in range(0,len(filenames)):
 
75
    print("\n-------------- file: %s --------------" %(filenames[i]))
 
76
    sil = Silhouette(filenames[i], plot=False, transpose=transpose)
 
77
                             
 
78
    if sil.status == True:
 
79
        if sil.diameter > 0:
 
80
            diameters[i] = sil.diameter
 
81
            if sil.curvature_valid:
 
82
                valid_flag[i] = True
 
83
                notch_radii[i] = sil.notch_radius
 
84
                print("current diameter in pixels is: ", sil.diameter, " notch radius is; ", sil.notch_radius, "sigma is", sil.notch_sigma)
 
85
            notch_radii[i] = max(notch_radii[i], 0.25*diameters[i]) # limit severe triaxiality to 1.3
 
86
                
 
87
    else:
 
88
        print("something went wrong in the analysis, exiting prematurely")
 
89
        break
 
90
 
 
91
eps_eq = (1./nueps) * np.log(diameters[0]/diameters) # equivalent true strain
 
92
 
 
93
savedata = np.column_stack((np.arange(len(diameters)), eps_eq, diameters, notch_radii))
 
94
np.savetxt("strain.txt",savedata, header="index, eps_eq, diameter, notch_radius")
 
95
 
 
96
 
 
97
plt.style.use('dark_background')
 
98
fig, axs = plt.subplots(2,2)
 
99
 
 
100
# --- TOP LEFT plot: strain vs. frame number ---
 
101
ax = axs[0,0]
 
102
color = 'tab:red'
 
103
ax.set_xlabel('frame No.')
 
104
ax.set_ylabel('equivalent true strain')
 
105
ax.plot(eps_eq, color=color, label="strain")
 
106
 
 
107
# --- BOTTOM LEFT plt: diamater vs frame number ---
 
108
ax = axs[1,0]
 
109
ax.set_xlabel('frame No.')
 
110
ax.set_ylabel('diameter [px]')
 
111
ax.plot(diameters, "rx", label="diameter")
 
112
 
 
113
# --- TOP RIGHT plot: stress triaxiality vs strain ---
 
114
ax = axs[0,1]
 
115
ax.set_xlabel('eq. true strain')
 
116
ax.set_ylabel('stress triaxiality [-]')
 
117
ax.plot(eps_eq,triaxiality.triax_function(diameters, notch_radii), "bo", label="stress triax.")
 
118
ax.legend()
 
119
 
 
120
# --- BOTTOM RIGHT plot: Bridgman factor vs strain ---
 
121
ax = axs[1,1]
 
122
ax.set_xlabel('eq. true strain')
 
123
ax.set_ylabel('Bridgman factor [-]')
 
124
ax.plot(eps_eq, triaxiality.bridgman_function(diameters, notch_radii), "go", label="Bridgman factor")
 
125
ax.legend()
 
126
 
 
127
fig.tight_layout()  # otherwise the right y-label is slightly clipped
 
128
plt.show()
 
129
 
 
130
 
 
131
 
 
132
# if len(filenames) > 2:
 
133
#     def powerlaw(x, a, n, offset):
 
134
#         return a * (np.abs(x)**n) + offset
 
135
#     def powerlaw_unnotched(x, a, n):
 
136
#         return a * (np.abs(x)**n)
 
137
    
 
138
#     # need a data subset which contains only strain and ratios if valid_flag is set to true
 
139
#     eps_eq_sub = np.compress(valid_flag, eps_eq)
 
140
#     ratios_sub = np.compress(valid_flag, ratios)
 
141
#     #print("length of original array: ", len(eps_eq))
 
142
#     #print("length of subset array: ", len(eps_eq_sub))
 
143
#     #print(eps_eq_sub)
 
144
    
 
145
#     if notched_specimen:
 
146
#         try:
 
147
#             p0 = [1, 0.5, 0.5]
 
148
#             popt, pcov = curve_fit(powerlaw, eps_eq_sub, ratios_sub, p0=p0)
 
149
#             ratio_fit = powerlaw(eps_eq, *popt)
 
150
#         except:
 
151
#             ratio_fit = ratios
 
152
            
 
153
#     else:
 
154
#         try:
 
155
#             p0 = [1, 0.5]
 
156
#             popt, pcov = curve_fit(powerlaw_unnotched, eps_eq_sub, ratios_sub, p0=p0)
 
157
#             ratio_fit = powerlaw_unnotched(eps_eq, *popt)
 
158
#         except:
 
159
#             ratio_fit = ratios
 
160
    
 
161
#     # now replace invalid ratios with fit
 
162
    
 
163
#     #print("original ratios", ratios)
 
164
#     ratios = np.where(valid_flag, ratios, ratio_fit)
 
165
#     #print("repaired ratios", ratios)
 
166
      
 
167
    
 
168
#     bridgman_fit = bridgman_function(ratio_fit)
 
169
#     triax_fit = triax_function(ratio_fit)
 
170
 
 
171
#     # compute Bridgman factor and stress triaxiality
 
172
#     bridgmans = bridgman_function(ratios)
 
173
#     triaxs = triax_function(ratios)    
 
174
    
 
175
# else:
 
176
#     bridgman_fit = bridgmans = bridgman_function(ratios)
 
177
#     triax_fit = triaxs = triax_function(ratios)
 
178
 
 
179