Thành viên:Phạm Thạch Thảo/Note: Vẽ đồ thị với Matlab
Vẽ hình (ta nói đến chủ yếu là đồ thị 2D) cho ấn bản khoa học là công việc khá công phu, đòi hỏi khá nhiều thời gian điều chỉnh và google tìm hiểu các chức năng của công cụ vẽ. Vẽ hình cố nhiên phụ thuộc vào công cụ vẽ. Trong khi công cụ đồ họa có rất nhiều, chẳng hạn gnuplot, R, xmgrace, origin..., chỉ một số đạt yêu cầu của các ấn bản phát hành. Matlab xuất thân là công cụ tính toán, từ lâu đã tích hợp công cụ đồ họa khá mạnh cho mô phỏng và vẽ đồ thị. Tận dụng khả năng đồ họa của Matlab kết hợp với bản chất là một ngôn ngữ lập trình, đồ thị có thể thực hiện trên Matlab với khả năng "tự động hóa" và "tái sản xuất" cao thông qua các scripts. Điều đó khiến Matlab thể hiện ưu thế vượt trội so với các phần mềm sử dụng giao diện đồ họa thuần túy; trong khi bản thân nó cũng tích hợp hệ GUI (Graphical User Interface) rất đầy đủ tiện lợi cho các tinh chỉnh. Ngay cả những phần mềm hỗ trợ thực hiện tác vụ qua các scripts như xmgrace cũng khó có độ linh hoạt như một ngôn ngữ lập trình thứ thiệt như vậy. Điểm yếu lớn nhất của Matlab có lẽ liên quan đến tài chính: Matlab là phần mềm thương mại, và với sinh viên thì có lẽ không phải là loại "rẻ bèo".
Ghi chú này đơn thuần kết hợp các mẩu thông tin khác nhau từ các nguồn khác nhau thu được trong quá trình tìm hiểu cách vẽ hình với Matlab, từ việc đọc số liệu đến xuất hình theo định dạng.
Mục lục
Vài vấn đề cơ bản của Matlab cần thiết khi vẽ hình[sửa]
Viết "hướng dẫn sử dụng" Matlab trong đôi ba câu là điều không thể và nói ra sẽ làm cho các cộng tác viên của MathWorks tự ái (!) Vì vậy về cơ bản làm trước hiểu sau là lựa chọn hay nhất. Khởi động Matlab sẽ cho cửa sổ chính là command windows, qua đó người dùng gõ trực tiếp các lệnh đòi hỏi Matlab thực thi. Ta cần sử dụng cửa sổ Editor để soạn thảo scripts, là một dãy lệnh viết trước và thực hiện liên tục thay vì "thông dịch" từng câu. Cuối cùng là cửa sổ đồ họa trên đó Matlab thực hiện các thao tác vẽ hình.
Thư mục hiện hành[sửa]
Thư mục hiện hành là thư mục Matlab làm việc, các thực đơn, dữ liệu phục vụ thông thường nên đặt trong thư mục hiện hành.
Tìm thư mục hiện hành bằng cách gõ vào cửa sổ command,
>pwd
Đổi thư mục hiện hành bằng lệnh,
>cd <đường dẫn>
Về cơ bản Matlab hỗ trợ rất nhiều lệnh bash như trong Linux.
MatLab 7 trở đi có thể hiện thư mục hiện hành bên tay trái và người dùng có thể đổi bằng các "click" như trong các chương trình explorer.
Editor[sửa]
Từ cửa sổ command, gõ
>edit mkfigure.m
ta sẽ gọi là chương trình (cửa sổ) soạn thảo thực đơn (scripts) mkfigue.m trong thư mục hiện hành của Matlab. Thao tác này cũng có thể thực hiện bằng cách ấn nút new đâu đó trên toolbar của Matlab. Editor của Matlab 7 trở đi tương đối là đẹp!
Chạy thực đơn: khi thực đơn đã nằm trong thư mục hiện hành, gọi tên thực đơn đó từ cửa sổ command sẽ thực hiện thực đơn, ví dụ
>mkfigure
Figures[sửa]
Từ của sổ command, gõ
>figure(1)
ta sẽ gọi là cửa sổ đồ họa số 1. Việc gọi trước các cửa sổ đồ họa về cơ bản là không cần thiết, khi thực hiện lệnh vẽ lần đầu, tự động một cửa sổ đồ họa sẽ được mở. Tuy nhiên nếu ta thực hiện vẽ trên nhiều cửa sổ, việc gọi figure(1), figure(2) ... là cần thiết để xác định thao tác vẽ sẽ thực hiện trên cửa sổ nào.
Về
cơ
bản
các
vấn
đề
trừu
tượng
hơn
hoàn
toàn
có
thể
bỏ
qua,
sao
các
tệp
cần
thiết
vào
thư
mục
hiện
hành,
soạn
thảo
thực
đơn,
lưu
thực
đơn
và
chạy
là
tất
cả
những
gì
cần
thiết.
Đọc số liệu[sửa]
Có một vài các đọc số liệu khác nhau trong Matlab, có lẽ đơn giản hơn cả là dùng lệnh
data = dlmread("data.dat")
Lệnh này đọc một bảng số chữ nhật và ghi vào biến data. Yêu cầu hơi khắt khe với cách sự dụng cơ bản (so với R): bảng phải thuần túy số và phải hình chữ nhật. Thông thường dữ liệu thường có các comment đi kèm, đơn giản nhất là ta xóa chúng bằng tay, phức tạp hơn có thể dùng R, và phức tạp hơn nữa có thể dùng chính Matlab.
Cấu trúc cơ bản nhất của bảng số liệu thường là cột 1 là đối số X, cột 2, 3, ... là các hàm phụ thuộc Y1, Y2...
{Ghi chú: Dạng của data là một ma trận, có thể truy cập đến phần tử (k1, k2) bằng lệnh data(k1,k2), cột k bằng lệnh data(:,k), hàng k bằng lệnh data(k,:).}
Vẽ hình[sửa]
Có lẽ ta nên hiểu của sổ đồ họa figure là một nền cơ bản, các lệnh vẽ hình sẽ cho phép đặt các thực thể liên tiếp theo các lớp (layers) lên của sổ đó. Mặc định là mỗi lần đặt một thực thể mới lên thì Matlab sẽ xóa thực thể cũ, đó là lý do ta phải sử dụng "hold on" để giữ các thực thể cũ khi cần thiết (dưới đây). Các đối tượng đó có thể thấy khi ta "ngoắng" chuột click lên chúng trong các thao tác hiệu chỉnh bằng giao diện đồ họa.
Lệnh cơ bản plot(X,Y) sẽ đặt các điểm cho bởi toạ độ chứa trong X và Y lên cửa sổ đồ họa, đường nối chúng, cùng với trục tọa độ (cũng là một đối tượng). Chẳng hạn ta vẽ cột thứ 2 theo cột thứ 1 trong bảng số liệu bằng đoạn scripts:
X = data(,1) Y = data(,2) figure(1) % Lệnh này về cơ bản không cần thiết cho lần đầu tiên, nhưng về tác phong thì nên dùng! Dấu % dùng cho các comment plot(X,Y); hold on;
Lựa chọn của plot() cho điểm và đường[sửa]
Một đường vẽ mặc định thường quá mảnh, plot cho phép tích hợp các lựa chọn như màu, độ dày đường... plot(X,Y,'property',value)Ví dụ:
plot(X,Y,'Color','r','Marker','o','LineStyle', '-', 'LineWidth', 2.0)
Thực hiện vẽ Y theo X với màu đỏ, các điểm dữ liệu dạng điểm tròn, đường dạng liền nét với độ dày 2.0. Riêng ba lựa chọn đầu rất hay thường gặp và có thể viết gọn là
plot(X,Y,'ro-','LineWidth',2.0)
Các lựa chọn cho dạng điểm thường gặp là o, *, +, s; các lựa chọn cho màu thường gặp là r (red), g (green), b (blue), y (yellow), c (cyan), p (purple) , k (dark)...; các lựa chọn cho dạng đường thường là - (solid), -- (dashed), .-(dotted-dashed), :(dotted).
Với các yêu cầu phức tạp hơn màu có thể dùng một vector mô ta ba thành phần [R,G,B]. Kỹ thuật "pha màu" có thể thực hiện thông qua colormap, colorbar...
Hiệu chỉnh trục[sửa]
Hiệu chỉnh trục tương đối tỉ mỉ (ta nhớ rằng: trục cũng là một thực thể). Nói chung để thay đổi giá trị (value) các đặc tính (property) của thực thể (object) ta dùng lệnh set(<đối tượng>,<đặc tính>,<giá trị>). Trục của đồ thị hiện đang vẽ được gọi là gca (get current axis).
Thông thường trục thường mảnh quá, phông nhỏ... ta thực hiện set lại như sau:
h = gca; % Sao đồ thị hiện hành ra biến mới, chỉ cho chắc ăn mà thôi set(h,'LineWidth',2,'Box','on','FontSize',30, 'Layer', 'top'); % Set độ dày của trục, đóng khung đồ thị trong ô vuông thay vì hai trục x, y, font 30...
Lựa chọn "Layer" >"top" cần thiết khi muốn các ticks (và trục!- điều này thường thấy khi trục dày, một nửa của nó có thể bị che) không bị các đối tượng khác che đi mất.
Với lần vẽ đầu tiên xem phác thảo ta sẽ phải xác định "cắt" đồ thị ở đâu. Sau đó ấn định việc "cắt khung" bằng lệnh
%Trục X: set(h,'XLim',[0.4999,8.00001]); %Cắt khung set(h,'XTick',[0.5,1,1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,6.5,7,7.5,8]); %Đặt các ticks vào vị trí muốn đặt set(h,'XTickLabel',{'0.5','1','','2','','','','4','','','','','','','','8'}); %Đặt tên cho các ticks xlabel('M (\times 10^5)','FontSize',30,'FontWeight','n'); %Đặt tên trục, hỗ trợ phiên dịch Tex %Tương tụ với trục Y: set(h,'YLim',[0.9e-3,1.0001]); set(h,'YTick',[1e-3,1e-2,2e-2]); set(h,'YTickLabel',{'1e-3','1e-2','2e-2'}); ylabel('1-r','FontSize',30,'FontWeight','n','Rotation',0); %Rotation định vị việc quay tên đối với trục y, mặc định là tên được quay dọc theo trục y, nhưng nhiều người không thích điều đó và... quay lại bằng cách set rotation 0.
Về cơ bản thông thường người vẽ lười gõ lệnh và các thao tác chọn ticks, labels.. thường được thực hiện qua các "clicks" chuột. Tuy nhiên thường ta sẽ phải vẽ khoảng 100 lần trước khi được sếp gật đầu; "click" chuột 100 lần không lấy gì làm mỏi tay nhưng quả thật nhàm chán. Vì vậy ghi lại thao tác đó vào scripts là rất hữu ích.
Một bất tiện là các TickLabels của matlab hiện giờ không hỗ trợ đặt tên với Tex, và bất tiện biến thành phiền toái khi sếp cứ khăng khăng đòi đặt tên với Tex (!) Mình có viết một chương trình con đặt tên ticks của trục với Tex, nhưng vẫn có thể sẽ phải dùng... tay để kéo lại các Ticks cho... đẹp.
function [ output_args ] = setXTickLabels(h,XTickLabels) %SETXTICKLABELS Summary of this function goes here % Detailed explanation goes here: set(h, 'xTickLabel', []) %Remove tick labels %% Get tick mark positions xLims = get(h,'xLim'); yLims = get(h,'yLim'); xTicks = get(h, 'xTick'); yTicks = get(h,'yTick'); yOffset = 0.02*(yLims(2)-yLims(1)); for k = 1:length(xTicks) %Create text box and set appropriate properties text(xTicks(k), yLims(1) - yOffset,XTickLabels{k},... 'HorizontalAlignment','Right','Interpreter', 'Tex','FontSize',... get(h,'FontSize'),'FontWeight',get(h,'FontWeight'),'FontName',get(h,'FontName')); end; end
Inset[sửa]
Có người cho mình biết các nhà xuất bản thường rất tiết kiệm giấy, và hình với nhiều khoảng trắng trống là các thành phần... không được ưa thích từ phương diện các biên tập viên. Vì thế các hình vẽ thường phải đưa vào các inset.