How can I write a MATLAB script to plot 3D and 2D knee joint data from a CSV file with customized axes and medial–lateral connections?

44 ビュー (過去 30 日間)
The CSV file contains the following data:
  • Sensor names: sensorNames = data.Sensor(1:6,1)
  • Sensor coordinates: sensorCoordinates = data{1:6, 2:4}
  • Source number: (:,5)
  • Source coordinates: sourceCoordinates = data{:, 6:end}
I want to create a 3D plot in MATLAB that includes the following:
  1. Plot the sensor names and their coordinates.
  2. Plot the source coordinates. The source coordinates are categorized into two groups:
  • Medial: sourceCoordinates = data{7:end, 6:end}
  • Lateral: sourceCoordinates = data{1:6, 6:end}
3. Set the axis directions depending on the knee side (see figure. 1 below), using S2 as the reference sensor (0,0,0):
Figure.1
  • Right knee: X-axis positive leftward, Y-axis positive downward, Z-axis positive perpendicular to the depth of the plane.
  • Left knee: X-axis positive rightward, Y-axis positive downward, Z-axis positive perpendicular to the depth of the plane.
4. Generate three types of plots (similar to the figure.2):
  • A 3D plot with all axes.
  • A 2D plot of X vs. Y.
  • A 2D plot of X vs. Z.
5. Add a line (like the green line in the figure.2 below) that connects the medial and lateral sources. This line should represent the knee joint range in all axis directions.
Figure.2
Knee joint range determination table.
I would like to write a MATLAB script that reads the CSV file, extracts the relevant data, and generates the 3D and 2D plots including the above details.
I wrote the following code:
%% Read and Plot 3D/2D Data from CSV File
% Load the CSV file
filename = '3DPlot_KLII_Mori.csv';
data = readtable(filename);
%% Extract Sensor and Source Data
sensorNames = data.Sensor(1:6, 1); % Sensor names
sensorCoordinates = data{1:6, 2:4}; % Sensor coordinates (X, Y, Z)
sourceNumbers = data{:, 5}; % Source numbers
sourceCoordinates = data{:, 6:end}; % All source coordinates
% Categorize source coordinates
lateralSources = data{1:6, 6:end}; % Lateral sources
medialSources = data{7:end, 6:end}; % Medial sources
%% User input for knee side
kneeSide = "Right"; % Change to "Left" if left knee
% Adjust axis directions based on knee side
if strcmpi(kneeSide, "Right")
% Right knee: X positive leftward, Y downward, Z downward
sensorCoordinates(:,1) = -sensorCoordinates(:,1);
lateralSources(:,1) = -lateralSources(:,1);
medialSources(:,1) = -medialSources(:,1);
elseif strcmpi(kneeSide, "Left")
% Left knee: X positive rightward, Y downward, Z downward
% No inversion needed
else
error('Knee side must be either "Right" or "Left".');
end
%% Plotting - 3D Plot
figure;
hold on;
% Plot sensor coordinates
scatter3(sensorCoordinates(:,1), sensorCoordinates(:,2), sensorCoordinates(:,3), ...
80, 'filled', 'MarkerFaceColor', 'b');
% Add sensor name labels
for i = 1:length(sensorNames)
text(sensorCoordinates(i,1), sensorCoordinates(i,2), sensorCoordinates(i,3), ...
[' ' char(sensorNames{i})], 'FontSize', 10, 'Color', 'b');
end
% Plot lateral sources
scatter3(lateralSources(:,1), lateralSources(:,2), lateralSources(:,3), ...
60, 'o', 'MarkerEdgeColor', 'r', 'DisplayName', 'Lateral Sources');
% Plot medial sources
scatter3(medialSources(:,1), medialSources(:,2), medialSources(:,3), ...
60, 's', 'MarkerEdgeColor', 'g', 'DisplayName', 'Medial Sources');
%% Formatting for 3D plot
grid on;
xlabel('X-axis');
ylabel('Y-axis');
zlabel('Z-axis');
title(['3D Plot of Sensors and Sources (' kneeSide ' Knee)']);
legend;
view(3);
hold off;
%% Plotting - 2D Plot (X vs Y)
figure;
hold on;
scatter(sensorCoordinates(:,1), sensorCoordinates(:,2), 80, 'filled', 'b');
for i = 1:length(sensorNames)
text(sensorCoordinates(i,1), sensorCoordinates(i,2), [' ' char(sensorNames{i})], 'FontSize', 10, 'Color', 'b');
end
scatter(lateralSources(:,1), lateralSources(:,2), 60, 'ro', 'DisplayName', 'Lateral Sources');
scatter(medialSources(:,1), medialSources(:,2), 60, 'gs', 'DisplayName', 'Medial Sources');
xlabel('X-axis');
ylabel('Y-axis');
title(['2D Plot (X vs Y) - ' kneeSide ' Knee']);
legend;
grid on;
hold off;
%% Plotting - 2D Plot (X vs Z)
figure;
hold on;
scatter(sensorCoordinates(:,1), sensorCoordinates(:,3), 80, 'filled', 'b');
for i = 1:length(sensorNames)
text(sensorCoordinates(i,1), sensorCoordinates(i,3), [' ' char(sensorNames{i})], 'FontSize', 10, 'Color', 'b');
end
scatter(lateralSources(:,1), lateralSources(:,3), 60, 'ro', 'DisplayName', 'Lateral Sources');
scatter(medialSources(:,1), medialSources(:,3), 60, 'gs', 'DisplayName', 'Medial Sources');
xlabel('X-axis');
ylabel('Z-axis');
title(['2D Plot (X vs Z) - ' kneeSide ' Knee']);
legend;
grid on;
hold off;

