def setModel(self, model: QAbstractTableModel): super().setModel(model) for row in range(model.rowCount()): for col in range(model.columnCount()): span = model.span(model.index(row, col)) if span.height() > 1 or span.width() > 1: self.setSpan(row, col, span.height(), span.width())
def dataChangeIterator(it: Iterator[_A], model: QAbstractTableModel, *columns: int) -> Iterator[_A]: for i, data in enumerate(it): yield data for column in columns: model.dataChanged.emit(model.index(i, column), model.index(i, column), (Qt.DisplayRole, ))
def __init__(self, *args, model: QAbstractTableModel = None, column_id: int = None, mapping: dict = None, **kwargs): self._model = model self._column_id = column_id super().__init__(*args, **kwargs) self.lstUsedColumns.setItemDelegate(ItemDelegate()) self.lstColors.setItemDelegate(ItemDelegate()) data = self._model.headerData(self._column_id, Qt.Horizontal, role=ColumnDataRole) if data is not None and not isinstance(data, pd.Series): data = pd.Series(data) self._data = data if model is not None and column_id is not None: for i in range(model.columnCount()): index = model.index(0, i) text = model.headerData(i, Qt.Horizontal, Qt.DisplayRole) color = model.headerData(i, Qt.Horizontal, ColorMarkRole) item = ColumnListWidgetItem(text, column=index.column()) if color is not None: item.setBackground(color) if index.column() != column_id: self.lstColumns.addItem(item) self.lstUsedColumns.setSelectionMode(QAbstractItemView.ContiguousSelection) self.lstColumns.setSelectionMode(QAbstractItemView.SingleSelection) self.populate_bins(mapping) colors = QSettings().value('NetworkView/node_colors', [c.name() for c in generate_colors(8)], type=str) self.set_colors(colors) self.btUseSelectedColumns.clicked.connect(self.on_use_selected_column) self.btRemoveSelectedColumns.clicked.connect(self.on_unuse_selected_column)
def make_xlsx_report(): """ assume profile available """ pieces = gd.sessionInfo['Pieces'] cntrating = [cr for nm, x, cr, tl in pieces] # subdir if not reportsDir().is_dir(): reportsDir().mkdir() reportfile = reportsDir() / gd.config['Session'] crewname = gd.metaData['CrewName'] misc = gd.metaData['Misc'] calibration = gd.metaData['Calibration'] # create xlsx version of the report from the table data wb = Workbook() ws = wb.active ws.title = 'Boat report' ws.column_dimensions['A'].width = 30 # get table from boat report rows = gd.boattablemodel.rowCount() columns = gd.boattablemodel.columnCount() ws.append(['']) ws.append([f'Boat report for {crewname}']) ws.append([f'Calibration value: {calibration}']) ws.append(['']) ws.append([misc]) ws.append(['']) for i in range(rows): row = [] for j in range(columns): index = QAbstractTableModel.index(gd.boattablemodel, i, j) row.append(str(gd.boattablemodel.data(index))) ws.append(row) rcount = gd.sessionInfo['RowerCnt'] for i in range(rcount): name = gd.metaData['Rowers'][i][0] ws = wb.create_sheet(title=f"Rower report {name}") ws.column_dimensions['A'].width = 30 ws.append(['']) ws.append([f'Rower report {name} ']) ws.append(['']) rows = gd.rowertablemodel[i].rowCount() columns = gd.rowertablemodel[i].columnCount() for r in range(rows): row = [] for j in range(columns): index = QAbstractTableModel.index(gd.rowertablemodel[i], r, j) row.append(str(gd.rowertablemodel[i].data(index))) ws.append(row) # wb.save(reportfile.as_posix() + '.xlsx')
def make_csv_report(): """ assume profile available """ pieces = gd.sessionInfo['Pieces'] cntrating = [cr for nm, x, cr, tl in pieces] # subdir if not reportsDir().is_dir(): reportsDir().mkdir() reportfile = reportsDir() / gd.config['Session'] crewname = gd.metaData['CrewName'] misc = gd.metaData['Misc'] calibration = gd.metaData['Calibration'] # create csv version of the report from the table data # get table from boat report rows = gd.boattablemodel.rowCount() columns = gd.boattablemodel.columnCount() with open(reportfile.as_posix() + '.csv', mode='w') as report_file: report_writer = csv.writer(report_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) report_writer.writerow([crewname]) report_writer.writerow([misc]) report_writer.writerow([calibration]) report_writer.writerow([]) report_writer.writerow(['Boat report']) report_writer.writerow([]) # welk piece gebruikt erbij for i in range(rows): row = [] for j in range(columns): index = QAbstractTableModel.index(gd.boattablemodel, i, j) row.append(str(gd.boattablemodel.data(index))) report_writer.writerow(row) rcount = gd.sessionInfo['RowerCnt'] for i in range(rcount): name = gd.metaData['Rowers'][i][0] report_writer.writerow([]) report_writer.writerow([]) report_writer.writerow([f'Rower report {name}']) report_writer.writerow([]) # welk piece gebruikt erbij rows = gd.rowertablemodel[i].rowCount() columns = gd.rowertablemodel[i].columnCount() for r in range(rows): row = [] for j in range(columns): index = QAbstractTableModel.index(gd.rowertablemodel[i], r, j) row.append(str(gd.rowertablemodel[i].data(index))) report_writer.writerow(row)
def make_pdf_report(): """ assume profile available """ pieces = gd.sessionInfo['Pieces'] cntrating = [cr for nm, x, cr, tl in pieces] # we need a (single) temp dir for intermediates. tmpdir = Path(tempfile.gettempdir()) / 'RtcApp' if not tmpdir.is_dir(): tmpdir.mkdir() # subdir if not reportsDir().is_dir(): reportsDir().mkdir() reportfile = reportsDir() / gd.config['Session'] crewname = gd.metaData['CrewName'] geometry_options = { "top": "5mm", "bottom": "5mm", "right": "5mm", "left": "5mm" } doc = Document(documentclass='article', geometry_options=geometry_options, document_options=["12pt"]) doc.preamble.append(NoEscape(r'\usepackage{graphicx}')) # see https://doc.qt.io/qt-5/qml-color.html for colors doc.append(NoEscape(r'\definecolor{aquamarine}{HTML}{7fffd4}')) doc.append(NoEscape(r'\definecolor{gainsboro}{HTML}{dcdcdc}')) # First page with doc.create( Section(f'Boat report {gd.metaData["CrewName"]}', numbering=False)): r = gd.metaData["Rowers"] rwrcnt = gd.sessionInfo['RowerCnt'] if rwrcnt == 1: doc.append('Rowers: ') doc.append(f'{r[0][0]} ') else: doc.append('Rowers from bow: ') for i in range(rwrcnt): doc.append(f'{r[i][0]}, ') doc.append(NewLine()) doc.append(f'Boattype: {gd.metaData["BoatType"]}\n') doc.append(f'Calibration: {gd.metaData["Calibration"]}\n') doc.append(f'Misc: {gd.metaData["Misc"]}\n') doc.append(f'Powerline: {gd.metaData["PowerLine"]}\n') doc.append(f'Venue: {gd.metaData["Venue"]}\n') doc.append(VerticalSpace("5pt")) doc.append(NewLine()) # get table from boat report rows = gd.boattablemodel.rowCount() columns = gd.boattablemodel.columnCount() boattab = 'l|' + ''.join(['r' for i in range(columns - 1)]) + '|' with doc.create(Tabular(boattab)) as table: table.add_hline() row = [] for j in range(columns): index = QAbstractTableModel.index(gd.boattablemodel, 0, j) row.append(str(gd.boattablemodel.data(index))) table.add_row(row, color='aquamarine') table.add_hline() cnt = 0 for i in range(rows): row = [] if i == 0: continue for j in range(columns): index = QAbstractTableModel.index(gd.boattablemodel, i, j) row.append(str(gd.boattablemodel.data(index))) if cnt % 2 == 0: table.add_row(row, color='gainsboro') else: table.add_row(row, color='aquamarine') cnt += 1 table.add_hline() """ table.add_empty_row() table.add_row((4, 5, 6, 7)) """ doc.append(NewPage()) # for the plots fontP = FontProperties() fontP.set_size('xx-small') # Second page with doc.create( Section(f'Boat report {gd.metaData["CrewName"]}', numbering=False)): av = '' filt = '' if gd.averaging: av = 'averaging' if gd.filter: filt = 'filtered' pcs = ['all'] + gd.p_names + ['average'] doc.append(f'Using piece "{pcs[gd.boatPiece]}": {av} {filt}\n') doc.append(VerticalSpace("5pt")) doc.append(NewLine()) sensors = gd.sessionInfo['Header'] fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2) ax1.set_title('Speed') ax1.grid(True) ax2.set_title('Acceleration') ax2.grid(True) ax3.set_title('Pitch') ax3.grid(True) ax4.set_title('Accel-Tempo per Piece') ax4.grid(True) piece = gd.boatPiece if piece == 0: for i in range(len(gd.p_names)): ax1.plot(gd.norm_arrays[i, :, sensors.index('Speed')], linewidth=0.6, label=gd.p_names[i]) ax2.plot(gd.norm_arrays[i, :, sensors.index('Accel')], linewidth=0.6, label=gd.p_names[i]) ax3.plot(gd.norm_arrays[i, :, sensors.index('Pitch Angle')], linewidth=0.6, label=gd.p_names[i]) elif piece == 7: speed = np.zeros(gd.norm_arrays[0, :, 1].shape) accel = np.zeros(gd.norm_arrays[0, :, 1].shape) pitch = np.zeros(gd.norm_arrays[0, :, 1].shape) for i in range(len(gd.p_names)): speed += gd.norm_arrays[i, :, sensors.index('Speed')] accel += gd.norm_arrays[i, :, sensors.index('Accel')] pitch += gd.norm_arrays[i, :, sensors.index('Pitch Angle')] ax1.plot(speed / 6, linewidth=0.6, label=gd.p_names[i]) ax2.plot(accel / 6, linewidth=0.6, label=gd.p_names[i]) ax3.plot(pitch / 6, linewidth=0.6, label=gd.p_names[i]) else: i = piece - 1 ax1.plot(gd.norm_arrays[i, :, sensors.index('Speed')], linewidth=0.6, label=gd.p_names[i]) ax2.plot(gd.norm_arrays[i, :, sensors.index('Accel')], linewidth=0.6, label=gd.p_names[i]) ax3.plot(gd.norm_arrays[i, :, sensors.index('Pitch Angle')], linewidth=0.6, label=gd.p_names[i]) pa = [] for i in range(len(gd.p_names)): # accel and tempo per piece d, a = gd.prof_data[i] pa.append((d['Speed'], cntrating[i][1])) pa = list(zip(*pa)) p = [10 * x for x in pa[0]] # ad hoc scaling ax4.scatter(list(range(len(gd.p_names))), p, marker='H', color='green') ax4.scatter(list(range(len(gd.p_names))), pa[1], marker='H', color='blue') ax1.legend(loc='lower right', prop=fontP) plt.tight_layout() tmpfig = tmpdir / gd.config['Session'] plt.savefig(tmpfig) tmpfig = re.sub('\\\\', '/', str(tmpfig)) # for windows doc.append( NoEscape(r'\includegraphics[width=1.0\textwidth]{' + f'{tmpfig}' + r'}')) plt.close(fig) ## Third page doc.append(NewPage()) with doc.create(Section('Crew report', numbering=False)): pcs = gd.p_names + ['average'] doc.append(f'Piece "{pcs[gd.crewPiece]}" used.\n') fig = plt.figure() fig.subplots_adjust(hspace=0.7) gs = fig.add_gridspec(5, 2) ax1 = fig.add_subplot(gs[0:3, :]) ax2 = fig.add_subplot(gs[3:, 0]) ax3 = fig.add_subplot(gs[3:, 1]) ax1.set_title('Gate Angle - GateForceX/Y') ax1.grid(True) ax2.set_title('Stretcher ForceX') ax2.grid(True) ax3.set_title('Power') ax3.grid(True) rcnt = gd.sessionInfo['RowerCnt'] piece = gd.crewPiece if piece < len(gd.prof_data): # a seperate piece, from the tumbler cp = gd.crewPiece d, aa = gd.prof_data[cp] for r in range(rcnt): sns = rowersensors(r) if gd.sessionInfo['ScullSweep'] == 'sweep': i = sns['GateAngle'] j = sns['GateForceX'] k = sns['GateForceY'] else: i = sns['P GateAngle'] j = sns['P GateForceX'] k = sns['P GateForceY'] # stretchers not always present! # k = sns['Stretcher Z'] # todo: create switch to control working in this case ax1.plot(gd.norm_arrays[cp, :, i], gd.norm_arrays[cp, :, j], linewidth=0.6, label=f'R {r+1}') ax1.plot(gd.norm_arrays[cp, :, i], gd.norm_arrays[cp, :, k], linestyle=stippel, linewidth=0.6, label=f'R {r+1}Y') #twee = self.ax2.plot(gd.norm_arrays[gd.crewPiece, :, i], linewidth=0.6, label=f'R {r+1}') ax3.plot([gd.gmin[gd.crewPiece]], [0], marker='v', color='b') ax3.plot([gd.gmax[gd.crewPiece]], [0], marker='^', color='b') # reference curve derived from the stroke sns = rowersensors(rcnt - 1) fmean = d[rcnt - 1]['GFEff'] if gd.sessionInfo['ScullSweep'] == 'sweep': i = sns['GateAngle'] j = sns['GateForceX'] else: i = sns['P GateAngle'] j = sns['P GateForceX'] minpos = min(gd.norm_arrays[cp, :, i]) maxpos = max(gd.norm_arrays[cp, :, i]) minarg = np.argmin(gd.norm_arrays[cp, :, i]) maxarg = np.argmax(gd.norm_arrays[cp, :, i]) fmin = gd.norm_arrays[cp, minarg, j] fmax = gd.norm_arrays[cp, maxarg, j] xstep = (maxpos - minpos) / 20 ystep = (fmin - fmax) / 20 # assume fmin > fmax if gd.sessionInfo['ScullSweep'] == 'sweep': xref = np.array([ minpos, minpos + 0.4 * xstep, minpos + 2 * xstep, minpos + 5 * xstep, minpos + 7 * xstep, minpos + 9 * xstep, minpos + 11 * xstep, minpos + 14 * xstep, minpos + 16 * xstep, minpos + 20 * xstep ]) yref = np.array([ fmin, fmin + 20, 1.1 * fmean, 1.6 * fmean, 1.65 * fmean, 1.7 * fmean, 1.6 * fmean, 1.25 * fmean, 0.8 * fmean, fmax ]) else: xref = np.array([ minpos, minpos + 0.4 * xstep, minpos + 2 * xstep, minpos + 5 * xstep, minpos + 7 * xstep, minpos + 9 * xstep, minpos + 11 * xstep, minpos + 14 * xstep, minpos + 16 * xstep, minpos + 20 * xstep ]) yref = np.array([ fmin, fmin + 20, 1.1 * fmean, 1.6 * fmean, 1.65 * fmean, 1.7 * fmean, 1.6 * fmean, 1.25 * fmean, 0.8 * fmean, fmax ]) curveref = make_interp_spline(xref, yref, 2) xrefnew = np.linspace(min(xref), max(xref), int(maxpos - minpos)) ax1.plot(xrefnew, curveref(xrefnew), color='black', linewidth=0.5, linestyle=(0, (3, 6))) ax3.plot(aa[0 + r], linewidth=0.6, label=f'R {r+1}') else: # average for r in range(rcnt): sns = rowersensors(r) if gd.sessionInfo['ScullSweep'] == 'sweep': i = sns['GateAngle'] j = sns['GateForceX'] else: i = sns['P GateAngle'] j = sns['P GateForceX'] # stretchers not always available! # k = sns['Stretcher Z'] # average nmbrpieces = len(gd.p_names) angle = np.zeros((100, )) force = np.zeros((100, )) power = np.zeros((100, )) for p in range(nmbrpieces): angle += gd.norm_arrays[p, :, i] force += gd.norm_arrays[p, :, j] # stretcherZ = gd.norm_arrays[p, :, k] d, a = gd.prof_data[p] power += aa[0 + r] # plot #ax1.plot(angle/nmbrpieces, linewidth=0.6, label=f'R {r+1}') #ax2.plot(force/nmbrpieces, linewidth=0.6, label=f'R {r+1}') ax3.plot(power / nmbrpieces, linewidth=0.6, label=f'R {r+1}') ax3.legend(loc='upper right', prop=fontP) plt.tight_layout() # we keep using the same name tmpfig = tmpdir / (gd.config['Session'] + '_crew') plt.savefig(tmpfig) tmpfig = re.sub('\\\\', '/', str(tmpfig)) # for windows doc.append( NoEscape(r'\includegraphics[width=1.0\textwidth]{' + f'{tmpfig}' + r'}')) plt.close(fig) # Rower pages doc.append(NewPage()) rwrcnt = gd.sessionInfo['RowerCnt'] fig = [None for i in range(rwrcnt)] rax1 = [None for i in range(rwrcnt)] sax1 = [None for i in range(rwrcnt)] for rwr in range(rwrcnt): pcs = ['all'] + gd.p_names + ['average'] with doc.create( Section( f'Rower: {gd.metaData["Rowers"][rwr][0]}, using piece "{pcs[gd.rowerPiece[rwr]]}"', numbering=False)): rows = gd.rowertablemodel[rwr].rowCount() columns = gd.rowertablemodel[rwr].columnCount() rowertab = 'l|' + ''.join(['r' for i in range(columns - 1)]) + '|' with doc.create(Tabular(rowertab)) as table: table.add_hline() row = [] for j in range(columns): index = QAbstractTableModel.index(gd.rowertablemodel[rwr], 0, j) row.append(str(gd.rowertablemodel[rwr].data(index))) table.add_row(row, color='aquamarine') table.add_hline() cnt = 0 for i in range(rows): row = [] if i == 0: continue for j in range(columns): index = QAbstractTableModel.index( gd.rowertablemodel[rwr], i, j) row.append(str(gd.rowertablemodel[rwr].data(index))) if cnt % 2 == 0: table.add_row(row, color='gainsboro') else: table.add_row(row, color='aquamarine') cnt += 1 table.add_hline() doc.append('\n') fig[rwr], ((rax1[rwr])) = plt.subplots(nrows=1, ncols=1) rax1[rwr].set_title('GateAngle - GateForceX/Y') rax1[rwr].grid(True) rsens = rowersensors(rwr) piece = gd.rowerPiece[rwr] scaleAngle = 10 if gd.rowerPiece[rwr] == 0: # all for i in range(len(gd.p_names)): if gd.sessionInfo['ScullSweep'] == 'sweep': # print(f'Make rowerplot for {self.rower}') rax1[rwr].plot(gd.norm_arrays[i, :, rsens['GateAngle']], gd.norm_arrays[i, :, rsens['GateForceX']], linewidth=0.6, label=f'{gd.p_names[i]}') rax1[rwr].plot(gd.norm_arrays[i, :, rsens['GateAngle']], gd.norm_arrays[i, :, rsens['GateForceY']], linestyle=(0, (7, 10)), linewidth=0.6, label=f'{gd.p_names[i]}') else: rax1[rwr].plot(gd.norm_arrays[i, :, rsens['P GateAngle']], gd.norm_arrays[i, :, rsens['P GateForceX']], linewidth=0.6, label=f'{gd.p_names[i]}') rax1[rwr].plot(gd.norm_arrays[i, :, rsens['P GateAngle']], gd.norm_arrays[i, :, rsens['P GateForceY']], linestyle=(0, (7, 10)), linewidth=0.6, label=f'{gd.p_names[i]}') elif gd.rowerPiece[rwr] == 7: # average angle = np.zeros((100, )) forceX = np.zeros((100, )) if gd.sessionInfo['ScullSweep'] == 'sweep': for i in range(len(gd.p_names)): angle += gd.norm_arrays[i, :, rsens['GateAngle']] forceX += gd.norm_arrays[i, :, rsens['GateForceX']] forceY += gd.norm_arrays[i, :, rsens['GateForceY']] rax1[rwr].plot(angle / 6, forceX / 6, linewidth=0.6, label='FX') rax1[rwr].plot(angle / 6, forceY / 6, linestyle=(0, (7, 10)), linewidth=0.6, label='FY') else: for i in range(len(gd.p_names)): angle += gd.norm_arrays[i, :, rsens['P GateAngle']] forceX += gd.norm_arrays[i, :, rsens['P GateForceX']] forceY += gd.norm_arrays[i, :, rsens['P GateForceY']] rax1[rwr].plot(angle / 6, forceX / 6, linewidth=0.6, label='FX') rax1[rwr].plot(angle / 6, forceY / 6, linestyle=(0, (7, 10)), linewidth=0.6, label='FY') else: rp = gd.rowerPiece[rwr] - 1 sns = rowersensors(rwr) # ad hoc angle x 10. Bettet via (max-min). Scale is for force # print(f'Create rowerplot for {self.rower}') outboat = [d for d, e in gd.prof_data] ri = [a[rwr] for a in outboat] # rower info per piece fmean = ri[rp]['GFEff'] if gd.sessionInfo['ScullSweep'] == 'sweep': i = sns['GateAngle'] j = sns['GateForceX'] k = sns['GateForceY'] else: i = sns['P GateAngle'] j = sns['P GateForceX'] k = sns['P GateForceY'] # TESTING referentie curve # lengte uit tabel? Voorlopig 100, begin goed zetten # scale with avarage force minpos = min(gd.norm_arrays[rp, :, i]) maxpos = max(gd.norm_arrays[rp, :, i]) minarg = np.argmin(gd.norm_arrays[rp, :, i]) maxarg = np.argmax(gd.norm_arrays[rp, :, i]) fmin = gd.norm_arrays[rp, minarg, j] fmax = gd.norm_arrays[rp, maxarg, j] xstep = (maxpos - minpos) / 20 ystep = (fmin - fmax) / 20 # assume fmin > fmax if gd.sessionInfo['ScullSweep'] == 'sweep': xref = np.array([ minpos, minpos + 0.4 * xstep, minpos + 2 * xstep, minpos + 5 * xstep, minpos + 7 * xstep, minpos + 9 * xstep, minpos + 11 * xstep, minpos + 14 * xstep, minpos + 16 * xstep, minpos + 20 * xstep ]) yref = np.array([ fmin, fmin + 20, 1.1 * fmean, 1.6 * fmean, 1.65 * fmean, 1.7 * fmean, 1.6 * fmean, 1.25 * fmean, 0.8 * fmean, fmax ]) else: xref = np.array([ minpos, minpos + 0.4 * xstep, minpos + 2 * xstep, minpos + 5 * xstep, minpos + 7 * xstep, minpos + 9 * xstep, minpos + 11 * xstep, minpos + 14 * xstep, minpos + 16 * xstep, minpos + 20 * xstep ]) yref = np.array([ fmin, fmin + 20, 1.1 * fmean, 1.6 * fmean, 1.65 * fmean, 1.7 * fmean, 1.6 * fmean, 1.25 * fmean, 0.8 * fmean, fmax ]) curveref = make_interp_spline(xref, yref, 2) xrefnew = np.linspace(min(xref), max(xref), int(maxpos - minpos)) rax1[rwr].plot(gd.norm_arrays[rp, :, i], gd.norm_arrays[rp, :, j], linewidth=0.6, label=f'{gd.p_names[rp]} FX') rax1[rwr].plot(gd.norm_arrays[rp, :, i], gd.norm_arrays[rp, :, k], linestyle=stippel, linewidth=0.6, label=f'{gd.p_names[rp]} FY') rax1[rwr].plot(xrefnew, curveref(xrefnew), color='black', linewidth=0.5, linestyle=(0, (3, 6))) # rax1[rwr].legend(loc='lower right', prop=fontP, bbox_to_anchor=(1.05, 1)) rax1[rwr].legend(loc='upper right', prop=fontP) plt.tight_layout() tmpfig = tmpdir / (gd.config['Session'] + f'_{rwr}') plt.savefig(tmpfig) tmpfig = re.sub('\\\\', '/', str(tmpfig)) # for windows doc.append( NoEscape(r'\includegraphics[width=0.9\textwidth]{' + f'{tmpfig}' + r'}')) plt.close(fig[rwr]) if 'StretcherForceX' in sensors: doc.append('\n') # stretcher plot fig[rwr], sax1[rwr] = plt.subplots() sax1[rwr].set_title('Stretcher') sax1[rwr].grid(True) rsens = rowersensors(rwr) if gd.rowerPiece[rwr] == 0: # all DOEN WE NIET pass elif gd.rowerPiece[rwr] == len(gd.p_names) + 1: # average DOEN WE NIET pass else: # a piece (alleen dit) i = gd.rowerPiece[rwr] - 1 name, se, nr, sp = pieces[i] sax1[rwr].plot(gd.dataObject[sp[0]:sp[1], rsens['StretcherForceX']], linewidth=0.6, label='StretcherForceX') sax1[rwr].plot( 10 * gd.dataObject[sp[0]:sp[1], rsens['Stretcher RL']], linewidth=0.6, label='Stretcher RL') sax1[rwr].plot( 10 * gd.dataObject[sp[0]:sp[1], rsens['Stretcher TB']], linewidth=0.6, label='Stretcher TB') sax1[rwr].legend(loc='lower right', prop=fontP) plt.tight_layout() tmpfig = tmpdir / (gd.config['Session'] + f'_{rwr}_s') plt.savefig(tmpfig) tmpfig = re.sub('\\\\', '/', str(tmpfig)) # for windows doc.append( NoEscape(r'\includegraphics[width=0.6\textwidth]{' + f'{tmpfig}' + r'}')) plt.close(fig[rwr]) if rwr != rwrcnt - 1: doc.append(NewPage()) # Extra page if gd.extraplot: doc.append(NewPage()) fig, extr = plt.subplots() s2 = gd.config['Session2'] if s2 == '': extr.set_title('Custom plot') else: extr.set_title(f'Custom plot (second session: {s2})') extr.grid(True) # data from update_plot from View piece, can we do this simpler? [strt, end, strttime, center, scalex, slist, secslist] = gd.extrasettings times = list(map(lambda x: x / Hz, list(range(gd.view_tr.shape[0])))) for i, name, scaley in slist: extr.plot(times, gd.view_tr[:, i] * scaley, linewidth=0.6, label=name) for i, name, scale in secslist: extr.plot(times, gd.view_tr2[:, i] * scaley, linewidth=0.6, label=name, linestyle=stippel) dist = (end - strt) xFrom = center - scalex * dist / 2 xTo = center + scalex * dist / 2 extr.set_xlim(xFrom, xTo) # start at correct beginvalue locs = extr.get_xticks() ticks = [item + strttime for item in locs] extr.set_xticklabels(ticks) extr.legend() plt.tight_layout() # we keep using the same name tmpfig = tmpdir / (gd.config['Session'] + '_extra') plt.savefig(tmpfig) tmpfig = re.sub('\\\\', '/', str(tmpfig)) # for windows doc.append( NoEscape(r'\includegraphics[width=1.0\textwidth]{' + f'{tmpfig}' + r'}')) plt.close(fig) doc.append(NewLine()) doc.append(VerticalSpace("10pt")) doc.append(f' Piece: {gd.selPiece}') if gd.sd_selPiece != '': doc.append(NewLine()) doc.append(VerticalSpace("5pt")) doc.append(f'Secondary piece: {gd.sd_selPiece}') # generate report doc.generate_pdf(reportfile, clean_tex=True)