Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function App() {
const [configModalOpen, setConfigModalOpen] = useState(false);
const [configFile, setConfigFile] = useState(null);
const [globalDragOver, setGlobalDragOver] = useState(false);
const [dragCounter, setDragCounter] = useState(0);
const [, setDragCounter] = useState(0);
const [xRange, setXRange] = useState({ min: undefined, max: undefined });
const [maxStep, setMaxStep] = useState(0);

Expand Down
47 changes: 17 additions & 30 deletions src/components/ChartContainer.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo, useState, useRef, useCallback, useEffect } from 'react';
import React, { useMemo, useRef, useCallback, useEffect } from 'react';
import { Line } from 'react-chartjs-2';
import { ResizablePanel } from './ResizablePanel';
import {
Expand All @@ -12,6 +12,7 @@ import {
Tooltip,
Legend,
} from 'chart.js';
import zoomPlugin from 'chartjs-plugin-zoom';

ChartJS.register(
CategoryScale,
Expand All @@ -20,11 +21,12 @@ ChartJS.register(
LineElement,
Title,
Tooltip,
Legend
Legend,
zoomPlugin
);

// Chart wrapper component with error boundary
const ChartWrapper = ({ data, options, title, chartId, onRegisterChart, onSyncHover }) => {
const ChartWrapper = ({ data, options, chartId, onRegisterChart, onSyncHover }) => {
const chartRef = useRef(null);

const handleChartRef = useCallback((ref) => {
Expand All @@ -36,7 +38,7 @@ const ChartWrapper = ({ data, options, title, chartId, onRegisterChart, onSyncHo

const enhancedOptions = {
...options,
onHover: (event, activeElements, chart) => {
onHover: (event, activeElements) => {
if (activeElements.length > 0) {
const step = activeElements[0].index;
onSyncHover(step, chartId);
Expand Down Expand Up @@ -89,7 +91,6 @@ export default function ChartContainer({
onMaxStepChange
}) {
// 同步hover状态管理
const [syncHoverStep, setSyncHoverStep] = useState(null);
const chartRefs = useRef(new Map()); // 存储所有图表实例的引用

// 注册图表实例
Expand All @@ -101,14 +102,13 @@ export default function ChartContainer({
const syncHoverToAllCharts = useCallback((step, sourceChartId) => {
if (step === null) {
// 清除所有图表的hover状态(包括源图表)
chartRefs.current.forEach((chart, chartId) => {
chartRefs.current.forEach((chart) => {
if (chart) {
chart.setActiveElements([]);
chart.tooltip.setActiveElements([]);
chart.update('none');
}
});
setSyncHoverStep(null);
} else {
// 同步hover到所有图表(不包括源图表,避免重复操作)
chartRefs.current.forEach((chart, chartId) => {
Expand All @@ -130,7 +130,6 @@ export default function ChartContainer({
chart.update('none');
}
});
setSyncHoverStep(step);
}
}, []);

Expand Down Expand Up @@ -175,7 +174,7 @@ export default function ChartContainer({
// 数值正则:支持各种数值格式,包括科学计数法
const numberRegex = /[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/;

lines.forEach((line, lineIndex) => {
lines.forEach((line) => {
// 查找关键词(忽略大小写)
const keywordIndex = line.toLowerCase().indexOf(keyword.toLowerCase());
if (keywordIndex !== -1) {
Expand Down Expand Up @@ -204,7 +203,7 @@ export default function ChartContainer({
} else {
// 正则表达式匹配
const lossRegexObj = new RegExp(fileLossConfig.regex);
lines.forEach((line, index) => {
lines.forEach((line) => {
lossRegexObj.lastIndex = 0;
const lossMatch = lossRegexObj.exec(line);
if (lossMatch && lossMatch[1]) {
Expand All @@ -226,7 +225,7 @@ export default function ChartContainer({
// 数值正则:支持各种数值格式,包括科学计数法
const numberRegex = /[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/;

lines.forEach((line, lineIndex) => {
lines.forEach((line) => {
// 查找关键词(忽略大小写)
const keywordIndex = line.toLowerCase().indexOf(keyword.toLowerCase());
if (keywordIndex !== -1) {
Expand Down Expand Up @@ -255,7 +254,7 @@ export default function ChartContainer({
} else {
// 正则表达式匹配
const gradNormRegexObj = new RegExp(fileGradNormConfig.regex);
lines.forEach((line, index) => {
lines.forEach((line) => {
gradNormRegexObj.lastIndex = 0;
const gradNormMatch = gradNormRegexObj.exec(line);
if (gradNormMatch && gradNormMatch[1]) {
Expand Down Expand Up @@ -318,15 +317,6 @@ export default function ChartContainer({
onMaxStepChange(maxStep);
}, [parsedData, onMaxStepChange]);

const movingAverage = (data, windowSize = 10) => {
return data.map((point, index) => {
const start = Math.max(0, index - windowSize + 1);
const end = index + 1;
const window = data.slice(start, end);
const avg = window.reduce((sum, p) => sum + p.y, 0) / window.length;
return { x: point.x, y: avg };
});
};

const getComparisonData = (data1, data2, mode) => {
const minLength = Math.min(data1.length, data2.length);
Expand All @@ -341,11 +331,12 @@ export default function ChartContainer({
case 'absolute':
diff = Math.abs(val2 - val1);
break;
case 'relative':
case 'relative': {
// 相对误差:先计算绝对差值,再计算相对误差(不使用百分号)
const absoluteDiff = Math.abs(val2 - val1);
diff = val1 !== 0 ? (absoluteDiff / Math.abs(val1)) : 0;
diff = val1 !== 0 ? absoluteDiff / Math.abs(val1) : 0;
break;
}
default: // normal
diff = val2 - val1;
}
Expand Down Expand Up @@ -526,7 +517,7 @@ export default function ChartContainer({
'#f97316', // orange
];

const createChartData = (dataArray, title, yAxisLabel) => {
const createChartData = (dataArray) => {
const datasets = [];

dataArray.forEach((item, index) => {
Expand Down Expand Up @@ -691,7 +682,7 @@ export default function ChartContainer({
chartId="loss-main"
onRegisterChart={registerChart}
onSyncHover={syncHoverToAllCharts}
data={createChartData(lossDataArray, 'Loss', 'Loss Value')}
data={createChartData(lossDataArray)}
options={{
...chartOptions,
scales: {
Expand All @@ -705,7 +696,6 @@ export default function ChartContainer({
},
},
}}
title="Loss Function"
/>
</ResizablePanel>
)}
Expand All @@ -731,7 +721,6 @@ export default function ChartContainer({
},
},
}}
title="Loss Comparison"
/>
</ResizablePanel>
)}
Expand All @@ -747,7 +736,7 @@ export default function ChartContainer({
chartId="gradnorm-main"
onRegisterChart={registerChart}
onSyncHover={syncHoverToAllCharts}
data={createChartData(gradNormDataArray, 'Grad Norm', 'Grad Norm Value')}
data={createChartData(gradNormDataArray)}
options={{
...chartOptions,
scales: {
Expand All @@ -761,7 +750,6 @@ export default function ChartContainer({
},
},
}}
title="Gradient Norm"
/>
</ResizablePanel>
)}
Expand All @@ -787,7 +775,6 @@ export default function ChartContainer({
},
},
}}
title="Grad Norm Comparison"
/>
</ResizablePanel>
)}
Expand Down
28 changes: 12 additions & 16 deletions src/components/RegexControls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class ValueExtractor {
}
}
}
} catch (e) {
} catch {
// 不是JSON,继续其他格式
}

Expand Down Expand Up @@ -176,20 +176,18 @@ class ValueExtractor {
}
});
});
} catch (e) {
} catch {
// 无效正则表达式
}

return results;
}
}

export function RegexControls({
globalParsingConfig,
export function RegexControls({
globalParsingConfig,
onGlobalParsingConfigChange,
lossRegex,
gradNormRegex,
onRegexChange,
onRegexChange,
uploadedFiles = [],
xRange,
onXRangeChange,
Expand All @@ -199,7 +197,7 @@ export function RegexControls({
const [previewResults, setPreviewResults] = useState({ loss: [], gradNorm: [] });

// 提取数值的通用函数
const extractValues = useCallback((content, mode, config, type) => {
const extractValues = useCallback((content, mode, config) => {
switch (mode) {
case MATCH_MODES.KEYWORD:
return ValueExtractor.extractByKeyword(content, config.keyword);
Expand All @@ -218,10 +216,9 @@ export function RegexControls({
if (file.content) {
// Loss匹配
const lossMatches = extractValues(
file.content,
globalParsingConfig.loss.mode,
globalParsingConfig.loss,
'loss'
file.content,
globalParsingConfig.loss.mode,
globalParsingConfig.loss
);
results.loss.push({
fileName: file.name,
Expand All @@ -236,10 +233,9 @@ export function RegexControls({

// Grad Norm匹配
const gradNormMatches = extractValues(
file.content,
globalParsingConfig.gradNorm.mode,
globalParsingConfig.gradNorm,
'gradnorm'
file.content,
globalParsingConfig.gradNorm.mode,
globalParsingConfig.gradNorm
);
results.gradNorm.push({
fileName: file.name,
Expand Down