回答 (1 件)

William Rose
William Rose 2025 年 8 月 27 日 21:06
編集済み: William Rose 2025 年 8 月 27 日 21:21
[Edit: Fix spelling erros in my text. Fix incorrect matrix values for x-coordinates of medial box.]
It appers to me that you want to have lines for the edges of the boxes in your 3D plot and 2D plots, and your script is not making the lines.
Your code to read the data:
% Load the CSV file
filename = '3DPlot_KLII_Mori.csv';
data = readtable(filename);
%% Extract Sensor and Source Data
sensorNames = data.Sensor(1:6, 1); % Sensor names
sensorCoordinates = data{1:6, 2:4}; % Sensor coordinates (X, Y, Z)
sourceNumbers = data{:, 5}; % Source numbers
sourceCoordinates = data{:, 6:end}; % All source coordinates
Determine the knee joint ranges from the sensor coordinates. The knee joint determination tables above indicate that the z values are 0% of the way, and 125% of the way, from S1 to S5. Then the z-values are given by
boxZ=[1,0;-0.25,1.25]*sensorCoordinates([1,5],3); % z values for boxes
The knee joint determination tables above indicate that the y values are 45% of the way, and 80% of the way, from S2 to S1. (For x and z, the percentages are from S1. Is this really what you want for the y-values? I assume it is really what you want.) Then the y-values are given by
boxY=[0.45,0.55; 0.8,0.2]*sensorCoordinates([1,2],2); % y values for boxes
The knee joint determination tables above indicate that the x values for the medial box are 0% of the way, and 40% of the way, from S1 to S3. Then the medial box x-values are given by
boxXMed=[1,0; 0.6,0.4]*sensorCoordinates([1,3],1); % x values for medial box
The knee joint determination tables above indicate that the x values for the lateral box are 60% of the way, and 100% of the way, from S1 to S3. Then the lateral box x-values are given by
boxXLat=[0.4,0.6; 0,1]*sensorCoordinates([1,3],1); % x values for lateral box
Make grid matrices with the X,Y,Z coords of the medial box corners:
[X,Y,Z] = meshgrid(boxXMed,boxY,boxZ);
Convert the grid arrays to a 8x3 matrix representing the x,y,z coords of the 8 corners of the medial box:
boxCornersMed=[X(:),Y(:),Z(:)];
Make grid matrices with the X,Y,Z coords of the lateral box corners:
[X,Y,Z] = meshgrid(boxXLat,boxY,boxZ);
Convert the grid arrays to a 8x3 matrix representing the x,y,z coords of the 8 corners of the lateral box:
boxCornersLat=[X(:),Y(:),Z(:)];
Make an array that traverses every edge. This will require visiting some corners more than once.
boxPlotMed=boxCornersMed([1,2,4,3,1,5,6,2,6,8,4,8,7,3,7,5],:);
boxPlotLat=boxCornersLat([1,2,4,3,1,5,6,2,6,8,4,8,7,3,7,5],:);
Use plot3() for the 3D plot.
plot3(boxPlotMed(:,1),boxPlotMed(:,2),boxPlotMed(:,3),'-g') % medial box
hold on
plot3(boxPlotLat(:,1),boxPlotLat(:,2),boxPlotLat(:,3),'-r') % lateral box
xlabel('X'); ylabel('Y'); zlabel('Z');
legend('Medial Range','Lateral Range')
title(['3D Plot of Sensors and Sources']);
grid on; axis equal
I used "axis equal" so that the axes display in their true relative scale.
Add other elements to the plot, using your code:
% Categorize source coordinates
lateralSources = data{1:6, 6:end}; % Lateral sources
medialSources = data{7:end, 6:end}; % Medial sources
% Plot sensor coordinates
scatter3(sensorCoordinates(:,1), sensorCoordinates(:,2), sensorCoordinates(:,3), ...
80, 'filled', 'MarkerFaceColor', 'b', 'DisplayName', 'Sensors');
% Add sensor name labels
for i = 1:length(sensorNames)
text(sensorCoordinates(i,1), sensorCoordinates(i,2), sensorCoordinates(i,3), ...
[' ' char(sensorNames{i})], 'FontSize', 10, 'Color', 'b');
end
% Plot lateral sources
scatter3(lateralSources(:,1), lateralSources(:,2), lateralSources(:,3), ...
60, 'o', 'MarkerEdgeColor', 'r', 'DisplayName', 'Lateral Sources');
% Plot medial sources
scatter3(medialSources(:,1), medialSources(:,2), medialSources(:,3), ...
60, 's', 'MarkerEdgeColor', 'g', 'DisplayName', 'Medial Sources');
Do something similar for the 2D plots.
  4 件のコメント
MD MEHEDI HASSAN
MD MEHEDI HASSAN 約13時間 前
Thank you very much for your attempt to solve the problem and for your helpful comments. I will try to modify my script according to your suggestions.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeBiomechanics についてさらに検索

製品


リリース

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by