void PowerHist::recalc(bool force) { QVector<unsigned int> *array = NULL; QVector<unsigned int> *selectedArray = NULL; int arrayLength = 0; // lets make sure we need to recalculate if (force == false && LASTsource == source && LASTcache == cache && LASTrideItem == rideItem && LASTseries == series && LASTshade == shade && LASTuseMetricUnits == context->athlete->useMetricUnits && LASTlny == lny && LASTzoned == zoned && LASTbinw == binw && LASTwithz == withz && LASTdt == dt && LASTabsolutetime == absolutetime) { return; // nothing has changed } else { // remember for next time LASTsource = source; LASTcache = cache; LASTrideItem = rideItem; LASTseries = series; LASTshade = shade; LASTuseMetricUnits = context->athlete->useMetricUnits; LASTlny = lny; LASTzoned = zoned; LASTbinw = binw; LASTwithz = withz; LASTdt = dt; LASTabsolutetime = absolutetime; } if (source == Ride && !rideItem) return; // make sure the interval length is set if not plotting metrics if (source != Metric && dt <= 0) return; if (source == Metric) { // we use the metricArray array = &metricArray; arrayLength = metricArray.size(); selectedArray = NULL; } else if (series == RideFile::watts && zoned == false) { array = &wattsArray; arrayLength = wattsArray.size(); selectedArray = &wattsSelectedArray; } else if ((series == RideFile::watts || series == RideFile::wattsKg) && zoned == true) { array = &wattsZoneArray; arrayLength = wattsZoneArray.size(); selectedArray = &wattsZoneSelectedArray; } else if (series == RideFile::aPower && zoned == false) { array = &aPowerArray; arrayLength = aPowerArray.size(); selectedArray = &aPowerSelectedArray; } else if (series == RideFile::wattsKg && zoned == false) { array = &wattsKgArray; arrayLength = wattsKgArray.size(); selectedArray = &wattsKgSelectedArray; } else if (series == RideFile::nm) { array = &nmArray; arrayLength = nmArray.size(); selectedArray = &nmSelectedArray; } else if (series == RideFile::hr && zoned == false) { array = &hrArray; arrayLength = hrArray.size(); selectedArray = &hrSelectedArray; } else if (series == RideFile::hr && zoned == true) { array = &hrZoneArray; arrayLength = hrZoneArray.size(); selectedArray = &hrZoneSelectedArray; } else if (series == RideFile::kph) { array = &kphArray; arrayLength = kphArray.size(); selectedArray = &kphSelectedArray; } else if (series == RideFile::cad) { array = &cadArray; arrayLength = cadArray.size(); selectedArray = &cadSelectedArray; } RideFile::SeriesType baseSeries = (series == RideFile::wattsKg) ? RideFile::watts : series; // null curve please -- we have no data! if (!array || arrayLength == 0 || (source == Ride && !rideItem->ride()->isDataPresent(baseSeries))) { // create empty curves when no data const double zero = 0; curve->setData(&zero, &zero, 0); curveSelected->setData(&zero, &zero, 0); updatePlot(); return; } // binning of data when not zoned - we can't zone for series besides // watts and hr so ignore zoning for those data series if (zoned == false || (zoned == true && (series != RideFile::watts && series != RideFile::wattsKg && series != RideFile::hr))) { // we add a bin on the end since the last "incomplete" bin // will be dropped otherwise int count = int(ceil((arrayLength - 1) / (binw)))+1; // allocate space for data, plus beginning and ending point QVector<double> parameterValue(count+2, 0.0); QVector<double> totalTime(count+2, 0.0); QVector<double> totalTimeSelected(count+2, 0.0); int i; for (i = 1; i <= count; ++i) { double high = i * round(binw/delta); double low = high - round(binw/delta); if (low==0 && !withz) low++; parameterValue[i] = high*delta; totalTime[i] = 1e-9; // nonzero to accomodate log plot totalTimeSelected[i] = 1e-9; // nonzero to accomodate log plot while (low < high && low<arrayLength) { if (selectedArray && (*selectedArray).size()>low) totalTimeSelected[i] += dt * (*selectedArray)[low]; totalTime[i] += dt * (*array)[low++]; } } totalTime[i] = 1e-9; // nonzero to accomodate log plot totalTimeSelected[i] = 1e-9; // nonzero to accomodate log plot parameterValue[i] = i * delta * binw; totalTime[0] = 1e-9; totalTimeSelected[0] = 1e-9; parameterValue[0] = 0; // convert vectors from absolute time to percentage // if the user has selected that if (!absolutetime) { percentify(totalTime, 1); percentify(totalTimeSelected, 1); } curve->setData(parameterValue.data(), totalTime.data(), count + 2); curveSelected->setData(parameterValue.data(), totalTimeSelected.data(), count + 2); QwtScaleDraw *sd = new QwtScaleDraw; sd->setTickLength(QwtScaleDiv::MajorTick, 3); setAxisScaleDraw(QwtPlot::xBottom, sd); // HR typically starts at 80 or so, rather than zero // lets crop the chart so we can focus on the data // if we're working with HR data... minX=0; if (!withz && series == RideFile::hr) { for (int i=1; i<hrArray.size(); i++) { if (hrArray[i] > 0.1) { minX = i; break; } } } setAxisScale(xBottom, minX, parameterValue[count + 1]); // we only do zone labels when using absolute values refreshZoneLabels(); refreshHRZoneLabels(); } else { // we're not binning instead we are prettyfing the columnar // display in much the same way as the weekly summary workds // Each zone column will have 4 points QVector<double> xaxis (array->size() * 4); QVector<double> yaxis (array->size() * 4); QVector<double> selectedxaxis (selectedArray->size() * 4); QVector<double> selectedyaxis (selectedArray->size() * 4); // samples to time for (int i=0, offset=0; i<array->size(); i++) { double x = (double) i - 0.5; double y = dt * (double)(*array)[i]; xaxis[offset] = x +0.05; yaxis[offset] = 0; offset++; xaxis[offset] = x+0.05; yaxis[offset] = y; offset++; xaxis[offset] = x+0.95; yaxis[offset] = y; offset++; xaxis[offset] = x +0.95; yaxis[offset] = 0; offset++; } for (int i=0, offset=0; i<selectedArray->size(); i++) { double x = (double)i - 0.5; double y = dt * (double)(*selectedArray)[i]; selectedxaxis[offset] = x +0.05; selectedyaxis[offset] = 0; offset++; selectedxaxis[offset] = x+0.05; selectedyaxis[offset] = y; offset++; selectedxaxis[offset] = x+0.95; selectedyaxis[offset] = y; offset++; selectedxaxis[offset] = x +0.95; selectedyaxis[offset] = 0; offset++; } if (!absolutetime) { percentify(yaxis, 2); percentify(selectedyaxis, 2); } // set those curves curve->setData(xaxis.data(), yaxis.data(), xaxis.size()); curveSelected->setData(selectedxaxis.data(), selectedyaxis.data(), selectedxaxis.size()); // zone scale draw if ((series == RideFile::watts || series == RideFile::wattsKg) && zoned && rideItem && rideItem->zones) { setAxisScaleDraw(QwtPlot::xBottom, new ZoneScaleDraw(rideItem->zones, rideItem->zoneRange())); if (rideItem->zoneRange() >= 0) setAxisScale(QwtPlot::xBottom, -0.99, rideItem->zones->numZones(rideItem->zoneRange()), 1); else setAxisScale(QwtPlot::xBottom, -0.99, 0, 1); } // hr scale draw int hrRange; if (series == RideFile::hr && zoned && rideItem && context->athlete->hrZones() && (hrRange=context->athlete->hrZones()->whichRange(rideItem->dateTime.date())) != -1) { setAxisScaleDraw(QwtPlot::xBottom, new HrZoneScaleDraw(context->athlete->hrZones(), hrRange)); if (hrRange >= 0) setAxisScale(QwtPlot::xBottom, -0.99, context->athlete->hrZones()->numZones(hrRange), 1); else setAxisScale(QwtPlot::xBottom, -0.99, 0, 1); } // watts zoned for a time range if (source == Cache && zoned && (series == RideFile::watts || series == RideFile::wattsKg) && context->athlete->zones()) { setAxisScaleDraw(QwtPlot::xBottom, new ZoneScaleDraw(context->athlete->zones(), 0)); if (context->athlete->zones()->getRangeSize()) setAxisScale(QwtPlot::xBottom, -0.99, context->athlete->zones()->numZones(0), 1); // use zones from first defined range } // hr zoned for a time range if (source == Cache && zoned && series == RideFile::hr && context->athlete->hrZones()) { setAxisScaleDraw(QwtPlot::xBottom, new HrZoneScaleDraw(context->athlete->hrZones(), 0)); if (context->athlete->hrZones()->getRangeSize()) setAxisScale(QwtPlot::xBottom, -0.99, context->athlete->hrZones()->numZones(0), 1); // use zones from first defined range } setAxisMaxMinor(QwtPlot::xBottom, 0); } setYMax(); configChanged(); // setup the curve colors to appropriate values updatePlot(); }
void PowerHist::recalc() { QVector<unsigned int> *array; QVector<unsigned int> *selectedArray; int arrayLength = 0; double delta; // make sure the interval length is set if (dt <= 0) return; if (selected == watts) { array = &wattsArray; delta = wattsDelta; arrayLength = wattsArray.size(); selectedArray = &wattsSelectedArray; } else if (selected == wattsZone) { array = &wattsZoneArray; delta = 1; arrayLength = wattsZoneArray.size(); selectedArray = &wattsZoneSelectedArray; } else if (selected == nm) { array = &nmArray; delta = nmDelta; arrayLength = nmArray.size(); selectedArray = &nmSelectedArray; } else if (selected == hr) { array = &hrArray; delta = hrDelta; arrayLength = hrArray.size(); selectedArray = &hrSelectedArray; } else if (selected == hrZone) { array = &hrZoneArray; delta = 1; arrayLength = hrZoneArray.size(); selectedArray = &hrZoneSelectedArray; } else if (selected == kph) { array = &kphArray; delta = kphDelta; arrayLength = kphArray.size(); selectedArray = &kphSelectedArray; } else if (selected == cad) { array = &cadArray; delta = cadDelta; arrayLength = cadArray.size(); selectedArray = &cadSelectedArray; } if (!array) return; // binning of data when not zoned if (selected != wattsZone && selected != hrZone) { // we add a bin on the end since the last "incomplete" bin // will be dropped otherwise int count = int(ceil((arrayLength - 1) / binw))+1; // allocate space for data, plus beginning and ending point QVector<double> parameterValue(count+2, 0.0); QVector<double> totalTime(count+2, 0.0); QVector<double> totalTimeSelected(count+2, 0.0); int i; for (i = 1; i <= count; ++i) { int high = i * binw; int low = high - binw; if (low==0 && !withz) low++; parameterValue[i] = high * delta; totalTime[i] = 1e-9; // nonzero to accomodate log plot totalTimeSelected[i] = 1e-9; // nonzero to accomodate log plot while (low < high && low<arrayLength) { if (selectedArray && (*selectedArray).size()>low) totalTimeSelected[i] += dt * (*selectedArray)[low]; totalTime[i] += dt * (*array)[low++]; } } totalTime[i] = 1e-9; // nonzero to accomodate log plot parameterValue[i] = i * delta * binw; totalTime[0] = 1e-9; parameterValue[0] = 0; // convert vectors from absolute time to percentage // if the user has selected that if (!absolutetime) { percentify(totalTime, 1); percentify(totalTimeSelected, 1); } curve->setData(parameterValue.data(), totalTime.data(), count + 2); curveSelected->setData(parameterValue.data(), totalTimeSelected.data(), count + 2); // make see through if we're shading zones QBrush brush = curve->brush(); QColor bcol = brush.color(); bool zoning = (selected == watts && shadeZones()) || (selected == hr && shadeHRZones()); bcol.setAlpha(zoning ? 165 : 200); brush.setColor(bcol); curve->setBrush(brush); setAxisScaleDraw(QwtPlot::xBottom, new QwtScaleDraw); // HR typically starts at 80 or so, rather than zero // lets crop the chart so we can focus on the data // if we're working with HR data... if (selected == hr) { double MinX=0; for (int i=0; i<hrArray.size(); i++) { if (hrArray[i] > 0) { MinX = i; break; } } setAxisScale(xBottom, MinX, parameterValue[count + 1]); } else { setAxisScale(xBottom, 0.0, parameterValue[count + 1]); } // we only do zone labels when using absolute values refreshZoneLabels(); refreshHRZoneLabels(); } else { // we're not binning instead we are prettyfing the columnar // display in much the same way as the weekly summary workds // Each zone column will have 4 points QVector<double> xaxis (array->size() * 4); QVector<double> yaxis (array->size() * 4); QVector<double> selectedxaxis (selectedArray->size() * 4); QVector<double> selectedyaxis (selectedArray->size() * 4); // samples to time for (int i=0, offset=0; i<array->size(); i++) { double x = (double) i - 0.5; double y = dt * (double)(*array)[i]; xaxis[offset] = x +0.05; yaxis[offset] = 0; offset++; xaxis[offset] = x+0.05; yaxis[offset] = y; offset++; xaxis[offset] = x+0.95; yaxis[offset] = y; offset++; xaxis[offset] = x +0.95; yaxis[offset] = 0; offset++; } for (int i=0, offset=0; i<selectedArray->size(); i++) { double x = (double)i - 0.5; double y = dt * (double)(*selectedArray)[i]; selectedxaxis[offset] = x +0.05; selectedyaxis[offset] = 0; offset++; selectedxaxis[offset] = x+0.05; selectedyaxis[offset] = y; offset++; selectedxaxis[offset] = x+0.95; selectedyaxis[offset] = y; offset++; selectedxaxis[offset] = x +0.95; selectedyaxis[offset] = 0; offset++; } if (!absolutetime) { percentify(yaxis, 2); percentify(selectedyaxis, 2); } // set those curves curve->setData(xaxis.data(), yaxis.data(), xaxis.size()); // Opaque - we don't need to show zone shading QBrush brush = curve->brush(); QColor bcol = brush.color(); bcol.setAlpha(200); brush.setColor(bcol); curve->setBrush(brush); curveSelected->setData(selectedxaxis.data(), selectedyaxis.data(), selectedxaxis.size()); // zone scale draw if (selected == wattsZone && rideItem && rideItem->zones) { setAxisScaleDraw(QwtPlot::xBottom, new ZoneScaleDraw(rideItem->zones, rideItem->zoneRange())); setAxisScale(QwtPlot::xBottom, -0.99, rideItem->zones->numZones(rideItem->zoneRange()), 1); } // hr scale draw int hrRange; if (selected == hrZone && rideItem && mainWindow->hrZones() && (hrRange=mainWindow->hrZones()->whichRange(rideItem->dateTime.date())) != -1) { setAxisScaleDraw(QwtPlot::xBottom, new HrZoneScaleDraw(mainWindow->hrZones(), hrRange)); setAxisScale(QwtPlot::xBottom, -0.99, mainWindow->hrZones()->numZones(hrRange), 1); } setAxisMaxMinor(QwtPlot::xBottom, 0); } setYMax(); replot(); }
static void cg_fini(Int exitcode) { static char buf1[128], buf2[128], buf3[128], fmt [128]; CC D_total; ULong L2_total_m, L2_total_mr, L2_total_mw, L2_total, L2_total_r, L2_total_w; Int l1, l2, l3; Int p; fprint_CC_table_and_calc_totals(); if (VG_(clo_verbosity) == 0) return; /* I cache results. Use the I_refs value to determine the first column * width. */ l1 = ULong_width(Ir_total.a); l2 = ULong_width(Dr_total.a); l3 = ULong_width(Dw_total.a); /* Make format string, getting width right for numbers */ VG_(sprintf)(fmt, "%%s %%,%dld", l1); VG_(message)(Vg_UserMsg, fmt, "I refs: ", Ir_total.a); VG_(message)(Vg_UserMsg, fmt, "I1 misses: ", Ir_total.m1); VG_(message)(Vg_UserMsg, fmt, "L2i misses: ", Ir_total.m2); p = 100; if (0 == Ir_total.a) Ir_total.a = 1; percentify(Ir_total.m1 * 100 * p / Ir_total.a, p, l1+1, buf1); VG_(message)(Vg_UserMsg, "I1 miss rate: %s", buf1); percentify(Ir_total.m2 * 100 * p / Ir_total.a, p, l1+1, buf1); VG_(message)(Vg_UserMsg, "L2i miss rate: %s", buf1); VG_(message)(Vg_UserMsg, ""); /* D cache results. Use the D_refs.rd and D_refs.wr values to determine the * width of columns 2 & 3. */ D_total.a = Dr_total.a + Dw_total.a; D_total.m1 = Dr_total.m1 + Dw_total.m1; D_total.m2 = Dr_total.m2 + Dw_total.m2; /* Make format string, getting width right for numbers */ VG_(sprintf)(fmt, "%%s %%,%dld (%%,%dld rd + %%,%dld wr)", l1, l2, l3); VG_(message)(Vg_UserMsg, fmt, "D refs: ", D_total.a, Dr_total.a, Dw_total.a); VG_(message)(Vg_UserMsg, fmt, "D1 misses: ", D_total.m1, Dr_total.m1, Dw_total.m1); VG_(message)(Vg_UserMsg, fmt, "L2d misses: ", D_total.m2, Dr_total.m2, Dw_total.m2); p = 10; if (0 == D_total.a) D_total.a = 1; if (0 == Dr_total.a) Dr_total.a = 1; if (0 == Dw_total.a) Dw_total.a = 1; percentify( D_total.m1 * 100 * p / D_total.a, p, l1+1, buf1); percentify(Dr_total.m1 * 100 * p / Dr_total.a, p, l2+1, buf2); percentify(Dw_total.m1 * 100 * p / Dw_total.a, p, l3+1, buf3); VG_(message)(Vg_UserMsg, "D1 miss rate: %s (%s + %s )", buf1, buf2,buf3); percentify( D_total.m2 * 100 * p / D_total.a, p, l1+1, buf1); percentify(Dr_total.m2 * 100 * p / Dr_total.a, p, l2+1, buf2); percentify(Dw_total.m2 * 100 * p / Dw_total.a, p, l3+1, buf3); VG_(message)(Vg_UserMsg, "L2d miss rate: %s (%s + %s )", buf1, buf2,buf3); VG_(message)(Vg_UserMsg, ""); /* L2 overall results */ L2_total = Dr_total.m1 + Dw_total.m1 + Ir_total.m1; L2_total_r = Dr_total.m1 + Ir_total.m1; L2_total_w = Dw_total.m1; VG_(message)(Vg_UserMsg, fmt, "L2 refs: ", L2_total, L2_total_r, L2_total_w); L2_total_m = Dr_total.m2 + Dw_total.m2 + Ir_total.m2; L2_total_mr = Dr_total.m2 + Ir_total.m2; L2_total_mw = Dw_total.m2; VG_(message)(Vg_UserMsg, fmt, "L2 misses: ", L2_total_m, L2_total_mr, L2_total_mw); percentify(L2_total_m * 100 * p / (Ir_total.a + D_total.a), p, l1+1, buf1); percentify(L2_total_mr * 100 * p / (Ir_total.a + Dr_total.a), p, l2+1, buf2); percentify(L2_total_mw * 100 * p / Dw_total.a, p, l3+1, buf3); VG_(message)(Vg_UserMsg, "L2 miss rate: %s (%s + %s )", buf1, buf2,buf3); // Various stats if (VG_(clo_verbosity) > 1) { int BB_lookups = full_debug_BBs + fn_debug_BBs + file_line_debug_BBs + no_debug_BBs; VG_(message)(Vg_DebugMsg, ""); VG_(message)(Vg_DebugMsg, "Distinct files: %d", distinct_files); VG_(message)(Vg_DebugMsg, "Distinct fns: %d", distinct_fns); VG_(message)(Vg_DebugMsg, "Distinct lines: %d", distinct_lines); VG_(message)(Vg_DebugMsg, "Distinct instrs: %d", distinct_instrs); VG_(message)(Vg_DebugMsg, "BB lookups: %d", BB_lookups); VG_(message)(Vg_DebugMsg, "With full debug info:%3d%% (%d)", full_debug_BBs * 100 / BB_lookups, full_debug_BBs); VG_(message)(Vg_DebugMsg, "With file/line debug info:%3d%% (%d)", file_line_debug_BBs * 100 / BB_lookups, file_line_debug_BBs); VG_(message)(Vg_DebugMsg, "With fn name debug info:%3d%% (%d)", fn_debug_BBs * 100 / BB_lookups, fn_debug_BBs); VG_(message)(Vg_DebugMsg, "With no debug info:%3d%% (%d)", no_debug_BBs * 100 / BB_lookups, no_debug_BBs); VG_(message)(Vg_DebugMsg, "BBs Retranslated: %d", BB_retranslations); } VGP_POPCC(VgpCacheResults); }