PyFlex  1.0
Riser cross section analysis
timehist.py
Go to the documentation of this file.
1 """Copyright (C) 2016 Joakim A. Taby
2 
3  This program is free software: you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation, either version 3 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program. If not, see <http://www.gnu.org/licenses/>."""
14 import os
15 import fnmatch
16 import numpy as np
17 import operator
18 import math
19 import matplotlib
20 import functools
21 import h5py
22 from PySide import QtGui, QtCore
23 
24 matplotlib.rcParams['backend.qt4'] = "PySide"
25 # noinspection PyPep8
26 from matplotlib.backends.backend_qt4agg import (
27  FigureCanvasQTAgg as FigureCanvas,
28  NavigationToolbar2QT as NavigationToolbar)
29 # noinspection PyPep8
30 import coefficients
31 import axisymmetric
32 # noinspection PyPep8
33 import gc
34 
35 """Module for handling time series"""
36 
37 
38 class TimeHist(object):
39  """
40  Defining a time series object
41  :param object:
42  """
43 
44  def __init__(self, time_filename, histname, directory=None):
45  self.timeFileName = time_filename
46  self.name = histname
47  # initiation of instance variables other methods.
48  # plot
49  self.canvas = None
50  self.mpl_toolbar = None
51  if directory is not None:
52  self.directory = directory
53  if self.timeFileName[-3:] == 'tim':
54  if directory is not None:
55  self.timehist = self.set_from_tim(directory)
56  else:
57  self.timehist = self.set_from_tim('')
58 
59  def set_from_tim(self, directory):
60  """
61  Reads in a tim file or directory and retusnrs it
62  :param directory: The directory where the file is located
63  :return: The time history in a matrix as follows: [Time Tension Curvy Curvz] X nsteps
64  """
65  fid = open(directory + '/' + self.timeFileName, "r")
66  headercheck = fid.readline()
67  headercheck = headercheck.lower()
68  if headercheck[:3] == '# #':
69  tdict = dict(timeindex=headercheck.find('time'),
70  tensionindex=headercheck.find('tension'),
71  curvyindex=headercheck.find('curvy'),
72  curvzindex=headercheck.find('curvz'),
73  p_intindex=headercheck.find('p_int'),
74  p_extindex=headercheck.find('p_ext'))
75  sorted_dict = sorted(tdict.items(), key=operator.itemgetter(1))
76  dictionary = {}
77  for i in range(len(sorted_dict)):
78  dictionary[sorted_dict[i][0]] = i
79  else:
80  dictionary = dict(timeindex=0,
81  tensionindex=1,
82  curvyindex=2,
83  curvzindex=3,
84  p_intindex=4,
85  p_extindex=5)
86  unsorted = np.loadtxt(directory + '/' + self.timeFileName)
87  timehist = np.zeros([len(unsorted[:, 0]), 6])
88  timehist[:, 0] = unsorted[:, dictionary['timeindex']]
89  timehist[:, 1] = unsorted[:, dictionary['tensionindex']]
90  timehist[:, 2] = unsorted[:, dictionary['curvyindex']]
91  timehist[:, 3] = unsorted[:, dictionary['curvzindex']]
92  timehist[:, 4] = unsorted[:, dictionary['p_intindex']]
93  timehist[:, 5] = unsorted[:, dictionary['p_extindex']]
94  fid.close()
95  return timehist
96 
97  def plot(self, parent):
98  """
99  Method for plotting itself onto the parent widget.
100  :param parent:A widget where the canvas will be placed
101  """
102  fig = matplotlib.figure.Figure()
103  self.canvas = FigureCanvas(fig)
104  ax1 = fig.add_subplot(211)
105  ax1.plot(self.timehist[:, 0], self.timehist[:, 1])
106  ax1.set_title('Tension')
107  ax2 = fig.add_subplot(212)
108  ax2.plot(self.timehist[:, 0], self.timehist[:, 2], self.timehist[:, 0], self.timehist[:, 3])
109  ax2.set_title('Curvatures')
110  fig.suptitle('Time series %s' % str(self.name))
111  self.mpl_toolbar = NavigationToolbar(self.canvas, parent)
112 
113  temp = QtGui.QWidget()
114  templayout = QtGui.QVBoxLayout()
115  temp.setLayout(templayout)
116  templayout.addWidget(self.mpl_toolbar)
117  templayout.addWidget(self.canvas)
118  parent.addTab(temp, 'Plot of %s' % str(self.name))
119  parent.setCurrentWidget(temp)
120 
121 
122 class FrictionCalc(object):
123  """Class for holding data for friction calculations"""
124 
125  def __init__(self):
126  self.timehist = None
127  self.labels = []
128  self.startSlider = []
129  self.startSpinbox = []
130  self.endSlider = []
131  self.endSpinbox = []
132  self.enabled = []
133  # Initializing attributes difined elsewhere
134  # setup_tab
135  self.mainwidget = None
136  # setup setup_ts_edit
137  self.startTime = None
138  self.stopTime = None
139  # calculate
140  self.startindex = None
141  self.stopindex = None
142  self.time = None
143  self.bendStddev = None
144  self.bendMax = None
145  self.bendMin = None
146  self.bendStress = None
147  self.tension = None
148  self.p_int = None
149  self.p_ext = None
150  self.stickStress = None
151  self.stickStddev = None
152  self.stickMax = None
153  self.stickMin = None
154  self.axialStress = None
155  self.axialStddev = None
156  self.axialMax = None
157  self.axialMin = None
158  # plot
159  self.mpl_toolbar = None
160  self.canvas = plot = None
161  # setup_tab
162 
163  def add_ts(self, ts):
164  """ Adding/changing a timeseries obviously.
165  :param ts: A time series
166  """
167  self.timehist = ts
168 
169  def setup_tab(self, window):
170  """
171  Setting up a widget where the input to the friction calculation will be shown.
172  Needs to be placed into the application on the outside to be shown.
173  :param window: The main window of the application. Adds itself to it and uses its eventfilter only.
174  :return:
175  """
176  self.mainwidget = QtGui.QWidget()
177  self.mainwidget.setAcceptDrops(True)
178  self.mainwidget.installEventFilter(window)
179  mainlayout = QtGui.QVBoxLayout()
180  mainlayout.setObjectName('mainlayout')
181  self.mainwidget.setLayout(mainlayout)
182  frictiontitle = QtGui.QLabel('<H1> Friction calculations </H1>')
183  mainlayout.addWidget(frictiontitle)
184  # Adding a layout for adding the timeseries
185  # making gridlayout including all timeseries
186  tslayout = QtGui.QGridLayout()
187  tslayout.setObjectName('tslayout')
188  header_name = QtGui.QLabel('Name')
189  tslayout.addWidget(header_name, 1, 0)
190  header_starttime = QtGui.QLabel('Start time')
191  tslayout.addWidget(header_starttime, 1, 1, columnSpan=2)
192  header_stoptime = QtGui.QLabel('Stop time')
193  tslayout.addWidget(header_stoptime, 1, 3, columnSpan=2)
194  use_constant_tension = QtGui.QCheckBox('Use constant tension')
195  use_constant_tension.setObjectName('use_constant_tension')
196  use_constant_tension.setToolTip('From scenario definition')
197  if not hasattr(window.tree_model.slenderdata, 'typical_tension'):
198  use_constant_tension.setEnabled(False)
199  tslayout.addWidget(use_constant_tension, 0, 1)
200  use_constant_curvature = QtGui.QCheckBox('Use constant curvature')
201  use_constant_curvature.setObjectName('use_constant_curvature')
202  use_constant_curvature.setToolTip('From scenario definition')
203  if not hasattr(window.tree_model.slenderdata, 'typical_curvature'):
204  use_constant_curvature.setEnabled(False)
205  tslayout.addWidget(use_constant_curvature, 0, 2)
206  mainlayout.addLayout(tslayout)
207  # Add helping text
208  dragdrop = QtGui.QLabel('<font color="grey">Drag and drop time series here</font>')
209  dragdrop.setObjectName('dragdrop')
210  mainlayout.addWidget(dragdrop)
211  # Adding calculate buttons and plot button.
212  calcbutton = QtGui.QPushButton('Calculate')
213  calcbutton.setObjectName('calcbutton')
214  calcbutton.setEnabled(False)
215  mainlayout.addWidget(calcbutton)
216  calcbutton.clicked.connect(window.calculate_friction)
217 
218  def setup_ts_edit(self):
219  """
220  Setting up the widget for editing the timeseries. Called when a time series is dropped.
221  """
222  rows = 2
223  # filling up the widgets
224 
225  self.stopTime = self.timehist.timehist[-1, 0]
226  self.startTime = self.timehist.timehist[0, 0]
227  tslayout = self.mainwidget.findChild(QtGui.QGridLayout, 'tslayout')
228  if not hasattr(tslayout, 'made'):
229  label = QtGui.QLabel(self.timehist.name)
230  label.setObjectName('label')
231  tslayout.addWidget(label, rows, 0)
232  else:
233  label = self.mainwidget.findChild(QtGui.QLabel, 'label')
234  label.setText(self.timehist.name)
235 
236  # Selection of starttime
237  if not hasattr(tslayout, 'made'):
238  self.startSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
239  tslayout.addWidget(self.startSlider, rows, 1)
240  self.startSlider.setRange(self.startTime,
241  math.ceil(self.stopTime))
242 
243  if not hasattr(tslayout, 'made'):
244  self.startSpinbox = QtGui.QDoubleSpinBox()
245  tslayout.addWidget(self.startSpinbox, rows, 2)
246  self.startSpinbox.setRange(self.startTime,
247  self.stopTime)
248  self.startSlider.valueChanged.connect(self.startslider_changed)
249  self.startSpinbox.valueChanged.connect(self.startspinbox_changed)
250 
251  if not hasattr(tslayout, 'made'):
252  self.endSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
253  tslayout.addWidget(self.endSlider, rows, 3)
254  self.endSlider.setRange(self.startTime,
255  math.ceil(self.stopTime))
256  if not hasattr(tslayout, 'made'):
257  self.endSpinbox = QtGui.QDoubleSpinBox()
258  tslayout.addWidget(self.endSpinbox, rows, 4)
259  self.endSpinbox.setRange(self.startTime,
260  self.stopTime)
261  self.endSlider.valueChanged.connect(self.endslider_changed)
262  self.endSpinbox.valueChanged.connect(self.endspinbox_changed)
263 
264  self.endSlider.setValue(self.stopTime)
265  self.endSpinbox.setValue(self.stopTime)
266  calcbutton = self.mainwidget.findChild(QtGui.QPushButton, 'calcbutton')
267  calcbutton.setEnabled(True)
268  tslayout.made = True
269 
270  def calculate(self, model):
271  """
272  Calculates stress time histories based on given timehistory and model.
273  :param model:A model of slenders.Slender type
274  """
275  # finding time index
276  self.startindex = np.argmax(self.timehist.timehist[:, 0] > self.startTime)
277  self.startindex -= 1
278  self.stopindex = np.argmax(self.timehist.timehist[:, 0] >= self.stopTime)
279  if self.stopindex < self.startindex:
280  self.stopindex = len(self.time)
281  # finding which part of the curve to use
282  use_constant_curvature = self.mainwidget.findChild(QtGui.QCheckBox, 'use_constant_curvature')
283  if use_constant_curvature.isChecked():
284  curv = np.array([[model.typical_curvature, 0.0]])
285  else:
286  tmp = [self.timehist.timehist[self.startindex:self.stopindex+1, 2],
287  self.timehist.timehist[self.startindex:self.stopindex+1, 3]]
288  curv = np.array(tmp)
289  curv = np.transpose(curv)
290  # dealing with local bending stresses
291  self.time = self.timehist.timehist[self.startindex:self.stopindex+1, 0]
292  nphi = 16
293  ntheta = 16
294  all_bend_stress = coefficients.bending_stress_history(model, curv, nphi=nphi, ntheta=ntheta)
295  # finding bendingstress max and standard deviation
296  self.bendStddev = []
297  self.bendMax = []
298  self.bendMin = []
299  self.bendStress = []
300  thetaindex = []
301  phiindex = []
302  theta = []
303  for i in all_bend_stress:
304  i = np.reshape(i, (-1, ntheta, i.shape[-1]))
305  all_bend_stddev = np.std(i, axis=0)
306  self.bendStddev.append(np.amax(np.amax(all_bend_stddev)))
307  self.bendMax.append(np.amax(np.amax(np.amax(i))))
308  self.bendMin.append(np.amin(np.amin(np.amin(i))))
309  tmp = np.unravel_index(all_bend_stddev.argmax(), all_bend_stddev.shape)
310  self.mainwidget.findChild(QtGui.QCheckBox, 'use_constant_curvature')
311  if use_constant_curvature.isChecked():
312  self.bendStress.append(self.bendMax)
313  else:
314  self.bendStress.append(i[:, tmp[0], tmp[1]])
315  thetaindex.append(tmp[0])
316  theta.append(tmp[0] * 2 * np.pi / ntheta)
317  # phi is either corner number or angle around the crossection depending on the geometry
318  phiindex.append(tmp[1])
319  print('Contact pressures calculated by analytical means')
320  use_constant_tension = self.mainwidget.findChild(QtGui.QCheckBox, 'use_constant_tension')
321  if use_constant_tension.isChecked():
322  self.tension = np.array([model.typical_tension])
323  else:
324  self.tension = np.array(self.timehist.timehist[self.startindex:self.stopindex+1, 1])
325  t_eff = self.tension
326  p_int = self.timehist.timehist[self.startindex:self.stopindex+1,4]
327  p_ext = self.timehist.timehist[self.startindex:self.stopindex+1,5]
328  alpha=model.lay_angle
329  R=model.lay_angle
330  thick=model.thickness
331  A=model.tendon_area
332  E=model.youngs_modulus
333  n=model.comp_number
334 
335  # calculating axial stress
336  tendonstress,_,_,model.contPress=axisymmetric.solver(np.asarray(model.layer_type),np.asarray(model.layer_radii),
337  np.asarray(model.thickness), np.asarray(model.width),
338  np.asarray(model.tendon_area),
339  np.asarray(model.lay_angle), np.asarray(model.comp_number),
340  np.asarray(model.youngs_modulus),
341  np.asarray(model.poisson),
342  np.asarray(model.gap_ini),
343  model.intpresslayer-1, model.extpresslayer-1,
344  np.asarray(t_eff), np.asarray(p_int),np.asarray(p_ext))
345 
346  self.axialStress = []
347  #self.axialStddev = []
348  #self.axialMax = []
349  #self.axialMin = []
350  for i in range(len(model.layer_radii)):
351  self.axialStress.append(tendonstress[:,i])
352  self.axialStddev=np.std(self.axialStress,1)
353  self.axialMax=np.amax(self.axialStress,1)
354  self.axialMin=np.amin(self.axialStress,1)
355 
356  model.critcurv = coefficients.critical_curvature(model, model.contPress,
357  frictionfactors=np.array(model.fricfac))
358  # finding the friction stress
359  # assuming stick, but limiting stick stress to stress as critical curvature
360  self.stickStress = coefficients.stick_stress(model, curv, model.critcurv)
361  for i in range(len(self.stickStress)):
362  self.stickStress[i] = self.stickStress[i] * np.pi / 2.0
363  # finding maximum and standard deviation
364  self.stickStddev = []
365  self.stickMax = []
366  self.stickMin = []
367  for i in self.stickStress:
368  self.stickStddev.append(np.std(i, axis=0))
369  self.stickMax.append(np.amax(i))
370  self.stickMin.append(-np.amax(i))
371 
372  def plot(self, parent):
373  """
374  Plotting the calculated results
375 
376  :param parent: Where the plot should plot itself
377  """
378  fig = matplotlib.figure.Figure()
379  self.canvas = FigureCanvas(fig)
380  self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
381  self.canvas.setFocus()
382  self.canvas.ax1 = fig.add_subplot(111)
383  self.canvas.ax1.set_xlabel('Time')
384  self.canvas.ax1.set_ylabel('Stress')
385 
386  # Building up the plot data:
387  for i in range(len(self.bendStress)):
388  use_constant_curvature = self.mainwidget.findChild(QtGui.QCheckBox, 'use_constant_curvature')
389  if use_constant_curvature.isChecked():
390  self.canvas.ax1.plot([self.startTime, self.stopTime],
391  [self.bendStress[i], self.bendStress[i]],
392  label=('Bend stress for the %d th layer' % (i + 1)))
393  else:
394  self.canvas.ax1.plot(self.time,
395  self.bendStress[i],
396  label=('Bend stress for the %d th layer' % (i + 1)))
397  if use_constant_curvature.isChecked():
398  self.canvas.ax1.plot([self.startTime, self.stopTime],
399  [self.stickStress[i][0], self.stickStress[i][1]],
400  label=('Stick stress for the %d th layer' % (i + 1)))
401  else:
402  self.canvas.ax1.plot(self.time,
403  self.stickStress[i],
404  label=('Stick stress for the %d th layer' % (i + 1)))
405  use_constant_tension = self.mainwidget.findChild(QtGui.QCheckBox, 'use_constant_tension')
406  if use_constant_tension.isChecked():
407  self.canvas.ax1.plot([self.startTime, self.stopTime - 1],
408  [self.axialStress[i], self.axialStress[i]],
409  label=('Axial stress for the %d th layer' % (i + 1)))
410  else:
411  self.canvas.ax1.plot(self.time,
412  self.axialStress[i],
413  label=('Axial stress for the %d th layer' % (i + 1)))
414  self.canvas.ax1.legend(loc='best')
415  self.canvas.ax1.set_title('Stress components')
416  fig.subplots_adjust(left=0.1, right=0.97, top=0.9, bottom=0.2)
417  self.mpl_toolbar = FricCalcNavigationToolbar(self.canvas, parent)
418  self.canvas.mpl_connect('key_press_event', self.on_key_press, )
419  button_widget = QtGui.QToolButton()
420  # add the new widget to the existing navigation toolbar
421  self.mpl_toolbar.addWidget(button_widget)
422  temp = QtGui.QWidget()
423  templayout = QtGui.QVBoxLayout()
424  temp.setLayout(templayout)
425  templayout.addWidget(self.mpl_toolbar)
426  templayout.addWidget(self.canvas)
427  # finding if we already have one of these. if so, remove it and insert this there
428  tabs = parent.count()
429  found = 0
430  for index in range(tabs):
431  text = parent.tabText(index)
432  if text == 'Plot of stresses from friction calculations':
433  widget = parent.widget(index)
434  parent.removeTab(index)
435  widget.deleteLater()
436  found = 1
437  break
438  if found == 0:
439  parent.addTab(temp, 'Plot of stresses from friction calculations')
440  parent.setCurrentIndex(tabs)
441  elif found == 1:
442  # noinspection PyUnboundLocalVariable
443  parent.insertTab(index, temp, 'Plot of stresses from friction calculations')
444  parent.setCurrentIndex(index)
445 
446  def on_key_press(self, event):
447  """
448  Wrapper for custom toolbar.
449  implement the default mpl key press events described at
450  http://matplotlib.org/users/navigation_toolbar.html#navigation-keyboard-shortcuts
451  :param event:
452  :return:
453  """
454  matplotlib.backend_bases.key_press_handler(event, self.canvas, self.mpl_toolbar)
455 
456  def table(self):
457  """
458  Makes a table of results and puts it in a widget.
459  Max min and stddev is calculated shown.
460 
461  :return: A widget with the table in it
462  """
463 
464  items_per_layer = 3
465  ncols = 4
466  tablewidget = QtGui.QTableWidget(items_per_layer * len(self.bendMin), ncols)
467  # filling the tablewidget
468  # header first
469  headeritem = QtGui.QTableWidgetItem('Stress component')
470  tablewidget.setHorizontalHeaderItem(0, headeritem)
471  headeritem = QtGui.QTableWidgetItem('Minimum')
472  headeritem.setToolTip('The minimum obtain through the applied time series')
473  tablewidget.setHorizontalHeaderItem(1, headeritem)
474  headeritem = QtGui.QTableWidgetItem('Maximum')
475  headeritem.setToolTip('The maximum obtain through the applied time series')
476  tablewidget.setHorizontalHeaderItem(2, headeritem)
477  headeritem = QtGui.QTableWidgetItem('Std')
478  headeritem.setToolTip('The he standard deviation of the given stress component')
479  tablewidget.setHorizontalHeaderItem(3, headeritem)
480  for i in range(len(self.bendMin)):
481  # adding bending stress
482  newitem = QtGui.QTableWidgetItem('Local bending stress for layer %d' % (i + 1))
483  newitem.setToolTip('Local bending stress for layer %d' % (i + 1))
484  tablewidget.setItem(i * items_per_layer, 0, newitem)
485  newitem = QtGui.QTableWidgetItem(str(self.bendMin[i]))
486  tablewidget.setItem(i * items_per_layer, 1, newitem)
487  newitem = QtGui.QTableWidgetItem(str(self.bendMax[i]))
488  tablewidget.setItem(i * items_per_layer, 2, newitem)
489  newitem = QtGui.QTableWidgetItem(str(self.bendStddev[i]))
490  tablewidget.setItem(i * items_per_layer, 3, newitem)
491  # adding axial stress
492  newitem = QtGui.QTableWidgetItem('Axial stress for layer %d' % (i + 1))
493  newitem.setToolTip('Axial stress from tension variations %d.' % (i + 1))
494  tablewidget.setItem(i * items_per_layer + 1, 0, newitem)
495  newitem = QtGui.QTableWidgetItem(str(self.axialMin[i]))
496  tablewidget.setItem(i * items_per_layer + 1, 1, newitem)
497  newitem = QtGui.QTableWidgetItem(str(self.axialMax[i]))
498  tablewidget.setItem(i * items_per_layer + 1, 2, newitem)
499  newitem = QtGui.QTableWidgetItem(str(self.axialStddev[i]))
500  tablewidget.setItem(i * items_per_layer + 1, 3, newitem)
501  # adding axial stress
502  newitem = QtGui.QTableWidgetItem('Friction stress estimate for layer %d' % (i + 1))
503  newitem.setToolTip('Estimated based on stick slip, but capped by the stress at critical curvature')
504  tablewidget.setItem(i * items_per_layer + 2, 0, newitem)
505  newitem = QtGui.QTableWidgetItem(str(self.stickMin[i]))
506  tablewidget.setItem(i * items_per_layer + 2, 1, newitem)
507  newitem = QtGui.QTableWidgetItem(str(self.stickMax[i]))
508  tablewidget.setItem(i * items_per_layer + 2, 2, newitem)
509  newitem = QtGui.QTableWidgetItem(str(self.stickStddev[i]))
510  tablewidget.setItem(i * items_per_layer + 2, 3, newitem)
511  tablewidget.setSortingEnabled(True)
512  return tablewidget
513 
514  def startslider_changed(self, value):
515  """
516  :param value: Current value of slider
517  """
518 
519  # noinspection PyUnresolvedReferences
520  if self.startSlider.hasFocus():
521  self.startTime = value
522  # noinspection PyUnresolvedReferences
523  self.startSpinbox.setValue(value)
524  # noinspection PyUnresolvedReferences
525  self.endSlider.setRange(value, math.ceil(self.timehist.timehist[-1, 0]))
526  # noinspection PyUnresolvedReferences
527  self.endSpinbox.setRange(value, self.timehist.timehist[-1, 0])
528 
529  def startspinbox_changed(self, value):
530  """
531  :param value: Current value of spinbox
532  """
533  # noinspection PyUnresolvedReferences
534  if self.startSpinbox.hasFocus():
535  self.startTime = value
536  # noinspection PyUnresolvedReferences
537  self.startSlider.setValue(value)
538  # noinspection PyUnresolvedReferences
539  self.endSpinbox.setRange(value, self.timehist.timehist[-1, 0])
540  # noinspection PyUnresolvedReferences
541  self.endSlider.setRange(value, math.ceil(self.timehist.timehist[-1, 0]))
542 
543  def endslider_changed(self, value):
544  """
545  :param value: Current value of slider
546  """
547  # noinspection PyUnresolvedReferences
548  if self.endSlider.hasFocus():
549  self.stopTime = value
550  # noinspection PyUnresolvedReferences
551  self.endSpinbox.setValue(value)
552  # noinspection PyUnresolvedReferences
553  self.startSpinbox.setRange(self.timehist.timehist[0, 0], value)
554  # noinspection PyUnresolvedReferences
555  self.startSlider.setRange(math.floor(self.timehist.timehist[0, 0]), value)
556 
557  def endspinbox_changed(self, value):
558  """
559  :param value: Current value of spinbox
560  """
561  # noinspection PyUnresolvedReferences
562  if self.endSpinbox.hasFocus():
563  self.stopTime = value
564  # noinspection PyUnresolvedReferences
565  self.endSlider.setValue(value)
566  # noinspection PyUnresolvedReferences
567  self.startSpinbox.setRange(self.timehist.timehist[0, 0], value)
568  # noinspection PyUnresolvedReferences
569  self.startSlider.setRange(math.floor(self.timehist.timehist[0, 0]), value)
570 
571 
572 class FullStressCalc(QtCore.QObject):
573  """ Class for taking care of the full stress calculations
574  """
575  removeFullCalcResultSignal = QtCore.Signal()
576 
577  def __init__(self):
578  super(FullStressCalc, self).__init__()
579  self.timehists = []
580  self.removeButtons = []
581  self.labels = []
582  self.startSliders = []
583  self.startSpinboxes = []
584  self.endSliders = []
585  self.endSpinboxes = []
586  # defined in setup_tab
587  self.mainwidget = None
588  self.headerStartLinker = None
589  self.headerStopLinker = None
590  # container widget for time histories
591  self.widget = None
592  # defined in calculate
593  # list of analyses to be run
594  self.analyses = None
595  # plot
596  self.canvas = None
597  self.mpl_toolbar = None
598  # list of plots
599  self.plotlist = []
600  # container for plotted lines
601  self.lines = []
602 
603  def setup_tab(self, window):
604  """
605  Method for setting up the tab where user sets preferences
606  :param window: The main application window
607  """
608  self.mainwidget = QtGui.QWidget()
609  self.mainwidget.setAcceptDrops(True)
610  self.mainwidget.installEventFilter(window)
611  mainlayout = QtGui.QVBoxLayout()
612  self.mainwidget.setLayout(mainlayout)
613  title = QtGui.QLabel('<H1> Full stress calculations</H1>')
614  mainlayout.addWidget(title)
615  analysiscombo_layout = QtGui.QHBoxLayout()
616  analysiscombobox_text = QtGui.QLabel('Choose local methodology')
617  analysiscombo_layout.addWidget(analysiscombobox_text)
618  analysis_combobox = QtGui.QComboBox()
619  analysis_combobox.setObjectName('analysis_combobox')
620  analysis_combobox.addItem('Use analytical local analysis')
621  analysis_combobox.currentIndexChanged.connect(self.localmethod)
622  analysiscombo_layout.addWidget(analysis_combobox)
623  mainlayout.addLayout(analysiscombo_layout)
624  setupwidget = QtGui.QWidget()
625  setup_layout = QtGui.QHBoxLayout()
626  setup_layout.setObjectName('setup_layout')
627  setupwidget.setLayout(setup_layout)
628  self.localmethod(setup_layout)
629  mainlayout.addWidget(setupwidget)
630  tslayout = QtGui.QGridLayout()
631  tslayout.setObjectName('tslayout')
632  removeall_button = QtGui.QPushButton('Remove all')
633  tslayout.addWidget(removeall_button, 0, 0)
634  removeall_button.clicked.connect(self.remove_all_ts)
635  header_name = QtGui.QLabel('Name')
636  tslayout.addWidget(header_name, 0, 1)
637  header_starttime = QtGui.QLabel('Start time')
638  tslayout.addWidget(header_starttime, 0, 2)
639  self.headerStartLinker = QtGui.QCheckBox()
640  self.headerStartLinker.setToolTip('Set same starttime for all timeseries')
641  tslayout.addWidget(self.headerStartLinker, 0, 3)
642  header_starttime = QtGui.QLabel('Stop time')
643  tslayout.addWidget(header_starttime, 0, 4)
644  self.headerStopLinker = QtGui.QCheckBox()
645  self.headerStopLinker.setToolTip('Link stop time for all timeseries')
646  tslayout.addWidget(self.headerStopLinker, 0, 5)
647  scrollarea = QtGui.QScrollArea()
648  scrollarea.setWidgetResizable(True)
649  self.widget = QtGui.QWidget()
650  self.widget.setLayout(tslayout)
651  scrollarea.setWidget(self.widget)
652  mainlayout.addWidget(scrollarea)
653  dragdrop = QtGui.QLabel('<font color="grey">Drag and drop time series here</font>')
654  dragdrop.setObjectName('dragdrop')
655  mainlayout.addWidget(dragdrop)
656  calcbutton = QtGui.QPushButton('Calculate')
657  calcbutton.setObjectName('calcbutton')
658  calcbutton.setEnabled(False)
659  calcbutton.clicked.connect(window.fullcalc)
660  mainlayout.addWidget(calcbutton)
661 
662  def add_ts(self, ts):
663  """
664  MEthod for adding a time series. obviously
665  :param ts: time series object
666  """
667  self.timehists.append(ts)
668 
669  def setup_ts_edit(self):
670  """
671  Method for setting up the edit area for the time series
672  """
673  rows = len(self.timehists)
674  self.remove_all_ts(deletedata='no')
675  self.widget.setVisible(False)
676  for i in range(rows):
677  # filling up the widgets
678  # Adding a remove icon
679  removebutton = QtGui.QPushButton(QtGui.QIcon('../icons/remove.png'), '')
680  self.removeButtons.append(removebutton)
681  tslayout = self.mainwidget.findChild(QtGui.QGridLayout, 'tslayout')
682  tslayout.addWidget(self.removeButtons[-1], i + 1, 0)
683  label = QtGui.QLabel(self.timehists[i].name)
684  self.labels.append(label)
685  self.removeButtons[i].clicked.connect(functools.partial(self.remove_ts, self.labels[i]))
686  self.timehists[i].endTime = self.timehists[i].timehist[-1, 0]
687  self.timehists[i].startTime = self.timehists[i].timehist[0, 0]
688  tslayout.addWidget(self.labels[i], i + 1, 1)
689  # Selection of starttime
690  startslider = QtGui.QSlider(QtCore.Qt.Horizontal)
691  self.startSliders.append(startslider)
692  self.startSliders[i].setRange(self.timehists[i].startTime,
693  math.ceil(self.timehists[i].endTime))
694  tslayout.addWidget(self.startSliders[i], i + 1, 2)
695  startspinbox = QtGui.QDoubleSpinBox()
696  self.startSpinboxes.append(startspinbox)
697  self.startSpinboxes[i].setRange(self.timehists[i].startTime,
698  self.timehists[i].endTime)
699  # Connecting them to each other
700  self.startSliders[i].valueChanged.connect(functools.partial(self.startslider_changed, self.labels[i]))
701  self.startSpinboxes[i].valueChanged.connect(functools.partial(self.startspinbox_changed, self.labels[i]))
702  tslayout.addWidget(self.startSpinboxes[i], i + 1, 3)
703  # selection of endtime
704  endslider = QtGui.QSlider(QtCore.Qt.Horizontal)
705  self.endSliders.append(endslider)
706  self.endSliders[i].setRange(self.timehists[i].startTime,
707  math.ceil(self.timehists[i].endTime))
708  tslayout.addWidget(self.endSliders[i], i + 1, 4)
709  endspinbox = QtGui.QDoubleSpinBox()
710  self.endSpinboxes.append(endspinbox)
711  self.endSpinboxes[i].setRange(self.timehists[i].startTime,
712  self.timehists[i].endTime)
713  # connecting the widgets
714  self.endSliders[i].valueChanged.connect(functools.partial(self.endslider_changed, self.labels[i]))
715  self.endSpinboxes[i].valueChanged.connect(functools.partial(self.endspinbox_changed, self.labels[i]))
716  tslayout.addWidget(self.endSpinboxes[i], i + 1, 5)
717  self.endSliders[i].setValue(self.timehists[i].endTime)
718  self.endSpinboxes[i].setValue(self.timehists[i].endTime)
719  calcbutton = self.mainwidget.findChild(QtGui.QPushButton, 'calcbutton')
720  calcbutton.setEnabled(True)
721  self.widget.setVisible(True)
722 
723  def localmethod(self, setup_layout):
724  """
725  Method for setting up an area where the user can choose parameters to be used.
726  Should be split up if more options than analyticalare added
727  :param setup_layout: The parent layout in this case
728  """
729  analysis_combobox = self.mainwidget.findChild(QtGui.QComboBox, 'analysis_combobox')
730  text = analysis_combobox.currentText()
731  item = setup_layout.itemAt(0)
732  if item is not None:
733  widget = item.widget()
734  setup_layout.removeWidget(widget)
735  widget.hide()
736  if text == 'Use analytical local analysis':
737  # calculate some data and put them in the left menu
738  if not self.mainwidget.findChild(QtGui.QGridLayout, 'analytical_layout'):
739  analytical_layout = QtGui.QGridLayout()
740  label = QtGui.QLabel('<H2>Analytical settings</H2>')
741  analytical_layout.addWidget(label, 0, 0, 1, 3)
742  analytical_widget = QtGui.QWidget()
743  analytical_widget.setObjectName('analytical_widget')
744  analytical_widget.setLayout(analytical_layout)
745  corelabel = QtGui.QLabel('Number of cores for calculation')
746  analytical_layout.addWidget(corelabel, 1, 0, 1, 1)
747  corespinbox = QtGui.QSpinBox()
748  corespinbox.setObjectName('corespinbox')
749  corespinbox.setRange(1, 1000)
750  bandlabel = QtGui.QLabel('Bend model used for local bending stress')
751  analytical_layout.addWidget(bandlabel, 1, 2, 1, 1)
752  bendcombobox = QtGui.QComboBox()
753  bendcombobox.setObjectName('bendcombobox')
754  bendcombobox.addItem('Savik')
755  bendcombobox.addItem('Tan')
756  analytical_layout.addWidget(bendcombobox, 1, 3, 1, 1)
757  analytical_layout.addWidget(corespinbox, 1, 1, 1, 1)
758  thetalabel = QtGui.QLabel('Number of calculation points around the crossection')
759  analytical_layout.addWidget(thetalabel, 2, 0, 1, 1)
760  theta_combobox = QtGui.QComboBox()
761  theta_combobox.setObjectName('theta_combobox')
762  theta_combobox.addItem('4')
763  theta_combobox.addItem('8')
764  theta_combobox.addItem('16')
765  theta_combobox.addItem('32')
766  theta_combobox.addItem('64')
767  theta_combobox.setCurrentIndex(2)
768  analytical_layout.addWidget(theta_combobox, 2, 1, 1, 1)
769  philabel = QtGui.QLabel('Number of calculation points around the tendon')
770  analytical_layout.addWidget(philabel, 2, 2, 1, 1)
771  phi_combobox = QtGui.QComboBox()
772  phi_combobox.setObjectName('phi_combobox')
773  phi_combobox.addItem('4')
774  phi_combobox.addItem('8')
775  phi_combobox.addItem('16')
776  phi_combobox.addItem('32')
777  phi_combobox.addItem('64')
778  phi_combobox.setCurrentIndex(2)
779  phi_combobox.setToolTip('Only applicable for circular tendons')
780  analytical_layout.addWidget(phi_combobox, 2, 3, 1, 1)
781  else:
782  analytical_widget = self.mainwidget.findChild(QtGui.QWidget, 'analytical_widget')
783  analytical_widget.show()
784  setup_layout.addWidget(analytical_widget)
785  elif text == 'None':
786  displaytext = QtGui.QLabel('<font color="grey">You need to choose a local method</font>')
787  layout = QtGui.QHBoxLayout()
788  layout.addWidget(displaytext)
789  textwidget = QtGui.QWidget()
790  textwidget.setLayout(layout)
791  setup_layout.addWidget(textwidget)
792 
793  def remove_all_ts(self, deletedata='yes'):
794  """
795  Method for removing all the timeseries from view, and with option for also removing them from calculation scope
796  :param deletedata: Toggle for whether the underlying data should be removed
797  """
798  self.widget.setVisible(False)
799  for i in range(len(self.startSliders)):
800  self.remove_ts(self.labels[0], deletedata=deletedata)
801  self.widget.setVisible(True)
802 
803  def remove_ts(self, label, deletedata='yes'):
804  """
805  Method for removing a single time series from view. With option for removing the time
806  series from calculations scope as well
807  :param label: The label of the time series
808  :param deletedata:Toggle for whether the underlying data should be removed
809  """
810  # finding the row which have the given label
811  i = self.index_from_label(label)
812  # deleting data and corresponding widgets
813  tslayout = self.mainwidget.findChild(QtGui.QGridLayout, 'tslayout')
814  tslayout.removeWidget(self.removeButtons[i])
815  self.removeButtons[i].deleteLater()
816  del self.removeButtons[i]
817 
818  tslayout.removeWidget(self.labels[i])
819  self.labels[i].deleteLater()
820  del self.labels[i]
821 
822  tslayout.removeWidget(self.startSliders[i])
823  self.startSliders[i].deleteLater()
824  del self.startSliders[i]
825 
826  tslayout.removeWidget(self.startSpinboxes[i])
827  self.startSpinboxes[i].deleteLater()
828  del self.startSpinboxes[i]
829 
830  tslayout.removeWidget(self.endSliders[i])
831  self.endSliders[i].deleteLater()
832  del self.endSliders[i]
833 
834  tslayout.removeWidget(self.endSpinboxes[i])
835  self.endSpinboxes[i].deleteLater()
836  del self.endSpinboxes[i]
837  if deletedata == 'yes':
838  del self.timehists[i]
839 
840  # When ts is removed, plot interactivty is no longer working -> remove
841  self.removeFullCalcResultSignal.emit()
842 
843  def startslider_changed(self, label, value):
844  """
845  Method for keeping track of slider. With possible coupling between elements
846  :param label:Label of the time series of which the slider belong
847  :param value:Curent value of slider
848  """
849  # finding the row which have the given label
850  row = self.index_from_label(label)
851  if self.startSliders[row].hasFocus():
852  if self.headerStartLinker.isChecked():
853  increment = value - self.timehists[row].startTime
854  for i in range(len(self.startSliders)):
855  tmp = min(self.timehists[i].startTime + increment, self.timehists[i].endTime)
856  tmp = max(tmp, 0)
857  self.timehists[i].startTime = tmp
858  self.startSliders[i].setValue(self.timehists[i].startTime)
859  self.startSpinboxes[i].setValue(self.timehists[i].startTime)
860  self.endSpinboxes[i].setRange(tmp, self.timehists[i].timehist[-1, 0])
861  self.endSliders[i].setRange(tmp, math.ceil(self.timehists[i].timehist[-1, 0]))
862  else:
863  self.timehists[row].startTime = value
864  self.startSpinboxes[row].setValue(value)
865  self.endSpinboxes[row].setRange(value, self.timehists[row].timehist[-1, 0])
866  self.endSliders[row].setRange(value, math.ceil(self.timehists[row].timehist[-1, 0]))
867 
868  def startspinbox_changed(self, label, value):
869  """
870  Method for keeping track of spinbox. With possible coupling between elements
871  :param label:Label of the time series of which the slider belong
872  :param value:Curent value of slider
873  """
874  # finding the row which have the given label
875  row = self.index_from_label(label)
876  if self.startSpinboxes[row].hasFocus():
877  if self.headerStartLinker.isChecked():
878  increment = value - self.timehists[row].startTime
879  for i in range(len(self.startSpinboxes)):
880  tmp = min(self.timehists[i].startTime + increment, self.timehists[i].endTime)
881  tmp = max(tmp, 0)
882  self.timehists[i].startTime = tmp
883  self.startSliders[i].setValue(self.timehists[i].startTime)
884  self.startSpinboxes[i].setValue(self.timehists[i].startTime)
885  self.endSpinboxes[i].setRange(tmp, self.timehists[i].timehist[-1, 0])
886  self.endSliders[i].setRange(tmp, math.ceil(self.timehists[i].timehist[-1, 0]))
887  else:
888  self.timehists[row].startTime = value
889  self.startSliders[row].setValue(value)
890  self.endSpinboxes[row].setRange(value, self.timehists[row].timehist[-1, 0])
891  self.endSliders[row].setRange(value, math.ceil(self.timehists[row].timehist[-1, 0]))
892 
893  def endslider_changed(self, label, value):
894  """
895  Method for keeping track of slider. With possible coupling between elements
896  :param label:Label of the time series of which the slider belong
897  :param value:Curent value of slider
898  """
899  # finding the row which have the given label
900  row = self.index_from_label(label)
901  if self.endSliders[row].hasFocus():
902  if self.headerStopLinker.isChecked():
903  increment = value - self.timehists[row].endTime
904  for i in range(len(self.endSliders)):
905  tmp = max(self.timehists[i].endTime + increment, self.timehists[i].startTime)
906  tmp = min(tmp, self.timehists[i].timehist[-1, 0])
907  self.timehists[i].endTime = tmp
908  self.endSliders[i].setValue(self.timehists[i].endTime)
909  self.endSpinboxes[i].setValue(self.timehists[i].endTime)
910  self.startSpinboxes[i].setRange(self.timehists[row].timehist[0, 0], tmp)
911  self.startSliders[i].setRange(math.floor(self.timehists[row].timehist[0, 0]), tmp)
912  else:
913  self.timehists[row].endTime = value
914  self.endSpinboxes[row].setValue(value)
915  self.startSpinboxes[row].setRange(self.timehists[row].timehist[0, 0], value)
916  self.startSliders[row].setRange(math.floor(self.timehists[row].timehist[0, 0]), value)
917 
918  def endspinbox_changed(self, label, value):
919  """
920  Method for keeping track of slider. With possible coupling between elements
921  :param label:Label of the time series of which the spinbox belong
922  :param value:Curent value of slider
923  """
924  # finding the row which have the given label
925  row = self.index_from_label(label)
926  if self.endSpinboxes[row].hasFocus():
927  if self.headerStopLinker.isChecked():
928  increment = value - self.timehists[row].endTime
929  for i in range(len(self.endSpinboxes)):
930  tmp = max(self.timehists[i].endTime + increment, self.timehists[i].startTime)
931  tmp = min(tmp, self.timehists[i].timehist[-1, 0])
932  self.timehists[i].endTime = tmp
933  self.endSliders[i].setValue(self.timehists[i].endTime)
934  self.endSpinboxes[i].setValue(self.timehists[i].endTime)
935  self.startSpinboxes[i].setRange(0, tmp)
936  self.startSliders[i].setRange(0, tmp)
937  else:
938  self.timehists[row].endTime = value
939  self.endSliders[row].setValue(value)
940  self.startSpinboxes[row].setRange(0, value)
941  self.startSliders[row].setRange(0, value)
942 
943  def calculate(self, model):
944  """
945  Method responsible for setting up the calculation. Calculation thrown to threads
946  :param model: The model of the riser. Type slenders.Slender
947  """
948  self.analyses = []
949  calcbutton = self.mainwidget.findChild(QtGui.QPushButton, 'calcbutton')
950  calcbutton.setEnabled(False)
951  analysis_combobox = self.mainwidget.findChild(QtGui.QComboBox, 'analysis_combobox')
952  if analysis_combobox.currentText() == 'Use analytical local analysis':
953  corespinbox = self.mainwidget.findChild(QtGui.QSpinBox, 'corespinbox')
954  cores = corespinbox.value()
955  analysespercore = math.ceil(len(self.timehists) / cores)
956  theta_combobox = self.mainwidget.findChild(QtGui.QComboBox, 'theta_combobox')
957  ntheta = int(theta_combobox.currentText())
958  phi_combobox = self.mainwidget.findChild(QtGui.QComboBox, 'phi_combobox')
959  nphi = int(phi_combobox.currentText())
960  bendcombobox = self.mainwidget.findChild(QtGui.QComboBox, 'bendcombobox')
961  bendmodel = bendcombobox.currentText()
962  properties = AnalysisProp('Analytical', ntheta, nphi, bendmodel, model)
963  for i in range(cores):
964  startindex = i * analysespercore
965  stopindex = min(analysespercore * (i + 1), len(self.timehists))
966 
967  timehists = self.timehists[startindex:stopindex]
968  numbers = list(range(startindex, stopindex))
969  self.analyses.append(FullAnalysisThread(model, timehists, numbers, properties))
970  # self.analyses[-1].resultFinishedSignal.connect(self.receiveFullCalcs)
971  self.analyses[-1].finishedSignal.connect(self.enablecalcbutton)
972  self.analyses[-1].start()
973 
974  def index_from_label(self, label):
975  """
976  Method for finding the index in the time series vector .
977  :param label: Label of the timeseries
978  :return:
979  """
980  for i in range(len(self.labels)):
981  if self.labels[i] == label:
982  return i
983 
984  def index_from_name(self, name):
985  """
986  Method for finding the index in the time series vector .
987  :param name: Name of the timeseries
988  :return:
989  """
990  for i in range(len(self.timehists)):
991  if self.timehists[i].name == name:
992  return i
993 
994  # noinspection PyChainedComparisons
995  def plot(self, plotdata, layout):
996  """
997  Plots data on the layout <layout>. Uses the color given in plotdata
998  :param plotdata: object of PlotData type.
999  :param layout: Where to add the plot
1000  """
1001 
1002  if not self.canvas:
1003  fig = matplotlib.figure.Figure()
1004  self.canvas = FigureCanvas(fig)
1005  self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
1006  self.canvas.setFocus()
1007  self.canvas.ax1 = fig.add_subplot(111)
1008  fig.subplots_adjust(left=0.1, right=0.97, top=0.9, bottom=0.2)
1009  self.mpl_toolbar = FullCalcNavigationToolbar(self.canvas, None)
1010  self.canvas.mpl_connect('key_press_event', self.on_key_press, )
1011  anotherwidget = QtGui.QToolButton()
1012  # add the new widget to the existing navigation toolbar
1013  self.mpl_toolbar.addWidget(anotherwidget)
1014  temp = QtGui.QWidget()
1015  plotlayout = QtGui.QVBoxLayout()
1016  plotlayout.setObjectName('plotlayout')
1017  plotlayout.addWidget(self.mpl_toolbar)
1018  plotlayout.addWidget(self.canvas)
1019 
1020  for plot in plotdata:
1021  tsnumber = self.index_from_name(plot.label)
1022  fname = 'tmp/fullresult_' + str(tsnumber) + '.h5'
1023  f = h5py.File(fname, 'r')
1024  startindex, endindex = find_indices(self.timehists[tsnumber].startTime, self.timehists[tsnumber].endTime
1025  , self.timehists[tsnumber].timehist[:, 0])
1026  if plot.type == 'Axial stress':
1027  if plot.addRemove == 'Add':
1028  x_plot = self.timehists[tsnumber].timehist[startindex:endindex, 0]
1029  y_plot = f[self.timehists[tsnumber].name + '/AxialStress'][str(plot.layer - 1)]
1030  legend = plot.label + '/AxialStress/Layer' + str(plot.layer)
1031  color = (
1032  plot.color[0] * (1.0 / 255.0), plot.color[1] * (1.0 / 255.0), plot.color[2] * (1.0 / 255.0))
1033  self.plotlist.append(plot)
1034  else:
1035  # find where in the labellist given plot is
1036  for i in range(len(self.plotlist)):
1037  if self.plotlist[i].type == plot.type and self.plotlist[i].layer == plot.layer and \
1038  self.plotlist[i].label == plot.label:
1039  del self.plotlist[i]
1040  self.lines[i].pop(0).remove()
1041  self.lines.pop(i)
1042  break
1043 
1044  if plot.type == 'Critical curvature':
1045  if plot.addRemove == 'Add':
1046  x_plot = self.timehists[tsnumber].timehist[startindex:endindex, 0]
1047  y_plot = f[self.timehists[tsnumber].name + '/CriticalCurvature'][str(plot.layer - 1)]
1048  legend = plot.label + '/CriticalCurvature/Layer' + str(plot.layer)
1049  color = (
1050  plot.color[0] * (1.0 / 255.0), plot.color[1] * (1.0 / 255.0), plot.color[2] * (1.0 / 255.0))
1051  self.plotlist.append(plot)
1052  else:
1053  # find where in the labellist given plot is
1054  for i in range(len(self.plotlist)):
1055  if self.plotlist[i].type == plot.type and self.plotlist[i].layer == plot.layer and \
1056  self.plotlist[i].label == plot.label:
1057  del self.plotlist[i]
1058  self.lines[i].pop(0).remove()
1059  self.lines.pop(i)
1060  break
1061 
1062  if plot.type == 'Stick stress':
1063  if plot.addRemove == 'Add':
1064  x_plot = self.timehists[tsnumber].timehist[startindex:endindex, 0]
1065  y_plot = f[self.timehists[tsnumber].name + '/MaxStickStress'][str(plot.layer - 1)]
1066  legend = plot.label + '/MaxStickStress/Layer' + str(plot.layer)
1067  color = (
1068  plot.color[0] * (1.0 / 255.0), plot.color[1] * (1.0 / 255.0), plot.color[2] * (1.0 / 255.0))
1069  self.plotlist.append(plot)
1070  else:
1071  # find where in the labellist given plot is
1072  for i in range(len(self.plotlist)):
1073  if self.plotlist[i].type == plot.type and self.plotlist[i].layer == plot.layer and \
1074  self.plotlist[i].label == plot.label:
1075  del self.plotlist[i]
1076  self.lines[i].pop(0).remove()
1077  self.lines.pop(i)
1078  break
1079 
1080  if plot.type == 'Local bending stress':
1081  if plot.addRemove == 'Add':
1082  ntheta = f[self.timehists[tsnumber].name + '/LocalBendingStress'][str(plot.layer - 1)].shape[1]
1083  if f[self.timehists[tsnumber].name + '/StressResultant'][str(plot.layer - 1)].ndim==3:
1084  nphi = f[self.timehists[tsnumber].name + '/LocalBendingStress'][str(plot.layer - 1)].shape[2]
1085  for thetaindex in range(ntheta):
1086  theta = thetaindex * 2 * np.pi / ntheta
1087  if theta >= plot.theta - 1.0e-5:
1088  break
1089  if f[self.timehists[tsnumber].name + '/StressResultant'][str(plot.layer - 1)].ndim==3:
1090  if plot.corner:
1091  for phiindex in range(nphi):
1092  if phiindex + 1 == plot.cornerPhi:
1093  break
1094  else:
1095  for phiindex in range(nphi):
1096  phi = phiindex * 2 * np.pi / nphi
1097  if phi >= plot.cornerPhi - 1.0e-5:
1098  break
1099  x_plot = self.timehists[tsnumber].timehist[startindex:endindex, 0]
1100  y_plot = f[self.timehists[tsnumber].name + '/LocalBendingStress'][
1101  str(plot.layer - 1)][:, thetaindex, phiindex]
1102  if plot.corner:
1103  legend = plot.label + '/LocalBendingStress/Layer' + str(plot.layer) + 'Theta' + str(
1104  theta) + 'Corner' + str(phiindex)
1105  else:
1106  # noinspection PyUnboundLocalVariable
1107  legend = plot.label + '/LocalBendingStress/Layer' + str(plot.layer) + 'Theta' + str(
1108  theta) + 'Phi' + str(phi)
1109  if f[self.timehists[tsnumber].name + '/StressResultant'][str(plot.layer - 1)].ndim==2:
1110  x_plot = self.timehists[tsnumber].timehist[startindex:endindex, 0]
1111  y_plot = f[self.timehists[tsnumber].name + '/LocalBendingStress'][
1112  str(plot.layer - 1)][:, thetaindex]
1113  legend = plot.label + '/LocalBendingStress/Layer' + str(plot.layer) + 'Theta' + str(
1114  theta)
1115 
1116  color = (
1117  plot.color[0] * (1.0 / 255.0), plot.color[1] * (1.0 / 255.0), plot.color[2] * (1.0 / 255.0))
1118  self.plotlist.append(plot)
1119  else:
1120  for i in range(len(self.plotlist)):
1121  if self.plotlist[i].type == plot.type and self.plotlist[i].layer == plot.layer and \
1122  self.plotlist[i].label == plot.label:
1123  del self.plotlist[i]
1124  self.lines[i].pop(0).remove()
1125  self.lines.pop(i)
1126  break
1127  if plot.type == 'Friction stress':
1128  if plot.addRemove == 'Add':
1129  ntheta = f[self.timehists[tsnumber].name + '/FrictionStress'][str(plot.layer - 1)].shape[1]
1130  for thetaindex in range(ntheta):
1131  theta = thetaindex * 2 * np.pi / ntheta
1132  if theta >= plot.theta - 1.0e-5:
1133  break
1134  x_plot = self.timehists[tsnumber].timehist[startindex:endindex, 0]
1135  y_plot = f[self.timehists[tsnumber].name + '/FrictionStress'][str(plot.layer - 1)][:, thetaindex]
1136  legend = plot.label + '/FrictionStress/Layer' + str(plot.layer) + 'Theta' + str(theta)
1137  color = (
1138  plot.color[0] * (1.0 / 255.0), plot.color[1] * (1.0 / 255.0), plot.color[2] * (1.0 / 255.0))
1139  self.plotlist.append(plot)
1140  else:
1141  for i in range(len(self.plotlist)):
1142  if self.plotlist[i].type == plot.type and self.plotlist[i].layer == plot.layer and \
1143  self.plotlist[i].label == plot.label:
1144  del self.plotlist[i]
1145  self.lines[i].pop(0).remove()
1146  del self.lines[i]
1147  # self.lines.pop(i)
1148  break
1149  if plot.type == 'Stress resultant':
1150  if plot.addRemove == 'Add':
1151  ntheta = f[self.timehists[tsnumber].name + '/StressResultant'][str(plot.layer - 1)].shape[1]
1152  if f[self.timehists[tsnumber].name + '/StressResultant'][str(plot.layer - 1)].ndim==3:
1153  nphi = f[self.timehists[tsnumber].name + '/StressResultant'][str(plot.layer - 1)].shape[2]
1154  for thetaindex in range(ntheta):
1155  theta = thetaindex * 2 * np.pi / ntheta
1156  if theta >= plot.theta - 1.0e-5:
1157  break
1158  if f[self.timehists[tsnumber].name + '/StressResultant'][str(plot.layer - 1)].ndim==3:
1159  if plot.corner:
1160  for phiindex in range(nphi):
1161  if phiindex + 1 == plot.cornerPhi:
1162  break
1163  else:
1164  for phiindex in range(nphi):
1165  phi = phiindex * 2 * np.pi / nphi
1166  if phi >= plot.cornerPhi - 1.0e-5:
1167  break
1168  x_plot = self.timehists[tsnumber].timehist[startindex:endindex, 0]
1169  if f[self.timehists[tsnumber].name + '/StressResultant'][str(plot.layer - 1)].ndim==3:
1170  y_plot = f[self.timehists[tsnumber].name + '/StressResultant'][
1171  str(plot.layer - 1)][:, thetaindex, phiindex]
1172  if plot.corner:
1173  legend = plot.label + '/StressResultant/Layer' + str(plot.layer) + 'Theta' + str(
1174  theta) + 'Corner' + str(phiindex)
1175  else:
1176  # noinspection PyUnboundLocalVariable
1177  legend = plot.label + '/StressResultant/Layer' + str(plot.layer) + 'Theta' + str(
1178  theta) + 'Phi' + str(phi)
1179  elif f[self.timehists[tsnumber].name + '/StressResultant'][str(plot.layer - 1)].ndim==2:
1180  y_plot = f[self.timehists[tsnumber].name + '/StressResultant'][
1181  str(plot.layer - 1)][:, thetaindex]
1182  legend = plot.label + '/StressResultant/Layer' + str(plot.layer) + 'Theta' + str(
1183  theta)
1184 
1185  color = (
1186  plot.color[0] * (1.0 / 255.0), plot.color[1] * (1.0 / 255.0), plot.color[2] * (1.0 / 255.0))
1187  self.plotlist.append(plot)
1188  else:
1189  for i in range(len(self.plotlist)):
1190  if self.plotlist[i].type == plot.type and self.plotlist[i].layer == plot.layer and \
1191  self.plotlist[i].label == plot.label:
1192  del self.plotlist[i]
1193  self.lines[i].pop(0).remove()
1194  self.lines.pop(i)
1195  break
1196  # Plotting done here, removal done at finding point
1197  if plot.addRemove == 'Add':
1198  # noinspection PyUnboundLocalVariable,PyUnboundLocalVariable,PyUnboundLocalVariable,PyUnboundLocalVariable
1199  self.lines.append(self.canvas.ax1.plot(x_plot, y_plot, label=legend, c=color))
1200  f.close()
1201  plotted = self.canvas.ax1.get_lines()
1202  max_ylim = -float('Inf')
1203  min_ylim = float('Inf')
1204  max_xlim = -float('Inf')
1205  min_xlim = float('Inf')
1206  for plot in plotted:
1207  xdata = plot.get_xdata()
1208  ydata = plot.get_ydata()
1209  max_yplot = max(ydata)
1210  if max_yplot >= 0 and max_yplot > max_ylim:
1211  max_ylim = max(max_ylim, max_yplot * 1.1 + 0.1)
1212  else:
1213  max_ylim = max(max_ylim, max_yplot * 0.9 + 0.1)
1214  min_yplot = min(ydata)
1215  if min_yplot >= 0 and min_yplot < min_ylim:
1216  min_ylim = min(min_ylim, min_yplot * 0.9 - 0.1)
1217  else:
1218  min_ylim = min(min_ylim, min_yplot * 1.1 - 0.1)
1219  max_xplot = max(xdata)
1220  if max_xplot >= 0 and max_xplot > max_xlim:
1221  max_xlim = max(max_xlim, max_xplot * 1.1 + 0.1)
1222  else:
1223  max_xlim = max(max_xlim, max_xplot * 0.9 + 0.1)
1224  min_xplot = min(xdata)
1225  if min_xplot >= 0 and min_xplot < min_xlim:
1226  min_xlim = min(min_xlim, min_xplot * 0.9 - 0.1)
1227  else:
1228  min_xlim = min(min_xlim, min_xplot * 1.1 - 0.1)
1229  # set plot limits
1230  self.canvas.ax1.set_ylim([min_ylim, max_ylim])
1231  self.canvas.ax1.set_xlim([min_xlim, max_xlim])
1232 
1233  # find were to put this
1234  found = False
1235  for i in range(layout.count()):
1236  widget = layout.widget(i)
1237  if hasattr(widget, 'accessibleName'):
1238  name = widget.accessibleName()
1239  if name == 'plotwidget':
1240  # widget.deleteLater()
1241  found = True
1242  break
1243  if not found:
1244  plotwidget = QtGui.QWidget()
1245  plotwidget.setAccessibleName('plotwidget')
1246  # noinspection PyUnboundLocalVariable
1247  plotwidget.setLayout(plotlayout)
1248  layout.addWidget(plotwidget)
1249  plotwidget.show()
1250  else:
1251  self.canvas.draw()
1252  gc.collect()
1253 
1254  def deleteplot(self):
1255  """
1256  Method for removign the plot thouroghly
1257  """
1258  self.canvas = None
1259  del self.mpl_toolbar
1260  self.plotlist = []
1261  self.lines = []
1262 
1263  def on_key_press(self, event):
1264  """
1265  implement the default mpl key press events described at
1266  http://matplotlib.org/users/navigation_toolbar.html#navigation-keyboard-shortcuts
1267  """
1268 
1269  matplotlib.backend_bases.key_press_handler(event, self.canvas, self.mpl_toolbar)
1270 
1271  def enablecalcbutton(self):
1272  """
1273  Enables the calcbutton, so new calculations can be carried out
1274  """
1275  calcbutton = self.mainwidget.findChild(QtGui.QPushButton, 'calcbutton')
1276  calcbutton.setEnabled(True)
1277 
1279  """
1280  Method for merging all the files from the full calculations to one h5 file
1281  """
1282  file_dialog = QtGui.QFileDialog()
1283  file_types = "hdf5 file (*.h5);;Any file (*)"
1284  # show the dialog
1285  fname, extension = file_dialog.getSaveFileName(self.mainwidget, 'Save file', '', file_types)
1286  if fname:
1287  if extension.find('h5') == -1:
1288  # extension not specified
1289  output_file = h5py.File(fname, 'w')
1290  else:
1291  # extension specified
1292  if fname.find('h5', -2) != -1:
1293  # filename ends with h5
1294  output_file = h5py.File(fname, 'w')
1295  else:
1296  # filename not ending with h5
1297  output_file = h5py.File(fname + '.h5', 'w')
1298 
1299  # finding which files to copy
1300  for input_file_name in os.listdir('tmp'):
1301  if fnmatch.fnmatch(input_file_name, 'fullresult*.h5'):
1302  # copy the files
1303  input_file = h5py.File('tmp/' + input_file_name, 'r+')
1304  keys = input_file.keys()
1305  for key in keys:
1306  input_file.copy(key, output_file)
1307  # adding results from memory
1308  index = self.index_from_name(key)
1309  output_file[key].create_dataset('Time', data=self.timehists[index].timehist[:, 0])
1310  output_file[key].create_dataset('Tension', data=self.timehists[index].timehist[:, 1])
1311  output_file[key].create_dataset('Curvature', data=self.timehists[index].timehist[:, 2:4])
1312 
1313  input_file.close()
1314 
1315  output_file.close()
1316 
1317 
1318 class FullAnalysisThread(QtCore.QThread):
1319  """
1320  A thread to carry out full stress calculations.
1321  """
1322  addFullCalcSignal = QtCore.Signal(int)
1323  finishedSignal = QtCore.Signal(bool)
1324 
1325  def __init__(self, model, timeseries, indices, properties):
1326  QtCore.QThread.__init__(self)
1327  self.model = model
1328  self.timeseries = timeseries
1329  self.indices = indices
1330  self.ntheta = properties.ntheta
1331  self.nphi = properties.nphi
1332  self.bendmodel = properties.bendmodel
1333  # used in run and in filedump
1334  # results to be written to file
1335  self.axialstress = None
1336  self.bendstress = None
1337  self.critcurv = None
1338  self.maxStickStress = None
1339  self.fricStress = None
1340  # counter used for filedump
1341  self.currentindex = None
1342 
1343  # noinspection PyPep8
1344  def run(self):
1345  """
1346  Method for running the analysis
1347  """
1348  ntheta = self.ntheta
1349  nphi = self.nphi
1350  bend_model = self.bendmodel
1351  # timsesteps between each dump to file
1352  maxlength = 5000
1353  for k in range(len(self.indices)):
1354  ts = self.timeseries[k]
1355  globalindex = self.indices[k]
1356  globalstartindex, globalstopindex = find_indices(ts.startTime, ts.endTime, ts.timehist[:, 0])
1357  tslength = globalstopindex - globalstartindex
1358  # start midpoint for friction routine
1359  mid=[]
1360  for i in range(len(self.model.layer_radii)):
1361  mid.append([0.0, 0.0])
1362 
1363  parts = math.ceil((globalstopindex - globalstartindex) / maxlength)
1364  for part in range(parts): # maybe one more iteration?
1365  startindex = globalstartindex + part * maxlength
1366  stopindex = min(startindex + maxlength, globalstopindex)
1367 
1368  # finding axial stress
1369  self.axialstress = []
1370  thickness=self.model.thickness
1371  sigma,_,_,contactpressures=axisymmetric.solver(np.asarray(self.model.layer_type),
1372  np.asarray(self.model.layer_radii),
1373  np.asarray(self.model.thickness),
1374  np.asarray(self.model.width),
1375  np.asarray(self.model.tendon_area),
1376  np.asarray(self.model.lay_angle),
1377  np.asarray(self.model.comp_number),
1378  np.asarray(self.model.youngs_modulus),
1379  np.asarray(self.model.poisson),
1380  np.asarray(self.model.gap_ini),
1381  self.model.intpresslayer-1, self.model.extpresslayer-1,
1382  np.asarray(ts.timehist[startindex:stopindex,1]),
1383  np.asarray(ts.timehist[startindex:stopindex,4]),
1384  np.asarray(ts.timehist[startindex:stopindex,5]))
1385  for i in range(len(self.model.layer_radii)):
1386  self.axialstress.append(sigma[:,i])
1387 # self.axialstress.append(coefficients.tension_stress_history(ts.timehist
1388 # [startindex:stopindex, 1],
1389 # i))
1390  # finding local bending stress
1391  # implementation of analysis options should be done once.
1393  ts.timehist[startindex:stopindex, 2:4],
1394  ntheta=ntheta, nphi=max(nphi),
1395  bend_model=bend_model)
1396 
1397  critcurv = coefficients.critical_curvature(self.model, contactpressures,
1398  frictionfactors=np.array(self.model.fricfac))
1399  self.critcurv = []
1400  eff_full_slipcurvature = []
1401  for i in range(len(self.model.layer_radii)):
1402  self.critcurv.append(critcurv[:, i]*np.pi/2.0)
1403  eff_full_slipcurvature.append(critcurv[:, i] * np.pi / 2.0)
1404  self.maxStickStress = coefficients.max_stickstress(self.model, eff_full_slipcurvature)
1405  # for debugging. to be removed
1406  # self.stickStress=coefficients.stick_stress(self.model,ts.timehist[startindex:stopindex,2:4],
1407  # critcurv*np.pi/2.0)
1408  self.fricStress = []
1409  timehist = ts.timehist[startindex:stopindex, 2:4]
1410  for i in range(len(self.model.layer_radii)):
1411  if self.model.layer_type[i]=='wires':
1412  self.fricStress.append(np.empty([len(ts.timehist[startindex:stopindex, 0]), ntheta]))
1413  # removing dots for speed
1414  effectivecurvature = eff_full_slipcurvature[i]
1415  print('i',i)
1416  max_stickstress = self.maxStickStress[i]
1417  stress, mid[i] = coefficients.fric_stress(timehist, effectivecurvature, max_stickstress, mid[i])
1418  for j in range(ntheta):
1419  self.fricStress[i][:, j] = (stress[:, 0] * np.cos(j * 2 * np.pi / ntheta) +
1420  stress[:, 1] * np.sin(j * 2 * np.pi / ntheta))
1421  elif self.model.layer_type[i]=='sheath':
1422  self.fricStress.append(np.empty([len(ts.timehist[startindex:stopindex, 0]), ntheta]))
1423  else:
1424  print('Layer type for layer ',i+1,' not understood')
1425 
1427  for i in range(len(self.axialstress)):
1428  if self.model.layer_type[i]=='wires':
1429  self.resultantstress.append(np.swapaxes(np.swapaxes(self.bendstress[i],0,2)+
1430  np.swapaxes(self.fricStress[i],0,1)+self.axialstress[i],0,2))
1431  elif self.model.layer_type[i]=='sheath':
1432  self.resultantstress.append(np.swapaxes(np.swapaxes(self.bendstress[i],0,1)+
1433  +self.axialstress[i],0,1))
1434 
1435 
1436  self.filedump(part, tslength, k, globalindex)
1437  # the resultsFinishedSignal should be pointer to file!
1438  self.addFullCalcSignal.emit(globalindex)
1439  # self.resultFinishedSignal.emit(self.axialstress,self.bendstress,self.fricStress,self.critcurv,self.max_stickstress,localindex)
1440  self.finishedSignal.emit(True)
1441 
1442  def filedump(self, part, tslength, localindex, globalindex):
1443  """
1444  Method for dumping to file. Makes files, keep track of indices and dumps data
1445  :param part: counter for which part of the analysis is carried out.
1446  :param tslength: Total length of time series
1447  :param globalindex: index in all timeseries analysed
1448  :param localindex: index in timeseries analyzed in this thread
1449  """
1450  fname = 'tmp/fullresult_' + str(globalindex) + '.h5'
1451  # maybe better to keep the hf instance
1452  if part == 0:
1453  self.currentindex = 0
1454  hf = h5py.File(fname, 'w')
1455  # creating groups
1456  #print('globalindex', globalindex)
1457  #print('len(self.timeseries)', len(self.timeseries))
1458  #print('localindex', localindex)
1459  axial = hf.create_group(self.timeseries[localindex].name + '/AxialStress')
1460  bend = hf.create_group(self.timeseries[localindex].name + '/LocalBendingStress')
1461  fric = hf.create_group(self.timeseries[localindex].name + '/FrictionStress')
1462  stressres = hf.create_group(self.timeseries[localindex].name + '/StressResultant')
1463  critcurv = hf.create_group(self.timeseries[localindex].name + '/CriticalCurvature')
1464  maxstick = hf.create_group(self.timeseries[localindex].name + '/MaxStickStress')
1465  # creating datasets
1466  for i in range(len(self.axialstress)):
1467  axial.create_dataset(str(i), (tslength,))
1468  axial[str(i)][self.currentindex:self.currentindex + len(self.axialstress[i])] = self.axialstress[i]
1469  if self.model.layer_type[i]=='wires':
1470  bend.create_dataset(str(i), (tslength, self.ntheta, self.nphi[i]))
1471  elif self.model.layer_type[i]=='sheath':
1472  bend.create_dataset(str(i), (tslength, self.ntheta))
1473  bend[str(i)][self.currentindex:self.currentindex + len(self.bendstress[i])] = self.bendstress[i]
1474  if self.model.layer_type[i]=='wires':
1475  fric.create_dataset(str(i), (tslength, self.ntheta))
1476  fric[str(i)][self.currentindex:self.currentindex + len(self.fricStress[i])] = self.fricStress[i]
1477  if self.model.layer_type[i]=='wires':
1478  stressres.create_dataset(str(i), (tslength, self.ntheta, self.nphi[i]))
1479  elif self.model.layer_type[i]=='sheath':
1480  stressres.create_dataset(str(i), (tslength, self.ntheta))
1481  stressres[str(i)][self.currentindex:self.currentindex + len(self.resultantstress[i])] = self.resultantstress[i]
1482  if self.model.layer_type[i]=='wires':
1483  critcurv.create_dataset(str(i), (tslength,))
1484  critcurv[str(i)][self.currentindex:self.currentindex + len(self.critcurv[i])] = self.critcurv[i]
1485  maxstick.create_dataset(str(i), (tslength,))
1486  maxstick[str(i)][self.currentindex:self.currentindex + len(self.maxStickStress[i])] = \
1487  self.maxStickStress[i]
1488  hf.close()
1489  else:
1490  hf = h5py.File(fname, 'r+')
1491  for i in range(len(self.axialstress)):
1492  axial = hf[self.timeseries[localindex].name + '/AxialStress']
1493  axial[str(i)][self.currentindex:self.currentindex + len(self.axialstress[i])] = self.axialstress[i]
1494  bend = hf[self.timeseries[localindex].name + '/LocalBendingStress']
1495  bend[str(i)][self.currentindex:self.currentindex + len(self.axialstress[i]), :, :] = self.bendstress[i]
1496  fric = hf[self.timeseries[localindex].name + '/FrictionStress']
1497  fric[str(i)][self.currentindex:self.currentindex + len(self.axialstress[i]), :] = self.fricStress[i]
1498  bend = hf[self.timeseries[localindex].name + '/StressResultant']
1499  bend[str(i)][self.currentindex:self.currentindex + len(self.axialstress[i]), :, :] = self.resultantstress[i]
1500  critcurv = hf[self.timeseries[localindex].name + '/CriticalCurvature']
1501  critcurv[str(i)][self.currentindex:self.currentindex + len(self.axialstress[i])] = self.critcurv[i]
1502  maxstick = hf[self.timeseries[localindex].name + '/MaxStickStress']
1503  maxstick[str(i)][self.currentindex:self.currentindex + len(self.axialstress[i])] = self.maxStickStress[
1504  i]
1505  hf.close()
1506  self.currentindex += len(self.axialstress[0])
1507 
1508 
1509 class FricCalcNavigationToolbar(NavigationToolbar):
1510  """
1511  Custom toolbaer for friction class plot
1512  """
1513  picked = QtCore.Signal(int, name='picked')
1514 
1515  def __init__(self, canvas, parent):
1516  NavigationToolbar.__init__(self, canvas, parent)
1517  self.clearButtons = []
1518  # Search through existing buttons
1519  # next use for placement of custom button
1520  nextbutton = None
1521  for c in self.findChildren(QtGui.QToolButton):
1522  if c.text() == 'Customize':
1523  nextbutton = c
1524 
1525  savedata = QtGui.QAction("Save data", self)
1526  savedata.setIcon(QtGui.QIcon("../icons/savedata.png"))
1527  savedata.setCheckable(True)
1528  savedata.setToolTip("Save raw data")
1529  self.picker = savedata
1530  button = QtGui.QToolButton(self)
1531  button.setDefaultAction(self.picker)
1532 
1533  # Add it to the toolbar, and connect up event
1534  self.insertWidget(nextbutton.defaultAction(), button)
1535  savedata.toggled.connect(self.savedata_triggered)
1536 
1537  # Grab the picked event from the canvas
1538  # canvas.mpl_connect('pick_event',self.canvasPicked)
1539 
1540  def savedata_triggered(self, ):
1541  """
1542  Method for saving plot data to h5 file
1543  """
1544 
1545  file_dialog = QtGui.QFileDialog()
1546  file_types = "hdf5 file (*.h5);;Any file (*)"
1547  # show the dialog
1548  fname, extension = file_dialog.getSaveFileName(self, 'Save file', '', file_types)
1549  if fname:
1550  if extension.find('h5') == -1:
1551  # extension not specified
1552  hf = h5py.File(fname)
1553  else:
1554  # extension specified
1555  if fname.find('h5', -2) != -1:
1556  # filename ends with h5
1557  hf = h5py.File(fname)
1558  else:
1559  # filename not ending with h5
1560  hf = h5py.File(fname + '.h5')
1561 
1562  lines = self.canvas.ax1.get_lines()
1563  for line in lines:
1564  xydata = line.get_xydata()
1565  label = line.get_label()
1566  g1 = hf.create_group('frictioncalc/%s' % label)
1567  g1.create_dataset('x', data=xydata[:, 0])
1568  g1.create_dataset('y', data=xydata[:, 1])
1569  hf.close()
1570 
1571 
1573  """
1574  Class for custom toolbar for Full calculation plot
1575  """
1576  def __init__(self, canvas, parent):
1577  FricCalcNavigationToolbar.__init__(self, canvas, parent)
1578 
1579  def savedata_triggered(self, ):
1580  """
1581  Method for saving plot data as h5 file
1582  """
1583  file_dialog = QtGui.QFileDialog()
1584  file_types = "hdf5 file (*.h5);;ASCII file (*.ts)"
1585  # show the dialog
1586  fname, extension = file_dialog.getSaveFileName(self, 'Save file', '', file_types)
1587  if fname:
1588  if extension.find('ts') != -1:
1589  if fname[-3:-1]=='ts':
1590  filename=fname
1591  else:
1592  filename=fname+'.ts'
1593  type = 'ts'
1594  elif extension.find('h5') != -1:
1595  if fname[-2:]=='h5':
1596  filename=fname
1597  else:
1598  filename=fname+'.h5'
1599  type = 'h5'
1600 
1601  lines = self.canvas.ax1.get_lines()
1602  if type == 'ts':
1603  printmatrix=[]
1604  header='Time'
1605  printmatrix.append(lines[0].get_xdata())
1606  for line in lines:
1607  ydata = line.get_ydata()
1608  label = line.get_label()
1609  printmatrix.append(ydata)
1610  header+="\t"+label
1611  npprintmatrix=np.array(printmatrix)
1612  np.savetxt(filename, npprintmatrix.T, delimiter="\t", header=header)
1613 
1614  elif type == 'h5':
1615  hf = h5py.File(filename, 'w')
1616  for line in lines:
1617  xydata = line.get_xydata()
1618  label = line.get_label()
1619  g1 = hf.create_group(label)
1620  g1.create_dataset('Time', data=xydata[:, 0])
1621  g1.create_dataset('Value', data=xydata[:, 1])
1622  hf.close()
1623 
1624 
1625 class PlotData(object):
1626  """
1627  Class for making plot data. Keeps track of what color it should be and whether it should be removed or added
1628  Several plot data instances keep track of each other through colortaken and colorlist Could be made class
1629  variable really
1630  """
1631  def __init__(self, treedata, colorlist, colortaken, add_remove):
1632  self.label = treedata[0]
1633  self.layer = int(treedata[1].split()[-1])
1634  self.type = treedata[2]
1635  self.addRemove = add_remove
1636  if self.addRemove == 'Add':
1637  colormin = min(colortaken)
1638  for i in range(len(colortaken)):
1639  if colortaken[i] == colormin:
1640  self.color = colorlist[i]
1641  self.colorindex = i
1642  break
1643 
1644  def update(self, active, color_taken):
1645  """
1646  :param active: Whether the plot should be active or not
1647  :param color_taken: list of which colors that are currently in use in the plot
1648  """
1649  if self.addRemove == 'Add':
1650  color_taken[self.colorindex] += 1
1651  active.append(self)
1652  elif self.addRemove == 'Remove':
1653  for i in range(len(active)):
1654  if [active[i].type, active[i].label, active[i].layer] == [self.type, self.label, self.layer]:
1655  color_taken[active[i].colorindex] -= 1
1656  del active[i]
1657  break
1658 
1659 
1661  """ As parent, only with one more level of refineent with distinguishing thetas
1662  """
1663  def __init__(self, treedata, colorlist, colortaken, add_remove):
1664  super(FourLevelPlotData, self).__init__(treedata, colorlist, colortaken, add_remove)
1665  self.theta = float(treedata[3].split()[-1])
1666 
1667  def update(self, active, color_taken):
1668  if self.addRemove == 'Add':
1669  color_taken[self.colorindex] += 1
1670  active.append(self)
1671  elif self.addRemove == 'Remove':
1672  for i in range(len(active)):
1673  if hasattr(active, 'theta'):
1674  if ([active[i].type, active[i].label, active[i].layer, active[i].theta] ==
1675  [self.type, self.label, self.layer, self.theta]):
1676  color_taken[active[i].colorindex] -= 1
1677  del active[i]
1678  break
1679 
1680 
1682  """ As parent, only with one more level of refineent with distinguishing phis
1683  """
1684  def __init__(self, treedata, colorlist, colortaken, add_remove):
1685  super(FiveLevelPlotData, self).__init__(treedata, colorlist, colortaken, add_remove)
1686  self.cornerPhi = float(treedata[4].split()[-1])
1687  if treedata[4][0:4] == 'Corn':
1688  self.corner = True
1689  else:
1690  self.corner = False
1691 
1692  def update(self, active, color_taken):
1693  if self.addRemove == 'Add':
1694  color_taken[self.colorindex] += 1
1695  active.append(self)
1696  elif self.addRemove == 'Remove':
1697  for i in range(len(active)):
1698  if hasattr(active, 'theta') and hasattr(active, 'cornerPhi'):
1699  if ([active[i].type, active[i].label, active[i].layer, active[i].theta, active[i].cornerPhi] ==
1700  [self.type, self.label, self.layer, self.theta, self.cornerPhi]):
1701  color_taken[active[i].colorindex] -= 1
1702  del active[i]
1703  break
1704 
1705 
1706 class AnalysisProp(object):
1707  """
1708  Method for grouping together analysis properties
1709  """
1710  def __init__(self, analysistype, ntheta, nphi, bendmodel, model):
1711  if analysistype == 'Analytical':
1712  self.ntheta = ntheta
1713  self.bendmodel = bendmodel
1714  self.nphi = []
1715  for i in range(len(model.layer_radii)):
1716  self.nphi.append(4)
1717 
1718 
1719 def find_indices(startvalue, endvalue, vector):
1720  """
1721  Assumes sorted data.
1722  :param startvalue: start value in vector to find
1723  :param endvalue: End value to find in vector
1724  :param vector:
1725  :return startindex: index of last value smaller or equal to startvalue
1726  :return endindex: first index equal or larger than vector.Bound by length of vector
1727  """
1728  startindex = np.argmax(vector > startvalue)
1729  startindex -= 1
1730  endindex = np.argmax(vector >= endvalue)
1731  endindex = np.amin([endindex, len(vector)])
1732  endindex += 1
1733 
1734  return startindex, endindex
1735 
1736 class FullTreeProxyModel(QtGui.QSortFilterProxyModel):
1737  """
1738  Subclassed proxy model for custom filter behaviour
1739  """
1740  def __init__(self,parent = None):
1741  super(FullTreeProxyModel, self).__init__(parent)
1742 
1743  def filterAcceptsRow(self, sourceRow, sourceParent):
1744  index0 = self.sourceModel().index(sourceRow, 0, sourceParent)
1745  index1 = self.sourceModel().index(sourceRow, 1, sourceParent)
1746  index2 = self.sourceModel().index(sourceRow, 2, sourceParent)
1747 
1748  return ( (self.filterRegExp().indexIn(self.sourceModel().data(index0,QtCore.Qt.DisplayRole)) >= 0
1749  or self.filterRegExp().indexIn(self.sourceModel().data(index1,QtCore.Qt.DisplayRole)) >= 0))
1750 
1751 
def calculate(self, model)
Definition: timehist.py:270
def localmethod(self, setup_layout)
Definition: timehist.py:723
def on_key_press(self, event)
Definition: timehist.py:1263
def __init__(self, treedata, colorlist, colortaken, add_remove)
Definition: timehist.py:1631
def startspinbox_changed(self, value)
Definition: timehist.py:529
def add_ts(self, ts)
Definition: timehist.py:662
def __init__(self, time_filename, histname, directory=None)
Definition: timehist.py:44
def endspinbox_changed(self, value)
Definition: timehist.py:557
def update(self, active, color_taken)
Definition: timehist.py:1667
def enablecalcbutton(self)
Definition: timehist.py:1271
def startspinbox_changed(self, label, value)
Definition: timehist.py:868
def plot(self, plotdata, layout)
Definition: timehist.py:995
def on_key_press(self, event)
Definition: timehist.py:446
def update(self, active, color_taken)
Definition: timehist.py:1644
def add_ts(self, ts)
Definition: timehist.py:163
def __init__(self, treedata, colorlist, colortaken, add_remove)
Definition: timehist.py:1663
def update(self, active, color_taken)
Definition: timehist.py:1692
def fric_stress(curv, eps_mat, sig_mat, midpoint)
def startslider_changed(self, label, value)
Definition: timehist.py:843
def setup_tab(self, window)
Definition: timehist.py:603
def index_from_name(self, name)
Definition: timehist.py:984
def endspinbox_changed(self, label, value)
Definition: timehist.py:918
def __init__(self, parent=None)
Definition: timehist.py:1740
def export_all_results(self)
Definition: timehist.py:1278
def __init__(self, model, timeseries, indices, properties)
Definition: timehist.py:1325
def solver(layerinfo, r, t, b, A, alpha, n, E, nu, gap_ini, intpresslayer, extpresslayer, T_eff, p_int, p_ext)
Definition: axisymmetric.py:8
def plot(self, parent)
Definition: timehist.py:97
def setup_ts_edit(self)
Definition: timehist.py:218
def endslider_changed(self, label, value)
Definition: timehist.py:893
def plot(self, parent)
Definition: timehist.py:372
def __init__(self, canvas, parent)
Definition: timehist.py:1515
def filterAcceptsRow(self, sourceRow, sourceParent)
Definition: timehist.py:1743
def set_from_tim(self, directory)
Definition: timehist.py:59
def bending_stress_history(slenderobject, curvhist, ntheta=16, nphi=16, bend_model="Savik")
def max_stickstress(model, critcurv)
def remove_ts(self, label, deletedata='yes')
Definition: timehist.py:803
def __init__(self)
Definition: timehist.py:125
def __init__(self, treedata, colorlist, colortaken, add_remove)
Definition: timehist.py:1684
def setup_tab(self, window)
Definition: timehist.py:169
def find_indices(startvalue, endvalue, vector)
Definition: timehist.py:1719
def stick_stress(model, curv, critcurv, theta=None)
def __init__(self, analysistype, ntheta, nphi, bendmodel, model)
Definition: timehist.py:1710
def setup_ts_edit(self)
Definition: timehist.py:669
def __init__(self, canvas, parent)
Definition: timehist.py:1576
def calculate(self, model)
Definition: timehist.py:943
def index_from_label(self, label)
Definition: timehist.py:974
def remove_all_ts(self, deletedata='yes')
Definition: timehist.py:793
def critical_curvature(slenderobject, contact_pressure, frictionfactors=np.array([5, 5, 5]))
Definition: coefficients.py:72
def filedump(self, part, tslength, localindex, globalindex)
Definition: timehist.py:1442
def endslider_changed(self, value)
Definition: timehist.py:543
def startslider_changed(self, value)
Definition: timehist.py:514