@@ -11,8 +11,7 @@ https://www.coursera.org/learn/machine-learning | |||
本项目包含课程中的所有课后作业以及笔记,目前正在将手写笔记进行电子化。 | |||
1. 笔记(notes)都为中文,为了便于复习和扩充等,尽量会按照视频目录,以及视频内容进行提炼整理。 | |||
2. 所有课后作业(assignments)都已提交并通过 Coursera 编程测验。仅供参考,请勿抄袭。 | |||
2. 遵循[荣誉准则][honor code],现已移除已通过的课后编程作业的源代码,之后会改为指导笔记形式陆续更新。 | |||
For Andrew Ng's machine learning course on Coursera. | |||
@@ -26,11 +25,11 @@ You can read it by Typora or any other similar markdown editor. | |||
1. **在线阅读地址**:http://scruel.gitee.io/ml-andrewng-notes/ | |||
2. 直接在 GitHub Page 上阅读,需安装 Chrome 插件 —— [GitHub with MathJax][1](部分公式仍无法正常解析)。 | |||
2. 直接在 GitHub Page 上阅读,需安装 Chrome 插件 —— [GitHub with MathJax][GitHub with MathJax](部分公式仍无法正常解析)。 | |||
3. 下载 .html 网页文件及 笔记图片 image 文件夹,浏览器打开阅读。 | |||
4. 笔记源码(.md)基于支持 LaTeX 的 markdown 编辑器 [Typora][2],其他类似的编辑器也可以阅读及编辑,注意其他编辑器可能会产生排版问题。 | |||
4. 笔记源码(.md)基于支持 LaTeX 的 markdown 编辑器 [Typora][Typora],其他类似的编辑器也可以阅读及编辑,注意其他编辑器可能会产生排版问题。 | |||
@@ -39,12 +38,16 @@ You can read it by Typora or any other similar markdown editor. | |||
方便网络不方便的同学学习 | |||
[百度网盘下载](https://pan.baidu.com/s/1mkmnRIC) | 密码:fdzc(包含视频,讲义,以及编程作业题原题压缩包) | |||
[百度网盘下载][baidupan] | 密码:fdzc(包含视频,讲义,以及编程作业题原题压缩包) | |||
[B站在线中英双语](http://www.bilibili.com/video/av9912938?bbid=F8173D95-FF96-47EF-B7F4-0779D698B8051978infoc) | [B站在线英文版1](https://www.bilibili.com/video/av17624209/?from=search&seid=15848135050308500663) | [B站在线英文版2](https://www.bilibili.com/video/av17624412/?from=search&seid=15848135050308500663) | |||
[B站在线中英双语][bilibili_zh] | [B站在线英文版1][bilibili_en1] | [B站在线英文版2][bilibili_en2] | |||
当然,还是建议克服一下困难,最好能上 Coursera 网站学习,官网安排的贴心小测试可以检验你对知识的掌握情况。 | |||
如果遇到 Coursera 上提交编程作业失败的问题,以 [submitWithConfiguration.m](https://github.com/scruel/ML-AndrewNg-Notes/blob/master/assignments/submitWithConfiguration.m) 覆盖编程作业中 lib 文件夹下的同名文件即可解决。 | |||
## Thanks | |||
- Coursera 官网 | |||
@@ -55,18 +58,24 @@ You can read it by Typora or any other similar markdown editor. | |||
注:由于手写笔记成稿时间较早,有所参考无法一一致谢,在此统一表示谢意! | |||
## License | |||
[][3] | |||
[][CC BY-NC 4.0] | |||
This work is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License][3]. | |||
This work is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License][CC BY-NC 4.0]. | |||
[知乎文章](https://zhuanlan.zhihu.com/p/32781741) | |||
[知乎文章][zhihu] | |||
By: Scruel | |||
[1]: https://chrome.google.com/webstore/detail/ioemnmodlmafdkllaclgeombjnmnbima | |||
[2]: https://typora.io/ | |||
[3]: http://creativecommons.org/licenses/by-nc/4.0/ | |||
[zhihu]: https://zhuanlan.zhihu.com/p/32781741 | |||
[baidupan]: https://pan.baidu.com/s/1mkmnRIC | |||
[bilibili_zh]: http://www.bilibili.com/video/av9912938?bbid=F8173D95-FF96-47EF-B7F4-0779D698B8051978infoc | |||
[bilibili_en1]: https://www.bilibili.com/video/av17624209/?from=search&seid=15848135050308500663 | |||
[bilibili_en2]: https://www.bilibili.com/video/av17624412/?from=search&seid=15848135050308500663 | |||
[GitHub with MathJax]: https://chrome.google.com/webstore/detail/ioemnmodlmafdkllaclgeombjnmnbima | |||
[Typora]: https://typora.io/ | |||
[honor code]: https://www.coursera.org/learn/machine-learning/supplement/nh65Z/machine-learning-honor-code | |||
[CC BY-NC 4.0]: http://creativecommons.org/licenses/by-nc/4.0/ |
@@ -1,99 +0,0 @@ | |||
% Version 1.000 | |||
% | |||
% Code provided by Ruslan Salakhutdinov and Geoff Hinton | |||
% | |||
% Permission is granted for anyone to copy, use, modify, or distribute this | |||
% program and accompanying programs and documents for any purpose, provided | |||
% this copyright notice is retained and prominently displayed, along with | |||
% a note saying that the original programs are available from our | |||
% web page. | |||
% The programs and documents are distributed without any warranty, express or | |||
% implied. As the programs were written for research purposes only, they have | |||
% not been tested to the degree that would be advisable in any important | |||
% application. All use of these programs is entirely at the user's own risk. | |||
% This program reads raw MNIST files available at | |||
% http://yann.lecun.com/exdb/mnist/ | |||
% and converts them to files in matlab format | |||
% Before using this program you first need to download files: | |||
% train-images-idx3-ubyte.gz train-labels-idx1-ubyte.gz | |||
% t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz | |||
% and gunzip them. You need to allocate some space for this. | |||
% This program was originally written by Yee Whye Teh | |||
% Work with test files first | |||
fprintf(1,'You first need to download files:\n train-images-idx3-ubyte.gz\n train-labels-idx1-ubyte.gz\n t10k-images-idx3-ubyte.gz\n t10k-labels-idx1-ubyte.gz\n from http://yann.lecun.com/exdb/mnist/\n and gunzip them \n'); | |||
f = fopen('t10k-images-idx3-ubyte','r'); | |||
[a,count] = fread(f,4,'int32'); | |||
g = fopen('t10k-labels-idx1-ubyte','r'); | |||
[l,count] = fread(g,2,'int32'); | |||
fprintf(1,'Starting to convert Test MNIST images (prints 10 dots) \n'); | |||
n = 1000; | |||
Df = cell(1,10); | |||
for d=0:9, | |||
Df{d+1} = fopen(['test' num2str(d) '.ascii'],'w'); | |||
end; | |||
for i=1:10, | |||
fprintf('.'); | |||
rawimages = fread(f,28*28*n,'uchar'); | |||
rawlabels = fread(g,n,'uchar'); | |||
rawimages = reshape(rawimages,28*28,n); | |||
for j=1:n, | |||
fprintf(Df{rawlabels(j)+1},'%3d ',rawimages(:,j)); | |||
fprintf(Df{rawlabels(j)+1},'\n'); | |||
end; | |||
end; | |||
fprintf(1,'\n'); | |||
for d=0:9, | |||
fclose(Df{d+1}); | |||
D = load(['test' num2str(d) '.ascii'],'-ascii'); | |||
fprintf('%5d Digits of class %d\n',size(D,1),d); | |||
save(['test' num2str(d) '.mat'],'D','-mat'); | |||
end; | |||
% Work with trainig files second | |||
f = fopen('train-images-idx3-ubyte','r'); | |||
[a,count] = fread(f,4,'int32'); | |||
g = fopen('train-labels-idx1-ubyte','r'); | |||
[l,count] = fread(g,2,'int32'); | |||
fprintf(1,'Starting to convert Training MNIST images (prints 60 dots)\n'); | |||
n = 1000; | |||
Df = cell(1,10); | |||
for d=0:9, | |||
Df{d+1} = fopen(['digit' num2str(d) '.ascii'],'w'); | |||
end; | |||
for i=1:60, | |||
fprintf('.'); | |||
rawimages = fread(f,28*28*n,'uchar'); | |||
rawlabels = fread(g,n,'uchar'); | |||
rawimages = reshape(rawimages,28*28,n); | |||
for j=1:n, | |||
fprintf(Df{rawlabels(j)+1},'%3d ',rawimages(:,j)); | |||
fprintf(Df{rawlabels(j)+1},'\n'); | |||
end; | |||
end; | |||
fprintf(1,'\n'); | |||
for d=0:9, | |||
fclose(Df{d+1}); | |||
D = load(['digit' num2str(d) '.ascii'],'-ascii'); | |||
fprintf('%5d Digits of class %d\n',size(D,1),d); | |||
save(['digit' num2str(d) '.mat'],'D','-mat'); | |||
end; | |||
dos('rm *.ascii'); | |||
@@ -1,21 +0,0 @@ | |||
function J = computeCost(X, y, theta) | |||
%COMPUTECOST Compute cost for linear regression | |||
% J = COMPUTECOST(X, y, theta) computes the cost of using theta as the | |||
% parameter for linear regression to fit the data points in X and y | |||
% Initialize some useful values | |||
m = length(y); % number of training examples | |||
% You need to return the following variables correctly | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Compute the cost of a particular choice of theta | |||
% You should set J to the cost. | |||
J = 1 / 2 / m * sum((X * theta - y) .^ 2); | |||
%JVal = 1 / 2 / m * (X * theta - y)' * (X * theta -y); | |||
%gradient = theta - 1 / m * (X' * (X * theta - y)); | |||
% ========================================================================= | |||
end |
@@ -1,22 +0,0 @@ | |||
function J = computeCostMulti(X, y, theta) | |||
%COMPUTECOSTMULTI Compute cost for linear regression with multiple variables | |||
% J = COMPUTECOSTMULTI(X, y, theta) computes the cost of using theta as the | |||
% parameter for linear regression to fit the data points in X and y | |||
% Initialize some useful values | |||
m = length(y); % number of training examples | |||
% You need to return the following variables correctly | |||
J = 0; | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Compute the cost of a particular choice of theta | |||
% You should set J to the cost. | |||
J = 1 / 2 / m * sum((X * theta - y) .^ 2); | |||
%J = 1 / 2 / m * (X * theta - y)' * (X * theta - y); | |||
% ========================================================================= | |||
end |
@@ -1,122 +0,0 @@ | |||
%% Machine Learning Online Class - Exercise 1: Linear Regression | |||
% Instructions | |||
% ------------ | |||
% | |||
% This file contains code that helps you get started on the | |||
% linear exercise. You will need to complete the following functions | |||
% in this exericse: | |||
% | |||
% warmUpExercise.m | |||
% plotData.m | |||
% gradientDescent.m | |||
% computeCost.m | |||
% gradientDescentMulti.m | |||
% computeCostMulti.m | |||
% featureNormalize.m | |||
% normalEqn.m | |||
% | |||
% For this exercise, you will not need to change any code in this file, | |||
% or any other files other than those mentioned above. | |||
% | |||
% x refers to the population size in 10,000s | |||
% y refers to the profit in $10,000s | |||
% | |||
%% Initialization | |||
clear ; close all; clc | |||
%% ==================== Part 1: Basic Function ==================== | |||
% Complete warmUpExercise.m | |||
fprintf('Running warmUpExercise ... \n'); | |||
fprintf('5x5 Identity Matrix: \n'); | |||
warmUpExercise() | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% ======================= Part 2: Plotting ======================= | |||
fprintf('Plotting Data ...\n') | |||
data = load('ex1data1.txt'); | |||
X = data(:, 1); y = data(:, 2); | |||
m = length(y); % number of training examples | |||
% Plot Data | |||
% Note: You have to complete the code in plotData.m | |||
plotData(X, y); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% =================== Part 3: Gradient descent =================== | |||
fprintf('Running Gradient Descent ...\n') | |||
X = [ones(m, 1), data(:,1)]; % Add a column of ones to x | |||
theta = zeros(2, 1); % initialize fitting parameters | |||
% Some gradient descent settings | |||
iterations = 1500; | |||
alpha = 0.01; | |||
% compute and display initial cost | |||
computeCost(X, y, theta) | |||
% run gradient descent | |||
theta = gradientDescent(X, y, theta, alpha, iterations); | |||
% print theta to screen | |||
fprintf('Theta found by gradient descent: '); | |||
fprintf('%f %f \n', theta(1), theta(2)); | |||
% Plot the linear fit | |||
hold on; % keep previous plot visible | |||
plot(X(:,2), X*theta, '-') | |||
legend('Training data', 'Linear regression') | |||
hold off % don't overlay any more plots on this figure | |||
% Predict values for population sizes of 35,000 and 70,000 | |||
predict1 = [1, 3.5] *theta; | |||
fprintf('For population = 35,000, we predict a profit of %f\n',... | |||
predict1*10000); | |||
predict2 = [1, 7] * theta; | |||
fprintf('For population = 70,000, we predict a profit of %f\n',... | |||
predict2*10000); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% ============= Part 4: Visualizing J(theta_0, theta_1) ============= | |||
fprintf('Visualizing J(theta_0, theta_1) ...\n') | |||
% Grid over which we will calculate J | |||
theta0_vals = linspace(-10, 10, 100); | |||
theta1_vals = linspace(-1, 4, 100);%从-1到4之间取100个数组成一个向量 | |||
% initialize J_vals to a matrix of 0's | |||
J_vals = zeros(length(theta0_vals), length(theta1_vals)); | |||
% Fill out J_vals | |||
for i = 1:length(theta0_vals) | |||
for j = 1:length(theta1_vals) | |||
t = [theta0_vals(i); theta1_vals(j)]; | |||
J_vals(i,j) = computeCost(X, y, t); | |||
end | |||
end | |||
% Because of the way meshgrids work in the surf command, we need to | |||
% transpose J_vals before calling surf, or else the axes will be flipped | |||
J_vals = J_vals'; | |||
% Surface plot | |||
figure; | |||
surf(theta0_vals, theta1_vals, J_vals)%画出三维图形 | |||
xlabel('\theta_0'); ylabel('\theta_1'); | |||
% Contour plot 轮廓图 | |||
figure; | |||
% Plot J_vals as 15 contours spaced logarithmically between 0.01 and 100 | |||
contour(theta0_vals, theta1_vals, J_vals, logspace(-2, 3, 20)) | |||
xlabel('\theta_0'); ylabel('\theta_1'); | |||
hold on; | |||
plot(theta(1), theta(2), 'rx', 'MarkerSize', 10, 'LineWidth', 2); |
@@ -1,201 +0,0 @@ | |||
%% Machine Learning Online Class | |||
% Exercise 1: Linear regression with multiple variables | |||
% | |||
% Instructions | |||
% ------------ | |||
% | |||
% This file contains code that helps you get started on the | |||
% linear regression exercise. | |||
% | |||
% You will need to complete the following functions in this | |||
% exericse: | |||
% | |||
% warmUpExercise.m | |||
% plotData.m | |||
% gradientDescent.m | |||
% computeCost.m | |||
% gradientDescentMulti.m | |||
% computeCostMulti.m | |||
% featureNormalize.m | |||
% normalEqn.m | |||
% | |||
% For this part of the exercise, you will need to change some | |||
% parts of the code below for various experiments (e.g., changing | |||
% learning rates). | |||
% | |||
%% Initialization | |||
%% ================ Part 1: Feature Normalization ================ | |||
%% Clear and Close Figures | |||
clear ; close all; clc | |||
fprintf('Loading data ...\n'); | |||
%% Load Data | |||
data = load('ex1data2.txt'); | |||
X = data(:, 1:2); | |||
y = data(:, 3); | |||
m = length(y); | |||
% Print out some data points | |||
fprintf('First 10 examples from the dataset: \n'); | |||
fprintf(' x = [%.0f %.0f], y = %.0f \n', [X(1:10,:) y(1:10,:)]'); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
% Scale features and set them to zero mean | |||
fprintf('Normalizing Features ...\n'); | |||
[X mu sigma] = featureNormalize(X); | |||
% Add intercept term to X | |||
X = [ones(m, 1) X]; | |||
%% ================ Part 2: Gradient Descent ================ | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: We have provided you with the following starter | |||
% code that runs gradient descent with a particular | |||
% learning rate (alpha). | |||
% | |||
% Your task is to first make sure that your functions - | |||
% computeCost and gradientDescent already work with | |||
% this starter code and support multiple variables. | |||
% | |||
% After that, try running gradient descent with | |||
% different values of alpha and see which one gives | |||
% you the best result. | |||
% | |||
% Finally, you should complete the code at the end | |||
% to predict the price of a 1650 sq-ft, 3 br house. | |||
% | |||
% Hint: By using the 'hold on' command, you can plot multiple | |||
% graphs on the same figure. | |||
% | |||
% Hint: At prediction, make sure you do the same feature normalization. | |||
% | |||
fprintf('Running gradient descent ...\n'); | |||
% Choose some alpha value | |||
alpha = 0.001; | |||
num_iters = 4000; | |||
% Init Theta and Run Gradient Descent | |||
theta = zeros(3, 1); | |||
[theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters); | |||
%[theta, J_history] = gradientDescentMulti(X, y, zeros(3, 1), 0.001, 4000); | |||
%plot(1:numel(J_history), J_history, '-bc', 'LineWidth', 2); | |||
%price = theta(1) + (1650 - mu(1)) / sigma(1) * theta(2) + (3 - mu(2)) / sigma(2) * theta(3) % You should change this | |||
%price = theta(1) + (15 - mu(1)) / sigma(1) * theta(2) + (1 - mu(2)) / sigma(2) * theta(3) + (2 - mu(3)) / sigma(3) * theta(4) % You should change this | |||
fprintf(['Predicted price of a 1650 sq-ft, 3 br house ' ... | |||
'(using gradient descent):\n $%f\n'], price); | |||
% Plot the convergence graph | |||
figure; | |||
plot(1:numel(J_history), J_history, '-b', 'LineWidth', 2); | |||
xlabel('Number of iterations'); | |||
ylabel('Cost J'); | |||
% Display gradient descent's result | |||
fprintf('Theta computed from gradient descent: \n'); | |||
fprintf(' %f \n', theta); | |||
fprintf('\n'); | |||
% Estimate the price of a 1650 sq-ft, 3 br house | |||
% ====================== YOUR CODE HERE ====================== | |||
% Recall that the first column of X is all-ones. Thus, it does | |||
% not need to be normalized. | |||
price = 0; % You should change this | |||
% ============================================================ | |||
fprintf(['Predicted price of a 1650 sq-ft, 3 br house ' ... | |||
'(using gradient descent):\n $%f\n'], price); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% ================ Part 3: Normal Equations ================ | |||
fprintf('Solving with normal equations...\n'); | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: The following code computes the closed form | |||
% solution for linear regression using the normal | |||
% equations. You should complete the code in | |||
% normalEqn.m | |||
% | |||
% After doing so, you should complete this code | |||
% to predict the price of a 1650 sq-ft, 3 br house. | |||
% | |||
%% Load Data | |||
data = csvread('ex1data2.txt'); | |||
X = data(:, 1:2); | |||
y = data(:, 3); | |||
m = length(y); | |||
% Add intercept term to X | |||
X = [ones(m, 1) X]; | |||
% Calculate the parameters from the normal equation | |||
theta = normalEqn(X, y); | |||
% Display normal equation's result | |||
fprintf('Theta computed from the normal equations: \n'); | |||
fprintf(' %f \n', theta); | |||
fprintf('\n'); | |||
% Estimate the price of a 1650 sq-ft, 3 br house | |||
% ====================== YOUR CODE HERE ====================== | |||
price = theta(1) + 1650 * theta(2) + 3 * theta(3); % You should change this | |||
% ============================================================ | |||
fprintf(['Predicted price of a 1650 sq-ft, 3 br house ' ... | |||
'(using normal equations):\n $%f\n'], price); | |||
%% ============= Part 4: Visualizing J(theta_0, theta_1) ============= | |||
fprintf('Visualizing J(theta_0, theta_1) ...\n') | |||
% Grid over which we will calculate J | |||
theta0_vals = linspace(-10, 10, 100); | |||
theta1_vals = linspace(-1, 4, 100);%从-1到4之间取100个数组成一个向量 | |||
theta2_vals = linspace(-1, 4, 100);%从-1到4之间取100个数组成一个向量 | |||
% initialize J_vals to a matrix of 0's | |||
J_vals = zeros(length(theta0_vals), length(theta1_vals), length(theta1_vals)); | |||
% Fill out J_vals | |||
for i = 1:length(theta0_vals) | |||
for j = 1:length(theta1_vals) | |||
t = [theta0_vals(i); theta1_vals(j)]; | |||
J_vals(i,j) = computeCostMulti(X, y, t); | |||
end | |||
end | |||
% Because of the way meshgrids work in the surf command, we need to | |||
% transpose J_vals before calling surf, or else the axes will be flipped | |||
J_vals = J_vals'; | |||
% Surface plot | |||
figure; | |||
surf(theta0_vals, theta1_vals, J_vals)%画出三维图形 | |||
xlabel('\theta_0'); ylabel('\theta_1'); | |||
% Contour plot 轮廓图 | |||
figure; | |||
% Plot J_vals as 15 contours spaced logarithmically between 0.01 and 100 | |||
contour(theta0_vals, theta1_vals, J_vals, logspace(-2, 3, 20)) | |||
xlabel('\theta_0'); ylabel('\theta_1'); | |||
hold on; | |||
plot(theta(1), theta(2), 'rx', 'MarkerSize', 10, 'LineWidth', 2); |
@@ -1,97 +0,0 @@ | |||
6.1101,17.592 | |||
5.5277,9.1302 | |||
8.5186,13.662 | |||
7.0032,11.854 | |||
5.8598,6.8233 | |||
8.3829,11.886 | |||
7.4764,4.3483 | |||
8.5781,12 | |||
6.4862,6.5987 | |||
5.0546,3.8166 | |||
5.7107,3.2522 | |||
14.164,15.505 | |||
5.734,3.1551 | |||
8.4084,7.2258 | |||
5.6407,0.71618 | |||
5.3794,3.5129 | |||
6.3654,5.3048 | |||
5.1301,0.56077 | |||
6.4296,3.6518 | |||
7.0708,5.3893 | |||
6.1891,3.1386 | |||
20.27,21.767 | |||
5.4901,4.263 | |||
6.3261,5.1875 | |||
5.5649,3.0825 | |||
18.945,22.638 | |||
12.828,13.501 | |||
10.957,7.0467 | |||
13.176,14.692 | |||
22.203,24.147 | |||
5.2524,-1.22 | |||
6.5894,5.9966 | |||
9.2482,12.134 | |||
5.8918,1.8495 | |||
8.2111,6.5426 | |||
7.9334,4.5623 | |||
8.0959,4.1164 | |||
5.6063,3.3928 | |||
12.836,10.117 | |||
6.3534,5.4974 | |||
5.4069,0.55657 | |||
6.8825,3.9115 | |||
11.708,5.3854 | |||
5.7737,2.4406 | |||
7.8247,6.7318 | |||
7.0931,1.0463 | |||
5.0702,5.1337 | |||
5.8014,1.844 | |||
11.7,8.0043 | |||
5.5416,1.0179 | |||
7.5402,6.7504 | |||
5.3077,1.8396 | |||
7.4239,4.2885 | |||
7.6031,4.9981 | |||
6.3328,1.4233 | |||
6.3589,-1.4211 | |||
6.2742,2.4756 | |||
5.6397,4.6042 | |||
9.3102,3.9624 | |||
9.4536,5.4141 | |||
8.8254,5.1694 | |||
5.1793,-0.74279 | |||
21.279,17.929 | |||
14.908,12.054 | |||
18.959,17.054 | |||
7.2182,4.8852 | |||
8.2951,5.7442 | |||
10.236,7.7754 | |||
5.4994,1.0173 | |||
20.341,20.992 | |||
10.136,6.6799 | |||
7.3345,4.0259 | |||
6.0062,1.2784 | |||
7.2259,3.3411 | |||
5.0269,-2.6807 | |||
6.5479,0.29678 | |||
7.5386,3.8845 | |||
5.0365,5.7014 | |||
10.274,6.7526 | |||
5.1077,2.0576 | |||
5.7292,0.47953 | |||
5.1884,0.20421 | |||
6.3557,0.67861 | |||
9.7687,7.5435 | |||
6.5159,5.3436 | |||
8.5172,4.2415 | |||
9.1802,6.7981 | |||
6.002,0.92695 | |||
5.5204,0.152 | |||
5.0594,2.8214 | |||
5.7077,1.8451 | |||
7.6366,4.2959 | |||
5.8707,7.2029 | |||
5.3054,1.9869 | |||
8.2934,0.14454 | |||
13.394,9.0551 | |||
5.4369,0.61705 |
@@ -1,47 +0,0 @@ | |||
2104,3,399900 | |||
1600,3,329900 | |||
2400,3,369000 | |||
1416,2,232000 | |||
3000,4,539900 | |||
1985,4,299900 | |||
1534,3,314900 | |||
1427,3,198999 | |||
1380,3,212000 | |||
1494,3,242500 | |||
1940,4,239999 | |||
2000,3,347000 | |||
1890,3,329999 | |||
4478,5,699900 | |||
1268,3,259900 | |||
2300,4,449900 | |||
1320,2,299900 | |||
1236,3,199900 | |||
2609,4,499998 | |||
3031,4,599000 | |||
1767,3,252900 | |||
1888,2,255000 | |||
1604,3,242900 | |||
1962,4,259900 | |||
3890,3,573900 | |||
1100,3,249900 | |||
1458,3,464500 | |||
2526,3,469000 | |||
2200,3,475000 | |||
2637,3,299900 | |||
1839,2,349900 | |||
1000,1,169900 | |||
2040,4,314900 | |||
3137,3,579900 | |||
1811,4,285900 | |||
1437,3,249900 | |||
1239,3,229900 | |||
2132,4,345000 | |||
4215,4,549000 | |||
2162,4,287000 | |||
1664,2,368500 | |||
2238,3,329900 | |||
2567,4,314000 | |||
1200,3,299000 | |||
852,2,179900 | |||
1852,4,299900 | |||
1203,3,239500 |
@@ -1,47 +0,0 @@ | |||
2104,3,399900 | |||
1600,3,329900 | |||
2400,3,369000 | |||
1416,2,232000 | |||
3000,4,539900 | |||
1985,4,299900 | |||
1534,3,314900 | |||
1427,3,198999 | |||
1380,3,212000 | |||
1494,3,242500 | |||
1940,4,239999 | |||
2000,3,347000 | |||
1890,3,329999 | |||
4478,5,699900 | |||
1268,3,259900 | |||
2300,4,449900 | |||
1320,2,299900 | |||
1236,3,199900 | |||
2609,4,499998 | |||
3031,4,599000 | |||
1767,3,252900 | |||
1888,2,255000 | |||
1604,3,242900 | |||
1962,4,259900 | |||
3890,3,573900 | |||
1100,3,249900 | |||
1458,3,464500 | |||
2526,3,469000 | |||
2200,3,475000 | |||
2637,3,299900 | |||
1839,2,349900 | |||
1000,1,169900 | |||
2040,4,314900 | |||
3137,3,579900 | |||
1811,4,285900 | |||
1437,3,249900 | |||
1239,3,229900 | |||
2132,4,345000 | |||
4215,4,549000 | |||
2162,4,287000 | |||
1664,2,368500 | |||
2238,3,329900 | |||
2567,4,314000 | |||
1200,3,299000 | |||
852,2,179900 | |||
1852,4,299900 | |||
1203,3,239500 |
@@ -1,40 +0,0 @@ | |||
function [X_norm, mu, sigma] = featureNormalize(X) | |||
%FEATURENORMALIZE Normalizes the features in X | |||
% FEATURENORMALIZE(X) returns a normalized version of X where | |||
% the mean value of each feature is 0 and the standard deviation | |||
% is 1. This is often a good preprocessing step to do when | |||
% working with learning algorithms. | |||
% You need to set these values correctly | |||
X_norm = X; | |||
mu = zeros(1, size(X, 2)); | |||
sigma = zeros(1, size(X, 2)); | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: First, for each feature dimension, compute the mean | |||
% of the feature and subtract it from the dataset, | |||
% storing the mean value in mu. Next, compute the | |||
% standard deviation of each feature and divide | |||
% each feature by it's standard deviation, storing | |||
% the standard deviation in sigma. | |||
% | |||
% Note that X is a matrix where each column is a | |||
% feature and each row is an example. You need | |||
% to perform the normalization separately for | |||
% each feature. | |||
% | |||
% Hint: You might find the 'mean' and 'std' functions useful. | |||
% | |||
mu = mean(X_norm); | |||
sigma = std(X_norm); | |||
X_norm = (X_norm .- mu) ./ sigma; | |||
% ============================================================ | |||
end |
@@ -1,31 +0,0 @@ | |||
function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters) | |||
%GRADIENTDESCENT Performs gradient descent to learn theta | |||
% theta = GRADIENTDESENT(X, y, theta, alpha, num_iters) updates theta by | |||
% taking num_iters gradient steps with learning rate alpha | |||
% Initialize some useful values | |||
m = length(y); % number of training examples | |||
J_history = zeros(num_iters, 1); | |||
for iter = 1:num_iters | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Perform a single gradient step on the parameter vector | |||
% theta. | |||
% | |||
% Hint: While debugging, it can be useful to print out the values | |||
% of the cost function (computeCost) and gradient here. | |||
% | |||
theta = theta - alpha / m * (X' * (X * theta - y)); | |||
%X * theta 代表了hθ | |||
%X' (hθ-y)表示将每一个X中的元素(n * m)与(hθ-y)(m * 1)相乘,从而得到新的theta矩阵(n * 1) | |||
% ============================================================ | |||
% Save the cost J in every iteration | |||
J_history(iter) = computeCost(X, y, theta); | |||
end | |||
end |
@@ -1,31 +0,0 @@ | |||
function [theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters) | |||
%GRADIENTDESCENTMULTI Performs gradient descent to learn theta | |||
% theta = GRADIENTDESCENTMULTI(x, y, theta, alpha, num_iters) updates theta by | |||
% taking num_iters gradient steps with learning rate alpha | |||
% Initialize some useful values | |||
m = length(y); % number of training examples | |||
J_history = zeros(num_iters, 1); | |||
for iter = 1:num_iters | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Perform a single gradient step on the parameter vector | |||
% theta. | |||
% | |||
% Hint: While debugging, it can be useful to print out the values | |||
% of the cost function (computeCostMulti) and gradient here. | |||
% | |||
theta = theta - alpha / m * (X' * (X * theta - y)); | |||
%X * theta 代表了hθ | |||
%X' (hθ-y)表示将每一个X中的元素(n * m)与(hθ-y)(m * 1)相乘,从而得到新的theta矩阵(n * 1) | |||
% ============================================================ | |||
% Save the cost J in every iteration | |||
J_history(iter) = computeCostMulti(X, y, theta); | |||
end | |||
end |
@@ -1,41 +0,0 @@ | |||
The author of "jsonlab" toolbox is Qianqian Fang. Qianqian | |||
is currently an Assistant Professor at Massachusetts General Hospital, | |||
Harvard Medical School. | |||
Address: Martinos Center for Biomedical Imaging, | |||
Massachusetts General Hospital, | |||
Harvard Medical School | |||
Bldg 149, 13th St, Charlestown, MA 02129, USA | |||
URL: http://nmr.mgh.harvard.edu/~fangq/ | |||
Email: <fangq at nmr.mgh.harvard.edu> or <fangqq at gmail.com> | |||
The script loadjson.m was built upon previous works by | |||
- Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713 | |||
date: 2009/11/02 | |||
- François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393 | |||
date: 2009/03/22 | |||
- Joel Feenstra: http://www.mathworks.com/matlabcentral/fileexchange/20565 | |||
date: 2008/07/03 | |||
This toolbox contains patches submitted by the following contributors: | |||
- Blake Johnson <bjohnso at bbn.com> | |||
part of revision 341 | |||
- Niclas Borlin <Niclas.Borlin at cs.umu.se> | |||
various fixes in revision 394, including | |||
- loadjson crashes for all-zero sparse matrix. | |||
- loadjson crashes for empty sparse matrix. | |||
- Non-zero size of 0-by-N and N-by-0 empty matrices is lost after savejson/loadjson. | |||
- loadjson crashes for sparse real column vector. | |||
- loadjson crashes for sparse complex column vector. | |||
- Data is corrupted by savejson for sparse real row vector. | |||
- savejson crashes for sparse complex row vector. | |||
- Yul Kang <yul.kang.on at gmail.com> | |||
patches for svn revision 415. | |||
- savejson saves an empty cell array as [] instead of null | |||
- loadjson differentiates an empty struct from an empty array |
@@ -1,74 +0,0 @@ | |||
============================================================================ | |||
JSONlab - a toolbox to encode/decode JSON/UBJSON files in MATLAB/Octave | |||
---------------------------------------------------------------------------- | |||
JSONlab ChangeLog (key features marked by *): | |||
== JSONlab 1.0 (codename: Optimus - Final), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2015/01/02 polish help info for all major functions, update examples, finalize 1.0 | |||
2014/12/19 fix a bug to strictly respect NoRowBracket in savejson | |||
== JSONlab 1.0.0-RC2 (codename: Optimus - RC2), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2014/11/22 show progress bar in loadjson ('ShowProgress') | |||
2014/11/17 add Compact option in savejson to output compact JSON format ('Compact') | |||
2014/11/17 add FastArrayParser in loadjson to specify fast parser applicable levels | |||
2014/09/18 start official github mirror: https://github.com/fangq/jsonlab | |||
== JSONlab 1.0.0-RC1 (codename: Optimus - RC1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2014/09/17 fix several compatibility issues when running on octave versions 3.2-3.8 | |||
2014/09/17 support 2D cell and struct arrays in both savejson and saveubjson | |||
2014/08/04 escape special characters in a JSON string | |||
2014/02/16 fix a bug when saving ubjson files | |||
== JSONlab 0.9.9 (codename: Optimus - beta), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2014/01/22 use binary read and write in saveubjson and loadubjson | |||
== JSONlab 0.9.8-1 (codename: Optimus - alpha update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2013/10/07 better round-trip conservation for empty arrays and structs (patch submitted by Yul Kang) | |||
== JSONlab 0.9.8 (codename: Optimus - alpha), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2013/08/23 *universal Binary JSON (UBJSON) support, including both saveubjson and loadubjson | |||
== JSONlab 0.9.1 (codename: Rodimus, update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/12/18 *handling of various empty and sparse matrices (fixes submitted by Niclas Borlin) | |||
== JSONlab 0.9.0 (codename: Rodimus), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/06/17 *new format for an invalid leading char, unpacking hex code in savejson | |||
2012/06/01 support JSONP in savejson | |||
2012/05/25 fix the empty cell bug (reported by Cyril Davin) | |||
2012/04/05 savejson can save to a file (suggested by Patrick Rapin) | |||
== JSONlab 0.8.1 (codename: Sentiel, Update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/02/28 loadjson quotation mark escape bug, see http://bit.ly/yyk1nS | |||
2012/01/25 patch to handle root-less objects, contributed by Blake Johnson | |||
== JSONlab 0.8.0 (codename: Sentiel), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/01/13 *speed up loadjson by 20 fold when parsing large data arrays in matlab | |||
2012/01/11 remove row bracket if an array has 1 element, suggested by Mykel Kochenderfer | |||
2011/12/22 *accept sequence of 'param',value input in savejson and loadjson | |||
2011/11/18 fix struct array bug reported by Mykel Kochenderfer | |||
== JSONlab 0.5.1 (codename: Nexus Update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2011/10/21 fix a bug in loadjson, previous code does not use any of the acceleration | |||
2011/10/20 loadjson supports JSON collections - concatenated JSON objects | |||
== JSONlab 0.5.0 (codename: Nexus), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2011/10/16 package and release jsonlab 0.5.0 | |||
2011/10/15 *add json demo and regression test, support cpx numbers, fix double quote bug | |||
2011/10/11 *speed up readjson dramatically, interpret _Array* tags, show data in root level | |||
2011/10/10 create jsonlab project, start jsonlab website, add online documentation | |||
2011/10/07 *speed up savejson by 25x using sprintf instead of mat2str, add options support | |||
2011/10/06 *savejson works for structs, cells and arrays | |||
2011/09/09 derive loadjson from JSON parser from MATLAB Central, draft savejson.m |
@@ -1,25 +0,0 @@ | |||
Copyright 2011-2015 Qianqian Fang <fangq at nmr.mgh.harvard.edu>. All rights reserved. | |||
Redistribution and use in source and binary forms, with or without modification, are | |||
permitted provided that the following conditions are met: | |||
1. Redistributions of source code must retain the above copyright notice, this list of | |||
conditions and the following disclaimer. | |||
2. Redistributions in binary form must reproduce the above copyright notice, this list | |||
of conditions and the following disclaimer in the documentation and/or other materials | |||
provided with the distribution. | |||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED | |||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS | |||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
The views and conclusions contained in the software and documentation are those of the | |||
authors and should not be interpreted as representing official policies, either expressed | |||
or implied, of the copyright holders. |
@@ -1,394 +0,0 @@ | |||
=============================================================================== | |||
= JSONLab = | |||
= An open-source MATLAB/Octave JSON encoder and decoder = | |||
=============================================================================== | |||
*Copyright (C) 2011-2015 Qianqian Fang <fangq at nmr.mgh.harvard.edu> | |||
*License: BSD License, see License_BSD.txt for details | |||
*Version: 1.0 (Optimus - Final) | |||
------------------------------------------------------------------------------- | |||
Table of Content: | |||
I. Introduction | |||
II. Installation | |||
III.Using JSONLab | |||
IV. Known Issues and TODOs | |||
V. Contribution and feedback | |||
------------------------------------------------------------------------------- | |||
I. Introduction | |||
JSON ([http://www.json.org/ JavaScript Object Notation]) is a highly portable, | |||
human-readable and "[http://en.wikipedia.org/wiki/JSON fat-free]" text format | |||
to represent complex and hierarchical data. It is as powerful as | |||
[http://en.wikipedia.org/wiki/XML XML], but less verbose. JSON format is widely | |||
used for data-exchange in applications, and is essential for the wild success | |||
of [http://en.wikipedia.org/wiki/Ajax_(programming) Ajax] and | |||
[http://en.wikipedia.org/wiki/Web_2.0 Web2.0]. | |||
UBJSON (Universal Binary JSON) is a binary JSON format, specifically | |||
optimized for compact file size and better performance while keeping | |||
the semantics as simple as the text-based JSON format. Using the UBJSON | |||
format allows to wrap complex binary data in a flexible and extensible | |||
structure, making it possible to process complex and large dataset | |||
without accuracy loss due to text conversions. | |||
We envision that both JSON and its binary version will serve as part of | |||
the mainstream data-exchange formats for scientific research in the future. | |||
It will provide the flexibility and generality achieved by other popular | |||
general-purpose file specifications, such as | |||
[http://www.hdfgroup.org/HDF5/whatishdf5.html HDF5], with significantly | |||
reduced complexity and enhanced performance. | |||
JSONLab is a free and open-source implementation of a JSON/UBJSON encoder | |||
and a decoder in the native MATLAB language. It can be used to convert a MATLAB | |||
data structure (array, struct, cell, struct array and cell array) into | |||
JSON/UBJSON formatted strings, or to decode a JSON/UBJSON file into MATLAB | |||
data structure. JSONLab supports both MATLAB and | |||
[http://www.gnu.org/software/octave/ GNU Octave] (a free MATLAB clone). | |||
------------------------------------------------------------------------------- | |||
II. Installation | |||
The installation of JSONLab is no different than any other simple | |||
MATLAB toolbox. You only need to download/unzip the JSONLab package | |||
to a folder, and add the folder's path to MATLAB/Octave's path list | |||
by using the following command: | |||
addpath('/path/to/jsonlab'); | |||
If you want to add this path permanently, you need to type "pathtool", | |||
browse to the jsonlab root folder and add to the list, then click "Save". | |||
Then, run "rehash" in MATLAB, and type "which loadjson", if you see an | |||
output, that means JSONLab is installed for MATLAB/Octave. | |||
------------------------------------------------------------------------------- | |||
III.Using JSONLab | |||
JSONLab provides two functions, loadjson.m -- a MATLAB->JSON decoder, | |||
and savejson.m -- a MATLAB->JSON encoder, for the text-based JSON, and | |||
two equivallent functions -- loadubjson and saveubjson for the binary | |||
JSON. The detailed help info for the four functions can be found below: | |||
=== loadjson.m === | |||
<pre> | |||
data=loadjson(fname,opt) | |||
or | |||
data=loadjson(fname,'param1',value1,'param2',value2,...) | |||
parse a JSON (JavaScript Object Notation) file or string | |||
authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2011/09/09, including previous works from | |||
Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713 | |||
created on 2009/11/02 | |||
François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393 | |||
created on 2009/03/22 | |||
Joel Feenstra: | |||
http://www.mathworks.com/matlabcentral/fileexchange/20565 | |||
created on 2008/07/03 | |||
$Id: loadjson.m 452 2014-11-22 16:43:33Z fangq $ | |||
input: | |||
fname: input file name, if fname contains "{}" or "[]", fname | |||
will be interpreted as a JSON string | |||
opt: a struct to store parsing options, opt can be replaced by | |||
a list of ('param',value) pairs - the param string is equivallent | |||
to a field in opt. opt can have the following | |||
fields (first in [.|.] is the default) | |||
opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat | |||
for each element of the JSON data, and group | |||
arrays based on the cell2mat rules. | |||
opt.FastArrayParser [1|0 or integer]: if set to 1, use a | |||
speed-optimized array parser when loading an | |||
array object. The fast array parser may | |||
collapse block arrays into a single large | |||
array similar to rules defined in cell2mat; 0 to | |||
use a legacy parser; if set to a larger-than-1 | |||
value, this option will specify the minimum | |||
dimension to enable the fast array parser. For | |||
example, if the input is a 3D array, setting | |||
FastArrayParser to 1 will return a 3D array; | |||
setting to 2 will return a cell array of 2D | |||
arrays; setting to 3 will return to a 2D cell | |||
array of 1D vectors; setting to 4 will return a | |||
3D cell array. | |||
opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar. | |||
output: | |||
dat: a cell array, where {...} blocks are converted into cell arrays, | |||
and [...] are converted to arrays | |||
examples: | |||
dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}') | |||
dat=loadjson(['examples' filesep 'example1.json']) | |||
dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1) | |||
</pre> | |||
=== savejson.m === | |||
<pre> | |||
json=savejson(rootname,obj,filename) | |||
or | |||
json=savejson(rootname,obj,opt) | |||
json=savejson(rootname,obj,'param1',value1,'param2',value2,...) | |||
convert a MATLAB object (cell, struct or array) into a JSON (JavaScript | |||
Object Notation) string | |||
author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2011/09/09 | |||
$Id: savejson.m 458 2014-12-19 22:17:17Z fangq $ | |||
input: | |||
rootname: the name of the root-object, when set to '', the root name | |||
is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
the MATLAB variable name will be used as the root name. | |||
obj: a MATLAB object (array, cell, cell array, struct, struct array). | |||
filename: a string for the file name to save the output JSON data. | |||
opt: a struct for additional options, ignore to use default values. | |||
opt can have the following fields (first in [.|.] is the default) | |||
opt.FileName [''|string]: a file name to save the output JSON data | |||
opt.FloatFormat ['%.10g'|string]: format to show each numeric element | |||
of a 1D/2D array; | |||
opt.ArrayIndent [1|0]: if 1, output explicit data array with | |||
precedent indentation; if 0, no indentation | |||
opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D | |||
array in JSON array format; if sets to 1, an | |||
array will be shown as a struct with fields | |||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
sparse arrays, the non-zero elements will be | |||
saved to _ArrayData_ field in triplet-format i.e. | |||
(ix,iy,val) and "_ArrayIsSparse_" will be added | |||
with a value of 1; for a complex array, the | |||
_ArrayData_ array will include two columns | |||
(4 for sparse) to record the real and imaginary | |||
parts, and also "_ArrayIsComplex_":1 is added. | |||
opt.ParseLogical [0|1]: if this is set to 1, logical array elem | |||
will use true/false rather than 1/0. | |||
opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
numerical element will be shown without a square | |||
bracket, unless it is the root object; if 0, square | |||
brackets are forced for any numerical arrays. | |||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson | |||
will use the name of the passed obj variable as the | |||
root object name; if obj is an expression and | |||
does not have a name, 'root' will be used; if this | |||
is set to 0 and rootname is empty, the root level | |||
will be merged down to the lower level. | |||
opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern | |||
to represent +/-Inf. The matched pattern is '([-+]*)Inf' | |||
and $1 represents the sign. For those who want to use | |||
1e999 to represent Inf, they can set opt.Inf to '$11e999' | |||
opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern | |||
to represent NaN | |||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
for example, if opt.JSONP='foo', the JSON data is | |||
wrapped inside a function call as 'foo(...);' | |||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
back to the string form | |||
opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode. | |||
opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs) | |||
opt can be replaced by a list of ('param',value) pairs. The param | |||
string is equivallent to a field in opt and is case sensitive. | |||
output: | |||
json: a string in the JSON format (see http://json.org) | |||
examples: | |||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
'SpecialData',[nan, inf, -inf]); | |||
savejson('jmesh',jsonmesh) | |||
savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g') | |||
</pre> | |||
=== loadubjson.m === | |||
<pre> | |||
data=loadubjson(fname,opt) | |||
or | |||
data=loadubjson(fname,'param1',value1,'param2',value2,...) | |||
parse a JSON (JavaScript Object Notation) file or string | |||
authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2013/08/01 | |||
$Id: loadubjson.m 436 2014-08-05 20:51:40Z fangq $ | |||
input: | |||
fname: input file name, if fname contains "{}" or "[]", fname | |||
will be interpreted as a UBJSON string | |||
opt: a struct to store parsing options, opt can be replaced by | |||
a list of ('param',value) pairs - the param string is equivallent | |||
to a field in opt. opt can have the following | |||
fields (first in [.|.] is the default) | |||
opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat | |||
for each element of the JSON data, and group | |||
arrays based on the cell2mat rules. | |||
opt.IntEndian [B|L]: specify the endianness of the integer fields | |||
in the UBJSON input data. B - Big-Endian format for | |||
integers (as required in the UBJSON specification); | |||
L - input integer fields are in Little-Endian order. | |||
output: | |||
dat: a cell array, where {...} blocks are converted into cell arrays, | |||
and [...] are converted to arrays | |||
examples: | |||
obj=struct('string','value','array',[1 2 3]); | |||
ubjdata=saveubjson('obj',obj); | |||
dat=loadubjson(ubjdata) | |||
dat=loadubjson(['examples' filesep 'example1.ubj']) | |||
dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1) | |||
</pre> | |||
=== saveubjson.m === | |||
<pre> | |||
json=saveubjson(rootname,obj,filename) | |||
or | |||
json=saveubjson(rootname,obj,opt) | |||
json=saveubjson(rootname,obj,'param1',value1,'param2',value2,...) | |||
convert a MATLAB object (cell, struct or array) into a Universal | |||
Binary JSON (UBJSON) binary string | |||
author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2013/08/17 | |||
$Id: saveubjson.m 440 2014-09-17 19:59:45Z fangq $ | |||
input: | |||
rootname: the name of the root-object, when set to '', the root name | |||
is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
the MATLAB variable name will be used as the root name. | |||
obj: a MATLAB object (array, cell, cell array, struct, struct array) | |||
filename: a string for the file name to save the output UBJSON data | |||
opt: a struct for additional options, ignore to use default values. | |||
opt can have the following fields (first in [.|.] is the default) | |||
opt.FileName [''|string]: a file name to save the output JSON data | |||
opt.ArrayToStruct[0|1]: when set to 0, saveubjson outputs 1D/2D | |||
array in JSON array format; if sets to 1, an | |||
array will be shown as a struct with fields | |||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
sparse arrays, the non-zero elements will be | |||
saved to _ArrayData_ field in triplet-format i.e. | |||
(ix,iy,val) and "_ArrayIsSparse_" will be added | |||
with a value of 1; for a complex array, the | |||
_ArrayData_ array will include two columns | |||
(4 for sparse) to record the real and imaginary | |||
parts, and also "_ArrayIsComplex_":1 is added. | |||
opt.ParseLogical [1|0]: if this is set to 1, logical array elem | |||
will use true/false rather than 1/0. | |||
opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
numerical element will be shown without a square | |||
bracket, unless it is the root object; if 0, square | |||
brackets are forced for any numerical arrays. | |||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, saveubjson | |||
will use the name of the passed obj variable as the | |||
root object name; if obj is an expression and | |||
does not have a name, 'root' will be used; if this | |||
is set to 0 and rootname is empty, the root level | |||
will be merged down to the lower level. | |||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
for example, if opt.JSON='foo', the JSON data is | |||
wrapped inside a function call as 'foo(...);' | |||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
back to the string form | |||
opt can be replaced by a list of ('param',value) pairs. The param | |||
string is equivallent to a field in opt and is case sensitive. | |||
output: | |||
json: a binary string in the UBJSON format (see http://ubjson.org) | |||
examples: | |||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
'SpecialData',[nan, inf, -inf]); | |||
saveubjson('jsonmesh',jsonmesh) | |||
saveubjson('jsonmesh',jsonmesh,'meshdata.ubj') | |||
</pre> | |||
=== examples === | |||
Under the "examples" folder, you can find several scripts to demonstrate the | |||
basic utilities of JSONLab. Running the "demo_jsonlab_basic.m" script, you | |||
will see the conversions from MATLAB data structure to JSON text and backward. | |||
In "jsonlab_selftest.m", we load complex JSON files downloaded from the Internet | |||
and validate the loadjson/savejson functions for regression testing purposes. | |||
Similarly, a "demo_ubjson_basic.m" script is provided to test the saveubjson | |||
and loadubjson pairs for various matlab data structures. | |||
Please run these examples and understand how JSONLab works before you use | |||
it to process your data. | |||
------------------------------------------------------------------------------- | |||
IV. Known Issues and TODOs | |||
JSONLab has several known limitations. We are striving to make it more general | |||
and robust. Hopefully in a few future releases, the limitations become less. | |||
Here are the known issues: | |||
# 3D or higher dimensional cell/struct-arrays will be converted to 2D arrays; | |||
# When processing names containing multi-byte characters, Octave and MATLAB \ | |||
can give different field-names; you can use feature('DefaultCharacterSet','latin1') \ | |||
in MATLAB to get consistant results | |||
# savejson can not handle class and dataset. | |||
# saveubjson converts a logical array into a uint8 ([U]) array | |||
# an unofficial N-D array count syntax is implemented in saveubjson. We are \ | |||
actively communicating with the UBJSON spec maintainer to investigate the \ | |||
possibility of making it upstream | |||
# loadubjson can not parse all UBJSON Specification (Draft 9) compliant \ | |||
files, however, it can parse all UBJSON files produced by saveubjson. | |||
------------------------------------------------------------------------------- | |||
V. Contribution and feedback | |||
JSONLab is an open-source project. This means you can not only use it and modify | |||
it as you wish, but also you can contribute your changes back to JSONLab so | |||
that everyone else can enjoy the improvement. For anyone who want to contribute, | |||
please download JSONLab source code from it's subversion repository by using the | |||
following command: | |||
svn checkout svn://svn.code.sf.net/p/iso2mesh/code/trunk/jsonlab jsonlab | |||
You can make changes to the files as needed. Once you are satisfied with your | |||
changes, and ready to share it with others, please cd the root directory of | |||
JSONLab, and type | |||
svn diff > yourname_featurename.patch | |||
You then email the .patch file to JSONLab's maintainer, Qianqian Fang, at | |||
the email address shown in the beginning of this file. Qianqian will review | |||
the changes and commit it to the subversion if they are satisfactory. | |||
We appreciate any suggestions and feedbacks from you. Please use iso2mesh's | |||
mailing list to report any questions you may have with JSONLab: | |||
http://groups.google.com/group/iso2mesh-users?hl=en&pli=1 | |||
(Subscription to the mailing list is needed in order to post messages). |
@@ -1,32 +0,0 @@ | |||
function val=jsonopt(key,default,varargin) | |||
% | |||
% val=jsonopt(key,default,optstruct) | |||
% | |||
% setting options based on a struct. The struct can be produced | |||
% by varargin2struct from a list of 'param','value' pairs | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% | |||
% $Id: loadjson.m 371 2012-06-20 12:43:06Z fangq $ | |||
% | |||
% input: | |||
% key: a string with which one look up a value from a struct | |||
% default: if the key does not exist, return default | |||
% optstruct: a struct where each sub-field is a key | |||
% | |||
% output: | |||
% val: if key exists, val=optstruct.key; otherwise val=default | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
val=default; | |||
if(nargin<=2) return; end | |||
opt=varargin{1}; | |||
if(isstruct(opt) && isfield(opt,key)) | |||
val=getfield(opt,key); | |||
end | |||
@@ -1,566 +0,0 @@ | |||
function data = loadjson(fname,varargin) | |||
% | |||
% data=loadjson(fname,opt) | |||
% or | |||
% data=loadjson(fname,'param1',value1,'param2',value2,...) | |||
% | |||
% parse a JSON (JavaScript Object Notation) file or string | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2011/09/09, including previous works from | |||
% | |||
% Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713 | |||
% created on 2009/11/02 | |||
% François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393 | |||
% created on 2009/03/22 | |||
% Joel Feenstra: | |||
% http://www.mathworks.com/matlabcentral/fileexchange/20565 | |||
% created on 2008/07/03 | |||
% | |||
% $Id: loadjson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% fname: input file name, if fname contains "{}" or "[]", fname | |||
% will be interpreted as a JSON string | |||
% opt: a struct to store parsing options, opt can be replaced by | |||
% a list of ('param',value) pairs - the param string is equivallent | |||
% to a field in opt. opt can have the following | |||
% fields (first in [.|.] is the default) | |||
% | |||
% opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat | |||
% for each element of the JSON data, and group | |||
% arrays based on the cell2mat rules. | |||
% opt.FastArrayParser [1|0 or integer]: if set to 1, use a | |||
% speed-optimized array parser when loading an | |||
% array object. The fast array parser may | |||
% collapse block arrays into a single large | |||
% array similar to rules defined in cell2mat; 0 to | |||
% use a legacy parser; if set to a larger-than-1 | |||
% value, this option will specify the minimum | |||
% dimension to enable the fast array parser. For | |||
% example, if the input is a 3D array, setting | |||
% FastArrayParser to 1 will return a 3D array; | |||
% setting to 2 will return a cell array of 2D | |||
% arrays; setting to 3 will return to a 2D cell | |||
% array of 1D vectors; setting to 4 will return a | |||
% 3D cell array. | |||
% opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar. | |||
% | |||
% output: | |||
% dat: a cell array, where {...} blocks are converted into cell arrays, | |||
% and [...] are converted to arrays | |||
% | |||
% examples: | |||
% dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}') | |||
% dat=loadjson(['examples' filesep 'example1.json']) | |||
% dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1) | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
global pos inStr len esc index_esc len_esc isoct arraytoken | |||
if(regexp(fname,'[\{\}\]\[]','once')) | |||
string=fname; | |||
elseif(exist(fname,'file')) | |||
fid = fopen(fname,'rb'); | |||
string = fread(fid,inf,'uint8=>char')'; | |||
fclose(fid); | |||
else | |||
error('input file does not exist'); | |||
end | |||
pos = 1; len = length(string); inStr = string; | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"'); | |||
jstr=regexprep(inStr,'\\\\',' '); | |||
escquote=regexp(jstr,'\\"'); | |||
arraytoken=sort([arraytoken escquote]); | |||
% String delimiters and escape chars identified to improve speed: | |||
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]'); | |||
index_esc = 1; len_esc = length(esc); | |||
opt=varargin2struct(varargin{:}); | |||
if(jsonopt('ShowProgress',0,opt)==1) | |||
opt.progressbar_=waitbar(0,'loading ...'); | |||
end | |||
jsoncount=1; | |||
while pos <= len | |||
switch(next_char) | |||
case '{' | |||
data{jsoncount} = parse_object(opt); | |||
case '[' | |||
data{jsoncount} = parse_array(opt); | |||
otherwise | |||
error_pos('Outer level structure must be an object or an array'); | |||
end | |||
jsoncount=jsoncount+1; | |||
end % while | |||
jsoncount=length(data); | |||
if(jsoncount==1 && iscell(data)) | |||
data=data{1}; | |||
end | |||
if(~isempty(data)) | |||
if(isstruct(data)) % data can be a struct array | |||
data=jstruct2array(data); | |||
elseif(iscell(data)) | |||
data=jcell2array(data); | |||
end | |||
end | |||
if(isfield(opt,'progressbar_')) | |||
close(opt.progressbar_); | |||
end | |||
%% | |||
function newdata=jcell2array(data) | |||
len=length(data); | |||
newdata=data; | |||
for i=1:len | |||
if(isstruct(data{i})) | |||
newdata{i}=jstruct2array(data{i}); | |||
elseif(iscell(data{i})) | |||
newdata{i}=jcell2array(data{i}); | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newdata=jstruct2array(data) | |||
fn=fieldnames(data); | |||
newdata=data; | |||
len=length(data); | |||
for i=1:length(fn) % depth-first | |||
for j=1:len | |||
if(isstruct(getfield(data(j),fn{i}))) | |||
newdata(j)=setfield(newdata(j),fn{i},jstruct2array(getfield(data(j),fn{i}))); | |||
end | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayData_',fn))) | |||
newdata=cell(len,1); | |||
for j=1:len | |||
ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_); | |||
iscpx=0; | |||
if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn))) | |||
if(data(j).x0x5F_ArrayIsComplex_) | |||
iscpx=1; | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn))) | |||
if(data(j).x0x5F_ArrayIsSparse_) | |||
if(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
dim=data(j).x0x5F_ArraySize_; | |||
if(iscpx && size(ndata,2)==4-any(dim==1)) | |||
ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end)); | |||
end | |||
if isempty(ndata) | |||
% All-zeros sparse | |||
ndata=sparse(dim(1),prod(dim(2:end))); | |||
elseif dim(1)==1 | |||
% Sparse row vector | |||
ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end))); | |||
elseif dim(2)==1 | |||
% Sparse column vector | |||
ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end))); | |||
else | |||
% Generic sparse array. | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end))); | |||
end | |||
else | |||
if(iscpx && size(ndata,2)==4) | |||
ndata(:,3)=complex(ndata(:,3),ndata(:,4)); | |||
end | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3)); | |||
end | |||
end | |||
elseif(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
if(iscpx && size(ndata,2)==2) | |||
ndata=complex(ndata(:,1),ndata(:,2)); | |||
end | |||
ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_); | |||
end | |||
newdata{j}=ndata; | |||
end | |||
if(len==1) | |||
newdata=newdata{1}; | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function object = parse_object(varargin) | |||
parse_char('{'); | |||
object = []; | |||
if next_char ~= '}' | |||
while 1 | |||
str = parseStr(varargin{:}); | |||
if isempty(str) | |||
error_pos('Name of value at position %d cannot be empty'); | |||
end | |||
parse_char(':'); | |||
val = parse_value(varargin{:}); | |||
eval( sprintf( 'object.%s = val;', valid_field(str) ) ); | |||
if next_char == '}' | |||
break; | |||
end | |||
parse_char(','); | |||
end | |||
end | |||
parse_char('}'); | |||
%%------------------------------------------------------------------------- | |||
function object = parse_array(varargin) % JSON array is written in row-major order | |||
global pos inStr isoct | |||
parse_char('['); | |||
object = cell(0, 1); | |||
dim2=[]; | |||
arraydepth=jsonopt('JSONLAB_ArrayDepth_',1,varargin{:}); | |||
pbar=jsonopt('progressbar_',-1,varargin{:}); | |||
if next_char ~= ']' | |||
if(jsonopt('FastArrayParser',1,varargin{:})>=1 && arraydepth>=jsonopt('FastArrayParser',1,varargin{:})) | |||
[endpos, e1l, e1r, maxlevel]=matching_bracket(inStr,pos); | |||
arraystr=['[' inStr(pos:endpos)]; | |||
arraystr=regexprep(arraystr,'"_NaN_"','NaN'); | |||
arraystr=regexprep(arraystr,'"([-+]*)_Inf_"','$1Inf'); | |||
arraystr(arraystr==sprintf('\n'))=[]; | |||
arraystr(arraystr==sprintf('\r'))=[]; | |||
%arraystr=regexprep(arraystr,'\s*,',','); % this is slow,sometimes needed | |||
if(~isempty(e1l) && ~isempty(e1r)) % the array is in 2D or higher D | |||
astr=inStr((e1l+1):(e1r-1)); | |||
astr=regexprep(astr,'"_NaN_"','NaN'); | |||
astr=regexprep(astr,'"([-+]*)_Inf_"','$1Inf'); | |||
astr(astr==sprintf('\n'))=[]; | |||
astr(astr==sprintf('\r'))=[]; | |||
astr(astr==' ')=''; | |||
if(isempty(find(astr=='[', 1))) % array is 2D | |||
dim2=length(sscanf(astr,'%f,',[1 inf])); | |||
end | |||
else % array is 1D | |||
astr=arraystr(2:end-1); | |||
astr(astr==' ')=''; | |||
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',[1,inf]); | |||
if(nextidx>=length(astr)-1) | |||
object=obj; | |||
pos=endpos; | |||
parse_char(']'); | |||
return; | |||
end | |||
end | |||
if(~isempty(dim2)) | |||
astr=arraystr; | |||
astr(astr=='[')=''; | |||
astr(astr==']')=''; | |||
astr(astr==' ')=''; | |||
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',inf); | |||
if(nextidx>=length(astr)-1) | |||
object=reshape(obj,dim2,numel(obj)/dim2)'; | |||
pos=endpos; | |||
parse_char(']'); | |||
if(pbar>0) | |||
waitbar(pos/length(inStr),pbar,'loading ...'); | |||
end | |||
return; | |||
end | |||
end | |||
arraystr=regexprep(arraystr,'\]\s*,','];'); | |||
else | |||
arraystr='['; | |||
end | |||
try | |||
if(isoct && regexp(arraystr,'"','once')) | |||
error('Octave eval can produce empty cells for JSON-like input'); | |||
end | |||
object=eval(arraystr); | |||
pos=endpos; | |||
catch | |||
while 1 | |||
newopt=varargin2struct(varargin{:},'JSONLAB_ArrayDepth_',arraydepth+1); | |||
val = parse_value(newopt); | |||
object{end+1} = val; | |||
if next_char == ']' | |||
break; | |||
end | |||
parse_char(','); | |||
end | |||
end | |||
end | |||
if(jsonopt('SimplifyCell',0,varargin{:})==1) | |||
try | |||
oldobj=object; | |||
object=cell2mat(object')'; | |||
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0) | |||
object=oldobj; | |||
elseif(size(object,1)>1 && ndims(object)==2) | |||
object=object'; | |||
end | |||
catch | |||
end | |||
end | |||
parse_char(']'); | |||
if(pbar>0) | |||
waitbar(pos/length(inStr),pbar,'loading ...'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function parse_char(c) | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len || inStr(pos) ~= c | |||
error_pos(sprintf('Expected %c at position %%d', c)); | |||
else | |||
pos = pos + 1; | |||
skip_whitespace; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function c = next_char | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len | |||
c = []; | |||
else | |||
c = inStr(pos); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function skip_whitespace | |||
global pos inStr len | |||
while pos <= len && isspace(inStr(pos)) | |||
pos = pos + 1; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function str = parseStr(varargin) | |||
global pos inStr len esc index_esc len_esc | |||
% len, ns = length(inStr), keyboard | |||
if inStr(pos) ~= '"' | |||
error_pos('String starting with " expected at position %d'); | |||
else | |||
pos = pos + 1; | |||
end | |||
str = ''; | |||
while pos <= len | |||
while index_esc <= len_esc && esc(index_esc) < pos | |||
index_esc = index_esc + 1; | |||
end | |||
if index_esc > len_esc | |||
str = [str inStr(pos:len)]; | |||
pos = len + 1; | |||
break; | |||
else | |||
str = [str inStr(pos:esc(index_esc)-1)]; | |||
pos = esc(index_esc); | |||
end | |||
nstr = length(str); switch inStr(pos) | |||
case '"' | |||
pos = pos + 1; | |||
if(~isempty(str)) | |||
if(strcmp(str,'_Inf_')) | |||
str=Inf; | |||
elseif(strcmp(str,'-_Inf_')) | |||
str=-Inf; | |||
elseif(strcmp(str,'_NaN_')) | |||
str=NaN; | |||
end | |||
end | |||
return; | |||
case '\' | |||
if pos+1 > len | |||
error_pos('End of file reached right after escape character'); | |||
end | |||
pos = pos + 1; | |||
switch inStr(pos) | |||
case {'"' '\' '/'} | |||
str(nstr+1) = inStr(pos); | |||
pos = pos + 1; | |||
case {'b' 'f' 'n' 'r' 't'} | |||
str(nstr+1) = sprintf(['\' inStr(pos)]); | |||
pos = pos + 1; | |||
case 'u' | |||
if pos+4 > len | |||
error_pos('End of file reached in escaped unicode character'); | |||
end | |||
str(nstr+(1:6)) = inStr(pos-1:pos+4); | |||
pos = pos + 5; | |||
end | |||
otherwise % should never happen | |||
str(nstr+1) = inStr(pos), keyboard | |||
pos = pos + 1; | |||
end | |||
end | |||
error_pos('End of file while expecting end of inStr'); | |||
%%------------------------------------------------------------------------- | |||
function num = parse_number(varargin) | |||
global pos inStr len isoct | |||
currstr=inStr(pos:end); | |||
numstr=0; | |||
if(isoct~=0) | |||
numstr=regexp(currstr,'^\s*-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+\-]?\d+)?','end'); | |||
[num, one] = sscanf(currstr, '%f', 1); | |||
delta=numstr+1; | |||
else | |||
[num, one, err, delta] = sscanf(currstr, '%f', 1); | |||
if ~isempty(err) | |||
error_pos('Error reading number at position %d'); | |||
end | |||
end | |||
pos = pos + delta-1; | |||
%%------------------------------------------------------------------------- | |||
function val = parse_value(varargin) | |||
global pos inStr len | |||
true = 1; false = 0; | |||
pbar=jsonopt('progressbar_',-1,varargin{:}); | |||
if(pbar>0) | |||
waitbar(pos/len,pbar,'loading ...'); | |||
end | |||
switch(inStr(pos)) | |||
case '"' | |||
val = parseStr(varargin{:}); | |||
return; | |||
case '[' | |||
val = parse_array(varargin{:}); | |||
return; | |||
case '{' | |||
val = parse_object(varargin{:}); | |||
if isstruct(val) | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fieldnames(val), 'exact'))) | |||
val=jstruct2array(val); | |||
end | |||
elseif isempty(val) | |||
val = struct; | |||
end | |||
return; | |||
case {'-','0','1','2','3','4','5','6','7','8','9'} | |||
val = parse_number(varargin{:}); | |||
return; | |||
case 't' | |||
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'true') | |||
val = true; | |||
pos = pos + 4; | |||
return; | |||
end | |||
case 'f' | |||
if pos+4 <= len && strcmpi(inStr(pos:pos+4), 'false') | |||
val = false; | |||
pos = pos + 5; | |||
return; | |||
end | |||
case 'n' | |||
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'null') | |||
val = []; | |||
pos = pos + 4; | |||
return; | |||
end | |||
end | |||
error_pos('Value expected at position %d'); | |||
%%------------------------------------------------------------------------- | |||
function error_pos(msg) | |||
global pos inStr len | |||
poShow = max(min([pos-15 pos-1 pos pos+20],len),1); | |||
if poShow(3) == poShow(2) | |||
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after | |||
end | |||
msg = [sprintf(msg, pos) ': ' ... | |||
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ]; | |||
error( ['JSONparser:invalidFormat: ' msg] ); | |||
%%------------------------------------------------------------------------- | |||
function str = valid_field(str) | |||
global isoct | |||
% From MATLAB doc: field names must begin with a letter, which may be | |||
% followed by any combination of letters, digits, and underscores. | |||
% Invalid characters will be converted to underscores, and the prefix | |||
% "x0x[Hex code]_" will be added if the first character is not a letter. | |||
pos=regexp(str,'^[^A-Za-z]','once'); | |||
if(~isempty(pos)) | |||
if(~isoct) | |||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); | |||
else | |||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); | |||
end | |||
end | |||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end | |||
if(~isoct) | |||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_'); | |||
else | |||
pos=regexp(str,'[^0-9A-Za-z_]'); | |||
if(isempty(pos)) return; end | |||
str0=str; | |||
pos0=[0 pos(:)' length(str)]; | |||
str=''; | |||
for i=1:length(pos) | |||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))]; | |||
end | |||
if(pos(end)~=length(str)) | |||
str=[str str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_'; | |||
%%------------------------------------------------------------------------- | |||
function endpos = matching_quote(str,pos) | |||
len=length(str); | |||
while(pos<len) | |||
if(str(pos)=='"') | |||
if(~(pos>1 && str(pos-1)=='\')) | |||
endpos=pos; | |||
return; | |||
end | |||
end | |||
pos=pos+1; | |||
end | |||
error('unmatched quotation mark'); | |||
%%------------------------------------------------------------------------- | |||
function [endpos, e1l, e1r, maxlevel] = matching_bracket(str,pos) | |||
global arraytoken | |||
level=1; | |||
maxlevel=level; | |||
endpos=0; | |||
bpos=arraytoken(arraytoken>=pos); | |||
tokens=str(bpos); | |||
len=length(tokens); | |||
pos=1; | |||
e1l=[]; | |||
e1r=[]; | |||
while(pos<=len) | |||
c=tokens(pos); | |||
if(c==']') | |||
level=level-1; | |||
if(isempty(e1r)) e1r=bpos(pos); end | |||
if(level==0) | |||
endpos=bpos(pos); | |||
return | |||
end | |||
end | |||
if(c=='[') | |||
if(isempty(e1l)) e1l=bpos(pos); end | |||
level=level+1; | |||
maxlevel=max(maxlevel,level); | |||
end | |||
if(c=='"') | |||
pos=matching_quote(tokens,pos+1); | |||
end | |||
pos=pos+1; | |||
end | |||
if(endpos==0) | |||
error('unmatched "]"'); | |||
end | |||
@@ -1,528 +0,0 @@ | |||
function data = loadubjson(fname,varargin) | |||
% | |||
% data=loadubjson(fname,opt) | |||
% or | |||
% data=loadubjson(fname,'param1',value1,'param2',value2,...) | |||
% | |||
% parse a JSON (JavaScript Object Notation) file or string | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2013/08/01 | |||
% | |||
% $Id: loadubjson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% fname: input file name, if fname contains "{}" or "[]", fname | |||
% will be interpreted as a UBJSON string | |||
% opt: a struct to store parsing options, opt can be replaced by | |||
% a list of ('param',value) pairs - the param string is equivallent | |||
% to a field in opt. opt can have the following | |||
% fields (first in [.|.] is the default) | |||
% | |||
% opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat | |||
% for each element of the JSON data, and group | |||
% arrays based on the cell2mat rules. | |||
% opt.IntEndian [B|L]: specify the endianness of the integer fields | |||
% in the UBJSON input data. B - Big-Endian format for | |||
% integers (as required in the UBJSON specification); | |||
% L - input integer fields are in Little-Endian order. | |||
% | |||
% output: | |||
% dat: a cell array, where {...} blocks are converted into cell arrays, | |||
% and [...] are converted to arrays | |||
% | |||
% examples: | |||
% obj=struct('string','value','array',[1 2 3]); | |||
% ubjdata=saveubjson('obj',obj); | |||
% dat=loadubjson(ubjdata) | |||
% dat=loadubjson(['examples' filesep 'example1.ubj']) | |||
% dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1) | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
global pos inStr len esc index_esc len_esc isoct arraytoken fileendian systemendian | |||
if(regexp(fname,'[\{\}\]\[]','once')) | |||
string=fname; | |||
elseif(exist(fname,'file')) | |||
fid = fopen(fname,'rb'); | |||
string = fread(fid,inf,'uint8=>char')'; | |||
fclose(fid); | |||
else | |||
error('input file does not exist'); | |||
end | |||
pos = 1; len = length(string); inStr = string; | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"'); | |||
jstr=regexprep(inStr,'\\\\',' '); | |||
escquote=regexp(jstr,'\\"'); | |||
arraytoken=sort([arraytoken escquote]); | |||
% String delimiters and escape chars identified to improve speed: | |||
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]'); | |||
index_esc = 1; len_esc = length(esc); | |||
opt=varargin2struct(varargin{:}); | |||
fileendian=upper(jsonopt('IntEndian','B',opt)); | |||
[os,maxelem,systemendian]=computer; | |||
jsoncount=1; | |||
while pos <= len | |||
switch(next_char) | |||
case '{' | |||
data{jsoncount} = parse_object(opt); | |||
case '[' | |||
data{jsoncount} = parse_array(opt); | |||
otherwise | |||
error_pos('Outer level structure must be an object or an array'); | |||
end | |||
jsoncount=jsoncount+1; | |||
end % while | |||
jsoncount=length(data); | |||
if(jsoncount==1 && iscell(data)) | |||
data=data{1}; | |||
end | |||
if(~isempty(data)) | |||
if(isstruct(data)) % data can be a struct array | |||
data=jstruct2array(data); | |||
elseif(iscell(data)) | |||
data=jcell2array(data); | |||
end | |||
end | |||
%% | |||
function newdata=parse_collection(id,data,obj) | |||
if(jsoncount>0 && exist('data','var')) | |||
if(~iscell(data)) | |||
newdata=cell(1); | |||
newdata{1}=data; | |||
data=newdata; | |||
end | |||
end | |||
%% | |||
function newdata=jcell2array(data) | |||
len=length(data); | |||
newdata=data; | |||
for i=1:len | |||
if(isstruct(data{i})) | |||
newdata{i}=jstruct2array(data{i}); | |||
elseif(iscell(data{i})) | |||
newdata{i}=jcell2array(data{i}); | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newdata=jstruct2array(data) | |||
fn=fieldnames(data); | |||
newdata=data; | |||
len=length(data); | |||
for i=1:length(fn) % depth-first | |||
for j=1:len | |||
if(isstruct(getfield(data(j),fn{i}))) | |||
newdata(j)=setfield(newdata(j),fn{i},jstruct2array(getfield(data(j),fn{i}))); | |||
end | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayData_',fn))) | |||
newdata=cell(len,1); | |||
for j=1:len | |||
ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_); | |||
iscpx=0; | |||
if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn))) | |||
if(data(j).x0x5F_ArrayIsComplex_) | |||
iscpx=1; | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn))) | |||
if(data(j).x0x5F_ArrayIsSparse_) | |||
if(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
dim=double(data(j).x0x5F_ArraySize_); | |||
if(iscpx && size(ndata,2)==4-any(dim==1)) | |||
ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end)); | |||
end | |||
if isempty(ndata) | |||
% All-zeros sparse | |||
ndata=sparse(dim(1),prod(dim(2:end))); | |||
elseif dim(1)==1 | |||
% Sparse row vector | |||
ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end))); | |||
elseif dim(2)==1 | |||
% Sparse column vector | |||
ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end))); | |||
else | |||
% Generic sparse array. | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end))); | |||
end | |||
else | |||
if(iscpx && size(ndata,2)==4) | |||
ndata(:,3)=complex(ndata(:,3),ndata(:,4)); | |||
end | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3)); | |||
end | |||
end | |||
elseif(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
if(iscpx && size(ndata,2)==2) | |||
ndata=complex(ndata(:,1),ndata(:,2)); | |||
end | |||
ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_); | |||
end | |||
newdata{j}=ndata; | |||
end | |||
if(len==1) | |||
newdata=newdata{1}; | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function object = parse_object(varargin) | |||
parse_char('{'); | |||
object = []; | |||
type=''; | |||
count=-1; | |||
if(next_char == '$') | |||
type=inStr(pos+1); % TODO | |||
pos=pos+2; | |||
end | |||
if(next_char == '#') | |||
pos=pos+1; | |||
count=double(parse_number()); | |||
end | |||
if next_char ~= '}' | |||
num=0; | |||
while 1 | |||
str = parseStr(varargin{:}); | |||
if isempty(str) | |||
error_pos('Name of value at position %d cannot be empty'); | |||
end | |||
%parse_char(':'); | |||
val = parse_value(varargin{:}); | |||
num=num+1; | |||
eval( sprintf( 'object.%s = val;', valid_field(str) ) ); | |||
if next_char == '}' || (count>=0 && num>=count) | |||
break; | |||
end | |||
%parse_char(','); | |||
end | |||
end | |||
if(count==-1) | |||
parse_char('}'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function [cid,len]=elem_info(type) | |||
id=strfind('iUIlLdD',type); | |||
dataclass={'int8','uint8','int16','int32','int64','single','double'}; | |||
bytelen=[1,1,2,4,8,4,8]; | |||
if(id>0) | |||
cid=dataclass{id}; | |||
len=bytelen(id); | |||
else | |||
error_pos('unsupported type at position %d'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function [data adv]=parse_block(type,count,varargin) | |||
global pos inStr isoct fileendian systemendian | |||
[cid,len]=elem_info(type); | |||
datastr=inStr(pos:pos+len*count-1); | |||
if(isoct) | |||
newdata=int8(datastr); | |||
else | |||
newdata=uint8(datastr); | |||
end | |||
id=strfind('iUIlLdD',type); | |||
if(id<=5 && fileendian~=systemendian) | |||
newdata=swapbytes(typecast(newdata,cid)); | |||
end | |||
data=typecast(newdata,cid); | |||
adv=double(len*count); | |||
%%------------------------------------------------------------------------- | |||
function object = parse_array(varargin) % JSON array is written in row-major order | |||
global pos inStr isoct | |||
parse_char('['); | |||
object = cell(0, 1); | |||
dim=[]; | |||
type=''; | |||
count=-1; | |||
if(next_char == '$') | |||
type=inStr(pos+1); | |||
pos=pos+2; | |||
end | |||
if(next_char == '#') | |||
pos=pos+1; | |||
if(next_char=='[') | |||
dim=parse_array(varargin{:}); | |||
count=prod(double(dim)); | |||
else | |||
count=double(parse_number()); | |||
end | |||
end | |||
if(~isempty(type)) | |||
if(count>=0) | |||
[object adv]=parse_block(type,count,varargin{:}); | |||
if(~isempty(dim)) | |||
object=reshape(object,dim); | |||
end | |||
pos=pos+adv; | |||
return; | |||
else | |||
endpos=matching_bracket(inStr,pos); | |||
[cid,len]=elem_info(type); | |||
count=(endpos-pos)/len; | |||
[object adv]=parse_block(type,count,varargin{:}); | |||
pos=pos+adv; | |||
parse_char(']'); | |||
return; | |||
end | |||
end | |||
if next_char ~= ']' | |||
while 1 | |||
val = parse_value(varargin{:}); | |||
object{end+1} = val; | |||
if next_char == ']' | |||
break; | |||
end | |||
%parse_char(','); | |||
end | |||
end | |||
if(jsonopt('SimplifyCell',0,varargin{:})==1) | |||
try | |||
oldobj=object; | |||
object=cell2mat(object')'; | |||
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0) | |||
object=oldobj; | |||
elseif(size(object,1)>1 && ndims(object)==2) | |||
object=object'; | |||
end | |||
catch | |||
end | |||
end | |||
if(count==-1) | |||
parse_char(']'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function parse_char(c) | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len || inStr(pos) ~= c | |||
error_pos(sprintf('Expected %c at position %%d', c)); | |||
else | |||
pos = pos + 1; | |||
skip_whitespace; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function c = next_char | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len | |||
c = []; | |||
else | |||
c = inStr(pos); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function skip_whitespace | |||
global pos inStr len | |||
while pos <= len && isspace(inStr(pos)) | |||
pos = pos + 1; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function str = parseStr(varargin) | |||
global pos inStr esc index_esc len_esc | |||
% len, ns = length(inStr), keyboard | |||
type=inStr(pos); | |||
if type ~= 'S' && type ~= 'C' && type ~= 'H' | |||
error_pos('String starting with S expected at position %d'); | |||
else | |||
pos = pos + 1; | |||
end | |||
if(type == 'C') | |||
str=inStr(pos); | |||
pos=pos+1; | |||
return; | |||
end | |||
bytelen=double(parse_number()); | |||
if(length(inStr)>=pos+bytelen-1) | |||
str=inStr(pos:pos+bytelen-1); | |||
pos=pos+bytelen; | |||
else | |||
error_pos('End of file while expecting end of inStr'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function num = parse_number(varargin) | |||
global pos inStr len isoct fileendian systemendian | |||
id=strfind('iUIlLdD',inStr(pos)); | |||
if(isempty(id)) | |||
error_pos('expecting a number at position %d'); | |||
end | |||
type={'int8','uint8','int16','int32','int64','single','double'}; | |||
bytelen=[1,1,2,4,8,4,8]; | |||
datastr=inStr(pos+1:pos+bytelen(id)); | |||
if(isoct) | |||
newdata=int8(datastr); | |||
else | |||
newdata=uint8(datastr); | |||
end | |||
if(id<=5 && fileendian~=systemendian) | |||
newdata=swapbytes(typecast(newdata,type{id})); | |||
end | |||
num=typecast(newdata,type{id}); | |||
pos = pos + bytelen(id)+1; | |||
%%------------------------------------------------------------------------- | |||
function val = parse_value(varargin) | |||
global pos inStr len | |||
true = 1; false = 0; | |||
switch(inStr(pos)) | |||
case {'S','C','H'} | |||
val = parseStr(varargin{:}); | |||
return; | |||
case '[' | |||
val = parse_array(varargin{:}); | |||
return; | |||
case '{' | |||
val = parse_object(varargin{:}); | |||
if isstruct(val) | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fieldnames(val), 'exact'))) | |||
val=jstruct2array(val); | |||
end | |||
elseif isempty(val) | |||
val = struct; | |||
end | |||
return; | |||
case {'i','U','I','l','L','d','D'} | |||
val = parse_number(varargin{:}); | |||
return; | |||
case 'T' | |||
val = true; | |||
pos = pos + 1; | |||
return; | |||
case 'F' | |||
val = false; | |||
pos = pos + 1; | |||
return; | |||
case {'Z','N'} | |||
val = []; | |||
pos = pos + 1; | |||
return; | |||
end | |||
error_pos('Value expected at position %d'); | |||
%%------------------------------------------------------------------------- | |||
function error_pos(msg) | |||
global pos inStr len | |||
poShow = max(min([pos-15 pos-1 pos pos+20],len),1); | |||
if poShow(3) == poShow(2) | |||
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after | |||
end | |||
msg = [sprintf(msg, pos) ': ' ... | |||
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ]; | |||
error( ['JSONparser:invalidFormat: ' msg] ); | |||
%%------------------------------------------------------------------------- | |||
function str = valid_field(str) | |||
global isoct | |||
% From MATLAB doc: field names must begin with a letter, which may be | |||
% followed by any combination of letters, digits, and underscores. | |||
% Invalid characters will be converted to underscores, and the prefix | |||
% "x0x[Hex code]_" will be added if the first character is not a letter. | |||
pos=regexp(str,'^[^A-Za-z]','once'); | |||
if(~isempty(pos)) | |||
if(~isoct) | |||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); | |||
else | |||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); | |||
end | |||
end | |||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end | |||
if(~isoct) | |||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_'); | |||
else | |||
pos=regexp(str,'[^0-9A-Za-z_]'); | |||
if(isempty(pos)) return; end | |||
str0=str; | |||
pos0=[0 pos(:)' length(str)]; | |||
str=''; | |||
for i=1:length(pos) | |||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))]; | |||
end | |||
if(pos(end)~=length(str)) | |||
str=[str str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_'; | |||
%%------------------------------------------------------------------------- | |||
function endpos = matching_quote(str,pos) | |||
len=length(str); | |||
while(pos<len) | |||
if(str(pos)=='"') | |||
if(~(pos>1 && str(pos-1)=='\')) | |||
endpos=pos; | |||
return; | |||
end | |||
end | |||
pos=pos+1; | |||
end | |||
error('unmatched quotation mark'); | |||
%%------------------------------------------------------------------------- | |||
function [endpos e1l e1r maxlevel] = matching_bracket(str,pos) | |||
global arraytoken | |||
level=1; | |||
maxlevel=level; | |||
endpos=0; | |||
bpos=arraytoken(arraytoken>=pos); | |||
tokens=str(bpos); | |||
len=length(tokens); | |||
pos=1; | |||
e1l=[]; | |||
e1r=[]; | |||
while(pos<=len) | |||
c=tokens(pos); | |||
if(c==']') | |||
level=level-1; | |||
if(isempty(e1r)) e1r=bpos(pos); end | |||
if(level==0) | |||
endpos=bpos(pos); | |||
return | |||
end | |||
end | |||
if(c=='[') | |||
if(isempty(e1l)) e1l=bpos(pos); end | |||
level=level+1; | |||
maxlevel=max(maxlevel,level); | |||
end | |||
if(c=='"') | |||
pos=matching_quote(tokens,pos+1); | |||
end | |||
pos=pos+1; | |||
end | |||
if(endpos==0) | |||
error('unmatched "]"'); | |||
end | |||
@@ -1,33 +0,0 @@ | |||
function s=mergestruct(s1,s2) | |||
% | |||
% s=mergestruct(s1,s2) | |||
% | |||
% merge two struct objects into one | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% date: 2012/12/22 | |||
% | |||
% input: | |||
% s1,s2: a struct object, s1 and s2 can not be arrays | |||
% | |||
% output: | |||
% s: the merged struct object. fields in s1 and s2 will be combined in s. | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
if(~isstruct(s1) || ~isstruct(s2)) | |||
error('input parameters contain non-struct'); | |||
end | |||
if(length(s1)>1 || length(s2)>1) | |||
error('can not merge struct arrays'); | |||
end | |||
fn=fieldnames(s2); | |||
s=s1; | |||
for i=1:length(fn) | |||
s=setfield(s,fn{i},getfield(s2,fn{i})); | |||
end | |||
@@ -1,475 +0,0 @@ | |||
function json=savejson(rootname,obj,varargin) | |||
% | |||
% json=savejson(rootname,obj,filename) | |||
% or | |||
% json=savejson(rootname,obj,opt) | |||
% json=savejson(rootname,obj,'param1',value1,'param2',value2,...) | |||
% | |||
% convert a MATLAB object (cell, struct or array) into a JSON (JavaScript | |||
% Object Notation) string | |||
% | |||
% author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2011/09/09 | |||
% | |||
% $Id: savejson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% rootname: the name of the root-object, when set to '', the root name | |||
% is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
% the MATLAB variable name will be used as the root name. | |||
% obj: a MATLAB object (array, cell, cell array, struct, struct array). | |||
% filename: a string for the file name to save the output JSON data. | |||
% opt: a struct for additional options, ignore to use default values. | |||
% opt can have the following fields (first in [.|.] is the default) | |||
% | |||
% opt.FileName [''|string]: a file name to save the output JSON data | |||
% opt.FloatFormat ['%.10g'|string]: format to show each numeric element | |||
% of a 1D/2D array; | |||
% opt.ArrayIndent [1|0]: if 1, output explicit data array with | |||
% precedent indentation; if 0, no indentation | |||
% opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D | |||
% array in JSON array format; if sets to 1, an | |||
% array will be shown as a struct with fields | |||
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
% sparse arrays, the non-zero elements will be | |||
% saved to _ArrayData_ field in triplet-format i.e. | |||
% (ix,iy,val) and "_ArrayIsSparse_" will be added | |||
% with a value of 1; for a complex array, the | |||
% _ArrayData_ array will include two columns | |||
% (4 for sparse) to record the real and imaginary | |||
% parts, and also "_ArrayIsComplex_":1 is added. | |||
% opt.ParseLogical [0|1]: if this is set to 1, logical array elem | |||
% will use true/false rather than 1/0. | |||
% opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
% numerical element will be shown without a square | |||
% bracket, unless it is the root object; if 0, square | |||
% brackets are forced for any numerical arrays. | |||
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson | |||
% will use the name of the passed obj variable as the | |||
% root object name; if obj is an expression and | |||
% does not have a name, 'root' will be used; if this | |||
% is set to 0 and rootname is empty, the root level | |||
% will be merged down to the lower level. | |||
% opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern | |||
% to represent +/-Inf. The matched pattern is '([-+]*)Inf' | |||
% and $1 represents the sign. For those who want to use | |||
% 1e999 to represent Inf, they can set opt.Inf to '$11e999' | |||
% opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern | |||
% to represent NaN | |||
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
% for example, if opt.JSONP='foo', the JSON data is | |||
% wrapped inside a function call as 'foo(...);' | |||
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
% back to the string form | |||
% opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode. | |||
% opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs) | |||
% | |||
% opt can be replaced by a list of ('param',value) pairs. The param | |||
% string is equivallent to a field in opt and is case sensitive. | |||
% output: | |||
% json: a string in the JSON format (see http://json.org) | |||
% | |||
% examples: | |||
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
% 'SpecialData',[nan, inf, -inf]); | |||
% savejson('jmesh',jsonmesh) | |||
% savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g') | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
if(nargin==1) | |||
varname=inputname(1); | |||
obj=rootname; | |||
if(isempty(varname)) | |||
varname='root'; | |||
end | |||
rootname=varname; | |||
else | |||
varname=inputname(2); | |||
end | |||
if(length(varargin)==1 && ischar(varargin{1})) | |||
opt=struct('FileName',varargin{1}); | |||
else | |||
opt=varargin2struct(varargin{:}); | |||
end | |||
opt.IsOctave=exist('OCTAVE_VERSION','builtin'); | |||
rootisarray=0; | |||
rootlevel=1; | |||
forceroot=jsonopt('ForceRootName',0,opt); | |||
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || iscell(obj)) && isempty(rootname) && forceroot==0) | |||
rootisarray=1; | |||
rootlevel=0; | |||
else | |||
if(isempty(rootname)) | |||
rootname=varname; | |||
end | |||
end | |||
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot) | |||
rootname='root'; | |||
end | |||
whitespaces=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
if(jsonopt('Compact',0,opt)==1) | |||
whitespaces=struct('tab','','newline','','sep',','); | |||
end | |||
if(~isfield(opt,'whitespaces_')) | |||
opt.whitespaces_=whitespaces; | |||
end | |||
nl=whitespaces.newline; | |||
json=obj2json(rootname,obj,rootlevel,opt); | |||
if(rootisarray) | |||
json=sprintf('%s%s',json,nl); | |||
else | |||
json=sprintf('{%s%s%s}\n',nl,json,nl); | |||
end | |||
jsonp=jsonopt('JSONP','',opt); | |||
if(~isempty(jsonp)) | |||
json=sprintf('%s(%s);%s',jsonp,json,nl); | |||
end | |||
% save to a file if FileName is set, suggested by Patrick Rapin | |||
if(~isempty(jsonopt('FileName','',opt))) | |||
if(jsonopt('SaveBinary',0,opt)==1) | |||
fid = fopen(opt.FileName, 'wb'); | |||
fwrite(fid,json); | |||
else | |||
fid = fopen(opt.FileName, 'wt'); | |||
fwrite(fid,json,'char'); | |||
end | |||
fclose(fid); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=obj2json(name,item,level,varargin) | |||
if(iscell(item)) | |||
txt=cell2json(name,item,level,varargin{:}); | |||
elseif(isstruct(item)) | |||
txt=struct2json(name,item,level,varargin{:}); | |||
elseif(ischar(item)) | |||
txt=str2json(name,item,level,varargin{:}); | |||
else | |||
txt=mat2json(name,item,level,varargin{:}); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=cell2json(name,item,level,varargin) | |||
txt=''; | |||
if(~iscell(item)) | |||
error('input is not a cell'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); | |||
ws=jsonopt('whitespaces_',struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')),varargin{:}); | |||
padding0=repmat(ws.tab,1,level); | |||
padding2=repmat(ws.tab,1,level+1); | |||
nl=ws.newline; | |||
if(len>1) | |||
if(~isempty(name)) | |||
txt=sprintf('%s"%s": [%s',padding0, checkname(name,varargin{:}),nl); name=''; | |||
else | |||
txt=sprintf('%s[%s',padding0,nl); | |||
end | |||
elseif(len==0) | |||
if(~isempty(name)) | |||
txt=sprintf('%s"%s": []',padding0, checkname(name,varargin{:})); name=''; | |||
else | |||
txt=sprintf('%s[]',padding0); | |||
end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=sprintf('%s%s[%s',txt,padding2,nl); end | |||
for i=1:dim(1) | |||
txt=sprintf('%s%s',txt,obj2json(name,item{i,j},level+(dim(1)>1)+1,varargin{:})); | |||
if(i<dim(1)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(dim(1)>1) txt=sprintf('%s%s%s]',txt,nl,padding2); end | |||
if(j<dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
%if(j==dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(len>1) txt=sprintf('%s%s%s]',txt,nl,padding0); end | |||
%%------------------------------------------------------------------------- | |||
function txt=struct2json(name,item,level,varargin) | |||
txt=''; | |||
if(~isstruct(item)) | |||
error('input is not a struct'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
padding0=repmat(ws.tab,1,level); | |||
padding2=repmat(ws.tab,1,level+1); | |||
padding1=repmat(ws.tab,1,level+(dim(1)>1)+(len>1)); | |||
nl=ws.newline; | |||
if(~isempty(name)) | |||
if(len>1) txt=sprintf('%s"%s": [%s',padding0,checkname(name,varargin{:}),nl); end | |||
else | |||
if(len>1) txt=sprintf('%s[%s',padding0,nl); end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=sprintf('%s%s[%s',txt,padding2,nl); end | |||
for i=1:dim(1) | |||
names = fieldnames(item(i,j)); | |||
if(~isempty(name) && len==1) | |||
txt=sprintf('%s%s"%s": {%s',txt,padding1, checkname(name,varargin{:}),nl); | |||
else | |||
txt=sprintf('%s%s{%s',txt,padding1,nl); | |||
end | |||
if(~isempty(names)) | |||
for e=1:length(names) | |||
txt=sprintf('%s%s',txt,obj2json(names{e},getfield(item(i,j),... | |||
names{e}),level+(dim(1)>1)+1+(len>1),varargin{:})); | |||
if(e<length(names)) txt=sprintf('%s%s',txt,','); end | |||
txt=sprintf('%s%s',txt,nl); | |||
end | |||
end | |||
txt=sprintf('%s%s}',txt,padding1); | |||
if(i<dim(1)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(dim(1)>1) txt=sprintf('%s%s%s]',txt,nl,padding2); end | |||
if(j<dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(len>1) txt=sprintf('%s%s%s]',txt,nl,padding0); end | |||
%%------------------------------------------------------------------------- | |||
function txt=str2json(name,item,level,varargin) | |||
txt=''; | |||
if(~ischar(item)) | |||
error('input is not a string'); | |||
end | |||
item=reshape(item, max(size(item),[1 0])); | |||
len=size(item,1); | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
padding1=repmat(ws.tab,1,level); | |||
padding0=repmat(ws.tab,1,level+1); | |||
nl=ws.newline; | |||
sep=ws.sep; | |||
if(~isempty(name)) | |||
if(len>1) txt=sprintf('%s"%s": [%s',padding1,checkname(name,varargin{:}),nl); end | |||
else | |||
if(len>1) txt=sprintf('%s[%s',padding1,nl); end | |||
end | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
for e=1:len | |||
if(isoct) | |||
val=regexprep(item(e,:),'\\','\\'); | |||
val=regexprep(val,'"','\"'); | |||
val=regexprep(val,'^"','\"'); | |||
else | |||
val=regexprep(item(e,:),'\\','\\\\'); | |||
val=regexprep(val,'"','\\"'); | |||
val=regexprep(val,'^"','\\"'); | |||
end | |||
val=escapejsonstring(val); | |||
if(len==1) | |||
obj=['"' checkname(name,varargin{:}) '": ' '"',val,'"']; | |||
if(isempty(name)) obj=['"',val,'"']; end | |||
txt=sprintf('%s%s%s%s',txt,padding1,obj); | |||
else | |||
txt=sprintf('%s%s%s%s',txt,padding0,['"',val,'"']); | |||
end | |||
if(e==len) sep=''; end | |||
txt=sprintf('%s%s',txt,sep); | |||
end | |||
if(len>1) txt=sprintf('%s%s%s%s',txt,nl,padding1,']'); end | |||
%%------------------------------------------------------------------------- | |||
function txt=mat2json(name,item,level,varargin) | |||
if(~isnumeric(item) && ~islogical(item)) | |||
error('input is not an array'); | |||
end | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
padding1=repmat(ws.tab,1,level); | |||
padding0=repmat(ws.tab,1,level+1); | |||
nl=ws.newline; | |||
sep=ws.sep; | |||
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ... | |||
isempty(item) ||jsonopt('ArrayToStruct',0,varargin{:})) | |||
if(isempty(name)) | |||
txt=sprintf('%s{%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',... | |||
padding1,nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); | |||
else | |||
txt=sprintf('%s"%s": {%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',... | |||
padding1,checkname(name,varargin{:}),nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); | |||
end | |||
else | |||
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1 && level>0) | |||
numtxt=regexprep(regexprep(matdata2json(item,level+1,varargin{:}),'^\[',''),']',''); | |||
else | |||
numtxt=matdata2json(item,level+1,varargin{:}); | |||
end | |||
if(isempty(name)) | |||
txt=sprintf('%s%s',padding1,numtxt); | |||
else | |||
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1) | |||
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt); | |||
else | |||
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt); | |||
end | |||
end | |||
return; | |||
end | |||
dataformat='%s%s%s%s%s'; | |||
if(issparse(item)) | |||
[ix,iy]=find(item); | |||
data=full(item(find(item))); | |||
if(~isreal(item)) | |||
data=[real(data(:)),imag(data(:))]; | |||
if(size(item,1)==1) | |||
% Kludge to have data's 'transposedness' match item's. | |||
% (Necessary for complex row vector handling below.) | |||
data=data'; | |||
end | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep); | |||
end | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_": ','1', sep); | |||
if(size(item,1)==1) | |||
% Row vector, store only column indices. | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([iy(:),data'],level+2,varargin{:}), nl); | |||
elseif(size(item,2)==1) | |||
% Column vector, store only row indices. | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([ix,data],level+2,varargin{:}), nl); | |||
else | |||
% General case, store row and column indices. | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([ix,iy,data],level+2,varargin{:}), nl); | |||
end | |||
else | |||
if(isreal(item)) | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json(item(:)',level+2,varargin{:}), nl); | |||
else | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep); | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([real(item(:)) imag(item(:))],level+2,varargin{:}), nl); | |||
end | |||
end | |||
txt=sprintf('%s%s%s',txt,padding1,'}'); | |||
%%------------------------------------------------------------------------- | |||
function txt=matdata2json(mat,level,varargin) | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
tab=ws.tab; | |||
nl=ws.newline; | |||
if(size(mat,1)==1) | |||
pre=''; | |||
post=''; | |||
level=level-1; | |||
else | |||
pre=sprintf('[%s',nl); | |||
post=sprintf('%s%s]',nl,repmat(tab,1,level-1)); | |||
end | |||
if(isempty(mat)) | |||
txt='null'; | |||
return; | |||
end | |||
floatformat=jsonopt('FloatFormat','%.10g',varargin{:}); | |||
%if(numel(mat)>1) | |||
formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],%s',nl)]]; | |||
%else | |||
% formatstr=[repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf(',\n')]]; | |||
%end | |||
if(nargin>=2 && size(mat,1)>1 && jsonopt('ArrayIndent',1,varargin{:})==1) | |||
formatstr=[repmat(tab,1,level) formatstr]; | |||
end | |||
txt=sprintf(formatstr,mat'); | |||
txt(end-length(nl):end)=[]; | |||
if(islogical(mat) && jsonopt('ParseLogical',0,varargin{:})==1) | |||
txt=regexprep(txt,'1','true'); | |||
txt=regexprep(txt,'0','false'); | |||
end | |||
%txt=regexprep(mat2str(mat),'\s+',','); | |||
%txt=regexprep(txt,';',sprintf('],\n[')); | |||
% if(nargin>=2 && size(mat,1)>1) | |||
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']); | |||
% end | |||
txt=[pre txt post]; | |||
if(any(isinf(mat(:)))) | |||
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:})); | |||
end | |||
if(any(isnan(mat(:)))) | |||
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:})); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newname=checkname(name,varargin) | |||
isunpack=jsonopt('UnpackHex',1,varargin{:}); | |||
newname=name; | |||
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once'))) | |||
return | |||
end | |||
if(isunpack) | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
if(~isoct) | |||
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}'); | |||
else | |||
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start'); | |||
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end'); | |||
if(isempty(pos)) return; end | |||
str0=name; | |||
pos0=[0 pend(:)' length(name)]; | |||
newname=''; | |||
for i=1:length(pos) | |||
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))]; | |||
end | |||
if(pos(end)~=length(name)) | |||
newname=[newname str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newstr=escapejsonstring(str) | |||
newstr=str; | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
if(isoct) | |||
vv=sscanf(OCTAVE_VERSION,'%f'); | |||
if(vv(1)>=3.8) isoct=0; end | |||
end | |||
if(isoct) | |||
escapechars={'\a','\f','\n','\r','\t','\v'}; | |||
for i=1:length(escapechars); | |||
newstr=regexprep(newstr,escapechars{i},escapechars{i}); | |||
end | |||
else | |||
escapechars={'\a','\b','\f','\n','\r','\t','\v'}; | |||
for i=1:length(escapechars); | |||
newstr=regexprep(newstr,escapechars{i},regexprep(escapechars{i},'\\','\\\\')); | |||
end | |||
end |
@@ -1,504 +0,0 @@ | |||
function json=saveubjson(rootname,obj,varargin) | |||
% | |||
% json=saveubjson(rootname,obj,filename) | |||
% or | |||
% json=saveubjson(rootname,obj,opt) | |||
% json=saveubjson(rootname,obj,'param1',value1,'param2',value2,...) | |||
% | |||
% convert a MATLAB object (cell, struct or array) into a Universal | |||
% Binary JSON (UBJSON) binary string | |||
% | |||
% author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2013/08/17 | |||
% | |||
% $Id: saveubjson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% rootname: the name of the root-object, when set to '', the root name | |||
% is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
% the MATLAB variable name will be used as the root name. | |||
% obj: a MATLAB object (array, cell, cell array, struct, struct array) | |||
% filename: a string for the file name to save the output UBJSON data | |||
% opt: a struct for additional options, ignore to use default values. | |||
% opt can have the following fields (first in [.|.] is the default) | |||
% | |||
% opt.FileName [''|string]: a file name to save the output JSON data | |||
% opt.ArrayToStruct[0|1]: when set to 0, saveubjson outputs 1D/2D | |||
% array in JSON array format; if sets to 1, an | |||
% array will be shown as a struct with fields | |||
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
% sparse arrays, the non-zero elements will be | |||
% saved to _ArrayData_ field in triplet-format i.e. | |||
% (ix,iy,val) and "_ArrayIsSparse_" will be added | |||
% with a value of 1; for a complex array, the | |||
% _ArrayData_ array will include two columns | |||
% (4 for sparse) to record the real and imaginary | |||
% parts, and also "_ArrayIsComplex_":1 is added. | |||
% opt.ParseLogical [1|0]: if this is set to 1, logical array elem | |||
% will use true/false rather than 1/0. | |||
% opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
% numerical element will be shown without a square | |||
% bracket, unless it is the root object; if 0, square | |||
% brackets are forced for any numerical arrays. | |||
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, saveubjson | |||
% will use the name of the passed obj variable as the | |||
% root object name; if obj is an expression and | |||
% does not have a name, 'root' will be used; if this | |||
% is set to 0 and rootname is empty, the root level | |||
% will be merged down to the lower level. | |||
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
% for example, if opt.JSON='foo', the JSON data is | |||
% wrapped inside a function call as 'foo(...);' | |||
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
% back to the string form | |||
% | |||
% opt can be replaced by a list of ('param',value) pairs. The param | |||
% string is equivallent to a field in opt and is case sensitive. | |||
% output: | |||
% json: a binary string in the UBJSON format (see http://ubjson.org) | |||
% | |||
% examples: | |||
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
% 'SpecialData',[nan, inf, -inf]); | |||
% saveubjson('jsonmesh',jsonmesh) | |||
% saveubjson('jsonmesh',jsonmesh,'meshdata.ubj') | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
if(nargin==1) | |||
varname=inputname(1); | |||
obj=rootname; | |||
if(isempty(varname)) | |||
varname='root'; | |||
end | |||
rootname=varname; | |||
else | |||
varname=inputname(2); | |||
end | |||
if(length(varargin)==1 && ischar(varargin{1})) | |||
opt=struct('FileName',varargin{1}); | |||
else | |||
opt=varargin2struct(varargin{:}); | |||
end | |||
opt.IsOctave=exist('OCTAVE_VERSION','builtin'); | |||
rootisarray=0; | |||
rootlevel=1; | |||
forceroot=jsonopt('ForceRootName',0,opt); | |||
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || iscell(obj)) && isempty(rootname) && forceroot==0) | |||
rootisarray=1; | |||
rootlevel=0; | |||
else | |||
if(isempty(rootname)) | |||
rootname=varname; | |||
end | |||
end | |||
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot) | |||
rootname='root'; | |||
end | |||
json=obj2ubjson(rootname,obj,rootlevel,opt); | |||
if(~rootisarray) | |||
json=['{' json '}']; | |||
end | |||
jsonp=jsonopt('JSONP','',opt); | |||
if(~isempty(jsonp)) | |||
json=[jsonp '(' json ')']; | |||
end | |||
% save to a file if FileName is set, suggested by Patrick Rapin | |||
if(~isempty(jsonopt('FileName','',opt))) | |||
fid = fopen(opt.FileName, 'wb'); | |||
fwrite(fid,json); | |||
fclose(fid); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=obj2ubjson(name,item,level,varargin) | |||
if(iscell(item)) | |||
txt=cell2ubjson(name,item,level,varargin{:}); | |||
elseif(isstruct(item)) | |||
txt=struct2ubjson(name,item,level,varargin{:}); | |||
elseif(ischar(item)) | |||
txt=str2ubjson(name,item,level,varargin{:}); | |||
else | |||
txt=mat2ubjson(name,item,level,varargin{:}); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=cell2ubjson(name,item,level,varargin) | |||
txt=''; | |||
if(~iscell(item)) | |||
error('input is not a cell'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); % let's handle 1D cell first | |||
if(len>1) | |||
if(~isempty(name)) | |||
txt=[S_(checkname(name,varargin{:})) '[']; name=''; | |||
else | |||
txt='['; | |||
end | |||
elseif(len==0) | |||
if(~isempty(name)) | |||
txt=[S_(checkname(name,varargin{:})) 'Z']; name=''; | |||
else | |||
txt='Z'; | |||
end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=[txt '[']; end | |||
for i=1:dim(1) | |||
txt=[txt obj2ubjson(name,item{i,j},level+(len>1),varargin{:})]; | |||
end | |||
if(dim(1)>1) txt=[txt ']']; end | |||
end | |||
if(len>1) txt=[txt ']']; end | |||
%%------------------------------------------------------------------------- | |||
function txt=struct2ubjson(name,item,level,varargin) | |||
txt=''; | |||
if(~isstruct(item)) | |||
error('input is not a struct'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); | |||
if(~isempty(name)) | |||
if(len>1) txt=[S_(checkname(name,varargin{:})) '[']; end | |||
else | |||
if(len>1) txt='['; end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=[txt '[']; end | |||
for i=1:dim(1) | |||
names = fieldnames(item(i,j)); | |||
if(~isempty(name) && len==1) | |||
txt=[txt S_(checkname(name,varargin{:})) '{']; | |||
else | |||
txt=[txt '{']; | |||
end | |||
if(~isempty(names)) | |||
for e=1:length(names) | |||
txt=[txt obj2ubjson(names{e},getfield(item(i,j),... | |||
names{e}),level+(dim(1)>1)+1+(len>1),varargin{:})]; | |||
end | |||
end | |||
txt=[txt '}']; | |||
end | |||
if(dim(1)>1) txt=[txt ']']; end | |||
end | |||
if(len>1) txt=[txt ']']; end | |||
%%------------------------------------------------------------------------- | |||
function txt=str2ubjson(name,item,level,varargin) | |||
txt=''; | |||
if(~ischar(item)) | |||
error('input is not a string'); | |||
end | |||
item=reshape(item, max(size(item),[1 0])); | |||
len=size(item,1); | |||
if(~isempty(name)) | |||
if(len>1) txt=[S_(checkname(name,varargin{:})) '[']; end | |||
else | |||
if(len>1) txt='['; end | |||
end | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
for e=1:len | |||
val=item(e,:); | |||
if(len==1) | |||
obj=['' S_(checkname(name,varargin{:})) '' '',S_(val),'']; | |||
if(isempty(name)) obj=['',S_(val),'']; end | |||
txt=[txt,'',obj]; | |||
else | |||
txt=[txt,'',['',S_(val),'']]; | |||
end | |||
end | |||
if(len>1) txt=[txt ']']; end | |||
%%------------------------------------------------------------------------- | |||
function txt=mat2ubjson(name,item,level,varargin) | |||
if(~isnumeric(item) && ~islogical(item)) | |||
error('input is not an array'); | |||
end | |||
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ... | |||
isempty(item) || jsonopt('ArrayToStruct',0,varargin{:})) | |||
cid=I_(uint32(max(size(item)))); | |||
if(isempty(name)) | |||
txt=['{' S_('_ArrayType_'),S_(class(item)),S_('_ArraySize_'),I_a(size(item),cid(1)) ]; | |||
else | |||
if(isempty(item)) | |||
txt=[S_(checkname(name,varargin{:})),'Z']; | |||
return; | |||
else | |||
txt=[S_(checkname(name,varargin{:})),'{',S_('_ArrayType_'),S_(class(item)),S_('_ArraySize_'),I_a(size(item),cid(1))]; | |||
end | |||
end | |||
else | |||
if(isempty(name)) | |||
txt=matdata2ubjson(item,level+1,varargin{:}); | |||
else | |||
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1) | |||
numtxt=regexprep(regexprep(matdata2ubjson(item,level+1,varargin{:}),'^\[',''),']',''); | |||
txt=[S_(checkname(name,varargin{:})) numtxt]; | |||
else | |||
txt=[S_(checkname(name,varargin{:})),matdata2ubjson(item,level+1,varargin{:})]; | |||
end | |||
end | |||
return; | |||
end | |||
if(issparse(item)) | |||
[ix,iy]=find(item); | |||
data=full(item(find(item))); | |||
if(~isreal(item)) | |||
data=[real(data(:)),imag(data(:))]; | |||
if(size(item,1)==1) | |||
% Kludge to have data's 'transposedness' match item's. | |||
% (Necessary for complex row vector handling below.) | |||
data=data'; | |||
end | |||
txt=[txt,S_('_ArrayIsComplex_'),'T']; | |||
end | |||
txt=[txt,S_('_ArrayIsSparse_'),'T']; | |||
if(size(item,1)==1) | |||
% Row vector, store only column indices. | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([iy(:),data'],level+2,varargin{:})]; | |||
elseif(size(item,2)==1) | |||
% Column vector, store only row indices. | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([ix,data],level+2,varargin{:})]; | |||
else | |||
% General case, store row and column indices. | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([ix,iy,data],level+2,varargin{:})]; | |||
end | |||
else | |||
if(isreal(item)) | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson(item(:)',level+2,varargin{:})]; | |||
else | |||
txt=[txt,S_('_ArrayIsComplex_'),'T']; | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([real(item(:)) imag(item(:))],level+2,varargin{:})]; | |||
end | |||
end | |||
txt=[txt,'}']; | |||
%%------------------------------------------------------------------------- | |||
function txt=matdata2ubjson(mat,level,varargin) | |||
if(isempty(mat)) | |||
txt='Z'; | |||
return; | |||
end | |||
if(size(mat,1)==1) | |||
level=level-1; | |||
end | |||
type=''; | |||
hasnegtive=(mat<0); | |||
if(isa(mat,'integer') || isinteger(mat) || (isfloat(mat) && all(mod(mat(:),1) == 0))) | |||
if(isempty(hasnegtive)) | |||
if(max(mat(:))<=2^8) | |||
type='U'; | |||
end | |||
end | |||
if(isempty(type)) | |||
% todo - need to consider negative ones separately | |||
id= histc(abs(max(mat(:))),[0 2^7 2^15 2^31 2^63]); | |||
if(isempty(find(id))) | |||
error('high-precision data is not yet supported'); | |||
end | |||
key='iIlL'; | |||
type=key(find(id)); | |||
end | |||
txt=[I_a(mat(:),type,size(mat))]; | |||
elseif(islogical(mat)) | |||
logicalval='FT'; | |||
if(numel(mat)==1) | |||
txt=logicalval(mat+1); | |||
else | |||
txt=['[$U#' I_a(size(mat),'l') typecast(swapbytes(uint8(mat(:)')),'uint8')]; | |||
end | |||
else | |||
if(numel(mat)==1) | |||
txt=['[' D_(mat) ']']; | |||
else | |||
txt=D_a(mat(:),'D',size(mat)); | |||
end | |||
end | |||
%txt=regexprep(mat2str(mat),'\s+',','); | |||
%txt=regexprep(txt,';',sprintf('],[')); | |||
% if(nargin>=2 && size(mat,1)>1) | |||
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']); | |||
% end | |||
if(any(isinf(mat(:)))) | |||
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:})); | |||
end | |||
if(any(isnan(mat(:)))) | |||
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:})); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newname=checkname(name,varargin) | |||
isunpack=jsonopt('UnpackHex',1,varargin{:}); | |||
newname=name; | |||
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once'))) | |||
return | |||
end | |||
if(isunpack) | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
if(~isoct) | |||
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}'); | |||
else | |||
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start'); | |||
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end'); | |||
if(isempty(pos)) return; end | |||
str0=name; | |||
pos0=[0 pend(:)' length(name)]; | |||
newname=''; | |||
for i=1:length(pos) | |||
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))]; | |||
end | |||
if(pos(end)~=length(name)) | |||
newname=[newname str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function val=S_(str) | |||
if(length(str)==1) | |||
val=['C' str]; | |||
else | |||
val=['S' I_(int32(length(str))) str]; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function val=I_(num) | |||
if(~isinteger(num)) | |||
error('input is not an integer'); | |||
end | |||
if(num>=0 && num<255) | |||
val=['U' data2byte(swapbytes(cast(num,'uint8')),'uint8')]; | |||
return; | |||
end | |||
key='iIlL'; | |||
cid={'int8','int16','int32','int64'}; | |||
for i=1:4 | |||
if((num>0 && num<2^(i*8-1)) || (num<0 && num>=-2^(i*8-1))) | |||
val=[key(i) data2byte(swapbytes(cast(num,cid{i})),'uint8')]; | |||
return; | |||
end | |||
end | |||
error('unsupported integer'); | |||
%%------------------------------------------------------------------------- | |||
function val=D_(num) | |||
if(~isfloat(num)) | |||
error('input is not a float'); | |||
end | |||
if(isa(num,'single')) | |||
val=['d' data2byte(num,'uint8')]; | |||
else | |||
val=['D' data2byte(num,'uint8')]; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function data=I_a(num,type,dim,format) | |||
id=find(ismember('iUIlL',type)); | |||
if(id==0) | |||
error('unsupported integer array'); | |||
end | |||
% based on UBJSON specs, all integer types are stored in big endian format | |||
if(id==1) | |||
data=data2byte(swapbytes(int8(num)),'uint8'); | |||
blen=1; | |||
elseif(id==2) | |||
data=data2byte(swapbytes(uint8(num)),'uint8'); | |||
blen=1; | |||
elseif(id==3) | |||
data=data2byte(swapbytes(int16(num)),'uint8'); | |||
blen=2; | |||
elseif(id==4) | |||
data=data2byte(swapbytes(int32(num)),'uint8'); | |||
blen=4; | |||
elseif(id==5) | |||
data=data2byte(swapbytes(int64(num)),'uint8'); | |||
blen=8; | |||
end | |||
if(nargin>=3 && length(dim)>=2 && prod(dim)~=dim(2)) | |||
format='opt'; | |||
end | |||
if((nargin<4 || strcmp(format,'opt')) && numel(num)>1) | |||
if(nargin>=3 && (length(dim)==1 || (length(dim)>=2 && prod(dim)~=dim(2)))) | |||
cid=I_(uint32(max(dim))); | |||
data=['$' type '#' I_a(dim,cid(1)) data(:)']; | |||
else | |||
data=['$' type '#' I_(int32(numel(data)/blen)) data(:)']; | |||
end | |||
data=['[' data(:)']; | |||
else | |||
data=reshape(data,blen,numel(data)/blen); | |||
data(2:blen+1,:)=data; | |||
data(1,:)=type; | |||
data=data(:)'; | |||
data=['[' data(:)' ']']; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function data=D_a(num,type,dim,format) | |||
id=find(ismember('dD',type)); | |||
if(id==0) | |||
error('unsupported float array'); | |||
end | |||
if(id==1) | |||
data=data2byte(single(num),'uint8'); | |||
elseif(id==2) | |||
data=data2byte(double(num),'uint8'); | |||
end | |||
if(nargin>=3 && length(dim)>=2 && prod(dim)~=dim(2)) | |||
format='opt'; | |||
end | |||
if((nargin<4 || strcmp(format,'opt')) && numel(num)>1) | |||
if(nargin>=3 && (length(dim)==1 || (length(dim)>=2 && prod(dim)~=dim(2)))) | |||
cid=I_(uint32(max(dim))); | |||
data=['$' type '#' I_a(dim,cid(1)) data(:)']; | |||
else | |||
data=['$' type '#' I_(int32(numel(data)/(id*4))) data(:)']; | |||
end | |||
data=['[' data]; | |||
else | |||
data=reshape(data,(id*4),length(data)/(id*4)); | |||
data(2:(id*4+1),:)=data; | |||
data(1,:)=type; | |||
data=data(:)'; | |||
data=['[' data(:)' ']']; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function bytes=data2byte(varargin) | |||
bytes=typecast(varargin{:}); | |||
bytes=bytes(:)'; |
@@ -1,40 +0,0 @@ | |||
function opt=varargin2struct(varargin) | |||
% | |||
% opt=varargin2struct('param1',value1,'param2',value2,...) | |||
% or | |||
% opt=varargin2struct(...,optstruct,...) | |||
% | |||
% convert a series of input parameters into a structure | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% date: 2012/12/22 | |||
% | |||
% input: | |||
% 'param', value: the input parameters should be pairs of a string and a value | |||
% optstruct: if a parameter is a struct, the fields will be merged to the output struct | |||
% | |||
% output: | |||
% opt: a struct where opt.param1=value1, opt.param2=value2 ... | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
len=length(varargin); | |||
opt=struct; | |||
if(len==0) return; end | |||
i=1; | |||
while(i<=len) | |||
if(isstruct(varargin{i})) | |||
opt=mergestruct(opt,varargin{i}); | |||
elseif(ischar(varargin{i}) && i<len) | |||
opt=setfield(opt,varargin{i},varargin{i+1}); | |||
i=i+1; | |||
else | |||
error('input must be in the form of ...,''name'',value,... pairs or structs'); | |||
end | |||
i=i+1; | |||
end | |||
@@ -1,30 +0,0 @@ | |||
function str = makeValidFieldName(str) | |||
% From MATLAB doc: field names must begin with a letter, which may be | |||
% followed by any combination of letters, digits, and underscores. | |||
% Invalid characters will be converted to underscores, and the prefix | |||
% "x0x[Hex code]_" will be added if the first character is not a letter. | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
pos=regexp(str,'^[^A-Za-z]','once'); | |||
if(~isempty(pos)) | |||
if(~isoct) | |||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); | |||
else | |||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); | |||
end | |||
end | |||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end | |||
if(~isoct) | |||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_'); | |||
else | |||
pos=regexp(str,'[^0-9A-Za-z_]'); | |||
if(isempty(pos)) return; end | |||
str0=str; | |||
pos0=[0 pos(:)' length(str)]; | |||
str=''; | |||
for i=1:length(pos) | |||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))]; | |||
end | |||
if(pos(end)~=length(str)) | |||
str=[str str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end |
@@ -1,126 +0,0 @@ | |||
function submitWithConfiguration(conf) | |||
addpath('./lib/jsonlab'); | |||
parts = parts(conf); | |||
fprintf('== Submitting solutions | %s...\n', conf.itemName); | |||
tokenFile = 'token.mat'; | |||
if exist(tokenFile, 'file') | |||
load(tokenFile); | |||
[email token] = promptToken(email, token, tokenFile); | |||
else | |||
[email token] = promptToken('', '', tokenFile); | |||
end | |||
if isempty(token) | |||
fprintf('!! Submission Cancelled\n'); | |||
return | |||
end | |||
try | |||
response = submitParts(conf, email, token, parts); | |||
catch | |||
e = lasterror(); | |||
fprintf( ... | |||
'!! Submission failed: unexpected error: %s\n', ... | |||
e.message); | |||
fprintf('!! Please try again later.\n'); | |||
return | |||
end | |||
if isfield(response, 'errorMessage') | |||
fprintf('!! Submission failed: %s\n', response.errorMessage); | |||
else | |||
showFeedback(parts, response); | |||
save(tokenFile, 'email', 'token'); | |||
end | |||
end | |||
function [email token] = promptToken(email, existingToken, tokenFile) | |||
if (~isempty(email) && ~isempty(existingToken)) | |||
prompt = sprintf( ... | |||
'Use token from last successful submission (%s)? (Y/n): ', ... | |||
email); | |||
reenter = input(prompt, 's'); | |||
if (isempty(reenter) || reenter(1) == 'Y' || reenter(1) == 'y') | |||
token = existingToken; | |||
return; | |||
else | |||
delete(tokenFile); | |||
end | |||
end | |||
email = input('Login (email address): ', 's'); | |||
token = input('Token: ', 's'); | |||
end | |||
function isValid = isValidPartOptionIndex(partOptions, i) | |||
isValid = (~isempty(i)) && (1 <= i) && (i <= numel(partOptions)); | |||
end | |||
function response = submitParts(conf, email, token, parts) | |||
body = makePostBody(conf, email, token, parts); | |||
submissionUrl = submissionUrl(); | |||
params = {'jsonBody', body}; | |||
% responseBody = urlread(submissionUrl, 'post', params); | |||
[code, responseBody] = system(sprintf('echo jsonBody=%s | curl -k -X POST -d @- %s', body, submissionUrl)); | |||
response = loadjson(responseBody); | |||
end | |||
function body = makePostBody(conf, email, token, parts) | |||
bodyStruct.assignmentSlug = conf.assignmentSlug; | |||
bodyStruct.submitterEmail = email; | |||
bodyStruct.secret = token; | |||
bodyStruct.parts = makePartsStruct(conf, parts); | |||
opt.Compact = 1; | |||
body = savejson('', bodyStruct, opt); | |||
end | |||
function partsStruct = makePartsStruct(conf, parts) | |||
for part = parts | |||
partId = part{:}.id; | |||
fieldName = makeValidFieldName(partId); | |||
outputStruct.output = conf.output(partId); | |||
partsStruct.(fieldName) = outputStruct; | |||
end | |||
end | |||
function [parts] = parts(conf) | |||
parts = {}; | |||
for partArray = conf.partArrays | |||
part.id = partArray{:}{1}; | |||
part.sourceFiles = partArray{:}{2}; | |||
part.name = partArray{:}{3}; | |||
parts{end + 1} = part; | |||
end | |||
end | |||
function showFeedback(parts, response) | |||
fprintf('== \n'); | |||
fprintf('== %43s | %9s | %-s\n', 'Part Name', 'Score', 'Feedback'); | |||
fprintf('== %43s | %9s | %-s\n', '---------', '-----', '--------'); | |||
for part = parts | |||
score = ''; | |||
partFeedback = ''; | |||
partFeedback = response.partFeedbacks.(makeValidFieldName(part{:}.id)); | |||
partEvaluation = response.partEvaluations.(makeValidFieldName(part{:}.id)); | |||
score = sprintf('%d / %3d', partEvaluation.score, partEvaluation.maxScore); | |||
fprintf('== %43s | %9s | %-s\n', part{:}.name, score, partFeedback); | |||
end | |||
evaluation = response.evaluation; | |||
totalScore = sprintf('%d / %d', evaluation.score, evaluation.maxScore); | |||
fprintf('== --------------------------------\n'); | |||
fprintf('== %43s | %9s | %-s\n', '', totalScore, ''); | |||
fprintf('== \n'); | |||
end | |||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |||
% | |||
% Service configuration | |||
% | |||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |||
function submissionUrl = submissionUrl() | |||
submissionUrl = 'https://www-origin.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1'; | |||
end |
@@ -1,23 +0,0 @@ | |||
function [theta] = normalEqn(X, y) | |||
%NORMALEQN Computes the closed-form solution to linear regression | |||
% NORMALEQN(X,y) computes the closed-form solution to linear | |||
% regression using the normal equations. | |||
theta = zeros(size(X, 2), 1); | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Complete the code to compute the closed form solution | |||
% to linear regression and put the result in theta. | |||
% | |||
% ---------------------- Sample Solution ---------------------- | |||
theta = pinv(X' * X) * X' * y; | |||
% ------------------------------------------------------------- | |||
% ============================================================ | |||
end |
@@ -1,29 +0,0 @@ | |||
function plotData(x, y) | |||
%PLOTDATA Plots the data points x and y into a new figure | |||
% PLOTDATA(x,y) plots the data points and gives the figure axes labels of | |||
% population and profit. | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Plot the training data into a figure using the | |||
% "figure" and "plot" commands. Set the axes labels using | |||
% the "xlabel" and "ylabel" commands. Assume the | |||
% population and revenue data have been passed in | |||
% as the x and y arguments of this function. | |||
% | |||
% Hint: You can use the 'rx' option with plot to have the markers | |||
% appear as red crosses. Furthermore, you can make the | |||
% markers larger by using plot(..., 'rx', 'MarkerSize', 10); | |||
figure; % open a new figure window | |||
plot(x, y, 'rx', 'MarkerSize', 10); | |||
xlabel('xlabel'); | |||
ylabel('ylabel'); | |||
% ============================================================ | |||
end |
@@ -1,69 +0,0 @@ | |||
function submit() | |||
addpath('./lib'); | |||
conf.assignmentSlug = 'linear-regression'; | |||
conf.itemName = 'Linear Regression with Multiple Variables'; | |||
conf.partArrays = { ... | |||
{ ... | |||
'1', ... | |||
{ 'warmUpExercise.m' }, ... | |||
'Warm-up Exercise', ... | |||
}, ... | |||
{ ... | |||
'2', ... | |||
{ 'computeCost.m' }, ... | |||
'Computing Cost (for One Variable)', ... | |||
}, ... | |||
{ ... | |||
'3', ... | |||
{ 'gradientDescent.m' }, ... | |||
'Gradient Descent (for One Variable)', ... | |||
}, ... | |||
{ ... | |||
'4', ... | |||
{ 'featureNormalize.m' }, ... | |||
'Feature Normalization', ... | |||
}, ... | |||
{ ... | |||
'5', ... | |||
{ 'computeCostMulti.m' }, ... | |||
'Computing Cost (for Multiple Variables)', ... | |||
}, ... | |||
{ ... | |||
'6', ... | |||
{ 'gradientDescentMulti.m' }, ... | |||
'Gradient Descent (for Multiple Variables)', ... | |||
}, ... | |||
{ ... | |||
'7', ... | |||
{ 'normalEqn.m' }, ... | |||
'Normal Equations', ... | |||
}, ... | |||
}; | |||
conf.output = @output; | |||
submitWithConfiguration(conf); | |||
end | |||
function out = output(partId) | |||
% Random Test Cases | |||
X1 = [ones(20,1) (exp(1) + exp(2) * (0.1:0.1:2))']; | |||
Y1 = X1(:,2) + sin(X1(:,1)) + cos(X1(:,2)); | |||
X2 = [X1 X1(:,2).^0.5 X1(:,2).^0.25]; | |||
Y2 = Y1.^0.5 + Y1; | |||
if partId == '1' | |||
out = sprintf('%0.5f ', warmUpExercise()); | |||
elseif partId == '2' | |||
out = sprintf('%0.5f ', computeCost(X1, Y1, [0.5 -0.5]')); | |||
elseif partId == '3' | |||
out = sprintf('%0.5f ', gradientDescent(X1, Y1, [0.5 -0.5]', 0.01, 10)); | |||
elseif partId == '4' | |||
out = sprintf('%0.5f ', featureNormalize(X2(:,2:4))); | |||
elseif partId == '5' | |||
out = sprintf('%0.5f ', computeCostMulti(X2, Y2, [0.1 0.2 0.3 0.4]')); | |||
elseif partId == '6' | |||
out = sprintf('%0.5f ', gradientDescentMulti(X2, Y2, [-0.1 -0.2 -0.3 -0.4]', 0.01, 10)); | |||
elseif partId == '7' | |||
out = sprintf('%0.5f ', normalEqn(X2, Y2)); | |||
end | |||
end |
@@ -1,6 +0,0 @@ | |||
function [JVal, gradient] = functionCost(theta) | |||
JVal = theta' * theta; | |||
gradient = theta; | |||
% ========================================================================= | |||
end |
@@ -1,15 +0,0 @@ | |||
# Created by Octave 4.0.3, Mon Nov 14 10:25:22 2016 GMT <unknown@DESKTOP-1S2UOSP> | |||
# name: email | |||
# type: sq_string | |||
# elements: 1 | |||
# length: 16 | |||
scruel@vip.qq.com | |||
# name: token | |||
# type: sq_string | |||
# elements: 1 | |||
# length: 16 | |||
A3Wc4pI1qYjCUaRB | |||
@@ -1,21 +0,0 @@ | |||
function A = warmUpExercise() | |||
%WARMUPEXERCISE Example function in octave | |||
% A = WARMUPEXERCISE() is an example function that returns the 5x5 identity matrix | |||
A = []; | |||
% ============= YOUR CODE HERE ============== | |||
% Instructions: Return the 5x5 identity matrix | |||
% In octave, we return values by defining which variables | |||
% represent the return values (at the top of the file) | |||
% and then set them accordingly. | |||
A = eye(5); | |||
% =========================================== | |||
end |
@@ -1,32 +0,0 @@ | |||
function [J, grad] = costFunction(theta, X, y) | |||
%COSTFUNCTION Compute cost and gradient for logistic regression | |||
% J = COSTFUNCTION(theta, X, y) computes the cost of using theta as the | |||
% parameter for logistic regression and the gradient of the cost | |||
% w.r.t. to the parameters. | |||
% Initialize some useful values | |||
m = length(y); % number of training examples | |||
% You need to return the following variables correctly | |||
J = 0; | |||
grad = zeros(size(theta)); | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Compute the cost of a particular choice of theta. | |||
% You should set J to the cost. | |||
% Compute the partial derivatives and set grad to the partial | |||
% derivatives of the cost w.r.t. each parameter in theta | |||
% | |||
% Note: grad should have the same dimensions as theta | |||
% | |||
hx = sigmoid(X * theta); %hypothesis, m * 1 | |||
J = 1 / m * sum(-y' * log(hx) - (1 .- y)' * log(1 -hx)); | |||
grad = 1 / m * X' *(hx - y); | |||
% ============================================================= | |||
end |
@@ -1,32 +0,0 @@ | |||
function [J, grad] = costFunctionReg(theta, X, y, lambda) | |||
%COSTFUNCTIONREG Compute cost and gradient for logistic regression with regularization | |||
% J = COSTFUNCTIONREG(theta, X, y, lambda) computes the cost of using | |||
% theta as the parameter for regularized logistic regression and the | |||
% gradient of the cost w.r.t. to the parameters. | |||
% Initialize some useful values | |||
m = length(y); % number of training examples | |||
% You need to return the following variables correctly | |||
J = 0; | |||
grad = zeros(size(theta)); | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Compute the cost of a particular choice of theta. | |||
% You should set J to the cost. | |||
% Compute the partial derivatives and set grad to the partial | |||
% derivatives of the cost w.r.t. each parameter in theta | |||
hx = sigmoid(X * theta); %hypothesis, m * 1 | |||
J = 1 / m * sum(-y' * log(hx) - (1 - y)' * log(1 - hx)) + lambda / (2 * m) * theta(2:end)' * theta(2:end); | |||
gradf = (1 / m) * (X(:, 1)' * (hx - y)); | |||
gradb = (1 / m) * (X(:, 2:end)' * (hx - y)) + lambda * theta(2:end) / m; | |||
grad = [gradf;gradb]; | |||
% ============================================================= | |||
end |
@@ -1,135 +0,0 @@ | |||
%% Machine Learning Online Class - Exercise 2: Logistic Regression | |||
% | |||
% Instructions | |||
% ------------ | |||
% | |||
% This file contains code that helps you get started on the logistic | |||
% regression exercise. You will need to complete the following functions | |||
% in this exericse: | |||
% | |||
% sigmoid.m | |||
% costFunction.m | |||
% predict.m | |||
% costFunctionReg.m | |||
% | |||
% For this exercise, you will not need to change any code in this file, | |||
% or any other files other than those mentioned above. | |||
% | |||
%% Initialization | |||
clear ; close all; clc | |||
%% Load Data | |||
% The first two columns contains the exam scores and the third column | |||
% contains the label. | |||
data = load('ex2data1.txt'); | |||
X = data(:, [1, 2]); y = data(:, 3); | |||
%% ==================== Part 1: Plotting ==================== | |||
% We start the exercise by first plotting the data to understand the | |||
% the problem we are working with. | |||
fprintf(['Plotting data with + indicating (y = 1) examples and o ' ... | |||
'indicating (y = 0) examples.\n']); | |||
plotData(X, y); | |||
% Put some labels | |||
hold on; | |||
% Labels and Legend | |||
xlabel('Exam 1 score') | |||
ylabel('Exam 2 score') | |||
% Specified in plot order | |||
legend('Admitted', 'Not admitted') | |||
hold off; | |||
fprintf('\nProgram paused. Press enter to continue.\n'); | |||
pause; | |||
%% ============ Part 2: Compute Cost and Gradient ============ | |||
% In this part of the exercise, you will implement the cost and gradient | |||
% for logistic regression. You neeed to complete the code in | |||
% costFunction.m | |||
% Setup the data matrix appropriately, and add ones for the intercept term | |||
[m, n] = size(X); | |||
% Add intercept term to x and X_test | |||
X = [ones(m, 1) X]; | |||
% Initialize fitting parameters | |||
initial_theta = zeros(n + 1, 1); | |||
% Compute and display initial cost and gradient | |||
[cost, grad] = costFunction(initial_theta, X, y); | |||
fprintf('Cost at initial theta (zeros): %f\n', cost); | |||
fprintf('Gradient at initial theta (zeros): \n'); | |||
fprintf(' %f \n', grad); | |||
fprintf('\nProgram paused. Press enter to continue.\n'); | |||
pause; | |||
%% ============= Part 3: Optimizing using fminunc ============= | |||
% In this exercise, you will use a built-in function (fminunc) to find the | |||
% optimal parameters theta. | |||
% Set options for fminunc | |||
options = optimset('GradObj', 'on', 'MaxIter', 400); | |||
% Run fminunc to obtain the optimal theta | |||
% This function will return theta and the cost | |||
[theta, cost] = ... | |||
fminunc(@(t)(costFunction(t, X, y)), initial_theta, options); | |||
% Print theta to screen | |||
fprintf('Cost at theta found by fminunc: %f\n', cost); | |||
fprintf('theta: \n'); | |||
fprintf(' %f \n', theta); | |||
% Plot Boundary | |||
plotDecisionBoundary(theta, X, y); | |||
% Put some labels | |||
hold on; | |||
% Labels and Legend | |||
xlabel('Exam 1 score') | |||
ylabel('Exam 2 score') | |||
% Specified in plot order | |||
legend('Admitted', 'Not admitted') | |||
hold off; | |||
fprintf('\nProgram paused. Press enter to continue.\n'); | |||
pause; | |||
%% ============== Part 4: Predict and Accuracies ============== | |||
% After learning the parameters, you'll like to use it to predict the outcomes | |||
% on unseen data. In this part, you will use the logistic regression model | |||
% to predict the probability that a student with score 45 on exam 1 and | |||
% score 85 on exam 2 will be admitted. | |||
% | |||
% Furthermore, you will compute the training and test set accuracies of | |||
% our model. | |||
% | |||
% Your task is to complete the code in predict.m | |||
% Predict probability for a student with score 45 on exam 1 | |||
% and score 85 on exam 2 | |||
prob = sigmoid([1 45 85] * theta); | |||
fprintf(['For a student with scores 45 and 85, we predict an admission ' ... | |||
'probability of %f\n\n'], prob); | |||
% Compute accuracy on our training set | |||
p = predict(theta, X); | |||
fprintf('Train Accuracy: %f\n', mean(double(p == y)) * 100); | |||
fprintf('\nProgram paused. Press enter to continue.\n'); | |||
pause; | |||
@@ -1,116 +0,0 @@ | |||
%% Machine Learning Online Class - Exercise 2: Logistic Regression | |||
% | |||
% Instructions | |||
% ------------ | |||
% | |||
% This file contains code that helps you get started on the second part | |||
% of the exercise which covers regularization with logistic regression. | |||
% | |||
% You will need to complete the following functions in this exericse: | |||
% | |||
% sigmoid.m | |||
% costFunction.m | |||
% predict.m | |||
% costFunctionReg.m | |||
% | |||
% For this exercise, you will not need to change any code in this file, | |||
% or any other files other than those mentioned above. | |||
% | |||
%% Initialization | |||
clear ; close all; clc | |||
%% Load Data | |||
% The first two columns contains the X values and the third column | |||
% contains the label (y). | |||
data = load('ex2data2.txt'); | |||
X = data(:, [1, 2]); y = data(:, 3); | |||
plotData(X, y); | |||
% Put some labels | |||
hold on; | |||
% Labels and Legend | |||
xlabel('Microchip Test 1') | |||
ylabel('Microchip Test 2') | |||
% Specified in plot order | |||
legend('y = 1', 'y = 0') | |||
hold off; | |||
%% =========== Part 1: Regularized Logistic Regression ============ | |||
% In this part, you are given a dataset with data points that are not | |||
% linearly separable. However, you would still like to use logistic | |||
% regression to classify the data points. | |||
% | |||
% To do so, you introduce more features to use -- in particular, you add | |||
% polynomial features to our data matrix (similar to polynomial | |||
% regression). | |||
% | |||
% Add Polynomial Features | |||
% Note that mapFeature also adds a column of ones for us, so the intercept | |||
% term is handled | |||
X = mapFeature(X(:,1), X(:,2)); | |||
% Initialize fitting parameters | |||
initial_theta = zeros(size(X, 2), 1); | |||
% Set regularization parameter lambda to 1 | |||
lambda = 1; | |||
% Compute and display initial cost and gradient for regularized logistic | |||
% regression | |||
[cost, grad] = costFunctionReg(initial_theta, X, y, lambda); | |||
fprintf('Cost at initial theta (zeros): %f\n', cost); | |||
fprintf('\nProgram paused. Press enter to continue.\n'); | |||
pause; | |||
%% ============= Part 2: Regularization and Accuracies ============= | |||
% Optional Exercise: | |||
% In this part, you will get to try different values of lambda and | |||
% see how regularization affects the decision coundart | |||
% | |||
% Try the following values of lambda (0, 1, 10, 100). | |||
% | |||
% How does the decision boundary change when you vary lambda? How does | |||
% the training set accuracy vary? | |||
% | |||
% Initialize fitting parameters | |||
initial_theta = zeros(size(X, 2), 1); | |||
% Set regularization parameter lambda to 1 (you should vary this) | |||
lambda = 100; | |||
% Set Options | |||
options = optimset('GradObj', 'on', 'MaxIter', 400); | |||
% Optimize | |||
[theta, J, exit_flag] = ... | |||
fminunc(@(t)(costFunctionReg(t, X, y, 1)), initial_theta, options); | |||
% Plot Boundary | |||
plotDecisionBoundary(theta, X, y); | |||
hold on; | |||
title(sprintf('lambda = %g', lambda)) | |||
% Labels and Legend | |||
xlabel('Microchip Test 1') | |||
ylabel('Microchip Test 2') | |||
legend('y = 1', 'y = 0', 'Decision boundary') | |||
hold off; | |||
% Compute accuracy on our training set | |||
p = predict(theta, X); | |||
fprintf('Train Accuracy: %f\n', mean(double(p == y)) * 100); | |||
@@ -1,100 +0,0 @@ | |||
0,34.62365962,78.02469282 | |||
0,30.28671077,43.89499752 | |||
0,35.84740877,72.90219803 | |||
1,60.18259939,86.3085521 | |||
1,79.03273605,75.34437644 | |||
0,45.08327748,56.31637178 | |||
1,61.10666454,96.51142588 | |||
1,75.02474557,46.55401354 | |||
1,76.0987867,87.42056972 | |||
1,84.43281996,43.53339331 | |||
0,95.86155507,38.22527806 | |||
0,75.01365839,30.60326323 | |||
1,82.30705337,76.4819633 | |||
1,69.36458876,97.71869196 | |||
0,39.53833914,76.03681085 | |||
1,53.97105215,89.20735014 | |||
1,69.07014406,52.74046973 | |||
0,67.94685548,46.67857411 | |||
1,70.66150955,92.92713789 | |||
1,76.97878373,47.57596365 | |||
0,67.37202755,42.83843832 | |||
1,89.67677575,65.79936593 | |||
0,50.53478829,48.85581153 | |||
0,34.21206098,44.2095286 | |||
1,77.92409145,68.97235999 | |||
1,62.27101367,69.95445795 | |||
1,80.19018075,44.82162893 | |||
0,93.1143888,38.80067034 | |||
0,61.83020602,50.25610789 | |||
0,38.7858038,64.99568096 | |||
1,61.37928945,72.80788731 | |||
1,85.40451939,57.05198398 | |||
0,52.10797973,63.12762377 | |||
1,52.04540477,69.43286012 | |||
0,40.23689374,71.16774802 | |||
0,54.63510555,52.21388588 | |||
0,33.91550011,98.86943574 | |||
1,64.17698887,80.90806059 | |||
0,74.78925296,41.57341523 | |||
0,34.18364003,75.23772034 | |||
1,83.90239366,56.30804622 | |||
0,51.54772027,46.85629026 | |||
1,94.44336777,65.56892161 | |||
0,82.36875376,40.61825516 | |||
0,51.04775177,45.82270146 | |||
0,62.22267576,52.06099195 | |||
1,77.19303493,70.4582 | |||
1,97.77159928,86.72782233 | |||
1,62.0730638,96.76882412 | |||
1,91.5649745,88.69629255 | |||
1,79.94481794,74.16311935 | |||
1,99.27252693,60.999031 | |||
1,90.54671411,43.39060181 | |||
0,34.52451385,60.39634246 | |||
0,50.28649612,49.80453881 | |||
0,49.58667722,59.80895099 | |||
1,97.64563396,68.86157272 | |||
0,32.57720017,95.59854761 | |||
1,74.24869137,69.82457123 | |||
1,71.79646206,78.45356225 | |||
1,75.39561147,85.75993667 | |||
0,35.28611282,47.02051395 | |||
0,56.2538175,39.26147251 | |||
0,30.05882245,49.59297387 | |||
0,44.66826172,66.45008615 | |||
0,66.56089447,41.09209808 | |||
1,40.45755098,97.53518549 | |||
0,49.07256322,51.88321182 | |||
1,80.27957401,92.11606081 | |||
1,66.74671857,60.99139403 | |||
0,32.72283304,43.30717306 | |||
1,64.03932042,78.03168802 | |||
1,72.34649423,96.22759297 | |||
1,60.45788574,73.0949981 | |||
1,58.84095622,75.85844831 | |||
1,99.8278578,72.36925193 | |||
1,47.26426911,88.475865 | |||
1,50.4581598,75.80985953 | |||
0,60.45555629,42.50840944 | |||
0,82.22666158,42.71987854 | |||
1,88.91389642,69.8037889 | |||
1,94.83450672,45.6943068 | |||
1,67.31925747,66.58935318 | |||
1,57.23870632,59.51428198 | |||
1,80.366756,90.9601479 | |||
1,68.46852179,85.5943071 | |||
0,42.07545454,78.844786 | |||
1,75.47770201,90.424539 | |||
1,78.63542435,96.64742717 | |||
0,52.34800399,60.76950526 | |||
1,94.09433113,77.15910509 | |||
1,90.44855097,87.50879176 | |||
0,55.48216114,35.57070347 | |||
1,74.49269242,84.84513685 | |||
1,89.84580671,45.35828361 | |||
1,83.48916274,48.3802858 | |||
1,42.26170081,87.10385094 | |||
1,99.31500881,68.77540947 | |||
1,55.34001756,64.93193801 | |||
1,74.775893,89.5298129 |
@@ -1,100 +0,0 @@ | |||
34.62365962451697,78.0246928153624,0 | |||
30.28671076822607,43.89499752400101,0 | |||
35.84740876993872,72.90219802708364,0 | |||
60.18259938620976,86.30855209546826,1 | |||
79.0327360507101,75.3443764369103,1 | |||
45.08327747668339,56.3163717815305,0 | |||
61.10666453684766,96.51142588489624,1 | |||
75.02474556738889,46.55401354116538,1 | |||
76.09878670226257,87.42056971926803,1 | |||
84.43281996120035,43.53339331072109,1 | |||
95.86155507093572,38.22527805795094,0 | |||
75.01365838958247,30.60326323428011,0 | |||
82.30705337399482,76.48196330235604,1 | |||
69.36458875970939,97.71869196188608,1 | |||
39.53833914367223,76.03681085115882,0 | |||
53.9710521485623,89.20735013750205,1 | |||
69.07014406283025,52.74046973016765,1 | |||
67.94685547711617,46.67857410673128,0 | |||
70.66150955499435,92.92713789364831,1 | |||
76.97878372747498,47.57596364975532,1 | |||
67.37202754570876,42.83843832029179,0 | |||
89.67677575072079,65.79936592745237,1 | |||
50.534788289883,48.85581152764205,0 | |||
34.21206097786789,44.20952859866288,0 | |||
77.9240914545704,68.9723599933059,1 | |||
62.27101367004632,69.95445795447587,1 | |||
80.1901807509566,44.82162893218353,1 | |||
93.114388797442,38.80067033713209,0 | |||
61.83020602312595,50.25610789244621,0 | |||
38.78580379679423,64.99568095539578,0 | |||
61.379289447425,72.80788731317097,1 | |||
85.40451939411645,57.05198397627122,1 | |||
52.10797973193984,63.12762376881715,0 | |||
52.04540476831827,69.43286012045222,1 | |||
40.23689373545111,71.16774802184875,0 | |||
54.63510555424817,52.21388588061123,0 | |||
33.91550010906887,98.86943574220611,0 | |||
64.17698887494485,80.90806058670817,1 | |||
74.78925295941542,41.57341522824434,0 | |||
34.1836400264419,75.2377203360134,0 | |||
83.90239366249155,56.30804621605327,1 | |||
51.54772026906181,46.85629026349976,0 | |||
94.44336776917852,65.56892160559052,1 | |||
82.36875375713919,40.61825515970618,0 | |||
51.04775177128865,45.82270145776001,0 | |||
62.22267576120188,52.06099194836679,0 | |||
77.19303492601364,70.45820000180959,1 | |||
97.77159928000232,86.7278223300282,1 | |||
62.07306379667647,96.76882412413983,1 | |||
91.56497449807442,88.69629254546599,1 | |||
79.94481794066932,74.16311935043758,1 | |||
99.2725269292572,60.99903099844988,1 | |||
90.54671411399852,43.39060180650027,1 | |||
34.52451385320009,60.39634245837173,0 | |||
50.2864961189907,49.80453881323059,0 | |||
49.58667721632031,59.80895099453265,0 | |||
97.64563396007767,68.86157272420604,1 | |||
32.57720016809309,95.59854761387875,0 | |||
74.24869136721598,69.82457122657193,1 | |||
71.79646205863379,78.45356224515052,1 | |||
75.3956114656803,85.75993667331619,1 | |||
35.28611281526193,47.02051394723416,0 | |||
56.25381749711624,39.26147251058019,0 | |||
30.05882244669796,49.59297386723685,0 | |||
44.66826172480893,66.45008614558913,0 | |||
66.56089447242954,41.09209807936973,0 | |||
40.45755098375164,97.53518548909936,1 | |||
49.07256321908844,51.88321182073966,0 | |||
80.27957401466998,92.11606081344084,1 | |||
66.74671856944039,60.99139402740988,1 | |||
32.72283304060323,43.30717306430063,0 | |||
64.0393204150601,78.03168802018232,1 | |||
72.34649422579923,96.22759296761404,1 | |||
60.45788573918959,73.09499809758037,1 | |||
58.84095621726802,75.85844831279042,1 | |||
99.82785779692128,72.36925193383885,1 | |||
47.26426910848174,88.47586499559782,1 | |||
50.45815980285988,75.80985952982456,1 | |||
60.45555629271532,42.50840943572217,0 | |||
82.22666157785568,42.71987853716458,0 | |||
88.9138964166533,69.80378889835472,1 | |||
94.83450672430196,45.69430680250754,1 | |||
67.31925746917527,66.58935317747915,1 | |||
57.23870631569862,59.51428198012956,1 | |||
80.36675600171273,90.96014789746954,1 | |||
68.46852178591112,85.59430710452014,1 | |||
42.0754545384731,78.84478600148043,0 | |||
75.47770200533905,90.42453899753964,1 | |||
78.63542434898018,96.64742716885644,1 | |||
52.34800398794107,60.76950525602592,0 | |||
94.09433112516793,77.15910509073893,1 | |||
90.44855097096364,87.50879176484702,1 | |||
55.48216114069585,35.57070347228866,0 | |||
74.49269241843041,84.84513684930135,1 | |||
89.84580670720979,45.35828361091658,1 | |||
83.48916274498238,48.38028579728175,1 | |||
42.2617008099817,87.10385094025457,1 | |||
99.31500880510394,68.77540947206617,1 | |||
55.34001756003703,64.9319380069486,1 | |||
74.77589300092767,89.52981289513276,1 |
@@ -1,118 +0,0 @@ | |||
0.051267,0.69956,1 | |||
-0.092742,0.68494,1 | |||
-0.21371,0.69225,1 | |||
-0.375,0.50219,1 | |||
-0.51325,0.46564,1 | |||
-0.52477,0.2098,1 | |||
-0.39804,0.034357,1 | |||
-0.30588,-0.19225,1 | |||
0.016705,-0.40424,1 | |||
0.13191,-0.51389,1 | |||
0.38537,-0.56506,1 | |||
0.52938,-0.5212,1 | |||
0.63882,-0.24342,1 | |||
0.73675,-0.18494,1 | |||
0.54666,0.48757,1 | |||
0.322,0.5826,1 | |||
0.16647,0.53874,1 | |||
-0.046659,0.81652,1 | |||
-0.17339,0.69956,1 | |||
-0.47869,0.63377,1 | |||
-0.60541,0.59722,1 | |||
-0.62846,0.33406,1 | |||
-0.59389,0.005117,1 | |||
-0.42108,-0.27266,1 | |||
-0.11578,-0.39693,1 | |||
0.20104,-0.60161,1 | |||
0.46601,-0.53582,1 | |||
0.67339,-0.53582,1 | |||
-0.13882,0.54605,1 | |||
-0.29435,0.77997,1 | |||
-0.26555,0.96272,1 | |||
-0.16187,0.8019,1 | |||
-0.17339,0.64839,1 | |||
-0.28283,0.47295,1 | |||
-0.36348,0.31213,1 | |||
-0.30012,0.027047,1 | |||
-0.23675,-0.21418,1 | |||
-0.06394,-0.18494,1 | |||
0.062788,-0.16301,1 | |||
0.22984,-0.41155,1 | |||
0.2932,-0.2288,1 | |||
0.48329,-0.18494,1 | |||
0.64459,-0.14108,1 | |||
0.46025,0.012427,1 | |||
0.6273,0.15863,1 | |||
0.57546,0.26827,1 | |||
0.72523,0.44371,1 | |||
0.22408,0.52412,1 | |||
0.44297,0.67032,1 | |||
0.322,0.69225,1 | |||
0.13767,0.57529,1 | |||
-0.0063364,0.39985,1 | |||
-0.092742,0.55336,1 | |||
-0.20795,0.35599,1 | |||
-0.20795,0.17325,1 | |||
-0.43836,0.21711,1 | |||
-0.21947,-0.016813,1 | |||
-0.13882,-0.27266,1 | |||
0.18376,0.93348,0 | |||
0.22408,0.77997,0 | |||
0.29896,0.61915,0 | |||
0.50634,0.75804,0 | |||
0.61578,0.7288,0 | |||
0.60426,0.59722,0 | |||
0.76555,0.50219,0 | |||
0.92684,0.3633,0 | |||
0.82316,0.27558,0 | |||
0.96141,0.085526,0 | |||
0.93836,0.012427,0 | |||
0.86348,-0.082602,0 | |||
0.89804,-0.20687,0 | |||
0.85196,-0.36769,0 | |||
0.82892,-0.5212,0 | |||
0.79435,-0.55775,0 | |||
0.59274,-0.7405,0 | |||
0.51786,-0.5943,0 | |||
0.46601,-0.41886,0 | |||
0.35081,-0.57968,0 | |||
0.28744,-0.76974,0 | |||
0.085829,-0.75512,0 | |||
0.14919,-0.57968,0 | |||
-0.13306,-0.4481,0 | |||
-0.40956,-0.41155,0 | |||
-0.39228,-0.25804,0 | |||
-0.74366,-0.25804,0 | |||
-0.69758,0.041667,0 | |||
-0.75518,0.2902,0 | |||
-0.69758,0.68494,0 | |||
-0.4038,0.70687,0 | |||
-0.38076,0.91886,0 | |||
-0.50749,0.90424,0 | |||
-0.54781,0.70687,0 | |||
0.10311,0.77997,0 | |||
0.057028,0.91886,0 | |||
-0.10426,0.99196,0 | |||
-0.081221,1.1089,0 | |||
0.28744,1.087,0 | |||
0.39689,0.82383,0 | |||
0.63882,0.88962,0 | |||
0.82316,0.66301,0 | |||
0.67339,0.64108,0 | |||
1.0709,0.10015,0 | |||
-0.046659,-0.57968,0 | |||
-0.23675,-0.63816,0 | |||
-0.15035,-0.36769,0 | |||
-0.49021,-0.3019,0 | |||
-0.46717,-0.13377,0 | |||
-0.28859,-0.060673,0 | |||
-0.61118,-0.067982,0 | |||
-0.66302,-0.21418,0 | |||
-0.59965,-0.41886,0 | |||
-0.72638,-0.082602,0 | |||
-0.83007,0.31213,0 | |||
-0.72062,0.53874,0 | |||
-0.59389,0.49488,0 | |||
-0.48445,0.99927,0 | |||
-0.0063364,0.99927,0 | |||
0.63265,-0.030612,0 |
@@ -1,118 +0,0 @@ | |||
0.051267,0.69956,1 | |||
-0.092742,0.68494,1 | |||
-0.21371,0.69225,1 | |||
-0.375,0.50219,1 | |||
-0.51325,0.46564,1 | |||
-0.52477,0.2098,1 | |||
-0.39804,0.034357,1 | |||
-0.30588,-0.19225,1 | |||
0.016705,-0.40424,1 | |||
0.13191,-0.51389,1 | |||
0.38537,-0.56506,1 | |||
0.52938,-0.5212,1 | |||
0.63882,-0.24342,1 | |||
0.73675,-0.18494,1 | |||
0.54666,0.48757,1 | |||
0.322,0.5826,1 | |||
0.16647,0.53874,1 | |||
-0.046659,0.81652,1 | |||
-0.17339,0.69956,1 | |||
-0.47869,0.63377,1 | |||
-0.60541,0.59722,1 | |||
-0.62846,0.33406,1 | |||
-0.59389,0.005117,1 | |||
-0.42108,-0.27266,1 | |||
-0.11578,-0.39693,1 | |||
0.20104,-0.60161,1 | |||
0.46601,-0.53582,1 | |||
0.67339,-0.53582,1 | |||
-0.13882,0.54605,1 | |||
-0.29435,0.77997,1 | |||
-0.26555,0.96272,1 | |||
-0.16187,0.8019,1 | |||
-0.17339,0.64839,1 | |||
-0.28283,0.47295,1 | |||
-0.36348,0.31213,1 | |||
-0.30012,0.027047,1 | |||
-0.23675,-0.21418,1 | |||
-0.06394,-0.18494,1 | |||
0.062788,-0.16301,1 | |||
0.22984,-0.41155,1 | |||
0.2932,-0.2288,1 | |||
0.48329,-0.18494,1 | |||
0.64459,-0.14108,1 | |||
0.46025,0.012427,1 | |||
0.6273,0.15863,1 | |||
0.57546,0.26827,1 | |||
0.72523,0.44371,1 | |||
0.22408,0.52412,1 | |||
0.44297,0.67032,1 | |||
0.322,0.69225,1 | |||
0.13767,0.57529,1 | |||
-0.0063364,0.39985,1 | |||
-0.092742,0.55336,1 | |||
-0.20795,0.35599,1 | |||
-0.20795,0.17325,1 | |||
-0.43836,0.21711,1 | |||
-0.21947,-0.016813,1 | |||
-0.13882,-0.27266,1 | |||
0.18376,0.93348,0 | |||
0.22408,0.77997,0 | |||
0.29896,0.61915,0 | |||
0.50634,0.75804,0 | |||
0.61578,0.7288,0 | |||
0.60426,0.59722,0 | |||
0.76555,0.50219,0 | |||
0.92684,0.3633,0 | |||
0.82316,0.27558,0 | |||
0.96141,0.085526,0 | |||
0.93836,0.012427,0 | |||
0.86348,-0.082602,0 | |||
0.89804,-0.20687,0 | |||
0.85196,-0.36769,0 | |||
0.82892,-0.5212,0 | |||
0.79435,-0.55775,0 | |||
0.59274,-0.7405,0 | |||
0.51786,-0.5943,0 | |||
0.46601,-0.41886,0 | |||
0.35081,-0.57968,0 | |||
0.28744,-0.76974,0 | |||
0.085829,-0.75512,0 | |||
0.14919,-0.57968,0 | |||
-0.13306,-0.4481,0 | |||
-0.40956,-0.41155,0 | |||
-0.39228,-0.25804,0 | |||
-0.74366,-0.25804,0 | |||
-0.69758,0.041667,0 | |||
-0.75518,0.2902,0 | |||
-0.69758,0.68494,0 | |||
-0.4038,0.70687,0 | |||
-0.38076,0.91886,0 | |||
-0.50749,0.90424,0 | |||
-0.54781,0.70687,0 | |||
0.10311,0.77997,0 | |||
0.057028,0.91886,0 | |||
-0.10426,0.99196,0 | |||
-0.081221,1.1089,0 | |||
0.28744,1.087,0 | |||
0.39689,0.82383,0 | |||
0.63882,0.88962,0 | |||
0.82316,0.66301,0 | |||
0.67339,0.64108,0 | |||
1.0709,0.10015,0 | |||
-0.046659,-0.57968,0 | |||
-0.23675,-0.63816,0 | |||
-0.15035,-0.36769,0 | |||
-0.49021,-0.3019,0 | |||
-0.46717,-0.13377,0 | |||
-0.28859,-0.060673,0 | |||
-0.61118,-0.067982,0 | |||
-0.66302,-0.21418,0 | |||
-0.59965,-0.41886,0 | |||
-0.72638,-0.082602,0 | |||
-0.83007,0.31213,0 | |||
-0.72062,0.53874,0 | |||
-0.59389,0.49488,0 | |||
-0.48445,0.99927,0 | |||
-0.0063364,0.99927,0 | |||
0.63265,-0.030612,0 |
@@ -1,5 +0,0 @@ | |||
0,98.83450677,10.6943068 | |||
1,65.31925747,65.58935318 | |||
0,70.23870632,48.51428198 | |||
1,80.366756,70.9601479 | |||
0,60.46852179,60.5943071 |
@@ -1,5 +0,0 @@ | |||
98.83450676630196,10.69430680250754,0 | |||
65.31925746917527,65.58935317747915,1 | |||
70.23870631569862,48.51428198012956,0 | |||
80.36675600171273,70.96014789746954,1 | |||
60.46852178591112,60.59430710452014,0 |
@@ -1,41 +0,0 @@ | |||
The author of "jsonlab" toolbox is Qianqian Fang. Qianqian | |||
is currently an Assistant Professor at Massachusetts General Hospital, | |||
Harvard Medical School. | |||
Address: Martinos Center for Biomedical Imaging, | |||
Massachusetts General Hospital, | |||
Harvard Medical School | |||
Bldg 149, 13th St, Charlestown, MA 02129, USA | |||
URL: http://nmr.mgh.harvard.edu/~fangq/ | |||
Email: <fangq at nmr.mgh.harvard.edu> or <fangqq at gmail.com> | |||
The script loadjson.m was built upon previous works by | |||
- Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713 | |||
date: 2009/11/02 | |||
- François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393 | |||
date: 2009/03/22 | |||
- Joel Feenstra: http://www.mathworks.com/matlabcentral/fileexchange/20565 | |||
date: 2008/07/03 | |||
This toolbox contains patches submitted by the following contributors: | |||
- Blake Johnson <bjohnso at bbn.com> | |||
part of revision 341 | |||
- Niclas Borlin <Niclas.Borlin at cs.umu.se> | |||
various fixes in revision 394, including | |||
- loadjson crashes for all-zero sparse matrix. | |||
- loadjson crashes for empty sparse matrix. | |||
- Non-zero size of 0-by-N and N-by-0 empty matrices is lost after savejson/loadjson. | |||
- loadjson crashes for sparse real column vector. | |||
- loadjson crashes for sparse complex column vector. | |||
- Data is corrupted by savejson for sparse real row vector. | |||
- savejson crashes for sparse complex row vector. | |||
- Yul Kang <yul.kang.on at gmail.com> | |||
patches for svn revision 415. | |||
- savejson saves an empty cell array as [] instead of null | |||
- loadjson differentiates an empty struct from an empty array |
@@ -1,74 +0,0 @@ | |||
============================================================================ | |||
JSONlab - a toolbox to encode/decode JSON/UBJSON files in MATLAB/Octave | |||
---------------------------------------------------------------------------- | |||
JSONlab ChangeLog (key features marked by *): | |||
== JSONlab 1.0 (codename: Optimus - Final), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2015/01/02 polish help info for all major functions, update examples, finalize 1.0 | |||
2014/12/19 fix a bug to strictly respect NoRowBracket in savejson | |||
== JSONlab 1.0.0-RC2 (codename: Optimus - RC2), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2014/11/22 show progress bar in loadjson ('ShowProgress') | |||
2014/11/17 add Compact option in savejson to output compact JSON format ('Compact') | |||
2014/11/17 add FastArrayParser in loadjson to specify fast parser applicable levels | |||
2014/09/18 start official github mirror: https://github.com/fangq/jsonlab | |||
== JSONlab 1.0.0-RC1 (codename: Optimus - RC1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2014/09/17 fix several compatibility issues when running on octave versions 3.2-3.8 | |||
2014/09/17 support 2D cell and struct arrays in both savejson and saveubjson | |||
2014/08/04 escape special characters in a JSON string | |||
2014/02/16 fix a bug when saving ubjson files | |||
== JSONlab 0.9.9 (codename: Optimus - beta), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2014/01/22 use binary read and write in saveubjson and loadubjson | |||
== JSONlab 0.9.8-1 (codename: Optimus - alpha update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2013/10/07 better round-trip conservation for empty arrays and structs (patch submitted by Yul Kang) | |||
== JSONlab 0.9.8 (codename: Optimus - alpha), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2013/08/23 *universal Binary JSON (UBJSON) support, including both saveubjson and loadubjson | |||
== JSONlab 0.9.1 (codename: Rodimus, update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/12/18 *handling of various empty and sparse matrices (fixes submitted by Niclas Borlin) | |||
== JSONlab 0.9.0 (codename: Rodimus), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/06/17 *new format for an invalid leading char, unpacking hex code in savejson | |||
2012/06/01 support JSONP in savejson | |||
2012/05/25 fix the empty cell bug (reported by Cyril Davin) | |||
2012/04/05 savejson can save to a file (suggested by Patrick Rapin) | |||
== JSONlab 0.8.1 (codename: Sentiel, Update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/02/28 loadjson quotation mark escape bug, see http://bit.ly/yyk1nS | |||
2012/01/25 patch to handle root-less objects, contributed by Blake Johnson | |||
== JSONlab 0.8.0 (codename: Sentiel), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/01/13 *speed up loadjson by 20 fold when parsing large data arrays in matlab | |||
2012/01/11 remove row bracket if an array has 1 element, suggested by Mykel Kochenderfer | |||
2011/12/22 *accept sequence of 'param',value input in savejson and loadjson | |||
2011/11/18 fix struct array bug reported by Mykel Kochenderfer | |||
== JSONlab 0.5.1 (codename: Nexus Update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2011/10/21 fix a bug in loadjson, previous code does not use any of the acceleration | |||
2011/10/20 loadjson supports JSON collections - concatenated JSON objects | |||
== JSONlab 0.5.0 (codename: Nexus), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2011/10/16 package and release jsonlab 0.5.0 | |||
2011/10/15 *add json demo and regression test, support cpx numbers, fix double quote bug | |||
2011/10/11 *speed up readjson dramatically, interpret _Array* tags, show data in root level | |||
2011/10/10 create jsonlab project, start jsonlab website, add online documentation | |||
2011/10/07 *speed up savejson by 25x using sprintf instead of mat2str, add options support | |||
2011/10/06 *savejson works for structs, cells and arrays | |||
2011/09/09 derive loadjson from JSON parser from MATLAB Central, draft savejson.m |
@@ -1,25 +0,0 @@ | |||
Copyright 2011-2015 Qianqian Fang <fangq at nmr.mgh.harvard.edu>. All rights reserved. | |||
Redistribution and use in source and binary forms, with or without modification, are | |||
permitted provided that the following conditions are met: | |||
1. Redistributions of source code must retain the above copyright notice, this list of | |||
conditions and the following disclaimer. | |||
2. Redistributions in binary form must reproduce the above copyright notice, this list | |||
of conditions and the following disclaimer in the documentation and/or other materials | |||
provided with the distribution. | |||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED | |||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS | |||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
The views and conclusions contained in the software and documentation are those of the | |||
authors and should not be interpreted as representing official policies, either expressed | |||
or implied, of the copyright holders. |
@@ -1,394 +0,0 @@ | |||
=============================================================================== | |||
= JSONLab = | |||
= An open-source MATLAB/Octave JSON encoder and decoder = | |||
=============================================================================== | |||
*Copyright (C) 2011-2015 Qianqian Fang <fangq at nmr.mgh.harvard.edu> | |||
*License: BSD License, see License_BSD.txt for details | |||
*Version: 1.0 (Optimus - Final) | |||
------------------------------------------------------------------------------- | |||
Table of Content: | |||
I. Introduction | |||
II. Installation | |||
III.Using JSONLab | |||
IV. Known Issues and TODOs | |||
V. Contribution and feedback | |||
------------------------------------------------------------------------------- | |||
I. Introduction | |||
JSON ([http://www.json.org/ JavaScript Object Notation]) is a highly portable, | |||
human-readable and "[http://en.wikipedia.org/wiki/JSON fat-free]" text format | |||
to represent complex and hierarchical data. It is as powerful as | |||
[http://en.wikipedia.org/wiki/XML XML], but less verbose. JSON format is widely | |||
used for data-exchange in applications, and is essential for the wild success | |||
of [http://en.wikipedia.org/wiki/Ajax_(programming) Ajax] and | |||
[http://en.wikipedia.org/wiki/Web_2.0 Web2.0]. | |||
UBJSON (Universal Binary JSON) is a binary JSON format, specifically | |||
optimized for compact file size and better performance while keeping | |||
the semantics as simple as the text-based JSON format. Using the UBJSON | |||
format allows to wrap complex binary data in a flexible and extensible | |||
structure, making it possible to process complex and large dataset | |||
without accuracy loss due to text conversions. | |||
We envision that both JSON and its binary version will serve as part of | |||
the mainstream data-exchange formats for scientific research in the future. | |||
It will provide the flexibility and generality achieved by other popular | |||
general-purpose file specifications, such as | |||
[http://www.hdfgroup.org/HDF5/whatishdf5.html HDF5], with significantly | |||
reduced complexity and enhanced performance. | |||
JSONLab is a free and open-source implementation of a JSON/UBJSON encoder | |||
and a decoder in the native MATLAB language. It can be used to convert a MATLAB | |||
data structure (array, struct, cell, struct array and cell array) into | |||
JSON/UBJSON formatted strings, or to decode a JSON/UBJSON file into MATLAB | |||
data structure. JSONLab supports both MATLAB and | |||
[http://www.gnu.org/software/octave/ GNU Octave] (a free MATLAB clone). | |||
------------------------------------------------------------------------------- | |||
II. Installation | |||
The installation of JSONLab is no different than any other simple | |||
MATLAB toolbox. You only need to download/unzip the JSONLab package | |||
to a folder, and add the folder's path to MATLAB/Octave's path list | |||
by using the following command: | |||
addpath('/path/to/jsonlab'); | |||
If you want to add this path permanently, you need to type "pathtool", | |||
browse to the jsonlab root folder and add to the list, then click "Save". | |||
Then, run "rehash" in MATLAB, and type "which loadjson", if you see an | |||
output, that means JSONLab is installed for MATLAB/Octave. | |||
------------------------------------------------------------------------------- | |||
III.Using JSONLab | |||
JSONLab provides two functions, loadjson.m -- a MATLAB->JSON decoder, | |||
and savejson.m -- a MATLAB->JSON encoder, for the text-based JSON, and | |||
two equivallent functions -- loadubjson and saveubjson for the binary | |||
JSON. The detailed help info for the four functions can be found below: | |||
=== loadjson.m === | |||
<pre> | |||
data=loadjson(fname,opt) | |||
or | |||
data=loadjson(fname,'param1',value1,'param2',value2,...) | |||
parse a JSON (JavaScript Object Notation) file or string | |||
authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2011/09/09, including previous works from | |||
Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713 | |||
created on 2009/11/02 | |||
François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393 | |||
created on 2009/03/22 | |||
Joel Feenstra: | |||
http://www.mathworks.com/matlabcentral/fileexchange/20565 | |||
created on 2008/07/03 | |||
$Id: loadjson.m 452 2014-11-22 16:43:33Z fangq $ | |||
input: | |||
fname: input file name, if fname contains "{}" or "[]", fname | |||
will be interpreted as a JSON string | |||
opt: a struct to store parsing options, opt can be replaced by | |||
a list of ('param',value) pairs - the param string is equivallent | |||
to a field in opt. opt can have the following | |||
fields (first in [.|.] is the default) | |||
opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat | |||
for each element of the JSON data, and group | |||
arrays based on the cell2mat rules. | |||
opt.FastArrayParser [1|0 or integer]: if set to 1, use a | |||
speed-optimized array parser when loading an | |||
array object. The fast array parser may | |||
collapse block arrays into a single large | |||
array similar to rules defined in cell2mat; 0 to | |||
use a legacy parser; if set to a larger-than-1 | |||
value, this option will specify the minimum | |||
dimension to enable the fast array parser. For | |||
example, if the input is a 3D array, setting | |||
FastArrayParser to 1 will return a 3D array; | |||
setting to 2 will return a cell array of 2D | |||
arrays; setting to 3 will return to a 2D cell | |||
array of 1D vectors; setting to 4 will return a | |||
3D cell array. | |||
opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar. | |||
output: | |||
dat: a cell array, where {...} blocks are converted into cell arrays, | |||
and [...] are converted to arrays | |||
examples: | |||
dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}') | |||
dat=loadjson(['examples' filesep 'example1.json']) | |||
dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1) | |||
</pre> | |||
=== savejson.m === | |||
<pre> | |||
json=savejson(rootname,obj,filename) | |||
or | |||
json=savejson(rootname,obj,opt) | |||
json=savejson(rootname,obj,'param1',value1,'param2',value2,...) | |||
convert a MATLAB object (cell, struct or array) into a JSON (JavaScript | |||
Object Notation) string | |||
author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2011/09/09 | |||
$Id: savejson.m 458 2014-12-19 22:17:17Z fangq $ | |||
input: | |||
rootname: the name of the root-object, when set to '', the root name | |||
is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
the MATLAB variable name will be used as the root name. | |||
obj: a MATLAB object (array, cell, cell array, struct, struct array). | |||
filename: a string for the file name to save the output JSON data. | |||
opt: a struct for additional options, ignore to use default values. | |||
opt can have the following fields (first in [.|.] is the default) | |||
opt.FileName [''|string]: a file name to save the output JSON data | |||
opt.FloatFormat ['%.10g'|string]: format to show each numeric element | |||
of a 1D/2D array; | |||
opt.ArrayIndent [1|0]: if 1, output explicit data array with | |||
precedent indentation; if 0, no indentation | |||
opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D | |||
array in JSON array format; if sets to 1, an | |||
array will be shown as a struct with fields | |||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
sparse arrays, the non-zero elements will be | |||
saved to _ArrayData_ field in triplet-format i.e. | |||
(ix,iy,val) and "_ArrayIsSparse_" will be added | |||
with a value of 1; for a complex array, the | |||
_ArrayData_ array will include two columns | |||
(4 for sparse) to record the real and imaginary | |||
parts, and also "_ArrayIsComplex_":1 is added. | |||
opt.ParseLogical [0|1]: if this is set to 1, logical array elem | |||
will use true/false rather than 1/0. | |||
opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
numerical element will be shown without a square | |||
bracket, unless it is the root object; if 0, square | |||
brackets are forced for any numerical arrays. | |||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson | |||
will use the name of the passed obj variable as the | |||
root object name; if obj is an expression and | |||
does not have a name, 'root' will be used; if this | |||
is set to 0 and rootname is empty, the root level | |||
will be merged down to the lower level. | |||
opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern | |||
to represent +/-Inf. The matched pattern is '([-+]*)Inf' | |||
and $1 represents the sign. For those who want to use | |||
1e999 to represent Inf, they can set opt.Inf to '$11e999' | |||
opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern | |||
to represent NaN | |||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
for example, if opt.JSONP='foo', the JSON data is | |||
wrapped inside a function call as 'foo(...);' | |||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
back to the string form | |||
opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode. | |||
opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs) | |||
opt can be replaced by a list of ('param',value) pairs. The param | |||
string is equivallent to a field in opt and is case sensitive. | |||
output: | |||
json: a string in the JSON format (see http://json.org) | |||
examples: | |||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
'SpecialData',[nan, inf, -inf]); | |||
savejson('jmesh',jsonmesh) | |||
savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g') | |||
</pre> | |||
=== loadubjson.m === | |||
<pre> | |||
data=loadubjson(fname,opt) | |||
or | |||
data=loadubjson(fname,'param1',value1,'param2',value2,...) | |||
parse a JSON (JavaScript Object Notation) file or string | |||
authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2013/08/01 | |||
$Id: loadubjson.m 436 2014-08-05 20:51:40Z fangq $ | |||
input: | |||
fname: input file name, if fname contains "{}" or "[]", fname | |||
will be interpreted as a UBJSON string | |||
opt: a struct to store parsing options, opt can be replaced by | |||
a list of ('param',value) pairs - the param string is equivallent | |||
to a field in opt. opt can have the following | |||
fields (first in [.|.] is the default) | |||
opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat | |||
for each element of the JSON data, and group | |||
arrays based on the cell2mat rules. | |||
opt.IntEndian [B|L]: specify the endianness of the integer fields | |||
in the UBJSON input data. B - Big-Endian format for | |||
integers (as required in the UBJSON specification); | |||
L - input integer fields are in Little-Endian order. | |||
output: | |||
dat: a cell array, where {...} blocks are converted into cell arrays, | |||
and [...] are converted to arrays | |||
examples: | |||
obj=struct('string','value','array',[1 2 3]); | |||
ubjdata=saveubjson('obj',obj); | |||
dat=loadubjson(ubjdata) | |||
dat=loadubjson(['examples' filesep 'example1.ubj']) | |||
dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1) | |||
</pre> | |||
=== saveubjson.m === | |||
<pre> | |||
json=saveubjson(rootname,obj,filename) | |||
or | |||
json=saveubjson(rootname,obj,opt) | |||
json=saveubjson(rootname,obj,'param1',value1,'param2',value2,...) | |||
convert a MATLAB object (cell, struct or array) into a Universal | |||
Binary JSON (UBJSON) binary string | |||
author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2013/08/17 | |||
$Id: saveubjson.m 440 2014-09-17 19:59:45Z fangq $ | |||
input: | |||
rootname: the name of the root-object, when set to '', the root name | |||
is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
the MATLAB variable name will be used as the root name. | |||
obj: a MATLAB object (array, cell, cell array, struct, struct array) | |||
filename: a string for the file name to save the output UBJSON data | |||
opt: a struct for additional options, ignore to use default values. | |||
opt can have the following fields (first in [.|.] is the default) | |||
opt.FileName [''|string]: a file name to save the output JSON data | |||
opt.ArrayToStruct[0|1]: when set to 0, saveubjson outputs 1D/2D | |||
array in JSON array format; if sets to 1, an | |||
array will be shown as a struct with fields | |||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
sparse arrays, the non-zero elements will be | |||
saved to _ArrayData_ field in triplet-format i.e. | |||
(ix,iy,val) and "_ArrayIsSparse_" will be added | |||
with a value of 1; for a complex array, the | |||
_ArrayData_ array will include two columns | |||
(4 for sparse) to record the real and imaginary | |||
parts, and also "_ArrayIsComplex_":1 is added. | |||
opt.ParseLogical [1|0]: if this is set to 1, logical array elem | |||
will use true/false rather than 1/0. | |||
opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
numerical element will be shown without a square | |||
bracket, unless it is the root object; if 0, square | |||
brackets are forced for any numerical arrays. | |||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, saveubjson | |||
will use the name of the passed obj variable as the | |||
root object name; if obj is an expression and | |||
does not have a name, 'root' will be used; if this | |||
is set to 0 and rootname is empty, the root level | |||
will be merged down to the lower level. | |||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
for example, if opt.JSON='foo', the JSON data is | |||
wrapped inside a function call as 'foo(...);' | |||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
back to the string form | |||
opt can be replaced by a list of ('param',value) pairs. The param | |||
string is equivallent to a field in opt and is case sensitive. | |||
output: | |||
json: a binary string in the UBJSON format (see http://ubjson.org) | |||
examples: | |||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
'SpecialData',[nan, inf, -inf]); | |||
saveubjson('jsonmesh',jsonmesh) | |||
saveubjson('jsonmesh',jsonmesh,'meshdata.ubj') | |||
</pre> | |||
=== examples === | |||
Under the "examples" folder, you can find several scripts to demonstrate the | |||
basic utilities of JSONLab. Running the "demo_jsonlab_basic.m" script, you | |||
will see the conversions from MATLAB data structure to JSON text and backward. | |||
In "jsonlab_selftest.m", we load complex JSON files downloaded from the Internet | |||
and validate the loadjson/savejson functions for regression testing purposes. | |||
Similarly, a "demo_ubjson_basic.m" script is provided to test the saveubjson | |||
and loadubjson pairs for various matlab data structures. | |||
Please run these examples and understand how JSONLab works before you use | |||
it to process your data. | |||
------------------------------------------------------------------------------- | |||
IV. Known Issues and TODOs | |||
JSONLab has several known limitations. We are striving to make it more general | |||
and robust. Hopefully in a few future releases, the limitations become less. | |||
Here are the known issues: | |||
# 3D or higher dimensional cell/struct-arrays will be converted to 2D arrays; | |||
# When processing names containing multi-byte characters, Octave and MATLAB \ | |||
can give different field-names; you can use feature('DefaultCharacterSet','latin1') \ | |||
in MATLAB to get consistant results | |||
# savejson can not handle class and dataset. | |||
# saveubjson converts a logical array into a uint8 ([U]) array | |||
# an unofficial N-D array count syntax is implemented in saveubjson. We are \ | |||
actively communicating with the UBJSON spec maintainer to investigate the \ | |||
possibility of making it upstream | |||
# loadubjson can not parse all UBJSON Specification (Draft 9) compliant \ | |||
files, however, it can parse all UBJSON files produced by saveubjson. | |||
------------------------------------------------------------------------------- | |||
V. Contribution and feedback | |||
JSONLab is an open-source project. This means you can not only use it and modify | |||
it as you wish, but also you can contribute your changes back to JSONLab so | |||
that everyone else can enjoy the improvement. For anyone who want to contribute, | |||
please download JSONLab source code from it's subversion repository by using the | |||
following command: | |||
svn checkout svn://svn.code.sf.net/p/iso2mesh/code/trunk/jsonlab jsonlab | |||
You can make changes to the files as needed. Once you are satisfied with your | |||
changes, and ready to share it with others, please cd the root directory of | |||
JSONLab, and type | |||
svn diff > yourname_featurename.patch | |||
You then email the .patch file to JSONLab's maintainer, Qianqian Fang, at | |||
the email address shown in the beginning of this file. Qianqian will review | |||
the changes and commit it to the subversion if they are satisfactory. | |||
We appreciate any suggestions and feedbacks from you. Please use iso2mesh's | |||
mailing list to report any questions you may have with JSONLab: | |||
http://groups.google.com/group/iso2mesh-users?hl=en&pli=1 | |||
(Subscription to the mailing list is needed in order to post messages). |
@@ -1,32 +0,0 @@ | |||
function val=jsonopt(key,default,varargin) | |||
% | |||
% val=jsonopt(key,default,optstruct) | |||
% | |||
% setting options based on a struct. The struct can be produced | |||
% by varargin2struct from a list of 'param','value' pairs | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% | |||
% $Id: loadjson.m 371 2012-06-20 12:43:06Z fangq $ | |||
% | |||
% input: | |||
% key: a string with which one look up a value from a struct | |||
% default: if the key does not exist, return default | |||
% optstruct: a struct where each sub-field is a key | |||
% | |||
% output: | |||
% val: if key exists, val=optstruct.key; otherwise val=default | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
val=default; | |||
if(nargin<=2) return; end | |||
opt=varargin{1}; | |||
if(isstruct(opt) && isfield(opt,key)) | |||
val=getfield(opt,key); | |||
end | |||
@@ -1,566 +0,0 @@ | |||
function data = loadjson(fname,varargin) | |||
% | |||
% data=loadjson(fname,opt) | |||
% or | |||
% data=loadjson(fname,'param1',value1,'param2',value2,...) | |||
% | |||
% parse a JSON (JavaScript Object Notation) file or string | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2011/09/09, including previous works from | |||
% | |||
% Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713 | |||
% created on 2009/11/02 | |||
% François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393 | |||
% created on 2009/03/22 | |||
% Joel Feenstra: | |||
% http://www.mathworks.com/matlabcentral/fileexchange/20565 | |||
% created on 2008/07/03 | |||
% | |||
% $Id: loadjson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% fname: input file name, if fname contains "{}" or "[]", fname | |||
% will be interpreted as a JSON string | |||
% opt: a struct to store parsing options, opt can be replaced by | |||
% a list of ('param',value) pairs - the param string is equivallent | |||
% to a field in opt. opt can have the following | |||
% fields (first in [.|.] is the default) | |||
% | |||
% opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat | |||
% for each element of the JSON data, and group | |||
% arrays based on the cell2mat rules. | |||
% opt.FastArrayParser [1|0 or integer]: if set to 1, use a | |||
% speed-optimized array parser when loading an | |||
% array object. The fast array parser may | |||
% collapse block arrays into a single large | |||
% array similar to rules defined in cell2mat; 0 to | |||
% use a legacy parser; if set to a larger-than-1 | |||
% value, this option will specify the minimum | |||
% dimension to enable the fast array parser. For | |||
% example, if the input is a 3D array, setting | |||
% FastArrayParser to 1 will return a 3D array; | |||
% setting to 2 will return a cell array of 2D | |||
% arrays; setting to 3 will return to a 2D cell | |||
% array of 1D vectors; setting to 4 will return a | |||
% 3D cell array. | |||
% opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar. | |||
% | |||
% output: | |||
% dat: a cell array, where {...} blocks are converted into cell arrays, | |||
% and [...] are converted to arrays | |||
% | |||
% examples: | |||
% dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}') | |||
% dat=loadjson(['examples' filesep 'example1.json']) | |||
% dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1) | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
global pos inStr len esc index_esc len_esc isoct arraytoken | |||
if(regexp(fname,'[\{\}\]\[]','once')) | |||
string=fname; | |||
elseif(exist(fname,'file')) | |||
fid = fopen(fname,'rb'); | |||
string = fread(fid,inf,'uint8=>char')'; | |||
fclose(fid); | |||
else | |||
error('input file does not exist'); | |||
end | |||
pos = 1; len = length(string); inStr = string; | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"'); | |||
jstr=regexprep(inStr,'\\\\',' '); | |||
escquote=regexp(jstr,'\\"'); | |||
arraytoken=sort([arraytoken escquote]); | |||
% String delimiters and escape chars identified to improve speed: | |||
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]'); | |||
index_esc = 1; len_esc = length(esc); | |||
opt=varargin2struct(varargin{:}); | |||
if(jsonopt('ShowProgress',0,opt)==1) | |||
opt.progressbar_=waitbar(0,'loading ...'); | |||
end | |||
jsoncount=1; | |||
while pos <= len | |||
switch(next_char) | |||
case '{' | |||
data{jsoncount} = parse_object(opt); | |||
case '[' | |||
data{jsoncount} = parse_array(opt); | |||
otherwise | |||
error_pos('Outer level structure must be an object or an array'); | |||
end | |||
jsoncount=jsoncount+1; | |||
end % while | |||
jsoncount=length(data); | |||
if(jsoncount==1 && iscell(data)) | |||
data=data{1}; | |||
end | |||
if(~isempty(data)) | |||
if(isstruct(data)) % data can be a struct array | |||
data=jstruct2array(data); | |||
elseif(iscell(data)) | |||
data=jcell2array(data); | |||
end | |||
end | |||
if(isfield(opt,'progressbar_')) | |||
close(opt.progressbar_); | |||
end | |||
%% | |||
function newdata=jcell2array(data) | |||
len=length(data); | |||
newdata=data; | |||
for i=1:len | |||
if(isstruct(data{i})) | |||
newdata{i}=jstruct2array(data{i}); | |||
elseif(iscell(data{i})) | |||
newdata{i}=jcell2array(data{i}); | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newdata=jstruct2array(data) | |||
fn=fieldnames(data); | |||
newdata=data; | |||
len=length(data); | |||
for i=1:length(fn) % depth-first | |||
for j=1:len | |||
if(isstruct(getfield(data(j),fn{i}))) | |||
newdata(j)=setfield(newdata(j),fn{i},jstruct2array(getfield(data(j),fn{i}))); | |||
end | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayData_',fn))) | |||
newdata=cell(len,1); | |||
for j=1:len | |||
ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_); | |||
iscpx=0; | |||
if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn))) | |||
if(data(j).x0x5F_ArrayIsComplex_) | |||
iscpx=1; | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn))) | |||
if(data(j).x0x5F_ArrayIsSparse_) | |||
if(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
dim=data(j).x0x5F_ArraySize_; | |||
if(iscpx && size(ndata,2)==4-any(dim==1)) | |||
ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end)); | |||
end | |||
if isempty(ndata) | |||
% All-zeros sparse | |||
ndata=sparse(dim(1),prod(dim(2:end))); | |||
elseif dim(1)==1 | |||
% Sparse row vector | |||
ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end))); | |||
elseif dim(2)==1 | |||
% Sparse column vector | |||
ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end))); | |||
else | |||
% Generic sparse array. | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end))); | |||
end | |||
else | |||
if(iscpx && size(ndata,2)==4) | |||
ndata(:,3)=complex(ndata(:,3),ndata(:,4)); | |||
end | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3)); | |||
end | |||
end | |||
elseif(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
if(iscpx && size(ndata,2)==2) | |||
ndata=complex(ndata(:,1),ndata(:,2)); | |||
end | |||
ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_); | |||
end | |||
newdata{j}=ndata; | |||
end | |||
if(len==1) | |||
newdata=newdata{1}; | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function object = parse_object(varargin) | |||
parse_char('{'); | |||
object = []; | |||
if next_char ~= '}' | |||
while 1 | |||
str = parseStr(varargin{:}); | |||
if isempty(str) | |||
error_pos('Name of value at position %d cannot be empty'); | |||
end | |||
parse_char(':'); | |||
val = parse_value(varargin{:}); | |||
eval( sprintf( 'object.%s = val;', valid_field(str) ) ); | |||
if next_char == '}' | |||
break; | |||
end | |||
parse_char(','); | |||
end | |||
end | |||
parse_char('}'); | |||
%%------------------------------------------------------------------------- | |||
function object = parse_array(varargin) % JSON array is written in row-major order | |||
global pos inStr isoct | |||
parse_char('['); | |||
object = cell(0, 1); | |||
dim2=[]; | |||
arraydepth=jsonopt('JSONLAB_ArrayDepth_',1,varargin{:}); | |||
pbar=jsonopt('progressbar_',-1,varargin{:}); | |||
if next_char ~= ']' | |||
if(jsonopt('FastArrayParser',1,varargin{:})>=1 && arraydepth>=jsonopt('FastArrayParser',1,varargin{:})) | |||
[endpos, e1l, e1r, maxlevel]=matching_bracket(inStr,pos); | |||
arraystr=['[' inStr(pos:endpos)]; | |||
arraystr=regexprep(arraystr,'"_NaN_"','NaN'); | |||
arraystr=regexprep(arraystr,'"([-+]*)_Inf_"','$1Inf'); | |||
arraystr(arraystr==sprintf('\n'))=[]; | |||
arraystr(arraystr==sprintf('\r'))=[]; | |||
%arraystr=regexprep(arraystr,'\s*,',','); % this is slow,sometimes needed | |||
if(~isempty(e1l) && ~isempty(e1r)) % the array is in 2D or higher D | |||
astr=inStr((e1l+1):(e1r-1)); | |||
astr=regexprep(astr,'"_NaN_"','NaN'); | |||
astr=regexprep(astr,'"([-+]*)_Inf_"','$1Inf'); | |||
astr(astr==sprintf('\n'))=[]; | |||
astr(astr==sprintf('\r'))=[]; | |||
astr(astr==' ')=''; | |||
if(isempty(find(astr=='[', 1))) % array is 2D | |||
dim2=length(sscanf(astr,'%f,',[1 inf])); | |||
end | |||
else % array is 1D | |||
astr=arraystr(2:end-1); | |||
astr(astr==' ')=''; | |||
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',[1,inf]); | |||
if(nextidx>=length(astr)-1) | |||
object=obj; | |||
pos=endpos; | |||
parse_char(']'); | |||
return; | |||
end | |||
end | |||
if(~isempty(dim2)) | |||
astr=arraystr; | |||
astr(astr=='[')=''; | |||
astr(astr==']')=''; | |||
astr(astr==' ')=''; | |||
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',inf); | |||
if(nextidx>=length(astr)-1) | |||
object=reshape(obj,dim2,numel(obj)/dim2)'; | |||
pos=endpos; | |||
parse_char(']'); | |||
if(pbar>0) | |||
waitbar(pos/length(inStr),pbar,'loading ...'); | |||
end | |||
return; | |||
end | |||
end | |||
arraystr=regexprep(arraystr,'\]\s*,','];'); | |||
else | |||
arraystr='['; | |||
end | |||
try | |||
if(isoct && regexp(arraystr,'"','once')) | |||
error('Octave eval can produce empty cells for JSON-like input'); | |||
end | |||
object=eval(arraystr); | |||
pos=endpos; | |||
catch | |||
while 1 | |||
newopt=varargin2struct(varargin{:},'JSONLAB_ArrayDepth_',arraydepth+1); | |||
val = parse_value(newopt); | |||
object{end+1} = val; | |||
if next_char == ']' | |||
break; | |||
end | |||
parse_char(','); | |||
end | |||
end | |||
end | |||
if(jsonopt('SimplifyCell',0,varargin{:})==1) | |||
try | |||
oldobj=object; | |||
object=cell2mat(object')'; | |||
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0) | |||
object=oldobj; | |||
elseif(size(object,1)>1 && ndims(object)==2) | |||
object=object'; | |||
end | |||
catch | |||
end | |||
end | |||
parse_char(']'); | |||
if(pbar>0) | |||
waitbar(pos/length(inStr),pbar,'loading ...'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function parse_char(c) | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len || inStr(pos) ~= c | |||
error_pos(sprintf('Expected %c at position %%d', c)); | |||
else | |||
pos = pos + 1; | |||
skip_whitespace; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function c = next_char | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len | |||
c = []; | |||
else | |||
c = inStr(pos); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function skip_whitespace | |||
global pos inStr len | |||
while pos <= len && isspace(inStr(pos)) | |||
pos = pos + 1; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function str = parseStr(varargin) | |||
global pos inStr len esc index_esc len_esc | |||
% len, ns = length(inStr), keyboard | |||
if inStr(pos) ~= '"' | |||
error_pos('String starting with " expected at position %d'); | |||
else | |||
pos = pos + 1; | |||
end | |||
str = ''; | |||
while pos <= len | |||
while index_esc <= len_esc && esc(index_esc) < pos | |||
index_esc = index_esc + 1; | |||
end | |||
if index_esc > len_esc | |||
str = [str inStr(pos:len)]; | |||
pos = len + 1; | |||
break; | |||
else | |||
str = [str inStr(pos:esc(index_esc)-1)]; | |||
pos = esc(index_esc); | |||
end | |||
nstr = length(str); switch inStr(pos) | |||
case '"' | |||
pos = pos + 1; | |||
if(~isempty(str)) | |||
if(strcmp(str,'_Inf_')) | |||
str=Inf; | |||
elseif(strcmp(str,'-_Inf_')) | |||
str=-Inf; | |||
elseif(strcmp(str,'_NaN_')) | |||
str=NaN; | |||
end | |||
end | |||
return; | |||
case '\' | |||
if pos+1 > len | |||
error_pos('End of file reached right after escape character'); | |||
end | |||
pos = pos + 1; | |||
switch inStr(pos) | |||
case {'"' '\' '/'} | |||
str(nstr+1) = inStr(pos); | |||
pos = pos + 1; | |||
case {'b' 'f' 'n' 'r' 't'} | |||
str(nstr+1) = sprintf(['\' inStr(pos)]); | |||
pos = pos + 1; | |||
case 'u' | |||
if pos+4 > len | |||
error_pos('End of file reached in escaped unicode character'); | |||
end | |||
str(nstr+(1:6)) = inStr(pos-1:pos+4); | |||
pos = pos + 5; | |||
end | |||
otherwise % should never happen | |||
str(nstr+1) = inStr(pos), keyboard | |||
pos = pos + 1; | |||
end | |||
end | |||
error_pos('End of file while expecting end of inStr'); | |||
%%------------------------------------------------------------------------- | |||
function num = parse_number(varargin) | |||
global pos inStr len isoct | |||
currstr=inStr(pos:end); | |||
numstr=0; | |||
if(isoct~=0) | |||
numstr=regexp(currstr,'^\s*-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+\-]?\d+)?','end'); | |||
[num, one] = sscanf(currstr, '%f', 1); | |||
delta=numstr+1; | |||
else | |||
[num, one, err, delta] = sscanf(currstr, '%f', 1); | |||
if ~isempty(err) | |||
error_pos('Error reading number at position %d'); | |||
end | |||
end | |||
pos = pos + delta-1; | |||
%%------------------------------------------------------------------------- | |||
function val = parse_value(varargin) | |||
global pos inStr len | |||
true = 1; false = 0; | |||
pbar=jsonopt('progressbar_',-1,varargin{:}); | |||
if(pbar>0) | |||
waitbar(pos/len,pbar,'loading ...'); | |||
end | |||
switch(inStr(pos)) | |||
case '"' | |||
val = parseStr(varargin{:}); | |||
return; | |||
case '[' | |||
val = parse_array(varargin{:}); | |||
return; | |||
case '{' | |||
val = parse_object(varargin{:}); | |||
if isstruct(val) | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fieldnames(val), 'exact'))) | |||
val=jstruct2array(val); | |||
end | |||
elseif isempty(val) | |||
val = struct; | |||
end | |||
return; | |||
case {'-','0','1','2','3','4','5','6','7','8','9'} | |||
val = parse_number(varargin{:}); | |||
return; | |||
case 't' | |||
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'true') | |||
val = true; | |||
pos = pos + 4; | |||
return; | |||
end | |||
case 'f' | |||
if pos+4 <= len && strcmpi(inStr(pos:pos+4), 'false') | |||
val = false; | |||
pos = pos + 5; | |||
return; | |||
end | |||
case 'n' | |||
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'null') | |||
val = []; | |||
pos = pos + 4; | |||
return; | |||
end | |||
end | |||
error_pos('Value expected at position %d'); | |||
%%------------------------------------------------------------------------- | |||
function error_pos(msg) | |||
global pos inStr len | |||
poShow = max(min([pos-15 pos-1 pos pos+20],len),1); | |||
if poShow(3) == poShow(2) | |||
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after | |||
end | |||
msg = [sprintf(msg, pos) ': ' ... | |||
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ]; | |||
error( ['JSONparser:invalidFormat: ' msg] ); | |||
%%------------------------------------------------------------------------- | |||
function str = valid_field(str) | |||
global isoct | |||
% From MATLAB doc: field names must begin with a letter, which may be | |||
% followed by any combination of letters, digits, and underscores. | |||
% Invalid characters will be converted to underscores, and the prefix | |||
% "x0x[Hex code]_" will be added if the first character is not a letter. | |||
pos=regexp(str,'^[^A-Za-z]','once'); | |||
if(~isempty(pos)) | |||
if(~isoct) | |||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); | |||
else | |||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); | |||
end | |||
end | |||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end | |||
if(~isoct) | |||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_'); | |||
else | |||
pos=regexp(str,'[^0-9A-Za-z_]'); | |||
if(isempty(pos)) return; end | |||
str0=str; | |||
pos0=[0 pos(:)' length(str)]; | |||
str=''; | |||
for i=1:length(pos) | |||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))]; | |||
end | |||
if(pos(end)~=length(str)) | |||
str=[str str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_'; | |||
%%------------------------------------------------------------------------- | |||
function endpos = matching_quote(str,pos) | |||
len=length(str); | |||
while(pos<len) | |||
if(str(pos)=='"') | |||
if(~(pos>1 && str(pos-1)=='\')) | |||
endpos=pos; | |||
return; | |||
end | |||
end | |||
pos=pos+1; | |||
end | |||
error('unmatched quotation mark'); | |||
%%------------------------------------------------------------------------- | |||
function [endpos, e1l, e1r, maxlevel] = matching_bracket(str,pos) | |||
global arraytoken | |||
level=1; | |||
maxlevel=level; | |||
endpos=0; | |||
bpos=arraytoken(arraytoken>=pos); | |||
tokens=str(bpos); | |||
len=length(tokens); | |||
pos=1; | |||
e1l=[]; | |||
e1r=[]; | |||
while(pos<=len) | |||
c=tokens(pos); | |||
if(c==']') | |||
level=level-1; | |||
if(isempty(e1r)) e1r=bpos(pos); end | |||
if(level==0) | |||
endpos=bpos(pos); | |||
return | |||
end | |||
end | |||
if(c=='[') | |||
if(isempty(e1l)) e1l=bpos(pos); end | |||
level=level+1; | |||
maxlevel=max(maxlevel,level); | |||
end | |||
if(c=='"') | |||
pos=matching_quote(tokens,pos+1); | |||
end | |||
pos=pos+1; | |||
end | |||
if(endpos==0) | |||
error('unmatched "]"'); | |||
end | |||
@@ -1,528 +0,0 @@ | |||
function data = loadubjson(fname,varargin) | |||
% | |||
% data=loadubjson(fname,opt) | |||
% or | |||
% data=loadubjson(fname,'param1',value1,'param2',value2,...) | |||
% | |||
% parse a JSON (JavaScript Object Notation) file or string | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2013/08/01 | |||
% | |||
% $Id: loadubjson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% fname: input file name, if fname contains "{}" or "[]", fname | |||
% will be interpreted as a UBJSON string | |||
% opt: a struct to store parsing options, opt can be replaced by | |||
% a list of ('param',value) pairs - the param string is equivallent | |||
% to a field in opt. opt can have the following | |||
% fields (first in [.|.] is the default) | |||
% | |||
% opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat | |||
% for each element of the JSON data, and group | |||
% arrays based on the cell2mat rules. | |||
% opt.IntEndian [B|L]: specify the endianness of the integer fields | |||
% in the UBJSON input data. B - Big-Endian format for | |||
% integers (as required in the UBJSON specification); | |||
% L - input integer fields are in Little-Endian order. | |||
% | |||
% output: | |||
% dat: a cell array, where {...} blocks are converted into cell arrays, | |||
% and [...] are converted to arrays | |||
% | |||
% examples: | |||
% obj=struct('string','value','array',[1 2 3]); | |||
% ubjdata=saveubjson('obj',obj); | |||
% dat=loadubjson(ubjdata) | |||
% dat=loadubjson(['examples' filesep 'example1.ubj']) | |||
% dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1) | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
global pos inStr len esc index_esc len_esc isoct arraytoken fileendian systemendian | |||
if(regexp(fname,'[\{\}\]\[]','once')) | |||
string=fname; | |||
elseif(exist(fname,'file')) | |||
fid = fopen(fname,'rb'); | |||
string = fread(fid,inf,'uint8=>char')'; | |||
fclose(fid); | |||
else | |||
error('input file does not exist'); | |||
end | |||
pos = 1; len = length(string); inStr = string; | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"'); | |||
jstr=regexprep(inStr,'\\\\',' '); | |||
escquote=regexp(jstr,'\\"'); | |||
arraytoken=sort([arraytoken escquote]); | |||
% String delimiters and escape chars identified to improve speed: | |||
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]'); | |||
index_esc = 1; len_esc = length(esc); | |||
opt=varargin2struct(varargin{:}); | |||
fileendian=upper(jsonopt('IntEndian','B',opt)); | |||
[os,maxelem,systemendian]=computer; | |||
jsoncount=1; | |||
while pos <= len | |||
switch(next_char) | |||
case '{' | |||
data{jsoncount} = parse_object(opt); | |||
case '[' | |||
data{jsoncount} = parse_array(opt); | |||
otherwise | |||
error_pos('Outer level structure must be an object or an array'); | |||
end | |||
jsoncount=jsoncount+1; | |||
end % while | |||
jsoncount=length(data); | |||
if(jsoncount==1 && iscell(data)) | |||
data=data{1}; | |||
end | |||
if(~isempty(data)) | |||
if(isstruct(data)) % data can be a struct array | |||
data=jstruct2array(data); | |||
elseif(iscell(data)) | |||
data=jcell2array(data); | |||
end | |||
end | |||
%% | |||
function newdata=parse_collection(id,data,obj) | |||
if(jsoncount>0 && exist('data','var')) | |||
if(~iscell(data)) | |||
newdata=cell(1); | |||
newdata{1}=data; | |||
data=newdata; | |||
end | |||
end | |||
%% | |||
function newdata=jcell2array(data) | |||
len=length(data); | |||
newdata=data; | |||
for i=1:len | |||
if(isstruct(data{i})) | |||
newdata{i}=jstruct2array(data{i}); | |||
elseif(iscell(data{i})) | |||
newdata{i}=jcell2array(data{i}); | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newdata=jstruct2array(data) | |||
fn=fieldnames(data); | |||
newdata=data; | |||
len=length(data); | |||
for i=1:length(fn) % depth-first | |||
for j=1:len | |||
if(isstruct(getfield(data(j),fn{i}))) | |||
newdata(j)=setfield(newdata(j),fn{i},jstruct2array(getfield(data(j),fn{i}))); | |||
end | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayData_',fn))) | |||
newdata=cell(len,1); | |||
for j=1:len | |||
ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_); | |||
iscpx=0; | |||
if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn))) | |||
if(data(j).x0x5F_ArrayIsComplex_) | |||
iscpx=1; | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn))) | |||
if(data(j).x0x5F_ArrayIsSparse_) | |||
if(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
dim=double(data(j).x0x5F_ArraySize_); | |||
if(iscpx && size(ndata,2)==4-any(dim==1)) | |||
ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end)); | |||
end | |||
if isempty(ndata) | |||
% All-zeros sparse | |||
ndata=sparse(dim(1),prod(dim(2:end))); | |||
elseif dim(1)==1 | |||
% Sparse row vector | |||
ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end))); | |||
elseif dim(2)==1 | |||
% Sparse column vector | |||
ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end))); | |||
else | |||
% Generic sparse array. | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end))); | |||
end | |||
else | |||
if(iscpx && size(ndata,2)==4) | |||
ndata(:,3)=complex(ndata(:,3),ndata(:,4)); | |||
end | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3)); | |||
end | |||
end | |||
elseif(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
if(iscpx && size(ndata,2)==2) | |||
ndata=complex(ndata(:,1),ndata(:,2)); | |||
end | |||
ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_); | |||
end | |||
newdata{j}=ndata; | |||
end | |||
if(len==1) | |||
newdata=newdata{1}; | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function object = parse_object(varargin) | |||
parse_char('{'); | |||
object = []; | |||
type=''; | |||
count=-1; | |||
if(next_char == '$') | |||
type=inStr(pos+1); % TODO | |||
pos=pos+2; | |||
end | |||
if(next_char == '#') | |||
pos=pos+1; | |||
count=double(parse_number()); | |||
end | |||
if next_char ~= '}' | |||
num=0; | |||
while 1 | |||
str = parseStr(varargin{:}); | |||
if isempty(str) | |||
error_pos('Name of value at position %d cannot be empty'); | |||
end | |||
%parse_char(':'); | |||
val = parse_value(varargin{:}); | |||
num=num+1; | |||
eval( sprintf( 'object.%s = val;', valid_field(str) ) ); | |||
if next_char == '}' || (count>=0 && num>=count) | |||
break; | |||
end | |||
%parse_char(','); | |||
end | |||
end | |||
if(count==-1) | |||
parse_char('}'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function [cid,len]=elem_info(type) | |||
id=strfind('iUIlLdD',type); | |||
dataclass={'int8','uint8','int16','int32','int64','single','double'}; | |||
bytelen=[1,1,2,4,8,4,8]; | |||
if(id>0) | |||
cid=dataclass{id}; | |||
len=bytelen(id); | |||
else | |||
error_pos('unsupported type at position %d'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function [data adv]=parse_block(type,count,varargin) | |||
global pos inStr isoct fileendian systemendian | |||
[cid,len]=elem_info(type); | |||
datastr=inStr(pos:pos+len*count-1); | |||
if(isoct) | |||
newdata=int8(datastr); | |||
else | |||
newdata=uint8(datastr); | |||
end | |||
id=strfind('iUIlLdD',type); | |||
if(id<=5 && fileendian~=systemendian) | |||
newdata=swapbytes(typecast(newdata,cid)); | |||
end | |||
data=typecast(newdata,cid); | |||
adv=double(len*count); | |||
%%------------------------------------------------------------------------- | |||
function object = parse_array(varargin) % JSON array is written in row-major order | |||
global pos inStr isoct | |||
parse_char('['); | |||
object = cell(0, 1); | |||
dim=[]; | |||
type=''; | |||
count=-1; | |||
if(next_char == '$') | |||
type=inStr(pos+1); | |||
pos=pos+2; | |||
end | |||
if(next_char == '#') | |||
pos=pos+1; | |||
if(next_char=='[') | |||
dim=parse_array(varargin{:}); | |||
count=prod(double(dim)); | |||
else | |||
count=double(parse_number()); | |||
end | |||
end | |||
if(~isempty(type)) | |||
if(count>=0) | |||
[object adv]=parse_block(type,count,varargin{:}); | |||
if(~isempty(dim)) | |||
object=reshape(object,dim); | |||
end | |||
pos=pos+adv; | |||
return; | |||
else | |||
endpos=matching_bracket(inStr,pos); | |||
[cid,len]=elem_info(type); | |||
count=(endpos-pos)/len; | |||
[object adv]=parse_block(type,count,varargin{:}); | |||
pos=pos+adv; | |||
parse_char(']'); | |||
return; | |||
end | |||
end | |||
if next_char ~= ']' | |||
while 1 | |||
val = parse_value(varargin{:}); | |||
object{end+1} = val; | |||
if next_char == ']' | |||
break; | |||
end | |||
%parse_char(','); | |||
end | |||
end | |||
if(jsonopt('SimplifyCell',0,varargin{:})==1) | |||
try | |||
oldobj=object; | |||
object=cell2mat(object')'; | |||
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0) | |||
object=oldobj; | |||
elseif(size(object,1)>1 && ndims(object)==2) | |||
object=object'; | |||
end | |||
catch | |||
end | |||
end | |||
if(count==-1) | |||
parse_char(']'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function parse_char(c) | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len || inStr(pos) ~= c | |||
error_pos(sprintf('Expected %c at position %%d', c)); | |||
else | |||
pos = pos + 1; | |||
skip_whitespace; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function c = next_char | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len | |||
c = []; | |||
else | |||
c = inStr(pos); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function skip_whitespace | |||
global pos inStr len | |||
while pos <= len && isspace(inStr(pos)) | |||
pos = pos + 1; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function str = parseStr(varargin) | |||
global pos inStr esc index_esc len_esc | |||
% len, ns = length(inStr), keyboard | |||
type=inStr(pos); | |||
if type ~= 'S' && type ~= 'C' && type ~= 'H' | |||
error_pos('String starting with S expected at position %d'); | |||
else | |||
pos = pos + 1; | |||
end | |||
if(type == 'C') | |||
str=inStr(pos); | |||
pos=pos+1; | |||
return; | |||
end | |||
bytelen=double(parse_number()); | |||
if(length(inStr)>=pos+bytelen-1) | |||
str=inStr(pos:pos+bytelen-1); | |||
pos=pos+bytelen; | |||
else | |||
error_pos('End of file while expecting end of inStr'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function num = parse_number(varargin) | |||
global pos inStr len isoct fileendian systemendian | |||
id=strfind('iUIlLdD',inStr(pos)); | |||
if(isempty(id)) | |||
error_pos('expecting a number at position %d'); | |||
end | |||
type={'int8','uint8','int16','int32','int64','single','double'}; | |||
bytelen=[1,1,2,4,8,4,8]; | |||
datastr=inStr(pos+1:pos+bytelen(id)); | |||
if(isoct) | |||
newdata=int8(datastr); | |||
else | |||
newdata=uint8(datastr); | |||
end | |||
if(id<=5 && fileendian~=systemendian) | |||
newdata=swapbytes(typecast(newdata,type{id})); | |||
end | |||
num=typecast(newdata,type{id}); | |||
pos = pos + bytelen(id)+1; | |||
%%------------------------------------------------------------------------- | |||
function val = parse_value(varargin) | |||
global pos inStr len | |||
true = 1; false = 0; | |||
switch(inStr(pos)) | |||
case {'S','C','H'} | |||
val = parseStr(varargin{:}); | |||
return; | |||
case '[' | |||
val = parse_array(varargin{:}); | |||
return; | |||
case '{' | |||
val = parse_object(varargin{:}); | |||
if isstruct(val) | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fieldnames(val), 'exact'))) | |||
val=jstruct2array(val); | |||
end | |||
elseif isempty(val) | |||
val = struct; | |||
end | |||
return; | |||
case {'i','U','I','l','L','d','D'} | |||
val = parse_number(varargin{:}); | |||
return; | |||
case 'T' | |||
val = true; | |||
pos = pos + 1; | |||
return; | |||
case 'F' | |||
val = false; | |||
pos = pos + 1; | |||
return; | |||
case {'Z','N'} | |||
val = []; | |||
pos = pos + 1; | |||
return; | |||
end | |||
error_pos('Value expected at position %d'); | |||
%%------------------------------------------------------------------------- | |||
function error_pos(msg) | |||
global pos inStr len | |||
poShow = max(min([pos-15 pos-1 pos pos+20],len),1); | |||
if poShow(3) == poShow(2) | |||
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after | |||
end | |||
msg = [sprintf(msg, pos) ': ' ... | |||
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ]; | |||
error( ['JSONparser:invalidFormat: ' msg] ); | |||
%%------------------------------------------------------------------------- | |||
function str = valid_field(str) | |||
global isoct | |||
% From MATLAB doc: field names must begin with a letter, which may be | |||
% followed by any combination of letters, digits, and underscores. | |||
% Invalid characters will be converted to underscores, and the prefix | |||
% "x0x[Hex code]_" will be added if the first character is not a letter. | |||
pos=regexp(str,'^[^A-Za-z]','once'); | |||
if(~isempty(pos)) | |||
if(~isoct) | |||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); | |||
else | |||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); | |||
end | |||
end | |||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end | |||
if(~isoct) | |||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_'); | |||
else | |||
pos=regexp(str,'[^0-9A-Za-z_]'); | |||
if(isempty(pos)) return; end | |||
str0=str; | |||
pos0=[0 pos(:)' length(str)]; | |||
str=''; | |||
for i=1:length(pos) | |||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))]; | |||
end | |||
if(pos(end)~=length(str)) | |||
str=[str str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_'; | |||
%%------------------------------------------------------------------------- | |||
function endpos = matching_quote(str,pos) | |||
len=length(str); | |||
while(pos<len) | |||
if(str(pos)=='"') | |||
if(~(pos>1 && str(pos-1)=='\')) | |||
endpos=pos; | |||
return; | |||
end | |||
end | |||
pos=pos+1; | |||
end | |||
error('unmatched quotation mark'); | |||
%%------------------------------------------------------------------------- | |||
function [endpos e1l e1r maxlevel] = matching_bracket(str,pos) | |||
global arraytoken | |||
level=1; | |||
maxlevel=level; | |||
endpos=0; | |||
bpos=arraytoken(arraytoken>=pos); | |||
tokens=str(bpos); | |||
len=length(tokens); | |||
pos=1; | |||
e1l=[]; | |||
e1r=[]; | |||
while(pos<=len) | |||
c=tokens(pos); | |||
if(c==']') | |||
level=level-1; | |||
if(isempty(e1r)) e1r=bpos(pos); end | |||
if(level==0) | |||
endpos=bpos(pos); | |||
return | |||
end | |||
end | |||
if(c=='[') | |||
if(isempty(e1l)) e1l=bpos(pos); end | |||
level=level+1; | |||
maxlevel=max(maxlevel,level); | |||
end | |||
if(c=='"') | |||
pos=matching_quote(tokens,pos+1); | |||
end | |||
pos=pos+1; | |||
end | |||
if(endpos==0) | |||
error('unmatched "]"'); | |||
end | |||
@@ -1,33 +0,0 @@ | |||
function s=mergestruct(s1,s2) | |||
% | |||
% s=mergestruct(s1,s2) | |||
% | |||
% merge two struct objects into one | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% date: 2012/12/22 | |||
% | |||
% input: | |||
% s1,s2: a struct object, s1 and s2 can not be arrays | |||
% | |||
% output: | |||
% s: the merged struct object. fields in s1 and s2 will be combined in s. | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
if(~isstruct(s1) || ~isstruct(s2)) | |||
error('input parameters contain non-struct'); | |||
end | |||
if(length(s1)>1 || length(s2)>1) | |||
error('can not merge struct arrays'); | |||
end | |||
fn=fieldnames(s2); | |||
s=s1; | |||
for i=1:length(fn) | |||
s=setfield(s,fn{i},getfield(s2,fn{i})); | |||
end | |||
@@ -1,475 +0,0 @@ | |||
function json=savejson(rootname,obj,varargin) | |||
% | |||
% json=savejson(rootname,obj,filename) | |||
% or | |||
% json=savejson(rootname,obj,opt) | |||
% json=savejson(rootname,obj,'param1',value1,'param2',value2,...) | |||
% | |||
% convert a MATLAB object (cell, struct or array) into a JSON (JavaScript | |||
% Object Notation) string | |||
% | |||
% author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2011/09/09 | |||
% | |||
% $Id: savejson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% rootname: the name of the root-object, when set to '', the root name | |||
% is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
% the MATLAB variable name will be used as the root name. | |||
% obj: a MATLAB object (array, cell, cell array, struct, struct array). | |||
% filename: a string for the file name to save the output JSON data. | |||
% opt: a struct for additional options, ignore to use default values. | |||
% opt can have the following fields (first in [.|.] is the default) | |||
% | |||
% opt.FileName [''|string]: a file name to save the output JSON data | |||
% opt.FloatFormat ['%.10g'|string]: format to show each numeric element | |||
% of a 1D/2D array; | |||
% opt.ArrayIndent [1|0]: if 1, output explicit data array with | |||
% precedent indentation; if 0, no indentation | |||
% opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D | |||
% array in JSON array format; if sets to 1, an | |||
% array will be shown as a struct with fields | |||
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
% sparse arrays, the non-zero elements will be | |||
% saved to _ArrayData_ field in triplet-format i.e. | |||
% (ix,iy,val) and "_ArrayIsSparse_" will be added | |||
% with a value of 1; for a complex array, the | |||
% _ArrayData_ array will include two columns | |||
% (4 for sparse) to record the real and imaginary | |||
% parts, and also "_ArrayIsComplex_":1 is added. | |||
% opt.ParseLogical [0|1]: if this is set to 1, logical array elem | |||
% will use true/false rather than 1/0. | |||
% opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
% numerical element will be shown without a square | |||
% bracket, unless it is the root object; if 0, square | |||
% brackets are forced for any numerical arrays. | |||
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson | |||
% will use the name of the passed obj variable as the | |||
% root object name; if obj is an expression and | |||
% does not have a name, 'root' will be used; if this | |||
% is set to 0 and rootname is empty, the root level | |||
% will be merged down to the lower level. | |||
% opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern | |||
% to represent +/-Inf. The matched pattern is '([-+]*)Inf' | |||
% and $1 represents the sign. For those who want to use | |||
% 1e999 to represent Inf, they can set opt.Inf to '$11e999' | |||
% opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern | |||
% to represent NaN | |||
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
% for example, if opt.JSONP='foo', the JSON data is | |||
% wrapped inside a function call as 'foo(...);' | |||
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
% back to the string form | |||
% opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode. | |||
% opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs) | |||
% | |||
% opt can be replaced by a list of ('param',value) pairs. The param | |||
% string is equivallent to a field in opt and is case sensitive. | |||
% output: | |||
% json: a string in the JSON format (see http://json.org) | |||
% | |||
% examples: | |||
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
% 'SpecialData',[nan, inf, -inf]); | |||
% savejson('jmesh',jsonmesh) | |||
% savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g') | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
if(nargin==1) | |||
varname=inputname(1); | |||
obj=rootname; | |||
if(isempty(varname)) | |||
varname='root'; | |||
end | |||
rootname=varname; | |||
else | |||
varname=inputname(2); | |||
end | |||
if(length(varargin)==1 && ischar(varargin{1})) | |||
opt=struct('FileName',varargin{1}); | |||
else | |||
opt=varargin2struct(varargin{:}); | |||
end | |||
opt.IsOctave=exist('OCTAVE_VERSION','builtin'); | |||
rootisarray=0; | |||
rootlevel=1; | |||
forceroot=jsonopt('ForceRootName',0,opt); | |||
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || iscell(obj)) && isempty(rootname) && forceroot==0) | |||
rootisarray=1; | |||
rootlevel=0; | |||
else | |||
if(isempty(rootname)) | |||
rootname=varname; | |||
end | |||
end | |||
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot) | |||
rootname='root'; | |||
end | |||
whitespaces=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
if(jsonopt('Compact',0,opt)==1) | |||
whitespaces=struct('tab','','newline','','sep',','); | |||
end | |||
if(~isfield(opt,'whitespaces_')) | |||
opt.whitespaces_=whitespaces; | |||
end | |||
nl=whitespaces.newline; | |||
json=obj2json(rootname,obj,rootlevel,opt); | |||
if(rootisarray) | |||
json=sprintf('%s%s',json,nl); | |||
else | |||
json=sprintf('{%s%s%s}\n',nl,json,nl); | |||
end | |||
jsonp=jsonopt('JSONP','',opt); | |||
if(~isempty(jsonp)) | |||
json=sprintf('%s(%s);%s',jsonp,json,nl); | |||
end | |||
% save to a file if FileName is set, suggested by Patrick Rapin | |||
if(~isempty(jsonopt('FileName','',opt))) | |||
if(jsonopt('SaveBinary',0,opt)==1) | |||
fid = fopen(opt.FileName, 'wb'); | |||
fwrite(fid,json); | |||
else | |||
fid = fopen(opt.FileName, 'wt'); | |||
fwrite(fid,json,'char'); | |||
end | |||
fclose(fid); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=obj2json(name,item,level,varargin) | |||
if(iscell(item)) | |||
txt=cell2json(name,item,level,varargin{:}); | |||
elseif(isstruct(item)) | |||
txt=struct2json(name,item,level,varargin{:}); | |||
elseif(ischar(item)) | |||
txt=str2json(name,item,level,varargin{:}); | |||
else | |||
txt=mat2json(name,item,level,varargin{:}); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=cell2json(name,item,level,varargin) | |||
txt=''; | |||
if(~iscell(item)) | |||
error('input is not a cell'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); | |||
ws=jsonopt('whitespaces_',struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')),varargin{:}); | |||
padding0=repmat(ws.tab,1,level); | |||
padding2=repmat(ws.tab,1,level+1); | |||
nl=ws.newline; | |||
if(len>1) | |||
if(~isempty(name)) | |||
txt=sprintf('%s"%s": [%s',padding0, checkname(name,varargin{:}),nl); name=''; | |||
else | |||
txt=sprintf('%s[%s',padding0,nl); | |||
end | |||
elseif(len==0) | |||
if(~isempty(name)) | |||
txt=sprintf('%s"%s": []',padding0, checkname(name,varargin{:})); name=''; | |||
else | |||
txt=sprintf('%s[]',padding0); | |||
end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=sprintf('%s%s[%s',txt,padding2,nl); end | |||
for i=1:dim(1) | |||
txt=sprintf('%s%s',txt,obj2json(name,item{i,j},level+(dim(1)>1)+1,varargin{:})); | |||
if(i<dim(1)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(dim(1)>1) txt=sprintf('%s%s%s]',txt,nl,padding2); end | |||
if(j<dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
%if(j==dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(len>1) txt=sprintf('%s%s%s]',txt,nl,padding0); end | |||
%%------------------------------------------------------------------------- | |||
function txt=struct2json(name,item,level,varargin) | |||
txt=''; | |||
if(~isstruct(item)) | |||
error('input is not a struct'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
padding0=repmat(ws.tab,1,level); | |||
padding2=repmat(ws.tab,1,level+1); | |||
padding1=repmat(ws.tab,1,level+(dim(1)>1)+(len>1)); | |||
nl=ws.newline; | |||
if(~isempty(name)) | |||
if(len>1) txt=sprintf('%s"%s": [%s',padding0,checkname(name,varargin{:}),nl); end | |||
else | |||
if(len>1) txt=sprintf('%s[%s',padding0,nl); end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=sprintf('%s%s[%s',txt,padding2,nl); end | |||
for i=1:dim(1) | |||
names = fieldnames(item(i,j)); | |||
if(~isempty(name) && len==1) | |||
txt=sprintf('%s%s"%s": {%s',txt,padding1, checkname(name,varargin{:}),nl); | |||
else | |||
txt=sprintf('%s%s{%s',txt,padding1,nl); | |||
end | |||
if(~isempty(names)) | |||
for e=1:length(names) | |||
txt=sprintf('%s%s',txt,obj2json(names{e},getfield(item(i,j),... | |||
names{e}),level+(dim(1)>1)+1+(len>1),varargin{:})); | |||
if(e<length(names)) txt=sprintf('%s%s',txt,','); end | |||
txt=sprintf('%s%s',txt,nl); | |||
end | |||
end | |||
txt=sprintf('%s%s}',txt,padding1); | |||
if(i<dim(1)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(dim(1)>1) txt=sprintf('%s%s%s]',txt,nl,padding2); end | |||
if(j<dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(len>1) txt=sprintf('%s%s%s]',txt,nl,padding0); end | |||
%%------------------------------------------------------------------------- | |||
function txt=str2json(name,item,level,varargin) | |||
txt=''; | |||
if(~ischar(item)) | |||
error('input is not a string'); | |||
end | |||
item=reshape(item, max(size(item),[1 0])); | |||
len=size(item,1); | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
padding1=repmat(ws.tab,1,level); | |||
padding0=repmat(ws.tab,1,level+1); | |||
nl=ws.newline; | |||
sep=ws.sep; | |||
if(~isempty(name)) | |||
if(len>1) txt=sprintf('%s"%s": [%s',padding1,checkname(name,varargin{:}),nl); end | |||
else | |||
if(len>1) txt=sprintf('%s[%s',padding1,nl); end | |||
end | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
for e=1:len | |||
if(isoct) | |||
val=regexprep(item(e,:),'\\','\\'); | |||
val=regexprep(val,'"','\"'); | |||
val=regexprep(val,'^"','\"'); | |||
else | |||
val=regexprep(item(e,:),'\\','\\\\'); | |||
val=regexprep(val,'"','\\"'); | |||
val=regexprep(val,'^"','\\"'); | |||
end | |||
val=escapejsonstring(val); | |||
if(len==1) | |||
obj=['"' checkname(name,varargin{:}) '": ' '"',val,'"']; | |||
if(isempty(name)) obj=['"',val,'"']; end | |||
txt=sprintf('%s%s%s%s',txt,padding1,obj); | |||
else | |||
txt=sprintf('%s%s%s%s',txt,padding0,['"',val,'"']); | |||
end | |||
if(e==len) sep=''; end | |||
txt=sprintf('%s%s',txt,sep); | |||
end | |||
if(len>1) txt=sprintf('%s%s%s%s',txt,nl,padding1,']'); end | |||
%%------------------------------------------------------------------------- | |||
function txt=mat2json(name,item,level,varargin) | |||
if(~isnumeric(item) && ~islogical(item)) | |||
error('input is not an array'); | |||
end | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
padding1=repmat(ws.tab,1,level); | |||
padding0=repmat(ws.tab,1,level+1); | |||
nl=ws.newline; | |||
sep=ws.sep; | |||
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ... | |||
isempty(item) ||jsonopt('ArrayToStruct',0,varargin{:})) | |||
if(isempty(name)) | |||
txt=sprintf('%s{%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',... | |||
padding1,nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); | |||
else | |||
txt=sprintf('%s"%s": {%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',... | |||
padding1,checkname(name,varargin{:}),nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); | |||
end | |||
else | |||
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1 && level>0) | |||
numtxt=regexprep(regexprep(matdata2json(item,level+1,varargin{:}),'^\[',''),']',''); | |||
else | |||
numtxt=matdata2json(item,level+1,varargin{:}); | |||
end | |||
if(isempty(name)) | |||
txt=sprintf('%s%s',padding1,numtxt); | |||
else | |||
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1) | |||
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt); | |||
else | |||
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt); | |||
end | |||
end | |||
return; | |||
end | |||
dataformat='%s%s%s%s%s'; | |||
if(issparse(item)) | |||
[ix,iy]=find(item); | |||
data=full(item(find(item))); | |||
if(~isreal(item)) | |||
data=[real(data(:)),imag(data(:))]; | |||
if(size(item,1)==1) | |||
% Kludge to have data's 'transposedness' match item's. | |||
% (Necessary for complex row vector handling below.) | |||
data=data'; | |||
end | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep); | |||
end | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_": ','1', sep); | |||
if(size(item,1)==1) | |||
% Row vector, store only column indices. | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([iy(:),data'],level+2,varargin{:}), nl); | |||
elseif(size(item,2)==1) | |||
% Column vector, store only row indices. | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([ix,data],level+2,varargin{:}), nl); | |||
else | |||
% General case, store row and column indices. | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([ix,iy,data],level+2,varargin{:}), nl); | |||
end | |||
else | |||
if(isreal(item)) | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json(item(:)',level+2,varargin{:}), nl); | |||
else | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep); | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([real(item(:)) imag(item(:))],level+2,varargin{:}), nl); | |||
end | |||
end | |||
txt=sprintf('%s%s%s',txt,padding1,'}'); | |||
%%------------------------------------------------------------------------- | |||
function txt=matdata2json(mat,level,varargin) | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
tab=ws.tab; | |||
nl=ws.newline; | |||
if(size(mat,1)==1) | |||
pre=''; | |||
post=''; | |||
level=level-1; | |||
else | |||
pre=sprintf('[%s',nl); | |||
post=sprintf('%s%s]',nl,repmat(tab,1,level-1)); | |||
end | |||
if(isempty(mat)) | |||
txt='null'; | |||
return; | |||
end | |||
floatformat=jsonopt('FloatFormat','%.10g',varargin{:}); | |||
%if(numel(mat)>1) | |||
formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],%s',nl)]]; | |||
%else | |||
% formatstr=[repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf(',\n')]]; | |||
%end | |||
if(nargin>=2 && size(mat,1)>1 && jsonopt('ArrayIndent',1,varargin{:})==1) | |||
formatstr=[repmat(tab,1,level) formatstr]; | |||
end | |||
txt=sprintf(formatstr,mat'); | |||
txt(end-length(nl):end)=[]; | |||
if(islogical(mat) && jsonopt('ParseLogical',0,varargin{:})==1) | |||
txt=regexprep(txt,'1','true'); | |||
txt=regexprep(txt,'0','false'); | |||
end | |||
%txt=regexprep(mat2str(mat),'\s+',','); | |||
%txt=regexprep(txt,';',sprintf('],\n[')); | |||
% if(nargin>=2 && size(mat,1)>1) | |||
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']); | |||
% end | |||
txt=[pre txt post]; | |||
if(any(isinf(mat(:)))) | |||
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:})); | |||
end | |||
if(any(isnan(mat(:)))) | |||
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:})); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newname=checkname(name,varargin) | |||
isunpack=jsonopt('UnpackHex',1,varargin{:}); | |||
newname=name; | |||
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once'))) | |||
return | |||
end | |||
if(isunpack) | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
if(~isoct) | |||
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}'); | |||
else | |||
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start'); | |||
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end'); | |||
if(isempty(pos)) return; end | |||
str0=name; | |||
pos0=[0 pend(:)' length(name)]; | |||
newname=''; | |||
for i=1:length(pos) | |||
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))]; | |||
end | |||
if(pos(end)~=length(name)) | |||
newname=[newname str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newstr=escapejsonstring(str) | |||
newstr=str; | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
if(isoct) | |||
vv=sscanf(OCTAVE_VERSION,'%f'); | |||
if(vv(1)>=3.8) isoct=0; end | |||
end | |||
if(isoct) | |||
escapechars={'\a','\f','\n','\r','\t','\v'}; | |||
for i=1:length(escapechars); | |||
newstr=regexprep(newstr,escapechars{i},escapechars{i}); | |||
end | |||
else | |||
escapechars={'\a','\b','\f','\n','\r','\t','\v'}; | |||
for i=1:length(escapechars); | |||
newstr=regexprep(newstr,escapechars{i},regexprep(escapechars{i},'\\','\\\\')); | |||
end | |||
end |
@@ -1,504 +0,0 @@ | |||
function json=saveubjson(rootname,obj,varargin) | |||
% | |||
% json=saveubjson(rootname,obj,filename) | |||
% or | |||
% json=saveubjson(rootname,obj,opt) | |||
% json=saveubjson(rootname,obj,'param1',value1,'param2',value2,...) | |||
% | |||
% convert a MATLAB object (cell, struct or array) into a Universal | |||
% Binary JSON (UBJSON) binary string | |||
% | |||
% author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2013/08/17 | |||
% | |||
% $Id: saveubjson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% rootname: the name of the root-object, when set to '', the root name | |||
% is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
% the MATLAB variable name will be used as the root name. | |||
% obj: a MATLAB object (array, cell, cell array, struct, struct array) | |||
% filename: a string for the file name to save the output UBJSON data | |||
% opt: a struct for additional options, ignore to use default values. | |||
% opt can have the following fields (first in [.|.] is the default) | |||
% | |||
% opt.FileName [''|string]: a file name to save the output JSON data | |||
% opt.ArrayToStruct[0|1]: when set to 0, saveubjson outputs 1D/2D | |||
% array in JSON array format; if sets to 1, an | |||
% array will be shown as a struct with fields | |||
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
% sparse arrays, the non-zero elements will be | |||
% saved to _ArrayData_ field in triplet-format i.e. | |||
% (ix,iy,val) and "_ArrayIsSparse_" will be added | |||
% with a value of 1; for a complex array, the | |||
% _ArrayData_ array will include two columns | |||
% (4 for sparse) to record the real and imaginary | |||
% parts, and also "_ArrayIsComplex_":1 is added. | |||
% opt.ParseLogical [1|0]: if this is set to 1, logical array elem | |||
% will use true/false rather than 1/0. | |||
% opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
% numerical element will be shown without a square | |||
% bracket, unless it is the root object; if 0, square | |||
% brackets are forced for any numerical arrays. | |||
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, saveubjson | |||
% will use the name of the passed obj variable as the | |||
% root object name; if obj is an expression and | |||
% does not have a name, 'root' will be used; if this | |||
% is set to 0 and rootname is empty, the root level | |||
% will be merged down to the lower level. | |||
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
% for example, if opt.JSON='foo', the JSON data is | |||
% wrapped inside a function call as 'foo(...);' | |||
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
% back to the string form | |||
% | |||
% opt can be replaced by a list of ('param',value) pairs. The param | |||
% string is equivallent to a field in opt and is case sensitive. | |||
% output: | |||
% json: a binary string in the UBJSON format (see http://ubjson.org) | |||
% | |||
% examples: | |||
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
% 'SpecialData',[nan, inf, -inf]); | |||
% saveubjson('jsonmesh',jsonmesh) | |||
% saveubjson('jsonmesh',jsonmesh,'meshdata.ubj') | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
if(nargin==1) | |||
varname=inputname(1); | |||
obj=rootname; | |||
if(isempty(varname)) | |||
varname='root'; | |||
end | |||
rootname=varname; | |||
else | |||
varname=inputname(2); | |||
end | |||
if(length(varargin)==1 && ischar(varargin{1})) | |||
opt=struct('FileName',varargin{1}); | |||
else | |||
opt=varargin2struct(varargin{:}); | |||
end | |||
opt.IsOctave=exist('OCTAVE_VERSION','builtin'); | |||
rootisarray=0; | |||
rootlevel=1; | |||
forceroot=jsonopt('ForceRootName',0,opt); | |||
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || iscell(obj)) && isempty(rootname) && forceroot==0) | |||
rootisarray=1; | |||
rootlevel=0; | |||
else | |||
if(isempty(rootname)) | |||
rootname=varname; | |||
end | |||
end | |||
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot) | |||
rootname='root'; | |||
end | |||
json=obj2ubjson(rootname,obj,rootlevel,opt); | |||
if(~rootisarray) | |||
json=['{' json '}']; | |||
end | |||
jsonp=jsonopt('JSONP','',opt); | |||
if(~isempty(jsonp)) | |||
json=[jsonp '(' json ')']; | |||
end | |||
% save to a file if FileName is set, suggested by Patrick Rapin | |||
if(~isempty(jsonopt('FileName','',opt))) | |||
fid = fopen(opt.FileName, 'wb'); | |||
fwrite(fid,json); | |||
fclose(fid); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=obj2ubjson(name,item,level,varargin) | |||
if(iscell(item)) | |||
txt=cell2ubjson(name,item,level,varargin{:}); | |||
elseif(isstruct(item)) | |||
txt=struct2ubjson(name,item,level,varargin{:}); | |||
elseif(ischar(item)) | |||
txt=str2ubjson(name,item,level,varargin{:}); | |||
else | |||
txt=mat2ubjson(name,item,level,varargin{:}); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=cell2ubjson(name,item,level,varargin) | |||
txt=''; | |||
if(~iscell(item)) | |||
error('input is not a cell'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); % let's handle 1D cell first | |||
if(len>1) | |||
if(~isempty(name)) | |||
txt=[S_(checkname(name,varargin{:})) '[']; name=''; | |||
else | |||
txt='['; | |||
end | |||
elseif(len==0) | |||
if(~isempty(name)) | |||
txt=[S_(checkname(name,varargin{:})) 'Z']; name=''; | |||
else | |||
txt='Z'; | |||
end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=[txt '[']; end | |||
for i=1:dim(1) | |||
txt=[txt obj2ubjson(name,item{i,j},level+(len>1),varargin{:})]; | |||
end | |||
if(dim(1)>1) txt=[txt ']']; end | |||
end | |||
if(len>1) txt=[txt ']']; end | |||
%%------------------------------------------------------------------------- | |||
function txt=struct2ubjson(name,item,level,varargin) | |||
txt=''; | |||
if(~isstruct(item)) | |||
error('input is not a struct'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); | |||
if(~isempty(name)) | |||
if(len>1) txt=[S_(checkname(name,varargin{:})) '[']; end | |||
else | |||
if(len>1) txt='['; end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=[txt '[']; end | |||
for i=1:dim(1) | |||
names = fieldnames(item(i,j)); | |||
if(~isempty(name) && len==1) | |||
txt=[txt S_(checkname(name,varargin{:})) '{']; | |||
else | |||
txt=[txt '{']; | |||
end | |||
if(~isempty(names)) | |||
for e=1:length(names) | |||
txt=[txt obj2ubjson(names{e},getfield(item(i,j),... | |||
names{e}),level+(dim(1)>1)+1+(len>1),varargin{:})]; | |||
end | |||
end | |||
txt=[txt '}']; | |||
end | |||
if(dim(1)>1) txt=[txt ']']; end | |||
end | |||
if(len>1) txt=[txt ']']; end | |||
%%------------------------------------------------------------------------- | |||
function txt=str2ubjson(name,item,level,varargin) | |||
txt=''; | |||
if(~ischar(item)) | |||
error('input is not a string'); | |||
end | |||
item=reshape(item, max(size(item),[1 0])); | |||
len=size(item,1); | |||
if(~isempty(name)) | |||
if(len>1) txt=[S_(checkname(name,varargin{:})) '[']; end | |||
else | |||
if(len>1) txt='['; end | |||
end | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
for e=1:len | |||
val=item(e,:); | |||
if(len==1) | |||
obj=['' S_(checkname(name,varargin{:})) '' '',S_(val),'']; | |||
if(isempty(name)) obj=['',S_(val),'']; end | |||
txt=[txt,'',obj]; | |||
else | |||
txt=[txt,'',['',S_(val),'']]; | |||
end | |||
end | |||
if(len>1) txt=[txt ']']; end | |||
%%------------------------------------------------------------------------- | |||
function txt=mat2ubjson(name,item,level,varargin) | |||
if(~isnumeric(item) && ~islogical(item)) | |||
error('input is not an array'); | |||
end | |||
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ... | |||
isempty(item) || jsonopt('ArrayToStruct',0,varargin{:})) | |||
cid=I_(uint32(max(size(item)))); | |||
if(isempty(name)) | |||
txt=['{' S_('_ArrayType_'),S_(class(item)),S_('_ArraySize_'),I_a(size(item),cid(1)) ]; | |||
else | |||
if(isempty(item)) | |||
txt=[S_(checkname(name,varargin{:})),'Z']; | |||
return; | |||
else | |||
txt=[S_(checkname(name,varargin{:})),'{',S_('_ArrayType_'),S_(class(item)),S_('_ArraySize_'),I_a(size(item),cid(1))]; | |||
end | |||
end | |||
else | |||
if(isempty(name)) | |||
txt=matdata2ubjson(item,level+1,varargin{:}); | |||
else | |||
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1) | |||
numtxt=regexprep(regexprep(matdata2ubjson(item,level+1,varargin{:}),'^\[',''),']',''); | |||
txt=[S_(checkname(name,varargin{:})) numtxt]; | |||
else | |||
txt=[S_(checkname(name,varargin{:})),matdata2ubjson(item,level+1,varargin{:})]; | |||
end | |||
end | |||
return; | |||
end | |||
if(issparse(item)) | |||
[ix,iy]=find(item); | |||
data=full(item(find(item))); | |||
if(~isreal(item)) | |||
data=[real(data(:)),imag(data(:))]; | |||
if(size(item,1)==1) | |||
% Kludge to have data's 'transposedness' match item's. | |||
% (Necessary for complex row vector handling below.) | |||
data=data'; | |||
end | |||
txt=[txt,S_('_ArrayIsComplex_'),'T']; | |||
end | |||
txt=[txt,S_('_ArrayIsSparse_'),'T']; | |||
if(size(item,1)==1) | |||
% Row vector, store only column indices. | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([iy(:),data'],level+2,varargin{:})]; | |||
elseif(size(item,2)==1) | |||
% Column vector, store only row indices. | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([ix,data],level+2,varargin{:})]; | |||
else | |||
% General case, store row and column indices. | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([ix,iy,data],level+2,varargin{:})]; | |||
end | |||
else | |||
if(isreal(item)) | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson(item(:)',level+2,varargin{:})]; | |||
else | |||
txt=[txt,S_('_ArrayIsComplex_'),'T']; | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([real(item(:)) imag(item(:))],level+2,varargin{:})]; | |||
end | |||
end | |||
txt=[txt,'}']; | |||
%%------------------------------------------------------------------------- | |||
function txt=matdata2ubjson(mat,level,varargin) | |||
if(isempty(mat)) | |||
txt='Z'; | |||
return; | |||
end | |||
if(size(mat,1)==1) | |||
level=level-1; | |||
end | |||
type=''; | |||
hasnegtive=(mat<0); | |||
if(isa(mat,'integer') || isinteger(mat) || (isfloat(mat) && all(mod(mat(:),1) == 0))) | |||
if(isempty(hasnegtive)) | |||
if(max(mat(:))<=2^8) | |||
type='U'; | |||
end | |||
end | |||
if(isempty(type)) | |||
% todo - need to consider negative ones separately | |||
id= histc(abs(max(mat(:))),[0 2^7 2^15 2^31 2^63]); | |||
if(isempty(find(id))) | |||
error('high-precision data is not yet supported'); | |||
end | |||
key='iIlL'; | |||
type=key(find(id)); | |||
end | |||
txt=[I_a(mat(:),type,size(mat))]; | |||
elseif(islogical(mat)) | |||
logicalval='FT'; | |||
if(numel(mat)==1) | |||
txt=logicalval(mat+1); | |||
else | |||
txt=['[$U#' I_a(size(mat),'l') typecast(swapbytes(uint8(mat(:)')),'uint8')]; | |||
end | |||
else | |||
if(numel(mat)==1) | |||
txt=['[' D_(mat) ']']; | |||
else | |||
txt=D_a(mat(:),'D',size(mat)); | |||
end | |||
end | |||
%txt=regexprep(mat2str(mat),'\s+',','); | |||
%txt=regexprep(txt,';',sprintf('],[')); | |||
% if(nargin>=2 && size(mat,1)>1) | |||
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']); | |||
% end | |||
if(any(isinf(mat(:)))) | |||
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:})); | |||
end | |||
if(any(isnan(mat(:)))) | |||
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:})); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newname=checkname(name,varargin) | |||
isunpack=jsonopt('UnpackHex',1,varargin{:}); | |||
newname=name; | |||
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once'))) | |||
return | |||
end | |||
if(isunpack) | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
if(~isoct) | |||
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}'); | |||
else | |||
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start'); | |||
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end'); | |||
if(isempty(pos)) return; end | |||
str0=name; | |||
pos0=[0 pend(:)' length(name)]; | |||
newname=''; | |||
for i=1:length(pos) | |||
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))]; | |||
end | |||
if(pos(end)~=length(name)) | |||
newname=[newname str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function val=S_(str) | |||
if(length(str)==1) | |||
val=['C' str]; | |||
else | |||
val=['S' I_(int32(length(str))) str]; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function val=I_(num) | |||
if(~isinteger(num)) | |||
error('input is not an integer'); | |||
end | |||
if(num>=0 && num<255) | |||
val=['U' data2byte(swapbytes(cast(num,'uint8')),'uint8')]; | |||
return; | |||
end | |||
key='iIlL'; | |||
cid={'int8','int16','int32','int64'}; | |||
for i=1:4 | |||
if((num>0 && num<2^(i*8-1)) || (num<0 && num>=-2^(i*8-1))) | |||
val=[key(i) data2byte(swapbytes(cast(num,cid{i})),'uint8')]; | |||
return; | |||
end | |||
end | |||
error('unsupported integer'); | |||
%%------------------------------------------------------------------------- | |||
function val=D_(num) | |||
if(~isfloat(num)) | |||
error('input is not a float'); | |||
end | |||
if(isa(num,'single')) | |||
val=['d' data2byte(num,'uint8')]; | |||
else | |||
val=['D' data2byte(num,'uint8')]; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function data=I_a(num,type,dim,format) | |||
id=find(ismember('iUIlL',type)); | |||
if(id==0) | |||
error('unsupported integer array'); | |||
end | |||
% based on UBJSON specs, all integer types are stored in big endian format | |||
if(id==1) | |||
data=data2byte(swapbytes(int8(num)),'uint8'); | |||
blen=1; | |||
elseif(id==2) | |||
data=data2byte(swapbytes(uint8(num)),'uint8'); | |||
blen=1; | |||
elseif(id==3) | |||
data=data2byte(swapbytes(int16(num)),'uint8'); | |||
blen=2; | |||
elseif(id==4) | |||
data=data2byte(swapbytes(int32(num)),'uint8'); | |||
blen=4; | |||
elseif(id==5) | |||
data=data2byte(swapbytes(int64(num)),'uint8'); | |||
blen=8; | |||
end | |||
if(nargin>=3 && length(dim)>=2 && prod(dim)~=dim(2)) | |||
format='opt'; | |||
end | |||
if((nargin<4 || strcmp(format,'opt')) && numel(num)>1) | |||
if(nargin>=3 && (length(dim)==1 || (length(dim)>=2 && prod(dim)~=dim(2)))) | |||
cid=I_(uint32(max(dim))); | |||
data=['$' type '#' I_a(dim,cid(1)) data(:)']; | |||
else | |||
data=['$' type '#' I_(int32(numel(data)/blen)) data(:)']; | |||
end | |||
data=['[' data(:)']; | |||
else | |||
data=reshape(data,blen,numel(data)/blen); | |||
data(2:blen+1,:)=data; | |||
data(1,:)=type; | |||
data=data(:)'; | |||
data=['[' data(:)' ']']; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function data=D_a(num,type,dim,format) | |||
id=find(ismember('dD',type)); | |||
if(id==0) | |||
error('unsupported float array'); | |||
end | |||
if(id==1) | |||
data=data2byte(single(num),'uint8'); | |||
elseif(id==2) | |||
data=data2byte(double(num),'uint8'); | |||
end | |||
if(nargin>=3 && length(dim)>=2 && prod(dim)~=dim(2)) | |||
format='opt'; | |||
end | |||
if((nargin<4 || strcmp(format,'opt')) && numel(num)>1) | |||
if(nargin>=3 && (length(dim)==1 || (length(dim)>=2 && prod(dim)~=dim(2)))) | |||
cid=I_(uint32(max(dim))); | |||
data=['$' type '#' I_a(dim,cid(1)) data(:)']; | |||
else | |||
data=['$' type '#' I_(int32(numel(data)/(id*4))) data(:)']; | |||
end | |||
data=['[' data]; | |||
else | |||
data=reshape(data,(id*4),length(data)/(id*4)); | |||
data(2:(id*4+1),:)=data; | |||
data(1,:)=type; | |||
data=data(:)'; | |||
data=['[' data(:)' ']']; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function bytes=data2byte(varargin) | |||
bytes=typecast(varargin{:}); | |||
bytes=bytes(:)'; |
@@ -1,40 +0,0 @@ | |||
function opt=varargin2struct(varargin) | |||
% | |||
% opt=varargin2struct('param1',value1,'param2',value2,...) | |||
% or | |||
% opt=varargin2struct(...,optstruct,...) | |||
% | |||
% convert a series of input parameters into a structure | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% date: 2012/12/22 | |||
% | |||
% input: | |||
% 'param', value: the input parameters should be pairs of a string and a value | |||
% optstruct: if a parameter is a struct, the fields will be merged to the output struct | |||
% | |||
% output: | |||
% opt: a struct where opt.param1=value1, opt.param2=value2 ... | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
len=length(varargin); | |||
opt=struct; | |||
if(len==0) return; end | |||
i=1; | |||
while(i<=len) | |||
if(isstruct(varargin{i})) | |||
opt=mergestruct(opt,varargin{i}); | |||
elseif(ischar(varargin{i}) && i<len) | |||
opt=setfield(opt,varargin{i},varargin{i+1}); | |||
i=i+1; | |||
else | |||
error('input must be in the form of ...,''name'',value,... pairs or structs'); | |||
end | |||
i=i+1; | |||
end | |||
@@ -1,30 +0,0 @@ | |||
function str = makeValidFieldName(str) | |||
% From MATLAB doc: field names must begin with a letter, which may be | |||
% followed by any combination of letters, digits, and underscores. | |||
% Invalid characters will be converted to underscores, and the prefix | |||
% "x0x[Hex code]_" will be added if the first character is not a letter. | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
pos=regexp(str,'^[^A-Za-z]','once'); | |||
if(~isempty(pos)) | |||
if(~isoct) | |||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); | |||
else | |||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); | |||
end | |||
end | |||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end | |||
if(~isoct) | |||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_'); | |||
else | |||
pos=regexp(str,'[^0-9A-Za-z_]'); | |||
if(isempty(pos)) return; end | |||
str0=str; | |||
pos0=[0 pos(:)' length(str)]; | |||
str=''; | |||
for i=1:length(pos) | |||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))]; | |||
end | |||
if(pos(end)~=length(str)) | |||
str=[str str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end |
@@ -1,125 +0,0 @@ | |||
function submitWithConfiguration(conf) | |||
addpath('./lib/jsonlab'); | |||
parts = parts(conf); | |||
fprintf('== Submitting solutions | %s...\n', conf.itemName); | |||
tokenFile = 'token.mat'; | |||
if exist(tokenFile, 'file') | |||
load(tokenFile); | |||
[email token] = promptToken(email, token, tokenFile); | |||
else | |||
[email token] = promptToken('', '', tokenFile); | |||
end | |||
if isempty(token) | |||
fprintf('!! Submission Cancelled\n'); | |||
return | |||
end | |||
try | |||
response = submitParts(conf, email, token, parts); | |||
catch | |||
e = lasterror(); | |||
fprintf( ... | |||
'!! Submission failed: unexpected error: %s\n', ... | |||
e.message); | |||
fprintf('!! Please try again later.\n'); | |||
return | |||
end | |||
if isfield(response, 'errorMessage') | |||
fprintf('!! Submission failed: %s\n', response.errorMessage); | |||
else | |||
showFeedback(parts, response); | |||
save(tokenFile, 'email', 'token'); | |||
end | |||
end | |||
function [email token] = promptToken(email, existingToken, tokenFile) | |||
if (~isempty(email) && ~isempty(existingToken)) | |||
prompt = sprintf( ... | |||
'Use token from last successful submission (%s)? (Y/n): ', ... | |||
email); | |||
reenter = input(prompt, 's'); | |||
if (isempty(reenter) || reenter(1) == 'Y' || reenter(1) == 'y') | |||
token = existingToken; | |||
return; | |||
else | |||
delete(tokenFile); | |||
end | |||
end | |||
email = input('Login (email address): ', 's'); | |||
token = input('Token: ', 's'); | |||
end | |||
function isValid = isValidPartOptionIndex(partOptions, i) | |||
isValid = (~isempty(i)) && (1 <= i) && (i <= numel(partOptions)); | |||
end | |||
function response = submitParts(conf, email, token, parts) | |||
body = makePostBody(conf, email, token, parts); | |||
submissionUrl = submissionUrl(); | |||
params = {'jsonBody', body}; | |||
[code, responseBody] = system(sprintf('echo jsonBody=%s | curl -k -X POST -d @- %s', body, submissionUrl)); | |||
response = loadjson(responseBody); | |||
end | |||
function body = makePostBody(conf, email, token, parts) | |||
bodyStruct.assignmentSlug = conf.assignmentSlug; | |||
bodyStruct.submitterEmail = email; | |||
bodyStruct.secret = token; | |||
bodyStruct.parts = makePartsStruct(conf, parts); | |||
opt.Compact = 1; | |||
body = savejson('', bodyStruct, opt); | |||
end | |||
function partsStruct = makePartsStruct(conf, parts) | |||
for part = parts | |||
partId = part{:}.id; | |||
fieldName = makeValidFieldName(partId); | |||
outputStruct.output = conf.output(partId); | |||
partsStruct.(fieldName) = outputStruct; | |||
end | |||
end | |||
function [parts] = parts(conf) | |||
parts = {}; | |||
for partArray = conf.partArrays | |||
part.id = partArray{:}{1}; | |||
part.sourceFiles = partArray{:}{2}; | |||
part.name = partArray{:}{3}; | |||
parts{end + 1} = part; | |||
end | |||
end | |||
function showFeedback(parts, response) | |||
fprintf('== \n'); | |||
fprintf('== %43s | %9s | %-s\n', 'Part Name', 'Score', 'Feedback'); | |||
fprintf('== %43s | %9s | %-s\n', '---------', '-----', '--------'); | |||
for part = parts | |||
score = ''; | |||
partFeedback = ''; | |||
partFeedback = response.partFeedbacks.(makeValidFieldName(part{:}.id)); | |||
partEvaluation = response.partEvaluations.(makeValidFieldName(part{:}.id)); | |||
score = sprintf('%d / %3d', partEvaluation.score, partEvaluation.maxScore); | |||
fprintf('== %43s | %9s | %-s\n', part{:}.name, score, partFeedback); | |||
end | |||
evaluation = response.evaluation; | |||
totalScore = sprintf('%d / %d', evaluation.score, evaluation.maxScore); | |||
fprintf('== --------------------------------\n'); | |||
fprintf('== %43s | %9s | %-s\n', '', totalScore, ''); | |||
fprintf('== \n'); | |||
end | |||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |||
% | |||
% Service configuration | |||
% | |||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |||
function submissionUrl = submissionUrl() | |||
submissionUrl = 'https://www-origin.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1'; | |||
end |
@@ -1,21 +0,0 @@ | |||
function out = mapFeature(X1, X2) | |||
% MAPFEATURE Feature mapping function to polynomial features | |||
% | |||
% MAPFEATURE(X1, X2) maps the two input features | |||
% to quadratic features used in the regularization exercise. | |||
% | |||
% Returns a new feature array with more features, comprising of | |||
% X1, X2, X1.^2, X2.^2, X1*X2, X1*X2.^2, etc.. | |||
% | |||
% Inputs X1, X2 must be the same size | |||
% | |||
degree = 6; | |||
out = ones(size(X1(:,1))); | |||
for i = 1:degree | |||
for j = 0:i | |||
out(:, end+1) = (X1.^(i-j)).*(X2.^j); | |||
end | |||
end | |||
end |
@@ -1,30 +0,0 @@ | |||
function plotData(X, y) | |||
%PLOTDATA Plots the data points X and y into a new figure | |||
% PLOTDATA(x,y) plots the data points with + for the positive examples | |||
% and o for the negative examples. X is assumed to be a Mx2 matrix. | |||
% Create New Figure | |||
figure; hold on; | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Plot the positive and negative examples on a | |||
% 2D plot, using the option 'k+' for the positive | |||
% examples and 'ko' for the negative examples. | |||
% | |||
pos = find(y == 1); | |||
neg = find(y == 0); | |||
plot(X(pos, 1), X(pos, 2), 'k+' ,'LineWidth', 2, 'MarkerSize', 7); | |||
plot(X(neg, 1), X(neg, 2), 'ko', 'MarkerFaceColor', 'y', 'MarkerSize', 7); | |||
% ========================================================================= | |||
hold off; | |||
end |
@@ -1,48 +0,0 @@ | |||
function plotDecisionBoundary(theta, X, y) | |||
%PLOTDECISIONBOUNDARY Plots the data points X and y into a new figure with | |||
%the decision boundary defined by theta | |||
% PLOTDECISIONBOUNDARY(theta, X,y) plots the data points with + for the | |||
% positive examples and o for the negative examples. X is assumed to be | |||
% a either | |||
% 1) Mx3 matrix, where the first column is an all-ones column for the | |||
% intercept. | |||
% 2) MxN, N>3 matrix, where the first column is all-ones | |||
% Plot Data | |||
plotData(X(:,2:3), y); | |||
hold on | |||
if size(X, 2) <= 3 | |||
% Only need 2 points to define a line, so choose two endpoints | |||
plot_x = [min(X(:,2))-2, max(X(:,2))+2]; | |||
% Calculate the decision boundary line | |||
plot_y = (-1./theta(3)).*(theta(2).*plot_x + theta(1)); | |||
% Plot, and adjust axes for better viewing | |||
plot(plot_x, plot_y) | |||
% Legend, specific for the exercise | |||
legend('Admitted', 'Not admitted', 'Decision Boundary') | |||
axis([30, 100, 30, 100]) | |||
else | |||
% Here is the grid range | |||
u = linspace(-1, 1.5, 50); | |||
v = linspace(-1, 1.5, 50); | |||
z = zeros(length(u), length(v)); | |||
% Evaluate z = theta*x over the grid | |||
for i = 1:length(u) | |||
for j = 1:length(v) | |||
z(i,j) = mapFeature(u(i), v(j))*theta; | |||
end | |||
end | |||
z = z'; % important to transpose z before calling contour | |||
% Plot z = 0 | |||
% Notice you need to specify the range [0, 0] | |||
contour(u, v, z, [0, 0], 'LineWidth', 2) | |||
end | |||
hold off | |||
end |
@@ -1,27 +0,0 @@ | |||
function p = predict(theta, X) | |||
%PREDICT Predict whether the label is 0 or 1 using learned logistic | |||
%regression parameters theta | |||
% p = PREDICT(theta, X) computes the predictions for X using a | |||
% threshold at 0.5 (i.e., if sigmoid(theta'*x) >= 0.5, predict 1) | |||
m = size(X, 1); % Number of training examples | |||
% You need to return the following variables correctly | |||
p = zeros(m, 1); | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Complete the following code to make predictions using | |||
% your learned logistic regression parameters. | |||
% You should set p to a vector of 0's and 1's | |||
% | |||
prob = sigmoid(X * theta); | |||
pos = find(prob >= 0.5); | |||
p(pos,1) = 1; | |||
% ========================================================================= | |||
end |
@@ -1,19 +0,0 @@ | |||
function g = sigmoid(z) | |||
%SIGMOID Compute sigmoid functoon | |||
% J = SIGMOID(z) computes the sigmoid of z. | |||
% You need to return the following variables correctly | |||
g = zeros(size(z)); | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Compute the sigmoid of each value of z (z can be a matrix, | |||
% vector or scalar). | |||
%g = 1 ./ (1 .+ e .^ -z); | |||
g = 1.0 ./ (1.0 + exp(-z));%exp(n)-->e的n次方 | |||
% ============================================================= | |||
end |
@@ -1,62 +0,0 @@ | |||
function submit() | |||
addpath('./lib'); | |||
conf.assignmentSlug = 'logistic-regression'; | |||
conf.itemName = 'Logistic Regression'; | |||
conf.partArrays = { ... | |||
{ ... | |||
'1', ... | |||
{ 'sigmoid.m' }, ... | |||
'Sigmoid Function', ... | |||
}, ... | |||
{ ... | |||
'2', ... | |||
{ 'costFunction.m' }, ... | |||
'Logistic Regression Cost', ... | |||
}, ... | |||
{ ... | |||
'3', ... | |||
{ 'costFunction.m' }, ... | |||
'Logistic Regression Gradient', ... | |||
}, ... | |||
{ ... | |||
'4', ... | |||
{ 'predict.m' }, ... | |||
'Predict', ... | |||
}, ... | |||
{ ... | |||
'5', ... | |||
{ 'costFunctionReg.m' }, ... | |||
'Regularized Logistic Regression Cost', ... | |||
}, ... | |||
{ ... | |||
'6', ... | |||
{ 'costFunctionReg.m' }, ... | |||
'Regularized Logistic Regression Gradient', ... | |||
}, ... | |||
}; | |||
conf.output = @output; | |||
submitWithConfiguration(conf); | |||
end | |||
function out = output(partId, auxstring) | |||
% Random Test Cases | |||
X = [ones(20,1) (exp(1) * sin(1:1:20))' (exp(0.5) * cos(1:1:20))']; | |||
y = sin(X(:,1) + X(:,2)) > 0; | |||
if partId == '1' | |||
out = sprintf('%0.5f ', sigmoid(X)); | |||
elseif partId == '2' | |||
out = sprintf('%0.5f ', costFunction([0.25 0.5 -0.5]', X, y)); | |||
elseif partId == '3' | |||
[cost, grad] = costFunction([0.25 0.5 -0.5]', X, y); | |||
out = sprintf('%0.5f ', grad); | |||
elseif partId == '4' | |||
out = sprintf('%0.5f ', predict([0.25 0.5 -0.5]', X)); | |||
elseif partId == '5' | |||
out = sprintf('%0.5f ', costFunctionReg([0.25 0.5 -0.5]', X, y, 0.1)); | |||
elseif partId == '6' | |||
[cost, grad] = costFunctionReg([0.25 0.5 -0.5]', X, y, 0.1); | |||
out = sprintf('%0.5f ', grad); | |||
end | |||
end |
@@ -1,15 +0,0 @@ | |||
# Created by Octave 4.2.0, Sat Nov 19 20:17:18 2016 GMT <unknown@unknown> | |||
# name: email | |||
# type: sq_string | |||
# elements: 1 | |||
# length: 17 | |||
scruel@vip.qq.com | |||
# name: token | |||
# type: sq_string | |||
# elements: 1 | |||
# length: 16 | |||
A3Wc4pI1qYjCUaRB | |||
@@ -1,59 +0,0 @@ | |||
function [h, display_array] = displayData(X, example_width) | |||
%DISPLAYDATA Display 2D data in a nice grid | |||
% [h, display_array] = DISPLAYDATA(X, example_width) displays 2D data | |||
% stored in X in a nice grid. It returns the figure handle h and the | |||
% displayed array if requested. | |||
% Set example_width automatically if not passed in | |||
if ~exist('example_width', 'var') || isempty(example_width) | |||
example_width = round(sqrt(size(X, 2))); | |||
end | |||
% Gray Image | |||
colormap(gray); | |||
% Compute rows, cols | |||
[m n] = size(X); | |||
example_height = (n / example_width); | |||
% Compute number of items to display | |||
display_rows = floor(sqrt(m)); | |||
display_cols = ceil(m / display_rows); | |||
% Between images padding | |||
pad = 1; | |||
% Setup blank display | |||
display_array = - ones(pad + display_rows * (example_height + pad), ... | |||
pad + display_cols * (example_width + pad)); | |||
% Copy each example into a patch on the display array | |||
curr_ex = 1; | |||
for j = 1:display_rows | |||
for i = 1:display_cols | |||
if curr_ex > m, | |||
break; | |||
end | |||
% Copy the patch | |||
% Get the max value of the patch | |||
max_val = max(abs(X(curr_ex, :))); | |||
display_array(pad + (j - 1) * (example_height + pad) + (1:example_height), ... | |||
pad + (i - 1) * (example_width + pad) + (1:example_width)) = ... | |||
reshape(X(curr_ex, :), example_height, example_width) / max_val; | |||
curr_ex = curr_ex + 1; | |||
end | |||
if curr_ex > m, | |||
break; | |||
end | |||
end | |||
% Display Image | |||
h = imagesc(display_array, [-1 1]); | |||
% Do not show axis | |||
axis image off | |||
drawnow; | |||
end |
@@ -1,69 +0,0 @@ | |||
%% Machine Learning Online Class - Exercise 3 | Part 1: One-vs-all | |||
% Instructions | |||
% ------------ | |||
% | |||
% This file contains code that helps you get started on the | |||
% linear exercise. You will need to complete the following functions | |||
% in this exericse: | |||
% | |||
% lrCostFunction.m (logistic regression cost function) | |||
% oneVsAll.m | |||
% predictOneVsAll.m | |||
% predict.m | |||
% | |||
% For this exercise, you will not need to change any code in this file, | |||
% or any other files other than those mentioned above. | |||
% | |||
%% Initialization | |||
clear ; close all; clc | |||
%% Setup the parameters you will use for this part of the exercise | |||
input_layer_size = 400; % 20x20 Input Images of Digits | |||
num_labels = 10; % 10 labels, from 1 to 10 ~k | |||
% (note that we have mapped "0" to label 10) | |||
%% =========== Part 1: Loading and Visualizing Data ============= | |||
% We start the exercise by first loading and visualizing the dataset. | |||
% You will be working with a dataset that contains handwritten digits. | |||
% | |||
% Load Training Data | |||
fprintf('Loading and Visualizing Data ...\n') | |||
load('ex3data1.mat'); % training data stored in arrays X, y | |||
m = size(X, 1); | |||
% Randomly select 100 data points to display | |||
%rand_indices = randperm(m); | |||
%sel = X(rand_indices(1:100), :); | |||
%displayData(sel); | |||
%fprintf('Program paused. Press enter to continue.\n'); | |||
%pause; | |||
%% ============ Part 2: Vectorize Logistic Regression ============ | |||
% In this part of the exercise, you will reuse your logistic regression | |||
% code from the last exercise. You task here is to make sure that your | |||
% regularized logistic regression implementation is vectorized. After | |||
% that, you will implement one-vs-all classification for the handwritten | |||
% digit dataset. | |||
% | |||
fprintf('\nTraining One-vs-All Logistic Regression...\n') | |||
lambda = 0.1; | |||
[all_theta] = oneVsAll(X, y, num_labels, lambda); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% ================ Part 3: Predict for One-Vs-All ================ | |||
% After ... | |||
pred = predictOneVsAll(all_theta, X); | |||
fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100); | |||
@@ -1,88 +0,0 @@ | |||
%% Machine Learning Online Class - Exercise 3 | Part 2: Neural Networks | |||
% Instructions | |||
% ------------ | |||
% | |||
% This file contains code that helps you get started on the | |||
% linear exercise. You will need to complete the following functions | |||
% in this exericse: | |||
% | |||
% lrCostFunction.m (logistic regression cost function) | |||
% oneVsAll.m | |||
% predictOneVsAll.m | |||
% predict.m | |||
% | |||
% For this exercise, you will not need to change any code in this file, | |||
% or any other files other than those mentioned above. | |||
% | |||
%% Initialization | |||
clear ; close all; clc | |||
%% Setup the parameters you will use for this exercise | |||
input_layer_size = 400; % 20x20 Input Images of Digits | |||
hidden_layer_size = 25; % 25 hidden units | |||
num_labels = 10; % 10 labels, from 1 to 10 | |||
% (note that we have mapped "0" to label 10) | |||
%% =========== Part 1: Loading and Visualizing Data ============= | |||
% We start the exercise by first loading and visualizing the dataset. | |||
% You will be working with a dataset that contains handwritten digits. | |||
% | |||
% Load Training Data | |||
fprintf('Loading and Visualizing Data ...\n') | |||
load('ex3data1.mat'); | |||
m = size(X, 1); | |||
% Randomly select 100 data points to display | |||
sel = randperm(size(X, 1)); | |||
sel = sel(1:100); | |||
displayData(X(sel, :)); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% ================ Part 2: Loading Pameters ================ | |||
% In this part of the exercise, we load some pre-initialized | |||
% neural network parameters. | |||
fprintf('\nLoading Saved Neural Network Parameters ...\n') | |||
% Load the weights into variables Theta1 and Theta2 | |||
load('ex3weights.mat'); | |||
%% ================= Part 3: Implement Predict ================= | |||
% After training the neural network, we would like to use it to predict | |||
% the labels. You will now implement the "predict" function to use the | |||
% neural network to predict the labels of the training set. This lets | |||
% you compute the training set accuracy. | |||
%Theta1,Theta2 = fmincg(@CostFunction, initial_theta, option) | |||
pred = predict(Theta1, Theta2, X); | |||
fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
% To give you an idea of the network's output, you can also run | |||
% through the examples one at the a time to see what it is predicting. | |||
% Randomly permute examples | |||
rp = randperm(m); | |||
for i = 1:m | |||
% Display | |||
fprintf('\nDisplaying Example Image\n'); | |||
displayData(X(rp(i), :)); | |||
pred = predict(Theta1, Theta2, X(rp(i),:)); | |||
fprintf('\nNeural Network Prediction: %d (digit %d)\n', pred, mod(pred, 10)); | |||
% Pause | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
end | |||
@@ -1,175 +0,0 @@ | |||
function [X, fX, i] = fmincg(f, X, options, P1, P2, P3, P4, P5) | |||
% Minimize a continuous differentialble multivariate function. Starting point | |||
% is given by "X" (D by 1), and the function named in the string "f", must | |||
% return a function value and a vector of partial derivatives. The Polack- | |||
% Ribiere flavour of conjugate gradients is used to compute search directions, | |||
% and a line search using quadratic and cubic polynomial approximations and the | |||
% Wolfe-Powell stopping criteria is used together with the slope ratio method | |||
% for guessing initial step sizes. Additionally a bunch of checks are made to | |||
% make sure that exploration is taking place and that extrapolation will not | |||
% be unboundedly large. The "length" gives the length of the run: if it is | |||
% positive, it gives the maximum number of line searches, if negative its | |||
% absolute gives the maximum allowed number of function evaluations. You can | |||
% (optionally) give "length" a second component, which will indicate the | |||
% reduction in function value to be expected in the first line-search (defaults | |||
% to 1.0). The function returns when either its length is up, or if no further | |||
% progress can be made (ie, we are at a minimum, or so close that due to | |||
% numerical problems, we cannot get any closer). If the function terminates | |||
% within a few iterations, it could be an indication that the function value | |||
% and derivatives are not consistent (ie, there may be a bug in the | |||
% implementation of your "f" function). The function returns the found | |||
% solution "X", a vector of function values "fX" indicating the progress made | |||
% and "i" the number of iterations (line searches or function evaluations, | |||
% depending on the sign of "length") used. | |||
% | |||
% Usage: [X, fX, i] = fmincg(f, X, options, P1, P2, P3, P4, P5) | |||
% | |||
% See also: checkgrad | |||
% | |||
% Copyright (C) 2001 and 2002 by Carl Edward Rasmussen. Date 2002-02-13 | |||
% | |||
% | |||
% (C) Copyright 1999, 2000 & 2001, Carl Edward Rasmussen | |||
% | |||
% Permission is granted for anyone to copy, use, or modify these | |||
% programs and accompanying documents for purposes of research or | |||
% education, provided this copyright notice is retained, and note is | |||
% made of any changes that have been made. | |||
% | |||
% These programs and documents are distributed without any warranty, | |||
% express or implied. As the programs were written for research | |||
% purposes only, they have not been tested to the degree that would be | |||
% advisable in any important application. All use of these programs is | |||
% entirely at the user's own risk. | |||
% | |||
% [ml-class] Changes Made: | |||
% 1) Function name and argument specifications | |||
% 2) Output display | |||
% | |||
% Read options | |||
if exist('options', 'var') && ~isempty(options) && isfield(options, 'MaxIter') | |||
length = options.MaxIter; | |||
else | |||
length = 100; | |||
end | |||
RHO = 0.01; % a bunch of constants for line searches | |||
SIG = 0.5; % RHO and SIG are the constants in the Wolfe-Powell conditions | |||
INT = 0.1; % don't reevaluate within 0.1 of the limit of the current bracket | |||
EXT = 3.0; % extrapolate maximum 3 times the current bracket | |||
MAX = 20; % max 20 function evaluations per line search | |||
RATIO = 100; % maximum allowed slope ratio | |||
argstr = ['feval(f, X']; % compose string used to call function | |||
for i = 1:(nargin - 3) | |||
argstr = [argstr, ',P', int2str(i)]; | |||
end | |||
argstr = [argstr, ')']; | |||
if max(size(length)) == 2, red=length(2); length=length(1); else red=1; end | |||
S=['Iteration ']; | |||
i = 0; % zero the run length counter | |||
ls_failed = 0; % no previous line search has failed | |||
fX = []; | |||
[f1 df1] = eval(argstr); % get function value and gradient | |||
i = i + (length<0); % count epochs?! | |||
s = -df1; % search direction is steepest | |||
d1 = -s'*s; % this is the slope | |||
z1 = red/(1-d1); % initial step is red/(|s|+1) | |||
while i < abs(length) % while not finished | |||
i = i + (length>0); % count iterations?! | |||
X0 = X; f0 = f1; df0 = df1; % make a copy of current values | |||
X = X + z1*s; % begin line search | |||
[f2 df2] = eval(argstr); | |||
i = i + (length<0); % count epochs?! | |||
d2 = df2'*s; | |||
f3 = f1; d3 = d1; z3 = -z1; % initialize point 3 equal to point 1 | |||
if length>0, M = MAX; else M = min(MAX, -length-i); end | |||
success = 0; limit = -1; % initialize quanteties | |||
while 1 | |||
while ((f2 > f1+z1*RHO*d1) || (d2 > -SIG*d1)) && (M > 0) | |||
limit = z1; % tighten the bracket | |||
if f2 > f1 | |||
z2 = z3 - (0.5*d3*z3*z3)/(d3*z3+f2-f3); % quadratic fit | |||
else | |||
A = 6*(f2-f3)/z3+3*(d2+d3); % cubic fit | |||
B = 3*(f3-f2)-z3*(d3+2*d2); | |||
z2 = (sqrt(B*B-A*d2*z3*z3)-B)/A; % numerical error possible - ok! | |||
end | |||
if isnan(z2) || isinf(z2) | |||
z2 = z3/2; % if we had a numerical problem then bisect | |||
end | |||
z2 = max(min(z2, INT*z3),(1-INT)*z3); % don't accept too close to limits | |||
z1 = z1 + z2; % update the step | |||
X = X + z2*s; | |||
[f2 df2] = eval(argstr); | |||
M = M - 1; i = i + (length<0); % count epochs?! | |||
d2 = df2'*s; | |||
z3 = z3-z2; % z3 is now relative to the location of z2 | |||
end | |||
if f2 > f1+z1*RHO*d1 || d2 > -SIG*d1 | |||
break; % this is a failure | |||
elseif d2 > SIG*d1 | |||
success = 1; break; % success | |||
elseif M == 0 | |||
break; % failure | |||
end | |||
A = 6*(f2-f3)/z3+3*(d2+d3); % make cubic extrapolation | |||
B = 3*(f3-f2)-z3*(d3+2*d2); | |||
z2 = -d2*z3*z3/(B+sqrt(B*B-A*d2*z3*z3)); % num. error possible - ok! | |||
if ~isreal(z2) || isnan(z2) || isinf(z2) || z2 < 0 % num prob or wrong sign? | |||
if limit < -0.5 % if we have no upper limit | |||
z2 = z1 * (EXT-1); % the extrapolate the maximum amount | |||
else | |||
z2 = (limit-z1)/2; % otherwise bisect | |||
end | |||
elseif (limit > -0.5) && (z2+z1 > limit) % extraplation beyond max? | |||
z2 = (limit-z1)/2; % bisect | |||
elseif (limit < -0.5) && (z2+z1 > z1*EXT) % extrapolation beyond limit | |||
z2 = z1*(EXT-1.0); % set to extrapolation limit | |||
elseif z2 < -z3*INT | |||
z2 = -z3*INT; | |||
elseif (limit > -0.5) && (z2 < (limit-z1)*(1.0-INT)) % too close to limit? | |||
z2 = (limit-z1)*(1.0-INT); | |||
end | |||
f3 = f2; d3 = d2; z3 = -z2; % set point 3 equal to point 2 | |||
z1 = z1 + z2; X = X + z2*s; % update current estimates | |||
[f2 df2] = eval(argstr); | |||
M = M - 1; i = i + (length<0); % count epochs?! | |||
d2 = df2'*s; | |||
end % end of line search | |||
if success % if line search succeeded | |||
f1 = f2; fX = [fX' f1]'; | |||
fprintf('%s %4i | Cost: %4.6e\r', S, i, f1); | |||
s = (df2'*df2-df1'*df2)/(df1'*df1)*s - df2; % Polack-Ribiere direction | |||
tmp = df1; df1 = df2; df2 = tmp; % swap derivatives | |||
d2 = df1'*s; | |||
if d2 > 0 % new slope must be negative | |||
s = -df1; % otherwise use steepest direction | |||
d2 = -s'*s; | |||
end | |||
z1 = z1 * min(RATIO, d1/(d2-realmin)); % slope ratio but max RATIO | |||
d1 = d2; | |||
ls_failed = 0; % this line search did not fail | |||
else | |||
X = X0; f1 = f0; df1 = df0; % restore point from before failed line search | |||
if ls_failed || i > abs(length) % line search failed twice in a row | |||
break; % or we ran out of time, so we give up | |||
end | |||
tmp = df1; df1 = df2; df2 = tmp; % swap derivatives | |||
s = -df1; % try steepest | |||
d1 = -s'*s; | |||
z1 = 1/(1-d1); | |||
ls_failed = 1; % this line search failed | |||
end | |||
if exist('OCTAVE_VERSION') | |||
fflush(stdout); | |||
end | |||
end | |||
fprintf('\n'); |
@@ -1,41 +0,0 @@ | |||
The author of "jsonlab" toolbox is Qianqian Fang. Qianqian | |||
is currently an Assistant Professor at Massachusetts General Hospital, | |||
Harvard Medical School. | |||
Address: Martinos Center for Biomedical Imaging, | |||
Massachusetts General Hospital, | |||
Harvard Medical School | |||
Bldg 149, 13th St, Charlestown, MA 02129, USA | |||
URL: http://nmr.mgh.harvard.edu/~fangq/ | |||
Email: <fangq at nmr.mgh.harvard.edu> or <fangqq at gmail.com> | |||
The script loadjson.m was built upon previous works by | |||
- Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713 | |||
date: 2009/11/02 | |||
- François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393 | |||
date: 2009/03/22 | |||
- Joel Feenstra: http://www.mathworks.com/matlabcentral/fileexchange/20565 | |||
date: 2008/07/03 | |||
This toolbox contains patches submitted by the following contributors: | |||
- Blake Johnson <bjohnso at bbn.com> | |||
part of revision 341 | |||
- Niclas Borlin <Niclas.Borlin at cs.umu.se> | |||
various fixes in revision 394, including | |||
- loadjson crashes for all-zero sparse matrix. | |||
- loadjson crashes for empty sparse matrix. | |||
- Non-zero size of 0-by-N and N-by-0 empty matrices is lost after savejson/loadjson. | |||
- loadjson crashes for sparse real column vector. | |||
- loadjson crashes for sparse complex column vector. | |||
- Data is corrupted by savejson for sparse real row vector. | |||
- savejson crashes for sparse complex row vector. | |||
- Yul Kang <yul.kang.on at gmail.com> | |||
patches for svn revision 415. | |||
- savejson saves an empty cell array as [] instead of null | |||
- loadjson differentiates an empty struct from an empty array |
@@ -1,74 +0,0 @@ | |||
============================================================================ | |||
JSONlab - a toolbox to encode/decode JSON/UBJSON files in MATLAB/Octave | |||
---------------------------------------------------------------------------- | |||
JSONlab ChangeLog (key features marked by *): | |||
== JSONlab 1.0 (codename: Optimus - Final), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2015/01/02 polish help info for all major functions, update examples, finalize 1.0 | |||
2014/12/19 fix a bug to strictly respect NoRowBracket in savejson | |||
== JSONlab 1.0.0-RC2 (codename: Optimus - RC2), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2014/11/22 show progress bar in loadjson ('ShowProgress') | |||
2014/11/17 add Compact option in savejson to output compact JSON format ('Compact') | |||
2014/11/17 add FastArrayParser in loadjson to specify fast parser applicable levels | |||
2014/09/18 start official github mirror: https://github.com/fangq/jsonlab | |||
== JSONlab 1.0.0-RC1 (codename: Optimus - RC1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2014/09/17 fix several compatibility issues when running on octave versions 3.2-3.8 | |||
2014/09/17 support 2D cell and struct arrays in both savejson and saveubjson | |||
2014/08/04 escape special characters in a JSON string | |||
2014/02/16 fix a bug when saving ubjson files | |||
== JSONlab 0.9.9 (codename: Optimus - beta), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2014/01/22 use binary read and write in saveubjson and loadubjson | |||
== JSONlab 0.9.8-1 (codename: Optimus - alpha update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2013/10/07 better round-trip conservation for empty arrays and structs (patch submitted by Yul Kang) | |||
== JSONlab 0.9.8 (codename: Optimus - alpha), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2013/08/23 *universal Binary JSON (UBJSON) support, including both saveubjson and loadubjson | |||
== JSONlab 0.9.1 (codename: Rodimus, update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/12/18 *handling of various empty and sparse matrices (fixes submitted by Niclas Borlin) | |||
== JSONlab 0.9.0 (codename: Rodimus), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/06/17 *new format for an invalid leading char, unpacking hex code in savejson | |||
2012/06/01 support JSONP in savejson | |||
2012/05/25 fix the empty cell bug (reported by Cyril Davin) | |||
2012/04/05 savejson can save to a file (suggested by Patrick Rapin) | |||
== JSONlab 0.8.1 (codename: Sentiel, Update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/02/28 loadjson quotation mark escape bug, see http://bit.ly/yyk1nS | |||
2012/01/25 patch to handle root-less objects, contributed by Blake Johnson | |||
== JSONlab 0.8.0 (codename: Sentiel), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2012/01/13 *speed up loadjson by 20 fold when parsing large data arrays in matlab | |||
2012/01/11 remove row bracket if an array has 1 element, suggested by Mykel Kochenderfer | |||
2011/12/22 *accept sequence of 'param',value input in savejson and loadjson | |||
2011/11/18 fix struct array bug reported by Mykel Kochenderfer | |||
== JSONlab 0.5.1 (codename: Nexus Update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2011/10/21 fix a bug in loadjson, previous code does not use any of the acceleration | |||
2011/10/20 loadjson supports JSON collections - concatenated JSON objects | |||
== JSONlab 0.5.0 (codename: Nexus), FangQ <fangq (at) nmr.mgh.harvard.edu> == | |||
2011/10/16 package and release jsonlab 0.5.0 | |||
2011/10/15 *add json demo and regression test, support cpx numbers, fix double quote bug | |||
2011/10/11 *speed up readjson dramatically, interpret _Array* tags, show data in root level | |||
2011/10/10 create jsonlab project, start jsonlab website, add online documentation | |||
2011/10/07 *speed up savejson by 25x using sprintf instead of mat2str, add options support | |||
2011/10/06 *savejson works for structs, cells and arrays | |||
2011/09/09 derive loadjson from JSON parser from MATLAB Central, draft savejson.m |
@@ -1,25 +0,0 @@ | |||
Copyright 2011-2015 Qianqian Fang <fangq at nmr.mgh.harvard.edu>. All rights reserved. | |||
Redistribution and use in source and binary forms, with or without modification, are | |||
permitted provided that the following conditions are met: | |||
1. Redistributions of source code must retain the above copyright notice, this list of | |||
conditions and the following disclaimer. | |||
2. Redistributions in binary form must reproduce the above copyright notice, this list | |||
of conditions and the following disclaimer in the documentation and/or other materials | |||
provided with the distribution. | |||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED | |||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS | |||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
The views and conclusions contained in the software and documentation are those of the | |||
authors and should not be interpreted as representing official policies, either expressed | |||
or implied, of the copyright holders. |
@@ -1,394 +0,0 @@ | |||
=============================================================================== | |||
= JSONLab = | |||
= An open-source MATLAB/Octave JSON encoder and decoder = | |||
=============================================================================== | |||
*Copyright (C) 2011-2015 Qianqian Fang <fangq at nmr.mgh.harvard.edu> | |||
*License: BSD License, see License_BSD.txt for details | |||
*Version: 1.0 (Optimus - Final) | |||
------------------------------------------------------------------------------- | |||
Table of Content: | |||
I. Introduction | |||
II. Installation | |||
III.Using JSONLab | |||
IV. Known Issues and TODOs | |||
V. Contribution and feedback | |||
------------------------------------------------------------------------------- | |||
I. Introduction | |||
JSON ([http://www.json.org/ JavaScript Object Notation]) is a highly portable, | |||
human-readable and "[http://en.wikipedia.org/wiki/JSON fat-free]" text format | |||
to represent complex and hierarchical data. It is as powerful as | |||
[http://en.wikipedia.org/wiki/XML XML], but less verbose. JSON format is widely | |||
used for data-exchange in applications, and is essential for the wild success | |||
of [http://en.wikipedia.org/wiki/Ajax_(programming) Ajax] and | |||
[http://en.wikipedia.org/wiki/Web_2.0 Web2.0]. | |||
UBJSON (Universal Binary JSON) is a binary JSON format, specifically | |||
optimized for compact file size and better performance while keeping | |||
the semantics as simple as the text-based JSON format. Using the UBJSON | |||
format allows to wrap complex binary data in a flexible and extensible | |||
structure, making it possible to process complex and large dataset | |||
without accuracy loss due to text conversions. | |||
We envision that both JSON and its binary version will serve as part of | |||
the mainstream data-exchange formats for scientific research in the future. | |||
It will provide the flexibility and generality achieved by other popular | |||
general-purpose file specifications, such as | |||
[http://www.hdfgroup.org/HDF5/whatishdf5.html HDF5], with significantly | |||
reduced complexity and enhanced performance. | |||
JSONLab is a free and open-source implementation of a JSON/UBJSON encoder | |||
and a decoder in the native MATLAB language. It can be used to convert a MATLAB | |||
data structure (array, struct, cell, struct array and cell array) into | |||
JSON/UBJSON formatted strings, or to decode a JSON/UBJSON file into MATLAB | |||
data structure. JSONLab supports both MATLAB and | |||
[http://www.gnu.org/software/octave/ GNU Octave] (a free MATLAB clone). | |||
------------------------------------------------------------------------------- | |||
II. Installation | |||
The installation of JSONLab is no different than any other simple | |||
MATLAB toolbox. You only need to download/unzip the JSONLab package | |||
to a folder, and add the folder's path to MATLAB/Octave's path list | |||
by using the following command: | |||
addpath('/path/to/jsonlab'); | |||
If you want to add this path permanently, you need to type "pathtool", | |||
browse to the jsonlab root folder and add to the list, then click "Save". | |||
Then, run "rehash" in MATLAB, and type "which loadjson", if you see an | |||
output, that means JSONLab is installed for MATLAB/Octave. | |||
------------------------------------------------------------------------------- | |||
III.Using JSONLab | |||
JSONLab provides two functions, loadjson.m -- a MATLAB->JSON decoder, | |||
and savejson.m -- a MATLAB->JSON encoder, for the text-based JSON, and | |||
two equivallent functions -- loadubjson and saveubjson for the binary | |||
JSON. The detailed help info for the four functions can be found below: | |||
=== loadjson.m === | |||
<pre> | |||
data=loadjson(fname,opt) | |||
or | |||
data=loadjson(fname,'param1',value1,'param2',value2,...) | |||
parse a JSON (JavaScript Object Notation) file or string | |||
authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2011/09/09, including previous works from | |||
Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713 | |||
created on 2009/11/02 | |||
François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393 | |||
created on 2009/03/22 | |||
Joel Feenstra: | |||
http://www.mathworks.com/matlabcentral/fileexchange/20565 | |||
created on 2008/07/03 | |||
$Id: loadjson.m 452 2014-11-22 16:43:33Z fangq $ | |||
input: | |||
fname: input file name, if fname contains "{}" or "[]", fname | |||
will be interpreted as a JSON string | |||
opt: a struct to store parsing options, opt can be replaced by | |||
a list of ('param',value) pairs - the param string is equivallent | |||
to a field in opt. opt can have the following | |||
fields (first in [.|.] is the default) | |||
opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat | |||
for each element of the JSON data, and group | |||
arrays based on the cell2mat rules. | |||
opt.FastArrayParser [1|0 or integer]: if set to 1, use a | |||
speed-optimized array parser when loading an | |||
array object. The fast array parser may | |||
collapse block arrays into a single large | |||
array similar to rules defined in cell2mat; 0 to | |||
use a legacy parser; if set to a larger-than-1 | |||
value, this option will specify the minimum | |||
dimension to enable the fast array parser. For | |||
example, if the input is a 3D array, setting | |||
FastArrayParser to 1 will return a 3D array; | |||
setting to 2 will return a cell array of 2D | |||
arrays; setting to 3 will return to a 2D cell | |||
array of 1D vectors; setting to 4 will return a | |||
3D cell array. | |||
opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar. | |||
output: | |||
dat: a cell array, where {...} blocks are converted into cell arrays, | |||
and [...] are converted to arrays | |||
examples: | |||
dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}') | |||
dat=loadjson(['examples' filesep 'example1.json']) | |||
dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1) | |||
</pre> | |||
=== savejson.m === | |||
<pre> | |||
json=savejson(rootname,obj,filename) | |||
or | |||
json=savejson(rootname,obj,opt) | |||
json=savejson(rootname,obj,'param1',value1,'param2',value2,...) | |||
convert a MATLAB object (cell, struct or array) into a JSON (JavaScript | |||
Object Notation) string | |||
author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2011/09/09 | |||
$Id: savejson.m 458 2014-12-19 22:17:17Z fangq $ | |||
input: | |||
rootname: the name of the root-object, when set to '', the root name | |||
is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
the MATLAB variable name will be used as the root name. | |||
obj: a MATLAB object (array, cell, cell array, struct, struct array). | |||
filename: a string for the file name to save the output JSON data. | |||
opt: a struct for additional options, ignore to use default values. | |||
opt can have the following fields (first in [.|.] is the default) | |||
opt.FileName [''|string]: a file name to save the output JSON data | |||
opt.FloatFormat ['%.10g'|string]: format to show each numeric element | |||
of a 1D/2D array; | |||
opt.ArrayIndent [1|0]: if 1, output explicit data array with | |||
precedent indentation; if 0, no indentation | |||
opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D | |||
array in JSON array format; if sets to 1, an | |||
array will be shown as a struct with fields | |||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
sparse arrays, the non-zero elements will be | |||
saved to _ArrayData_ field in triplet-format i.e. | |||
(ix,iy,val) and "_ArrayIsSparse_" will be added | |||
with a value of 1; for a complex array, the | |||
_ArrayData_ array will include two columns | |||
(4 for sparse) to record the real and imaginary | |||
parts, and also "_ArrayIsComplex_":1 is added. | |||
opt.ParseLogical [0|1]: if this is set to 1, logical array elem | |||
will use true/false rather than 1/0. | |||
opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
numerical element will be shown without a square | |||
bracket, unless it is the root object; if 0, square | |||
brackets are forced for any numerical arrays. | |||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson | |||
will use the name of the passed obj variable as the | |||
root object name; if obj is an expression and | |||
does not have a name, 'root' will be used; if this | |||
is set to 0 and rootname is empty, the root level | |||
will be merged down to the lower level. | |||
opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern | |||
to represent +/-Inf. The matched pattern is '([-+]*)Inf' | |||
and $1 represents the sign. For those who want to use | |||
1e999 to represent Inf, they can set opt.Inf to '$11e999' | |||
opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern | |||
to represent NaN | |||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
for example, if opt.JSONP='foo', the JSON data is | |||
wrapped inside a function call as 'foo(...);' | |||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
back to the string form | |||
opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode. | |||
opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs) | |||
opt can be replaced by a list of ('param',value) pairs. The param | |||
string is equivallent to a field in opt and is case sensitive. | |||
output: | |||
json: a string in the JSON format (see http://json.org) | |||
examples: | |||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
'SpecialData',[nan, inf, -inf]); | |||
savejson('jmesh',jsonmesh) | |||
savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g') | |||
</pre> | |||
=== loadubjson.m === | |||
<pre> | |||
data=loadubjson(fname,opt) | |||
or | |||
data=loadubjson(fname,'param1',value1,'param2',value2,...) | |||
parse a JSON (JavaScript Object Notation) file or string | |||
authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2013/08/01 | |||
$Id: loadubjson.m 436 2014-08-05 20:51:40Z fangq $ | |||
input: | |||
fname: input file name, if fname contains "{}" or "[]", fname | |||
will be interpreted as a UBJSON string | |||
opt: a struct to store parsing options, opt can be replaced by | |||
a list of ('param',value) pairs - the param string is equivallent | |||
to a field in opt. opt can have the following | |||
fields (first in [.|.] is the default) | |||
opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat | |||
for each element of the JSON data, and group | |||
arrays based on the cell2mat rules. | |||
opt.IntEndian [B|L]: specify the endianness of the integer fields | |||
in the UBJSON input data. B - Big-Endian format for | |||
integers (as required in the UBJSON specification); | |||
L - input integer fields are in Little-Endian order. | |||
output: | |||
dat: a cell array, where {...} blocks are converted into cell arrays, | |||
and [...] are converted to arrays | |||
examples: | |||
obj=struct('string','value','array',[1 2 3]); | |||
ubjdata=saveubjson('obj',obj); | |||
dat=loadubjson(ubjdata) | |||
dat=loadubjson(['examples' filesep 'example1.ubj']) | |||
dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1) | |||
</pre> | |||
=== saveubjson.m === | |||
<pre> | |||
json=saveubjson(rootname,obj,filename) | |||
or | |||
json=saveubjson(rootname,obj,opt) | |||
json=saveubjson(rootname,obj,'param1',value1,'param2',value2,...) | |||
convert a MATLAB object (cell, struct or array) into a Universal | |||
Binary JSON (UBJSON) binary string | |||
author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
created on 2013/08/17 | |||
$Id: saveubjson.m 440 2014-09-17 19:59:45Z fangq $ | |||
input: | |||
rootname: the name of the root-object, when set to '', the root name | |||
is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
the MATLAB variable name will be used as the root name. | |||
obj: a MATLAB object (array, cell, cell array, struct, struct array) | |||
filename: a string for the file name to save the output UBJSON data | |||
opt: a struct for additional options, ignore to use default values. | |||
opt can have the following fields (first in [.|.] is the default) | |||
opt.FileName [''|string]: a file name to save the output JSON data | |||
opt.ArrayToStruct[0|1]: when set to 0, saveubjson outputs 1D/2D | |||
array in JSON array format; if sets to 1, an | |||
array will be shown as a struct with fields | |||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
sparse arrays, the non-zero elements will be | |||
saved to _ArrayData_ field in triplet-format i.e. | |||
(ix,iy,val) and "_ArrayIsSparse_" will be added | |||
with a value of 1; for a complex array, the | |||
_ArrayData_ array will include two columns | |||
(4 for sparse) to record the real and imaginary | |||
parts, and also "_ArrayIsComplex_":1 is added. | |||
opt.ParseLogical [1|0]: if this is set to 1, logical array elem | |||
will use true/false rather than 1/0. | |||
opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
numerical element will be shown without a square | |||
bracket, unless it is the root object; if 0, square | |||
brackets are forced for any numerical arrays. | |||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, saveubjson | |||
will use the name of the passed obj variable as the | |||
root object name; if obj is an expression and | |||
does not have a name, 'root' will be used; if this | |||
is set to 0 and rootname is empty, the root level | |||
will be merged down to the lower level. | |||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
for example, if opt.JSON='foo', the JSON data is | |||
wrapped inside a function call as 'foo(...);' | |||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
back to the string form | |||
opt can be replaced by a list of ('param',value) pairs. The param | |||
string is equivallent to a field in opt and is case sensitive. | |||
output: | |||
json: a binary string in the UBJSON format (see http://ubjson.org) | |||
examples: | |||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
'SpecialData',[nan, inf, -inf]); | |||
saveubjson('jsonmesh',jsonmesh) | |||
saveubjson('jsonmesh',jsonmesh,'meshdata.ubj') | |||
</pre> | |||
=== examples === | |||
Under the "examples" folder, you can find several scripts to demonstrate the | |||
basic utilities of JSONLab. Running the "demo_jsonlab_basic.m" script, you | |||
will see the conversions from MATLAB data structure to JSON text and backward. | |||
In "jsonlab_selftest.m", we load complex JSON files downloaded from the Internet | |||
and validate the loadjson/savejson functions for regression testing purposes. | |||
Similarly, a "demo_ubjson_basic.m" script is provided to test the saveubjson | |||
and loadubjson pairs for various matlab data structures. | |||
Please run these examples and understand how JSONLab works before you use | |||
it to process your data. | |||
------------------------------------------------------------------------------- | |||
IV. Known Issues and TODOs | |||
JSONLab has several known limitations. We are striving to make it more general | |||
and robust. Hopefully in a few future releases, the limitations become less. | |||
Here are the known issues: | |||
# 3D or higher dimensional cell/struct-arrays will be converted to 2D arrays; | |||
# When processing names containing multi-byte characters, Octave and MATLAB \ | |||
can give different field-names; you can use feature('DefaultCharacterSet','latin1') \ | |||
in MATLAB to get consistant results | |||
# savejson can not handle class and dataset. | |||
# saveubjson converts a logical array into a uint8 ([U]) array | |||
# an unofficial N-D array count syntax is implemented in saveubjson. We are \ | |||
actively communicating with the UBJSON spec maintainer to investigate the \ | |||
possibility of making it upstream | |||
# loadubjson can not parse all UBJSON Specification (Draft 9) compliant \ | |||
files, however, it can parse all UBJSON files produced by saveubjson. | |||
------------------------------------------------------------------------------- | |||
V. Contribution and feedback | |||
JSONLab is an open-source project. This means you can not only use it and modify | |||
it as you wish, but also you can contribute your changes back to JSONLab so | |||
that everyone else can enjoy the improvement. For anyone who want to contribute, | |||
please download JSONLab source code from it's subversion repository by using the | |||
following command: | |||
svn checkout svn://svn.code.sf.net/p/iso2mesh/code/trunk/jsonlab jsonlab | |||
You can make changes to the files as needed. Once you are satisfied with your | |||
changes, and ready to share it with others, please cd the root directory of | |||
JSONLab, and type | |||
svn diff > yourname_featurename.patch | |||
You then email the .patch file to JSONLab's maintainer, Qianqian Fang, at | |||
the email address shown in the beginning of this file. Qianqian will review | |||
the changes and commit it to the subversion if they are satisfactory. | |||
We appreciate any suggestions and feedbacks from you. Please use iso2mesh's | |||
mailing list to report any questions you may have with JSONLab: | |||
http://groups.google.com/group/iso2mesh-users?hl=en&pli=1 | |||
(Subscription to the mailing list is needed in order to post messages). |
@@ -1,32 +0,0 @@ | |||
function val=jsonopt(key,default,varargin) | |||
% | |||
% val=jsonopt(key,default,optstruct) | |||
% | |||
% setting options based on a struct. The struct can be produced | |||
% by varargin2struct from a list of 'param','value' pairs | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% | |||
% $Id: loadjson.m 371 2012-06-20 12:43:06Z fangq $ | |||
% | |||
% input: | |||
% key: a string with which one look up a value from a struct | |||
% default: if the key does not exist, return default | |||
% optstruct: a struct where each sub-field is a key | |||
% | |||
% output: | |||
% val: if key exists, val=optstruct.key; otherwise val=default | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
val=default; | |||
if(nargin<=2) return; end | |||
opt=varargin{1}; | |||
if(isstruct(opt) && isfield(opt,key)) | |||
val=getfield(opt,key); | |||
end | |||
@@ -1,566 +0,0 @@ | |||
function data = loadjson(fname,varargin) | |||
% | |||
% data=loadjson(fname,opt) | |||
% or | |||
% data=loadjson(fname,'param1',value1,'param2',value2,...) | |||
% | |||
% parse a JSON (JavaScript Object Notation) file or string | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2011/09/09, including previous works from | |||
% | |||
% Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713 | |||
% created on 2009/11/02 | |||
% François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393 | |||
% created on 2009/03/22 | |||
% Joel Feenstra: | |||
% http://www.mathworks.com/matlabcentral/fileexchange/20565 | |||
% created on 2008/07/03 | |||
% | |||
% $Id: loadjson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% fname: input file name, if fname contains "{}" or "[]", fname | |||
% will be interpreted as a JSON string | |||
% opt: a struct to store parsing options, opt can be replaced by | |||
% a list of ('param',value) pairs - the param string is equivallent | |||
% to a field in opt. opt can have the following | |||
% fields (first in [.|.] is the default) | |||
% | |||
% opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat | |||
% for each element of the JSON data, and group | |||
% arrays based on the cell2mat rules. | |||
% opt.FastArrayParser [1|0 or integer]: if set to 1, use a | |||
% speed-optimized array parser when loading an | |||
% array object. The fast array parser may | |||
% collapse block arrays into a single large | |||
% array similar to rules defined in cell2mat; 0 to | |||
% use a legacy parser; if set to a larger-than-1 | |||
% value, this option will specify the minimum | |||
% dimension to enable the fast array parser. For | |||
% example, if the input is a 3D array, setting | |||
% FastArrayParser to 1 will return a 3D array; | |||
% setting to 2 will return a cell array of 2D | |||
% arrays; setting to 3 will return to a 2D cell | |||
% array of 1D vectors; setting to 4 will return a | |||
% 3D cell array. | |||
% opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar. | |||
% | |||
% output: | |||
% dat: a cell array, where {...} blocks are converted into cell arrays, | |||
% and [...] are converted to arrays | |||
% | |||
% examples: | |||
% dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}') | |||
% dat=loadjson(['examples' filesep 'example1.json']) | |||
% dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1) | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
global pos inStr len esc index_esc len_esc isoct arraytoken | |||
if(regexp(fname,'[\{\}\]\[]','once')) | |||
string=fname; | |||
elseif(exist(fname,'file')) | |||
fid = fopen(fname,'rb'); | |||
string = fread(fid,inf,'uint8=>char')'; | |||
fclose(fid); | |||
else | |||
error('input file does not exist'); | |||
end | |||
pos = 1; len = length(string); inStr = string; | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"'); | |||
jstr=regexprep(inStr,'\\\\',' '); | |||
escquote=regexp(jstr,'\\"'); | |||
arraytoken=sort([arraytoken escquote]); | |||
% String delimiters and escape chars identified to improve speed: | |||
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]'); | |||
index_esc = 1; len_esc = length(esc); | |||
opt=varargin2struct(varargin{:}); | |||
if(jsonopt('ShowProgress',0,opt)==1) | |||
opt.progressbar_=waitbar(0,'loading ...'); | |||
end | |||
jsoncount=1; | |||
while pos <= len | |||
switch(next_char) | |||
case '{' | |||
data{jsoncount} = parse_object(opt); | |||
case '[' | |||
data{jsoncount} = parse_array(opt); | |||
otherwise | |||
error_pos('Outer level structure must be an object or an array'); | |||
end | |||
jsoncount=jsoncount+1; | |||
end % while | |||
jsoncount=length(data); | |||
if(jsoncount==1 && iscell(data)) | |||
data=data{1}; | |||
end | |||
if(~isempty(data)) | |||
if(isstruct(data)) % data can be a struct array | |||
data=jstruct2array(data); | |||
elseif(iscell(data)) | |||
data=jcell2array(data); | |||
end | |||
end | |||
if(isfield(opt,'progressbar_')) | |||
close(opt.progressbar_); | |||
end | |||
%% | |||
function newdata=jcell2array(data) | |||
len=length(data); | |||
newdata=data; | |||
for i=1:len | |||
if(isstruct(data{i})) | |||
newdata{i}=jstruct2array(data{i}); | |||
elseif(iscell(data{i})) | |||
newdata{i}=jcell2array(data{i}); | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newdata=jstruct2array(data) | |||
fn=fieldnames(data); | |||
newdata=data; | |||
len=length(data); | |||
for i=1:length(fn) % depth-first | |||
for j=1:len | |||
if(isstruct(getfield(data(j),fn{i}))) | |||
newdata(j)=setfield(newdata(j),fn{i},jstruct2array(getfield(data(j),fn{i}))); | |||
end | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayData_',fn))) | |||
newdata=cell(len,1); | |||
for j=1:len | |||
ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_); | |||
iscpx=0; | |||
if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn))) | |||
if(data(j).x0x5F_ArrayIsComplex_) | |||
iscpx=1; | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn))) | |||
if(data(j).x0x5F_ArrayIsSparse_) | |||
if(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
dim=data(j).x0x5F_ArraySize_; | |||
if(iscpx && size(ndata,2)==4-any(dim==1)) | |||
ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end)); | |||
end | |||
if isempty(ndata) | |||
% All-zeros sparse | |||
ndata=sparse(dim(1),prod(dim(2:end))); | |||
elseif dim(1)==1 | |||
% Sparse row vector | |||
ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end))); | |||
elseif dim(2)==1 | |||
% Sparse column vector | |||
ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end))); | |||
else | |||
% Generic sparse array. | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end))); | |||
end | |||
else | |||
if(iscpx && size(ndata,2)==4) | |||
ndata(:,3)=complex(ndata(:,3),ndata(:,4)); | |||
end | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3)); | |||
end | |||
end | |||
elseif(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
if(iscpx && size(ndata,2)==2) | |||
ndata=complex(ndata(:,1),ndata(:,2)); | |||
end | |||
ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_); | |||
end | |||
newdata{j}=ndata; | |||
end | |||
if(len==1) | |||
newdata=newdata{1}; | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function object = parse_object(varargin) | |||
parse_char('{'); | |||
object = []; | |||
if next_char ~= '}' | |||
while 1 | |||
str = parseStr(varargin{:}); | |||
if isempty(str) | |||
error_pos('Name of value at position %d cannot be empty'); | |||
end | |||
parse_char(':'); | |||
val = parse_value(varargin{:}); | |||
eval( sprintf( 'object.%s = val;', valid_field(str) ) ); | |||
if next_char == '}' | |||
break; | |||
end | |||
parse_char(','); | |||
end | |||
end | |||
parse_char('}'); | |||
%%------------------------------------------------------------------------- | |||
function object = parse_array(varargin) % JSON array is written in row-major order | |||
global pos inStr isoct | |||
parse_char('['); | |||
object = cell(0, 1); | |||
dim2=[]; | |||
arraydepth=jsonopt('JSONLAB_ArrayDepth_',1,varargin{:}); | |||
pbar=jsonopt('progressbar_',-1,varargin{:}); | |||
if next_char ~= ']' | |||
if(jsonopt('FastArrayParser',1,varargin{:})>=1 && arraydepth>=jsonopt('FastArrayParser',1,varargin{:})) | |||
[endpos, e1l, e1r, maxlevel]=matching_bracket(inStr,pos); | |||
arraystr=['[' inStr(pos:endpos)]; | |||
arraystr=regexprep(arraystr,'"_NaN_"','NaN'); | |||
arraystr=regexprep(arraystr,'"([-+]*)_Inf_"','$1Inf'); | |||
arraystr(arraystr==sprintf('\n'))=[]; | |||
arraystr(arraystr==sprintf('\r'))=[]; | |||
%arraystr=regexprep(arraystr,'\s*,',','); % this is slow,sometimes needed | |||
if(~isempty(e1l) && ~isempty(e1r)) % the array is in 2D or higher D | |||
astr=inStr((e1l+1):(e1r-1)); | |||
astr=regexprep(astr,'"_NaN_"','NaN'); | |||
astr=regexprep(astr,'"([-+]*)_Inf_"','$1Inf'); | |||
astr(astr==sprintf('\n'))=[]; | |||
astr(astr==sprintf('\r'))=[]; | |||
astr(astr==' ')=''; | |||
if(isempty(find(astr=='[', 1))) % array is 2D | |||
dim2=length(sscanf(astr,'%f,',[1 inf])); | |||
end | |||
else % array is 1D | |||
astr=arraystr(2:end-1); | |||
astr(astr==' ')=''; | |||
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',[1,inf]); | |||
if(nextidx>=length(astr)-1) | |||
object=obj; | |||
pos=endpos; | |||
parse_char(']'); | |||
return; | |||
end | |||
end | |||
if(~isempty(dim2)) | |||
astr=arraystr; | |||
astr(astr=='[')=''; | |||
astr(astr==']')=''; | |||
astr(astr==' ')=''; | |||
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',inf); | |||
if(nextidx>=length(astr)-1) | |||
object=reshape(obj,dim2,numel(obj)/dim2)'; | |||
pos=endpos; | |||
parse_char(']'); | |||
if(pbar>0) | |||
waitbar(pos/length(inStr),pbar,'loading ...'); | |||
end | |||
return; | |||
end | |||
end | |||
arraystr=regexprep(arraystr,'\]\s*,','];'); | |||
else | |||
arraystr='['; | |||
end | |||
try | |||
if(isoct && regexp(arraystr,'"','once')) | |||
error('Octave eval can produce empty cells for JSON-like input'); | |||
end | |||
object=eval(arraystr); | |||
pos=endpos; | |||
catch | |||
while 1 | |||
newopt=varargin2struct(varargin{:},'JSONLAB_ArrayDepth_',arraydepth+1); | |||
val = parse_value(newopt); | |||
object{end+1} = val; | |||
if next_char == ']' | |||
break; | |||
end | |||
parse_char(','); | |||
end | |||
end | |||
end | |||
if(jsonopt('SimplifyCell',0,varargin{:})==1) | |||
try | |||
oldobj=object; | |||
object=cell2mat(object')'; | |||
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0) | |||
object=oldobj; | |||
elseif(size(object,1)>1 && ndims(object)==2) | |||
object=object'; | |||
end | |||
catch | |||
end | |||
end | |||
parse_char(']'); | |||
if(pbar>0) | |||
waitbar(pos/length(inStr),pbar,'loading ...'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function parse_char(c) | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len || inStr(pos) ~= c | |||
error_pos(sprintf('Expected %c at position %%d', c)); | |||
else | |||
pos = pos + 1; | |||
skip_whitespace; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function c = next_char | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len | |||
c = []; | |||
else | |||
c = inStr(pos); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function skip_whitespace | |||
global pos inStr len | |||
while pos <= len && isspace(inStr(pos)) | |||
pos = pos + 1; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function str = parseStr(varargin) | |||
global pos inStr len esc index_esc len_esc | |||
% len, ns = length(inStr), keyboard | |||
if inStr(pos) ~= '"' | |||
error_pos('String starting with " expected at position %d'); | |||
else | |||
pos = pos + 1; | |||
end | |||
str = ''; | |||
while pos <= len | |||
while index_esc <= len_esc && esc(index_esc) < pos | |||
index_esc = index_esc + 1; | |||
end | |||
if index_esc > len_esc | |||
str = [str inStr(pos:len)]; | |||
pos = len + 1; | |||
break; | |||
else | |||
str = [str inStr(pos:esc(index_esc)-1)]; | |||
pos = esc(index_esc); | |||
end | |||
nstr = length(str); switch inStr(pos) | |||
case '"' | |||
pos = pos + 1; | |||
if(~isempty(str)) | |||
if(strcmp(str,'_Inf_')) | |||
str=Inf; | |||
elseif(strcmp(str,'-_Inf_')) | |||
str=-Inf; | |||
elseif(strcmp(str,'_NaN_')) | |||
str=NaN; | |||
end | |||
end | |||
return; | |||
case '\' | |||
if pos+1 > len | |||
error_pos('End of file reached right after escape character'); | |||
end | |||
pos = pos + 1; | |||
switch inStr(pos) | |||
case {'"' '\' '/'} | |||
str(nstr+1) = inStr(pos); | |||
pos = pos + 1; | |||
case {'b' 'f' 'n' 'r' 't'} | |||
str(nstr+1) = sprintf(['\' inStr(pos)]); | |||
pos = pos + 1; | |||
case 'u' | |||
if pos+4 > len | |||
error_pos('End of file reached in escaped unicode character'); | |||
end | |||
str(nstr+(1:6)) = inStr(pos-1:pos+4); | |||
pos = pos + 5; | |||
end | |||
otherwise % should never happen | |||
str(nstr+1) = inStr(pos), keyboard | |||
pos = pos + 1; | |||
end | |||
end | |||
error_pos('End of file while expecting end of inStr'); | |||
%%------------------------------------------------------------------------- | |||
function num = parse_number(varargin) | |||
global pos inStr len isoct | |||
currstr=inStr(pos:end); | |||
numstr=0; | |||
if(isoct~=0) | |||
numstr=regexp(currstr,'^\s*-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+\-]?\d+)?','end'); | |||
[num, one] = sscanf(currstr, '%f', 1); | |||
delta=numstr+1; | |||
else | |||
[num, one, err, delta] = sscanf(currstr, '%f', 1); | |||
if ~isempty(err) | |||
error_pos('Error reading number at position %d'); | |||
end | |||
end | |||
pos = pos + delta-1; | |||
%%------------------------------------------------------------------------- | |||
function val = parse_value(varargin) | |||
global pos inStr len | |||
true = 1; false = 0; | |||
pbar=jsonopt('progressbar_',-1,varargin{:}); | |||
if(pbar>0) | |||
waitbar(pos/len,pbar,'loading ...'); | |||
end | |||
switch(inStr(pos)) | |||
case '"' | |||
val = parseStr(varargin{:}); | |||
return; | |||
case '[' | |||
val = parse_array(varargin{:}); | |||
return; | |||
case '{' | |||
val = parse_object(varargin{:}); | |||
if isstruct(val) | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fieldnames(val), 'exact'))) | |||
val=jstruct2array(val); | |||
end | |||
elseif isempty(val) | |||
val = struct; | |||
end | |||
return; | |||
case {'-','0','1','2','3','4','5','6','7','8','9'} | |||
val = parse_number(varargin{:}); | |||
return; | |||
case 't' | |||
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'true') | |||
val = true; | |||
pos = pos + 4; | |||
return; | |||
end | |||
case 'f' | |||
if pos+4 <= len && strcmpi(inStr(pos:pos+4), 'false') | |||
val = false; | |||
pos = pos + 5; | |||
return; | |||
end | |||
case 'n' | |||
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'null') | |||
val = []; | |||
pos = pos + 4; | |||
return; | |||
end | |||
end | |||
error_pos('Value expected at position %d'); | |||
%%------------------------------------------------------------------------- | |||
function error_pos(msg) | |||
global pos inStr len | |||
poShow = max(min([pos-15 pos-1 pos pos+20],len),1); | |||
if poShow(3) == poShow(2) | |||
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after | |||
end | |||
msg = [sprintf(msg, pos) ': ' ... | |||
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ]; | |||
error( ['JSONparser:invalidFormat: ' msg] ); | |||
%%------------------------------------------------------------------------- | |||
function str = valid_field(str) | |||
global isoct | |||
% From MATLAB doc: field names must begin with a letter, which may be | |||
% followed by any combination of letters, digits, and underscores. | |||
% Invalid characters will be converted to underscores, and the prefix | |||
% "x0x[Hex code]_" will be added if the first character is not a letter. | |||
pos=regexp(str,'^[^A-Za-z]','once'); | |||
if(~isempty(pos)) | |||
if(~isoct) | |||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); | |||
else | |||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); | |||
end | |||
end | |||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end | |||
if(~isoct) | |||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_'); | |||
else | |||
pos=regexp(str,'[^0-9A-Za-z_]'); | |||
if(isempty(pos)) return; end | |||
str0=str; | |||
pos0=[0 pos(:)' length(str)]; | |||
str=''; | |||
for i=1:length(pos) | |||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))]; | |||
end | |||
if(pos(end)~=length(str)) | |||
str=[str str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_'; | |||
%%------------------------------------------------------------------------- | |||
function endpos = matching_quote(str,pos) | |||
len=length(str); | |||
while(pos<len) | |||
if(str(pos)=='"') | |||
if(~(pos>1 && str(pos-1)=='\')) | |||
endpos=pos; | |||
return; | |||
end | |||
end | |||
pos=pos+1; | |||
end | |||
error('unmatched quotation mark'); | |||
%%------------------------------------------------------------------------- | |||
function [endpos, e1l, e1r, maxlevel] = matching_bracket(str,pos) | |||
global arraytoken | |||
level=1; | |||
maxlevel=level; | |||
endpos=0; | |||
bpos=arraytoken(arraytoken>=pos); | |||
tokens=str(bpos); | |||
len=length(tokens); | |||
pos=1; | |||
e1l=[]; | |||
e1r=[]; | |||
while(pos<=len) | |||
c=tokens(pos); | |||
if(c==']') | |||
level=level-1; | |||
if(isempty(e1r)) e1r=bpos(pos); end | |||
if(level==0) | |||
endpos=bpos(pos); | |||
return | |||
end | |||
end | |||
if(c=='[') | |||
if(isempty(e1l)) e1l=bpos(pos); end | |||
level=level+1; | |||
maxlevel=max(maxlevel,level); | |||
end | |||
if(c=='"') | |||
pos=matching_quote(tokens,pos+1); | |||
end | |||
pos=pos+1; | |||
end | |||
if(endpos==0) | |||
error('unmatched "]"'); | |||
end | |||
@@ -1,528 +0,0 @@ | |||
function data = loadubjson(fname,varargin) | |||
% | |||
% data=loadubjson(fname,opt) | |||
% or | |||
% data=loadubjson(fname,'param1',value1,'param2',value2,...) | |||
% | |||
% parse a JSON (JavaScript Object Notation) file or string | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2013/08/01 | |||
% | |||
% $Id: loadubjson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% fname: input file name, if fname contains "{}" or "[]", fname | |||
% will be interpreted as a UBJSON string | |||
% opt: a struct to store parsing options, opt can be replaced by | |||
% a list of ('param',value) pairs - the param string is equivallent | |||
% to a field in opt. opt can have the following | |||
% fields (first in [.|.] is the default) | |||
% | |||
% opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat | |||
% for each element of the JSON data, and group | |||
% arrays based on the cell2mat rules. | |||
% opt.IntEndian [B|L]: specify the endianness of the integer fields | |||
% in the UBJSON input data. B - Big-Endian format for | |||
% integers (as required in the UBJSON specification); | |||
% L - input integer fields are in Little-Endian order. | |||
% | |||
% output: | |||
% dat: a cell array, where {...} blocks are converted into cell arrays, | |||
% and [...] are converted to arrays | |||
% | |||
% examples: | |||
% obj=struct('string','value','array',[1 2 3]); | |||
% ubjdata=saveubjson('obj',obj); | |||
% dat=loadubjson(ubjdata) | |||
% dat=loadubjson(['examples' filesep 'example1.ubj']) | |||
% dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1) | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
global pos inStr len esc index_esc len_esc isoct arraytoken fileendian systemendian | |||
if(regexp(fname,'[\{\}\]\[]','once')) | |||
string=fname; | |||
elseif(exist(fname,'file')) | |||
fid = fopen(fname,'rb'); | |||
string = fread(fid,inf,'uint8=>char')'; | |||
fclose(fid); | |||
else | |||
error('input file does not exist'); | |||
end | |||
pos = 1; len = length(string); inStr = string; | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"'); | |||
jstr=regexprep(inStr,'\\\\',' '); | |||
escquote=regexp(jstr,'\\"'); | |||
arraytoken=sort([arraytoken escquote]); | |||
% String delimiters and escape chars identified to improve speed: | |||
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]'); | |||
index_esc = 1; len_esc = length(esc); | |||
opt=varargin2struct(varargin{:}); | |||
fileendian=upper(jsonopt('IntEndian','B',opt)); | |||
[os,maxelem,systemendian]=computer; | |||
jsoncount=1; | |||
while pos <= len | |||
switch(next_char) | |||
case '{' | |||
data{jsoncount} = parse_object(opt); | |||
case '[' | |||
data{jsoncount} = parse_array(opt); | |||
otherwise | |||
error_pos('Outer level structure must be an object or an array'); | |||
end | |||
jsoncount=jsoncount+1; | |||
end % while | |||
jsoncount=length(data); | |||
if(jsoncount==1 && iscell(data)) | |||
data=data{1}; | |||
end | |||
if(~isempty(data)) | |||
if(isstruct(data)) % data can be a struct array | |||
data=jstruct2array(data); | |||
elseif(iscell(data)) | |||
data=jcell2array(data); | |||
end | |||
end | |||
%% | |||
function newdata=parse_collection(id,data,obj) | |||
if(jsoncount>0 && exist('data','var')) | |||
if(~iscell(data)) | |||
newdata=cell(1); | |||
newdata{1}=data; | |||
data=newdata; | |||
end | |||
end | |||
%% | |||
function newdata=jcell2array(data) | |||
len=length(data); | |||
newdata=data; | |||
for i=1:len | |||
if(isstruct(data{i})) | |||
newdata{i}=jstruct2array(data{i}); | |||
elseif(iscell(data{i})) | |||
newdata{i}=jcell2array(data{i}); | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newdata=jstruct2array(data) | |||
fn=fieldnames(data); | |||
newdata=data; | |||
len=length(data); | |||
for i=1:length(fn) % depth-first | |||
for j=1:len | |||
if(isstruct(getfield(data(j),fn{i}))) | |||
newdata(j)=setfield(newdata(j),fn{i},jstruct2array(getfield(data(j),fn{i}))); | |||
end | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayData_',fn))) | |||
newdata=cell(len,1); | |||
for j=1:len | |||
ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_); | |||
iscpx=0; | |||
if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn))) | |||
if(data(j).x0x5F_ArrayIsComplex_) | |||
iscpx=1; | |||
end | |||
end | |||
if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn))) | |||
if(data(j).x0x5F_ArrayIsSparse_) | |||
if(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
dim=double(data(j).x0x5F_ArraySize_); | |||
if(iscpx && size(ndata,2)==4-any(dim==1)) | |||
ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end)); | |||
end | |||
if isempty(ndata) | |||
% All-zeros sparse | |||
ndata=sparse(dim(1),prod(dim(2:end))); | |||
elseif dim(1)==1 | |||
% Sparse row vector | |||
ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end))); | |||
elseif dim(2)==1 | |||
% Sparse column vector | |||
ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end))); | |||
else | |||
% Generic sparse array. | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end))); | |||
end | |||
else | |||
if(iscpx && size(ndata,2)==4) | |||
ndata(:,3)=complex(ndata(:,3),ndata(:,4)); | |||
end | |||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3)); | |||
end | |||
end | |||
elseif(~isempty(strmatch('x0x5F_ArraySize_',fn))) | |||
if(iscpx && size(ndata,2)==2) | |||
ndata=complex(ndata(:,1),ndata(:,2)); | |||
end | |||
ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_); | |||
end | |||
newdata{j}=ndata; | |||
end | |||
if(len==1) | |||
newdata=newdata{1}; | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function object = parse_object(varargin) | |||
parse_char('{'); | |||
object = []; | |||
type=''; | |||
count=-1; | |||
if(next_char == '$') | |||
type=inStr(pos+1); % TODO | |||
pos=pos+2; | |||
end | |||
if(next_char == '#') | |||
pos=pos+1; | |||
count=double(parse_number()); | |||
end | |||
if next_char ~= '}' | |||
num=0; | |||
while 1 | |||
str = parseStr(varargin{:}); | |||
if isempty(str) | |||
error_pos('Name of value at position %d cannot be empty'); | |||
end | |||
%parse_char(':'); | |||
val = parse_value(varargin{:}); | |||
num=num+1; | |||
eval( sprintf( 'object.%s = val;', valid_field(str) ) ); | |||
if next_char == '}' || (count>=0 && num>=count) | |||
break; | |||
end | |||
%parse_char(','); | |||
end | |||
end | |||
if(count==-1) | |||
parse_char('}'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function [cid,len]=elem_info(type) | |||
id=strfind('iUIlLdD',type); | |||
dataclass={'int8','uint8','int16','int32','int64','single','double'}; | |||
bytelen=[1,1,2,4,8,4,8]; | |||
if(id>0) | |||
cid=dataclass{id}; | |||
len=bytelen(id); | |||
else | |||
error_pos('unsupported type at position %d'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function [data adv]=parse_block(type,count,varargin) | |||
global pos inStr isoct fileendian systemendian | |||
[cid,len]=elem_info(type); | |||
datastr=inStr(pos:pos+len*count-1); | |||
if(isoct) | |||
newdata=int8(datastr); | |||
else | |||
newdata=uint8(datastr); | |||
end | |||
id=strfind('iUIlLdD',type); | |||
if(id<=5 && fileendian~=systemendian) | |||
newdata=swapbytes(typecast(newdata,cid)); | |||
end | |||
data=typecast(newdata,cid); | |||
adv=double(len*count); | |||
%%------------------------------------------------------------------------- | |||
function object = parse_array(varargin) % JSON array is written in row-major order | |||
global pos inStr isoct | |||
parse_char('['); | |||
object = cell(0, 1); | |||
dim=[]; | |||
type=''; | |||
count=-1; | |||
if(next_char == '$') | |||
type=inStr(pos+1); | |||
pos=pos+2; | |||
end | |||
if(next_char == '#') | |||
pos=pos+1; | |||
if(next_char=='[') | |||
dim=parse_array(varargin{:}); | |||
count=prod(double(dim)); | |||
else | |||
count=double(parse_number()); | |||
end | |||
end | |||
if(~isempty(type)) | |||
if(count>=0) | |||
[object adv]=parse_block(type,count,varargin{:}); | |||
if(~isempty(dim)) | |||
object=reshape(object,dim); | |||
end | |||
pos=pos+adv; | |||
return; | |||
else | |||
endpos=matching_bracket(inStr,pos); | |||
[cid,len]=elem_info(type); | |||
count=(endpos-pos)/len; | |||
[object adv]=parse_block(type,count,varargin{:}); | |||
pos=pos+adv; | |||
parse_char(']'); | |||
return; | |||
end | |||
end | |||
if next_char ~= ']' | |||
while 1 | |||
val = parse_value(varargin{:}); | |||
object{end+1} = val; | |||
if next_char == ']' | |||
break; | |||
end | |||
%parse_char(','); | |||
end | |||
end | |||
if(jsonopt('SimplifyCell',0,varargin{:})==1) | |||
try | |||
oldobj=object; | |||
object=cell2mat(object')'; | |||
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0) | |||
object=oldobj; | |||
elseif(size(object,1)>1 && ndims(object)==2) | |||
object=object'; | |||
end | |||
catch | |||
end | |||
end | |||
if(count==-1) | |||
parse_char(']'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function parse_char(c) | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len || inStr(pos) ~= c | |||
error_pos(sprintf('Expected %c at position %%d', c)); | |||
else | |||
pos = pos + 1; | |||
skip_whitespace; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function c = next_char | |||
global pos inStr len | |||
skip_whitespace; | |||
if pos > len | |||
c = []; | |||
else | |||
c = inStr(pos); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function skip_whitespace | |||
global pos inStr len | |||
while pos <= len && isspace(inStr(pos)) | |||
pos = pos + 1; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function str = parseStr(varargin) | |||
global pos inStr esc index_esc len_esc | |||
% len, ns = length(inStr), keyboard | |||
type=inStr(pos); | |||
if type ~= 'S' && type ~= 'C' && type ~= 'H' | |||
error_pos('String starting with S expected at position %d'); | |||
else | |||
pos = pos + 1; | |||
end | |||
if(type == 'C') | |||
str=inStr(pos); | |||
pos=pos+1; | |||
return; | |||
end | |||
bytelen=double(parse_number()); | |||
if(length(inStr)>=pos+bytelen-1) | |||
str=inStr(pos:pos+bytelen-1); | |||
pos=pos+bytelen; | |||
else | |||
error_pos('End of file while expecting end of inStr'); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function num = parse_number(varargin) | |||
global pos inStr len isoct fileendian systemendian | |||
id=strfind('iUIlLdD',inStr(pos)); | |||
if(isempty(id)) | |||
error_pos('expecting a number at position %d'); | |||
end | |||
type={'int8','uint8','int16','int32','int64','single','double'}; | |||
bytelen=[1,1,2,4,8,4,8]; | |||
datastr=inStr(pos+1:pos+bytelen(id)); | |||
if(isoct) | |||
newdata=int8(datastr); | |||
else | |||
newdata=uint8(datastr); | |||
end | |||
if(id<=5 && fileendian~=systemendian) | |||
newdata=swapbytes(typecast(newdata,type{id})); | |||
end | |||
num=typecast(newdata,type{id}); | |||
pos = pos + bytelen(id)+1; | |||
%%------------------------------------------------------------------------- | |||
function val = parse_value(varargin) | |||
global pos inStr len | |||
true = 1; false = 0; | |||
switch(inStr(pos)) | |||
case {'S','C','H'} | |||
val = parseStr(varargin{:}); | |||
return; | |||
case '[' | |||
val = parse_array(varargin{:}); | |||
return; | |||
case '{' | |||
val = parse_object(varargin{:}); | |||
if isstruct(val) | |||
if(~isempty(strmatch('x0x5F_ArrayType_',fieldnames(val), 'exact'))) | |||
val=jstruct2array(val); | |||
end | |||
elseif isempty(val) | |||
val = struct; | |||
end | |||
return; | |||
case {'i','U','I','l','L','d','D'} | |||
val = parse_number(varargin{:}); | |||
return; | |||
case 'T' | |||
val = true; | |||
pos = pos + 1; | |||
return; | |||
case 'F' | |||
val = false; | |||
pos = pos + 1; | |||
return; | |||
case {'Z','N'} | |||
val = []; | |||
pos = pos + 1; | |||
return; | |||
end | |||
error_pos('Value expected at position %d'); | |||
%%------------------------------------------------------------------------- | |||
function error_pos(msg) | |||
global pos inStr len | |||
poShow = max(min([pos-15 pos-1 pos pos+20],len),1); | |||
if poShow(3) == poShow(2) | |||
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after | |||
end | |||
msg = [sprintf(msg, pos) ': ' ... | |||
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ]; | |||
error( ['JSONparser:invalidFormat: ' msg] ); | |||
%%------------------------------------------------------------------------- | |||
function str = valid_field(str) | |||
global isoct | |||
% From MATLAB doc: field names must begin with a letter, which may be | |||
% followed by any combination of letters, digits, and underscores. | |||
% Invalid characters will be converted to underscores, and the prefix | |||
% "x0x[Hex code]_" will be added if the first character is not a letter. | |||
pos=regexp(str,'^[^A-Za-z]','once'); | |||
if(~isempty(pos)) | |||
if(~isoct) | |||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); | |||
else | |||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); | |||
end | |||
end | |||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end | |||
if(~isoct) | |||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_'); | |||
else | |||
pos=regexp(str,'[^0-9A-Za-z_]'); | |||
if(isempty(pos)) return; end | |||
str0=str; | |||
pos0=[0 pos(:)' length(str)]; | |||
str=''; | |||
for i=1:length(pos) | |||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))]; | |||
end | |||
if(pos(end)~=length(str)) | |||
str=[str str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_'; | |||
%%------------------------------------------------------------------------- | |||
function endpos = matching_quote(str,pos) | |||
len=length(str); | |||
while(pos<len) | |||
if(str(pos)=='"') | |||
if(~(pos>1 && str(pos-1)=='\')) | |||
endpos=pos; | |||
return; | |||
end | |||
end | |||
pos=pos+1; | |||
end | |||
error('unmatched quotation mark'); | |||
%%------------------------------------------------------------------------- | |||
function [endpos e1l e1r maxlevel] = matching_bracket(str,pos) | |||
global arraytoken | |||
level=1; | |||
maxlevel=level; | |||
endpos=0; | |||
bpos=arraytoken(arraytoken>=pos); | |||
tokens=str(bpos); | |||
len=length(tokens); | |||
pos=1; | |||
e1l=[]; | |||
e1r=[]; | |||
while(pos<=len) | |||
c=tokens(pos); | |||
if(c==']') | |||
level=level-1; | |||
if(isempty(e1r)) e1r=bpos(pos); end | |||
if(level==0) | |||
endpos=bpos(pos); | |||
return | |||
end | |||
end | |||
if(c=='[') | |||
if(isempty(e1l)) e1l=bpos(pos); end | |||
level=level+1; | |||
maxlevel=max(maxlevel,level); | |||
end | |||
if(c=='"') | |||
pos=matching_quote(tokens,pos+1); | |||
end | |||
pos=pos+1; | |||
end | |||
if(endpos==0) | |||
error('unmatched "]"'); | |||
end | |||
@@ -1,33 +0,0 @@ | |||
function s=mergestruct(s1,s2) | |||
% | |||
% s=mergestruct(s1,s2) | |||
% | |||
% merge two struct objects into one | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% date: 2012/12/22 | |||
% | |||
% input: | |||
% s1,s2: a struct object, s1 and s2 can not be arrays | |||
% | |||
% output: | |||
% s: the merged struct object. fields in s1 and s2 will be combined in s. | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
if(~isstruct(s1) || ~isstruct(s2)) | |||
error('input parameters contain non-struct'); | |||
end | |||
if(length(s1)>1 || length(s2)>1) | |||
error('can not merge struct arrays'); | |||
end | |||
fn=fieldnames(s2); | |||
s=s1; | |||
for i=1:length(fn) | |||
s=setfield(s,fn{i},getfield(s2,fn{i})); | |||
end | |||
@@ -1,475 +0,0 @@ | |||
function json=savejson(rootname,obj,varargin) | |||
% | |||
% json=savejson(rootname,obj,filename) | |||
% or | |||
% json=savejson(rootname,obj,opt) | |||
% json=savejson(rootname,obj,'param1',value1,'param2',value2,...) | |||
% | |||
% convert a MATLAB object (cell, struct or array) into a JSON (JavaScript | |||
% Object Notation) string | |||
% | |||
% author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2011/09/09 | |||
% | |||
% $Id: savejson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% rootname: the name of the root-object, when set to '', the root name | |||
% is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
% the MATLAB variable name will be used as the root name. | |||
% obj: a MATLAB object (array, cell, cell array, struct, struct array). | |||
% filename: a string for the file name to save the output JSON data. | |||
% opt: a struct for additional options, ignore to use default values. | |||
% opt can have the following fields (first in [.|.] is the default) | |||
% | |||
% opt.FileName [''|string]: a file name to save the output JSON data | |||
% opt.FloatFormat ['%.10g'|string]: format to show each numeric element | |||
% of a 1D/2D array; | |||
% opt.ArrayIndent [1|0]: if 1, output explicit data array with | |||
% precedent indentation; if 0, no indentation | |||
% opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D | |||
% array in JSON array format; if sets to 1, an | |||
% array will be shown as a struct with fields | |||
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
% sparse arrays, the non-zero elements will be | |||
% saved to _ArrayData_ field in triplet-format i.e. | |||
% (ix,iy,val) and "_ArrayIsSparse_" will be added | |||
% with a value of 1; for a complex array, the | |||
% _ArrayData_ array will include two columns | |||
% (4 for sparse) to record the real and imaginary | |||
% parts, and also "_ArrayIsComplex_":1 is added. | |||
% opt.ParseLogical [0|1]: if this is set to 1, logical array elem | |||
% will use true/false rather than 1/0. | |||
% opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
% numerical element will be shown without a square | |||
% bracket, unless it is the root object; if 0, square | |||
% brackets are forced for any numerical arrays. | |||
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson | |||
% will use the name of the passed obj variable as the | |||
% root object name; if obj is an expression and | |||
% does not have a name, 'root' will be used; if this | |||
% is set to 0 and rootname is empty, the root level | |||
% will be merged down to the lower level. | |||
% opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern | |||
% to represent +/-Inf. The matched pattern is '([-+]*)Inf' | |||
% and $1 represents the sign. For those who want to use | |||
% 1e999 to represent Inf, they can set opt.Inf to '$11e999' | |||
% opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern | |||
% to represent NaN | |||
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
% for example, if opt.JSONP='foo', the JSON data is | |||
% wrapped inside a function call as 'foo(...);' | |||
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
% back to the string form | |||
% opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode. | |||
% opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs) | |||
% | |||
% opt can be replaced by a list of ('param',value) pairs. The param | |||
% string is equivallent to a field in opt and is case sensitive. | |||
% output: | |||
% json: a string in the JSON format (see http://json.org) | |||
% | |||
% examples: | |||
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
% 'SpecialData',[nan, inf, -inf]); | |||
% savejson('jmesh',jsonmesh) | |||
% savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g') | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
if(nargin==1) | |||
varname=inputname(1); | |||
obj=rootname; | |||
if(isempty(varname)) | |||
varname='root'; | |||
end | |||
rootname=varname; | |||
else | |||
varname=inputname(2); | |||
end | |||
if(length(varargin)==1 && ischar(varargin{1})) | |||
opt=struct('FileName',varargin{1}); | |||
else | |||
opt=varargin2struct(varargin{:}); | |||
end | |||
opt.IsOctave=exist('OCTAVE_VERSION','builtin'); | |||
rootisarray=0; | |||
rootlevel=1; | |||
forceroot=jsonopt('ForceRootName',0,opt); | |||
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || iscell(obj)) && isempty(rootname) && forceroot==0) | |||
rootisarray=1; | |||
rootlevel=0; | |||
else | |||
if(isempty(rootname)) | |||
rootname=varname; | |||
end | |||
end | |||
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot) | |||
rootname='root'; | |||
end | |||
whitespaces=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
if(jsonopt('Compact',0,opt)==1) | |||
whitespaces=struct('tab','','newline','','sep',','); | |||
end | |||
if(~isfield(opt,'whitespaces_')) | |||
opt.whitespaces_=whitespaces; | |||
end | |||
nl=whitespaces.newline; | |||
json=obj2json(rootname,obj,rootlevel,opt); | |||
if(rootisarray) | |||
json=sprintf('%s%s',json,nl); | |||
else | |||
json=sprintf('{%s%s%s}\n',nl,json,nl); | |||
end | |||
jsonp=jsonopt('JSONP','',opt); | |||
if(~isempty(jsonp)) | |||
json=sprintf('%s(%s);%s',jsonp,json,nl); | |||
end | |||
% save to a file if FileName is set, suggested by Patrick Rapin | |||
if(~isempty(jsonopt('FileName','',opt))) | |||
if(jsonopt('SaveBinary',0,opt)==1) | |||
fid = fopen(opt.FileName, 'wb'); | |||
fwrite(fid,json); | |||
else | |||
fid = fopen(opt.FileName, 'wt'); | |||
fwrite(fid,json,'char'); | |||
end | |||
fclose(fid); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=obj2json(name,item,level,varargin) | |||
if(iscell(item)) | |||
txt=cell2json(name,item,level,varargin{:}); | |||
elseif(isstruct(item)) | |||
txt=struct2json(name,item,level,varargin{:}); | |||
elseif(ischar(item)) | |||
txt=str2json(name,item,level,varargin{:}); | |||
else | |||
txt=mat2json(name,item,level,varargin{:}); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=cell2json(name,item,level,varargin) | |||
txt=''; | |||
if(~iscell(item)) | |||
error('input is not a cell'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); | |||
ws=jsonopt('whitespaces_',struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')),varargin{:}); | |||
padding0=repmat(ws.tab,1,level); | |||
padding2=repmat(ws.tab,1,level+1); | |||
nl=ws.newline; | |||
if(len>1) | |||
if(~isempty(name)) | |||
txt=sprintf('%s"%s": [%s',padding0, checkname(name,varargin{:}),nl); name=''; | |||
else | |||
txt=sprintf('%s[%s',padding0,nl); | |||
end | |||
elseif(len==0) | |||
if(~isempty(name)) | |||
txt=sprintf('%s"%s": []',padding0, checkname(name,varargin{:})); name=''; | |||
else | |||
txt=sprintf('%s[]',padding0); | |||
end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=sprintf('%s%s[%s',txt,padding2,nl); end | |||
for i=1:dim(1) | |||
txt=sprintf('%s%s',txt,obj2json(name,item{i,j},level+(dim(1)>1)+1,varargin{:})); | |||
if(i<dim(1)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(dim(1)>1) txt=sprintf('%s%s%s]',txt,nl,padding2); end | |||
if(j<dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
%if(j==dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(len>1) txt=sprintf('%s%s%s]',txt,nl,padding0); end | |||
%%------------------------------------------------------------------------- | |||
function txt=struct2json(name,item,level,varargin) | |||
txt=''; | |||
if(~isstruct(item)) | |||
error('input is not a struct'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
padding0=repmat(ws.tab,1,level); | |||
padding2=repmat(ws.tab,1,level+1); | |||
padding1=repmat(ws.tab,1,level+(dim(1)>1)+(len>1)); | |||
nl=ws.newline; | |||
if(~isempty(name)) | |||
if(len>1) txt=sprintf('%s"%s": [%s',padding0,checkname(name,varargin{:}),nl); end | |||
else | |||
if(len>1) txt=sprintf('%s[%s',padding0,nl); end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=sprintf('%s%s[%s',txt,padding2,nl); end | |||
for i=1:dim(1) | |||
names = fieldnames(item(i,j)); | |||
if(~isempty(name) && len==1) | |||
txt=sprintf('%s%s"%s": {%s',txt,padding1, checkname(name,varargin{:}),nl); | |||
else | |||
txt=sprintf('%s%s{%s',txt,padding1,nl); | |||
end | |||
if(~isempty(names)) | |||
for e=1:length(names) | |||
txt=sprintf('%s%s',txt,obj2json(names{e},getfield(item(i,j),... | |||
names{e}),level+(dim(1)>1)+1+(len>1),varargin{:})); | |||
if(e<length(names)) txt=sprintf('%s%s',txt,','); end | |||
txt=sprintf('%s%s',txt,nl); | |||
end | |||
end | |||
txt=sprintf('%s%s}',txt,padding1); | |||
if(i<dim(1)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(dim(1)>1) txt=sprintf('%s%s%s]',txt,nl,padding2); end | |||
if(j<dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end | |||
end | |||
if(len>1) txt=sprintf('%s%s%s]',txt,nl,padding0); end | |||
%%------------------------------------------------------------------------- | |||
function txt=str2json(name,item,level,varargin) | |||
txt=''; | |||
if(~ischar(item)) | |||
error('input is not a string'); | |||
end | |||
item=reshape(item, max(size(item),[1 0])); | |||
len=size(item,1); | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
padding1=repmat(ws.tab,1,level); | |||
padding0=repmat(ws.tab,1,level+1); | |||
nl=ws.newline; | |||
sep=ws.sep; | |||
if(~isempty(name)) | |||
if(len>1) txt=sprintf('%s"%s": [%s',padding1,checkname(name,varargin{:}),nl); end | |||
else | |||
if(len>1) txt=sprintf('%s[%s',padding1,nl); end | |||
end | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
for e=1:len | |||
if(isoct) | |||
val=regexprep(item(e,:),'\\','\\'); | |||
val=regexprep(val,'"','\"'); | |||
val=regexprep(val,'^"','\"'); | |||
else | |||
val=regexprep(item(e,:),'\\','\\\\'); | |||
val=regexprep(val,'"','\\"'); | |||
val=regexprep(val,'^"','\\"'); | |||
end | |||
val=escapejsonstring(val); | |||
if(len==1) | |||
obj=['"' checkname(name,varargin{:}) '": ' '"',val,'"']; | |||
if(isempty(name)) obj=['"',val,'"']; end | |||
txt=sprintf('%s%s%s%s',txt,padding1,obj); | |||
else | |||
txt=sprintf('%s%s%s%s',txt,padding0,['"',val,'"']); | |||
end | |||
if(e==len) sep=''; end | |||
txt=sprintf('%s%s',txt,sep); | |||
end | |||
if(len>1) txt=sprintf('%s%s%s%s',txt,nl,padding1,']'); end | |||
%%------------------------------------------------------------------------- | |||
function txt=mat2json(name,item,level,varargin) | |||
if(~isnumeric(item) && ~islogical(item)) | |||
error('input is not an array'); | |||
end | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
padding1=repmat(ws.tab,1,level); | |||
padding0=repmat(ws.tab,1,level+1); | |||
nl=ws.newline; | |||
sep=ws.sep; | |||
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ... | |||
isempty(item) ||jsonopt('ArrayToStruct',0,varargin{:})) | |||
if(isempty(name)) | |||
txt=sprintf('%s{%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',... | |||
padding1,nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); | |||
else | |||
txt=sprintf('%s"%s": {%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',... | |||
padding1,checkname(name,varargin{:}),nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); | |||
end | |||
else | |||
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1 && level>0) | |||
numtxt=regexprep(regexprep(matdata2json(item,level+1,varargin{:}),'^\[',''),']',''); | |||
else | |||
numtxt=matdata2json(item,level+1,varargin{:}); | |||
end | |||
if(isempty(name)) | |||
txt=sprintf('%s%s',padding1,numtxt); | |||
else | |||
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1) | |||
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt); | |||
else | |||
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt); | |||
end | |||
end | |||
return; | |||
end | |||
dataformat='%s%s%s%s%s'; | |||
if(issparse(item)) | |||
[ix,iy]=find(item); | |||
data=full(item(find(item))); | |||
if(~isreal(item)) | |||
data=[real(data(:)),imag(data(:))]; | |||
if(size(item,1)==1) | |||
% Kludge to have data's 'transposedness' match item's. | |||
% (Necessary for complex row vector handling below.) | |||
data=data'; | |||
end | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep); | |||
end | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_": ','1', sep); | |||
if(size(item,1)==1) | |||
% Row vector, store only column indices. | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([iy(:),data'],level+2,varargin{:}), nl); | |||
elseif(size(item,2)==1) | |||
% Column vector, store only row indices. | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([ix,data],level+2,varargin{:}), nl); | |||
else | |||
% General case, store row and column indices. | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([ix,iy,data],level+2,varargin{:}), nl); | |||
end | |||
else | |||
if(isreal(item)) | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json(item(:)',level+2,varargin{:}), nl); | |||
else | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep); | |||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',... | |||
matdata2json([real(item(:)) imag(item(:))],level+2,varargin{:}), nl); | |||
end | |||
end | |||
txt=sprintf('%s%s%s',txt,padding1,'}'); | |||
%%------------------------------------------------------------------------- | |||
function txt=matdata2json(mat,level,varargin) | |||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); | |||
ws=jsonopt('whitespaces_',ws,varargin{:}); | |||
tab=ws.tab; | |||
nl=ws.newline; | |||
if(size(mat,1)==1) | |||
pre=''; | |||
post=''; | |||
level=level-1; | |||
else | |||
pre=sprintf('[%s',nl); | |||
post=sprintf('%s%s]',nl,repmat(tab,1,level-1)); | |||
end | |||
if(isempty(mat)) | |||
txt='null'; | |||
return; | |||
end | |||
floatformat=jsonopt('FloatFormat','%.10g',varargin{:}); | |||
%if(numel(mat)>1) | |||
formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],%s',nl)]]; | |||
%else | |||
% formatstr=[repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf(',\n')]]; | |||
%end | |||
if(nargin>=2 && size(mat,1)>1 && jsonopt('ArrayIndent',1,varargin{:})==1) | |||
formatstr=[repmat(tab,1,level) formatstr]; | |||
end | |||
txt=sprintf(formatstr,mat'); | |||
txt(end-length(nl):end)=[]; | |||
if(islogical(mat) && jsonopt('ParseLogical',0,varargin{:})==1) | |||
txt=regexprep(txt,'1','true'); | |||
txt=regexprep(txt,'0','false'); | |||
end | |||
%txt=regexprep(mat2str(mat),'\s+',','); | |||
%txt=regexprep(txt,';',sprintf('],\n[')); | |||
% if(nargin>=2 && size(mat,1)>1) | |||
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']); | |||
% end | |||
txt=[pre txt post]; | |||
if(any(isinf(mat(:)))) | |||
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:})); | |||
end | |||
if(any(isnan(mat(:)))) | |||
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:})); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newname=checkname(name,varargin) | |||
isunpack=jsonopt('UnpackHex',1,varargin{:}); | |||
newname=name; | |||
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once'))) | |||
return | |||
end | |||
if(isunpack) | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
if(~isoct) | |||
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}'); | |||
else | |||
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start'); | |||
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end'); | |||
if(isempty(pos)) return; end | |||
str0=name; | |||
pos0=[0 pend(:)' length(name)]; | |||
newname=''; | |||
for i=1:length(pos) | |||
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))]; | |||
end | |||
if(pos(end)~=length(name)) | |||
newname=[newname str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newstr=escapejsonstring(str) | |||
newstr=str; | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
if(isoct) | |||
vv=sscanf(OCTAVE_VERSION,'%f'); | |||
if(vv(1)>=3.8) isoct=0; end | |||
end | |||
if(isoct) | |||
escapechars={'\a','\f','\n','\r','\t','\v'}; | |||
for i=1:length(escapechars); | |||
newstr=regexprep(newstr,escapechars{i},escapechars{i}); | |||
end | |||
else | |||
escapechars={'\a','\b','\f','\n','\r','\t','\v'}; | |||
for i=1:length(escapechars); | |||
newstr=regexprep(newstr,escapechars{i},regexprep(escapechars{i},'\\','\\\\')); | |||
end | |||
end |
@@ -1,504 +0,0 @@ | |||
function json=saveubjson(rootname,obj,varargin) | |||
% | |||
% json=saveubjson(rootname,obj,filename) | |||
% or | |||
% json=saveubjson(rootname,obj,opt) | |||
% json=saveubjson(rootname,obj,'param1',value1,'param2',value2,...) | |||
% | |||
% convert a MATLAB object (cell, struct or array) into a Universal | |||
% Binary JSON (UBJSON) binary string | |||
% | |||
% author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% created on 2013/08/17 | |||
% | |||
% $Id: saveubjson.m 460 2015-01-03 00:30:45Z fangq $ | |||
% | |||
% input: | |||
% rootname: the name of the root-object, when set to '', the root name | |||
% is ignored, however, when opt.ForceRootName is set to 1 (see below), | |||
% the MATLAB variable name will be used as the root name. | |||
% obj: a MATLAB object (array, cell, cell array, struct, struct array) | |||
% filename: a string for the file name to save the output UBJSON data | |||
% opt: a struct for additional options, ignore to use default values. | |||
% opt can have the following fields (first in [.|.] is the default) | |||
% | |||
% opt.FileName [''|string]: a file name to save the output JSON data | |||
% opt.ArrayToStruct[0|1]: when set to 0, saveubjson outputs 1D/2D | |||
% array in JSON array format; if sets to 1, an | |||
% array will be shown as a struct with fields | |||
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for | |||
% sparse arrays, the non-zero elements will be | |||
% saved to _ArrayData_ field in triplet-format i.e. | |||
% (ix,iy,val) and "_ArrayIsSparse_" will be added | |||
% with a value of 1; for a complex array, the | |||
% _ArrayData_ array will include two columns | |||
% (4 for sparse) to record the real and imaginary | |||
% parts, and also "_ArrayIsComplex_":1 is added. | |||
% opt.ParseLogical [1|0]: if this is set to 1, logical array elem | |||
% will use true/false rather than 1/0. | |||
% opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single | |||
% numerical element will be shown without a square | |||
% bracket, unless it is the root object; if 0, square | |||
% brackets are forced for any numerical arrays. | |||
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, saveubjson | |||
% will use the name of the passed obj variable as the | |||
% root object name; if obj is an expression and | |||
% does not have a name, 'root' will be used; if this | |||
% is set to 0 and rootname is empty, the root level | |||
% will be merged down to the lower level. | |||
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), | |||
% for example, if opt.JSON='foo', the JSON data is | |||
% wrapped inside a function call as 'foo(...);' | |||
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson | |||
% back to the string form | |||
% | |||
% opt can be replaced by a list of ('param',value) pairs. The param | |||
% string is equivallent to a field in opt and is case sensitive. | |||
% output: | |||
% json: a binary string in the UBJSON format (see http://ubjson.org) | |||
% | |||
% examples: | |||
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... | |||
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... | |||
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... | |||
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... | |||
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',... | |||
% 'SpecialData',[nan, inf, -inf]); | |||
% saveubjson('jsonmesh',jsonmesh) | |||
% saveubjson('jsonmesh',jsonmesh,'meshdata.ubj') | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
if(nargin==1) | |||
varname=inputname(1); | |||
obj=rootname; | |||
if(isempty(varname)) | |||
varname='root'; | |||
end | |||
rootname=varname; | |||
else | |||
varname=inputname(2); | |||
end | |||
if(length(varargin)==1 && ischar(varargin{1})) | |||
opt=struct('FileName',varargin{1}); | |||
else | |||
opt=varargin2struct(varargin{:}); | |||
end | |||
opt.IsOctave=exist('OCTAVE_VERSION','builtin'); | |||
rootisarray=0; | |||
rootlevel=1; | |||
forceroot=jsonopt('ForceRootName',0,opt); | |||
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || iscell(obj)) && isempty(rootname) && forceroot==0) | |||
rootisarray=1; | |||
rootlevel=0; | |||
else | |||
if(isempty(rootname)) | |||
rootname=varname; | |||
end | |||
end | |||
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot) | |||
rootname='root'; | |||
end | |||
json=obj2ubjson(rootname,obj,rootlevel,opt); | |||
if(~rootisarray) | |||
json=['{' json '}']; | |||
end | |||
jsonp=jsonopt('JSONP','',opt); | |||
if(~isempty(jsonp)) | |||
json=[jsonp '(' json ')']; | |||
end | |||
% save to a file if FileName is set, suggested by Patrick Rapin | |||
if(~isempty(jsonopt('FileName','',opt))) | |||
fid = fopen(opt.FileName, 'wb'); | |||
fwrite(fid,json); | |||
fclose(fid); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=obj2ubjson(name,item,level,varargin) | |||
if(iscell(item)) | |||
txt=cell2ubjson(name,item,level,varargin{:}); | |||
elseif(isstruct(item)) | |||
txt=struct2ubjson(name,item,level,varargin{:}); | |||
elseif(ischar(item)) | |||
txt=str2ubjson(name,item,level,varargin{:}); | |||
else | |||
txt=mat2ubjson(name,item,level,varargin{:}); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function txt=cell2ubjson(name,item,level,varargin) | |||
txt=''; | |||
if(~iscell(item)) | |||
error('input is not a cell'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); % let's handle 1D cell first | |||
if(len>1) | |||
if(~isempty(name)) | |||
txt=[S_(checkname(name,varargin{:})) '[']; name=''; | |||
else | |||
txt='['; | |||
end | |||
elseif(len==0) | |||
if(~isempty(name)) | |||
txt=[S_(checkname(name,varargin{:})) 'Z']; name=''; | |||
else | |||
txt='Z'; | |||
end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=[txt '[']; end | |||
for i=1:dim(1) | |||
txt=[txt obj2ubjson(name,item{i,j},level+(len>1),varargin{:})]; | |||
end | |||
if(dim(1)>1) txt=[txt ']']; end | |||
end | |||
if(len>1) txt=[txt ']']; end | |||
%%------------------------------------------------------------------------- | |||
function txt=struct2ubjson(name,item,level,varargin) | |||
txt=''; | |||
if(~isstruct(item)) | |||
error('input is not a struct'); | |||
end | |||
dim=size(item); | |||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now | |||
item=reshape(item,dim(1),numel(item)/dim(1)); | |||
dim=size(item); | |||
end | |||
len=numel(item); | |||
if(~isempty(name)) | |||
if(len>1) txt=[S_(checkname(name,varargin{:})) '[']; end | |||
else | |||
if(len>1) txt='['; end | |||
end | |||
for j=1:dim(2) | |||
if(dim(1)>1) txt=[txt '[']; end | |||
for i=1:dim(1) | |||
names = fieldnames(item(i,j)); | |||
if(~isempty(name) && len==1) | |||
txt=[txt S_(checkname(name,varargin{:})) '{']; | |||
else | |||
txt=[txt '{']; | |||
end | |||
if(~isempty(names)) | |||
for e=1:length(names) | |||
txt=[txt obj2ubjson(names{e},getfield(item(i,j),... | |||
names{e}),level+(dim(1)>1)+1+(len>1),varargin{:})]; | |||
end | |||
end | |||
txt=[txt '}']; | |||
end | |||
if(dim(1)>1) txt=[txt ']']; end | |||
end | |||
if(len>1) txt=[txt ']']; end | |||
%%------------------------------------------------------------------------- | |||
function txt=str2ubjson(name,item,level,varargin) | |||
txt=''; | |||
if(~ischar(item)) | |||
error('input is not a string'); | |||
end | |||
item=reshape(item, max(size(item),[1 0])); | |||
len=size(item,1); | |||
if(~isempty(name)) | |||
if(len>1) txt=[S_(checkname(name,varargin{:})) '[']; end | |||
else | |||
if(len>1) txt='['; end | |||
end | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
for e=1:len | |||
val=item(e,:); | |||
if(len==1) | |||
obj=['' S_(checkname(name,varargin{:})) '' '',S_(val),'']; | |||
if(isempty(name)) obj=['',S_(val),'']; end | |||
txt=[txt,'',obj]; | |||
else | |||
txt=[txt,'',['',S_(val),'']]; | |||
end | |||
end | |||
if(len>1) txt=[txt ']']; end | |||
%%------------------------------------------------------------------------- | |||
function txt=mat2ubjson(name,item,level,varargin) | |||
if(~isnumeric(item) && ~islogical(item)) | |||
error('input is not an array'); | |||
end | |||
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ... | |||
isempty(item) || jsonopt('ArrayToStruct',0,varargin{:})) | |||
cid=I_(uint32(max(size(item)))); | |||
if(isempty(name)) | |||
txt=['{' S_('_ArrayType_'),S_(class(item)),S_('_ArraySize_'),I_a(size(item),cid(1)) ]; | |||
else | |||
if(isempty(item)) | |||
txt=[S_(checkname(name,varargin{:})),'Z']; | |||
return; | |||
else | |||
txt=[S_(checkname(name,varargin{:})),'{',S_('_ArrayType_'),S_(class(item)),S_('_ArraySize_'),I_a(size(item),cid(1))]; | |||
end | |||
end | |||
else | |||
if(isempty(name)) | |||
txt=matdata2ubjson(item,level+1,varargin{:}); | |||
else | |||
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1) | |||
numtxt=regexprep(regexprep(matdata2ubjson(item,level+1,varargin{:}),'^\[',''),']',''); | |||
txt=[S_(checkname(name,varargin{:})) numtxt]; | |||
else | |||
txt=[S_(checkname(name,varargin{:})),matdata2ubjson(item,level+1,varargin{:})]; | |||
end | |||
end | |||
return; | |||
end | |||
if(issparse(item)) | |||
[ix,iy]=find(item); | |||
data=full(item(find(item))); | |||
if(~isreal(item)) | |||
data=[real(data(:)),imag(data(:))]; | |||
if(size(item,1)==1) | |||
% Kludge to have data's 'transposedness' match item's. | |||
% (Necessary for complex row vector handling below.) | |||
data=data'; | |||
end | |||
txt=[txt,S_('_ArrayIsComplex_'),'T']; | |||
end | |||
txt=[txt,S_('_ArrayIsSparse_'),'T']; | |||
if(size(item,1)==1) | |||
% Row vector, store only column indices. | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([iy(:),data'],level+2,varargin{:})]; | |||
elseif(size(item,2)==1) | |||
% Column vector, store only row indices. | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([ix,data],level+2,varargin{:})]; | |||
else | |||
% General case, store row and column indices. | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([ix,iy,data],level+2,varargin{:})]; | |||
end | |||
else | |||
if(isreal(item)) | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson(item(:)',level+2,varargin{:})]; | |||
else | |||
txt=[txt,S_('_ArrayIsComplex_'),'T']; | |||
txt=[txt,S_('_ArrayData_'),... | |||
matdata2ubjson([real(item(:)) imag(item(:))],level+2,varargin{:})]; | |||
end | |||
end | |||
txt=[txt,'}']; | |||
%%------------------------------------------------------------------------- | |||
function txt=matdata2ubjson(mat,level,varargin) | |||
if(isempty(mat)) | |||
txt='Z'; | |||
return; | |||
end | |||
if(size(mat,1)==1) | |||
level=level-1; | |||
end | |||
type=''; | |||
hasnegtive=(mat<0); | |||
if(isa(mat,'integer') || isinteger(mat) || (isfloat(mat) && all(mod(mat(:),1) == 0))) | |||
if(isempty(hasnegtive)) | |||
if(max(mat(:))<=2^8) | |||
type='U'; | |||
end | |||
end | |||
if(isempty(type)) | |||
% todo - need to consider negative ones separately | |||
id= histc(abs(max(mat(:))),[0 2^7 2^15 2^31 2^63]); | |||
if(isempty(find(id))) | |||
error('high-precision data is not yet supported'); | |||
end | |||
key='iIlL'; | |||
type=key(find(id)); | |||
end | |||
txt=[I_a(mat(:),type,size(mat))]; | |||
elseif(islogical(mat)) | |||
logicalval='FT'; | |||
if(numel(mat)==1) | |||
txt=logicalval(mat+1); | |||
else | |||
txt=['[$U#' I_a(size(mat),'l') typecast(swapbytes(uint8(mat(:)')),'uint8')]; | |||
end | |||
else | |||
if(numel(mat)==1) | |||
txt=['[' D_(mat) ']']; | |||
else | |||
txt=D_a(mat(:),'D',size(mat)); | |||
end | |||
end | |||
%txt=regexprep(mat2str(mat),'\s+',','); | |||
%txt=regexprep(txt,';',sprintf('],[')); | |||
% if(nargin>=2 && size(mat,1)>1) | |||
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']); | |||
% end | |||
if(any(isinf(mat(:)))) | |||
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:})); | |||
end | |||
if(any(isnan(mat(:)))) | |||
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:})); | |||
end | |||
%%------------------------------------------------------------------------- | |||
function newname=checkname(name,varargin) | |||
isunpack=jsonopt('UnpackHex',1,varargin{:}); | |||
newname=name; | |||
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once'))) | |||
return | |||
end | |||
if(isunpack) | |||
isoct=jsonopt('IsOctave',0,varargin{:}); | |||
if(~isoct) | |||
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}'); | |||
else | |||
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start'); | |||
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end'); | |||
if(isempty(pos)) return; end | |||
str0=name; | |||
pos0=[0 pend(:)' length(name)]; | |||
newname=''; | |||
for i=1:length(pos) | |||
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))]; | |||
end | |||
if(pos(end)~=length(name)) | |||
newname=[newname str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end | |||
end | |||
%%------------------------------------------------------------------------- | |||
function val=S_(str) | |||
if(length(str)==1) | |||
val=['C' str]; | |||
else | |||
val=['S' I_(int32(length(str))) str]; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function val=I_(num) | |||
if(~isinteger(num)) | |||
error('input is not an integer'); | |||
end | |||
if(num>=0 && num<255) | |||
val=['U' data2byte(swapbytes(cast(num,'uint8')),'uint8')]; | |||
return; | |||
end | |||
key='iIlL'; | |||
cid={'int8','int16','int32','int64'}; | |||
for i=1:4 | |||
if((num>0 && num<2^(i*8-1)) || (num<0 && num>=-2^(i*8-1))) | |||
val=[key(i) data2byte(swapbytes(cast(num,cid{i})),'uint8')]; | |||
return; | |||
end | |||
end | |||
error('unsupported integer'); | |||
%%------------------------------------------------------------------------- | |||
function val=D_(num) | |||
if(~isfloat(num)) | |||
error('input is not a float'); | |||
end | |||
if(isa(num,'single')) | |||
val=['d' data2byte(num,'uint8')]; | |||
else | |||
val=['D' data2byte(num,'uint8')]; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function data=I_a(num,type,dim,format) | |||
id=find(ismember('iUIlL',type)); | |||
if(id==0) | |||
error('unsupported integer array'); | |||
end | |||
% based on UBJSON specs, all integer types are stored in big endian format | |||
if(id==1) | |||
data=data2byte(swapbytes(int8(num)),'uint8'); | |||
blen=1; | |||
elseif(id==2) | |||
data=data2byte(swapbytes(uint8(num)),'uint8'); | |||
blen=1; | |||
elseif(id==3) | |||
data=data2byte(swapbytes(int16(num)),'uint8'); | |||
blen=2; | |||
elseif(id==4) | |||
data=data2byte(swapbytes(int32(num)),'uint8'); | |||
blen=4; | |||
elseif(id==5) | |||
data=data2byte(swapbytes(int64(num)),'uint8'); | |||
blen=8; | |||
end | |||
if(nargin>=3 && length(dim)>=2 && prod(dim)~=dim(2)) | |||
format='opt'; | |||
end | |||
if((nargin<4 || strcmp(format,'opt')) && numel(num)>1) | |||
if(nargin>=3 && (length(dim)==1 || (length(dim)>=2 && prod(dim)~=dim(2)))) | |||
cid=I_(uint32(max(dim))); | |||
data=['$' type '#' I_a(dim,cid(1)) data(:)']; | |||
else | |||
data=['$' type '#' I_(int32(numel(data)/blen)) data(:)']; | |||
end | |||
data=['[' data(:)']; | |||
else | |||
data=reshape(data,blen,numel(data)/blen); | |||
data(2:blen+1,:)=data; | |||
data(1,:)=type; | |||
data=data(:)'; | |||
data=['[' data(:)' ']']; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function data=D_a(num,type,dim,format) | |||
id=find(ismember('dD',type)); | |||
if(id==0) | |||
error('unsupported float array'); | |||
end | |||
if(id==1) | |||
data=data2byte(single(num),'uint8'); | |||
elseif(id==2) | |||
data=data2byte(double(num),'uint8'); | |||
end | |||
if(nargin>=3 && length(dim)>=2 && prod(dim)~=dim(2)) | |||
format='opt'; | |||
end | |||
if((nargin<4 || strcmp(format,'opt')) && numel(num)>1) | |||
if(nargin>=3 && (length(dim)==1 || (length(dim)>=2 && prod(dim)~=dim(2)))) | |||
cid=I_(uint32(max(dim))); | |||
data=['$' type '#' I_a(dim,cid(1)) data(:)']; | |||
else | |||
data=['$' type '#' I_(int32(numel(data)/(id*4))) data(:)']; | |||
end | |||
data=['[' data]; | |||
else | |||
data=reshape(data,(id*4),length(data)/(id*4)); | |||
data(2:(id*4+1),:)=data; | |||
data(1,:)=type; | |||
data=data(:)'; | |||
data=['[' data(:)' ']']; | |||
end | |||
%%------------------------------------------------------------------------- | |||
function bytes=data2byte(varargin) | |||
bytes=typecast(varargin{:}); | |||
bytes=bytes(:)'; |
@@ -1,40 +0,0 @@ | |||
function opt=varargin2struct(varargin) | |||
% | |||
% opt=varargin2struct('param1',value1,'param2',value2,...) | |||
% or | |||
% opt=varargin2struct(...,optstruct,...) | |||
% | |||
% convert a series of input parameters into a structure | |||
% | |||
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu) | |||
% date: 2012/12/22 | |||
% | |||
% input: | |||
% 'param', value: the input parameters should be pairs of a string and a value | |||
% optstruct: if a parameter is a struct, the fields will be merged to the output struct | |||
% | |||
% output: | |||
% opt: a struct where opt.param1=value1, opt.param2=value2 ... | |||
% | |||
% license: | |||
% BSD, see LICENSE_BSD.txt files for details | |||
% | |||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) | |||
% | |||
len=length(varargin); | |||
opt=struct; | |||
if(len==0) return; end | |||
i=1; | |||
while(i<=len) | |||
if(isstruct(varargin{i})) | |||
opt=mergestruct(opt,varargin{i}); | |||
elseif(ischar(varargin{i}) && i<len) | |||
opt=setfield(opt,varargin{i},varargin{i+1}); | |||
i=i+1; | |||
else | |||
error('input must be in the form of ...,''name'',value,... pairs or structs'); | |||
end | |||
i=i+1; | |||
end | |||
@@ -1,30 +0,0 @@ | |||
function str = makeValidFieldName(str) | |||
% From MATLAB doc: field names must begin with a letter, which may be | |||
% followed by any combination of letters, digits, and underscores. | |||
% Invalid characters will be converted to underscores, and the prefix | |||
% "x0x[Hex code]_" will be added if the first character is not a letter. | |||
isoct=exist('OCTAVE_VERSION','builtin'); | |||
pos=regexp(str,'^[^A-Za-z]','once'); | |||
if(~isempty(pos)) | |||
if(~isoct) | |||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); | |||
else | |||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); | |||
end | |||
end | |||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end | |||
if(~isoct) | |||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_'); | |||
else | |||
pos=regexp(str,'[^0-9A-Za-z_]'); | |||
if(isempty(pos)) return; end | |||
str0=str; | |||
pos0=[0 pos(:)' length(str)]; | |||
str=''; | |||
for i=1:length(pos) | |||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))]; | |||
end | |||
if(pos(end)~=length(str)) | |||
str=[str str0(pos0(end-1)+1:pos0(end))]; | |||
end | |||
end |
@@ -1,125 +0,0 @@ | |||
function submitWithConfiguration(conf) | |||
addpath('./lib/jsonlab'); | |||
parts = parts(conf); | |||
fprintf('== Submitting solutions | %s...\n', conf.itemName); | |||
tokenFile = 'token.mat'; | |||
if exist(tokenFile, 'file') | |||
load(tokenFile); | |||
[email token] = promptToken(email, token, tokenFile); | |||
else | |||
[email token] = promptToken('', '', tokenFile); | |||
end | |||
if isempty(token) | |||
fprintf('!! Submission Cancelled\n'); | |||
return | |||
end | |||
try | |||
response = submitParts(conf, email, token, parts); | |||
catch | |||
e = lasterror(); | |||
fprintf( ... | |||
'!! Submission failed: unexpected error: %s\n', ... | |||
e.message); | |||
fprintf('!! Please try again later.\n'); | |||
return | |||
end | |||
if isfield(response, 'errorMessage') | |||
fprintf('!! Submission failed: %s\n', response.errorMessage); | |||
else | |||
showFeedback(parts, response); | |||
save(tokenFile, 'email', 'token'); | |||
end | |||
end | |||
function [email token] = promptToken(email, existingToken, tokenFile) | |||
if (~isempty(email) && ~isempty(existingToken)) | |||
prompt = sprintf( ... | |||
'Use token from last successful submission (%s)? (Y/n): ', ... | |||
email); | |||
reenter = input(prompt, 's'); | |||
if (isempty(reenter) || reenter(1) == 'Y' || reenter(1) == 'y') | |||
token = existingToken; | |||
return; | |||
else | |||
delete(tokenFile); | |||
end | |||
end | |||
email = input('Login (email address): ', 's'); | |||
token = input('Token: ', 's'); | |||
end | |||
function isValid = isValidPartOptionIndex(partOptions, i) | |||
isValid = (~isempty(i)) && (1 <= i) && (i <= numel(partOptions)); | |||
end | |||
function response = submitParts(conf, email, token, parts) | |||
body = makePostBody(conf, email, token, parts); | |||
submissionUrl = submissionUrl(); | |||
params = {'jsonBody', body}; | |||
[code, responseBody] = system(sprintf('echo jsonBody=%s | curl -k -X POST -d @- %s', body, submissionUrl)); | |||
response = loadjson(responseBody); | |||
end | |||
function body = makePostBody(conf, email, token, parts) | |||
bodyStruct.assignmentSlug = conf.assignmentSlug; | |||
bodyStruct.submitterEmail = email; | |||
bodyStruct.secret = token; | |||
bodyStruct.parts = makePartsStruct(conf, parts); | |||
opt.Compact = 1; | |||
body = savejson('', bodyStruct, opt); | |||
end | |||
function partsStruct = makePartsStruct(conf, parts) | |||
for part = parts | |||
partId = part{:}.id; | |||
fieldName = makeValidFieldName(partId); | |||
outputStruct.output = conf.output(partId); | |||
partsStruct.(fieldName) = outputStruct; | |||
end | |||
end | |||
function [parts] = parts(conf) | |||
parts = {}; | |||
for partArray = conf.partArrays | |||
part.id = partArray{:}{1}; | |||
part.sourceFiles = partArray{:}{2}; | |||
part.name = partArray{:}{3}; | |||
parts{end + 1} = part; | |||
end | |||
end | |||
function showFeedback(parts, response) | |||
fprintf('== \n'); | |||
fprintf('== %43s | %9s | %-s\n', 'Part Name', 'Score', 'Feedback'); | |||
fprintf('== %43s | %9s | %-s\n', '---------', '-----', '--------'); | |||
for part = parts | |||
score = ''; | |||
partFeedback = ''; | |||
partFeedback = response.partFeedbacks.(makeValidFieldName(part{:}.id)); | |||
partEvaluation = response.partEvaluations.(makeValidFieldName(part{:}.id)); | |||
score = sprintf('%d / %3d', partEvaluation.score, partEvaluation.maxScore); | |||
fprintf('== %43s | %9s | %-s\n', part{:}.name, score, partFeedback); | |||
end | |||
evaluation = response.evaluation; | |||
totalScore = sprintf('%d / %d', evaluation.score, evaluation.maxScore); | |||
fprintf('== --------------------------------\n'); | |||
fprintf('== %43s | %9s | %-s\n', '', totalScore, ''); | |||
fprintf('== \n'); | |||
end | |||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |||
% | |||
% Service configuration | |||
% | |||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |||
function submissionUrl = submissionUrl() | |||
submissionUrl = 'https://www-origin.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1'; | |||
end |
@@ -1,58 +0,0 @@ | |||
function [J, grad] = lrCostFunction(theta, X, y, lambda) | |||
%LRCOSTFUNCTION Compute cost and gradient for logistic regression with | |||
%regularization | |||
% J = LRCOSTFUNCTION(theta, X, y, lambda) computes the cost of using | |||
% theta as the parameter for regularized logistic regression and the | |||
% gradient of the cost w.r.t. to the parameters. | |||
% Initialize some useful values | |||
m = length(y); % number of training examples | |||
% You need to return the following variables correctly | |||
J = 0; | |||
grad = zeros(size(theta)); | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Compute the cost of a particular choice of theta. | |||
% You should set J to the cost. | |||
% Compute the partial derivatives and set grad to the partial | |||
% derivatives of the cost w.r.t. each parameter in theta | |||
% | |||
hx = sigmoid(X * theta); %hypothesis, m * 1 | |||
% Hint: The computation of the cost function and gradients can be | |||
% efficiently vectorized. For example, consider the computation | |||
% | |||
% sigmoid(X * theta) | |||
% | |||
% Each row of the resulting matrix will contain the value of the | |||
% prediction for that example. You can make use of this to vectorize | |||
% the cost function and gradient computations. | |||
% | |||
J = 1 / m * sum(-y' * log(hx) - (1 - y)' * log(1 - hx)) + lambda / (2 * m) * theta(2:end)' * theta(2:end); | |||
% Hint: When computing the gradient of the regularized cost function, | |||
% there're many possible vectorized solutions, but one solution | |||
% looks like: | |||
% grad = (unregularized gradient for logistic regression) | |||
% temp = theta; | |||
% temp(1) = 0; % because we don't add anything for j = 0 | |||
% grad = grad + YOUR_CODE_HERE (using the temp variable) | |||
% | |||
gradf = (1 / m) * (X(:, 1)' * (hx - y)); | |||
gradb = (1 / m) * (X(:, 2:end)' * (hx - y)) + lambda * theta(2:end) / m; | |||
grad = [gradf;gradb]; | |||
size(grad) | |||
% ============================================================= | |||
grad = grad(:); | |||
end |
@@ -1,74 +0,0 @@ | |||
function [all_theta] = oneVsAll(X, y, num_labels, lambda) | |||
%ONEVSALL trains multiple logistic regression classifiers and returns all | |||
%the classifiers in a matrix all_theta, where the i-th row of all_theta | |||
%corresponds to the classifier for label i | |||
% [all_theta] = ONEVSALL(X, y, num_labels, lambda) trains num_labels | |||
% logisitc regression classifiers and returns each of these classifiers | |||
% in a matrix all_theta, where the i-th row of all_theta corresponds | |||
% to the classifier for label i | |||
% num_labels --> k | |||
% Some useful variables | |||
m = size(X, 1); | |||
n = size(X, 2); | |||
% You need to return the following variables correctly | |||
all_theta = zeros(num_labels, n + 1); | |||
% Add ones to the X data matrix | |||
X = [ones(m, 1) X]; | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: You should complete the following code to train num_labels | |||
% logistic regression classifiers with regularization | |||
% parameter lambda. | |||
% | |||
% Hint: theta(:) will return a column vector. | |||
% | |||
% Hint: You can use y == c to obtain a vector of 1's and 0's that tell use | |||
% whether the ground truth is true/false for this class. | |||
% | |||
% Note: For this assignment, we recommend using fmincg to optimize the cost | |||
% function. It is okay to use a for-loop (for c = 1:num_labels) to | |||
% loop over the different classes. | |||
% | |||
% fmincg works similarly to fminunc, but is more efficient when we | |||
% are dealing with large number of parameters. | |||
% | |||
% Example Code for fmincg: | |||
% | |||
% % Set Initial theta | |||
% initial_theta = zeros(n + 1, 1); | |||
% | |||
% % Set options for fminunc | |||
% options = optimset('GradObj', 'on', 'MaxIter', 50); | |||
% | |||
% % Run fmincg to obtain the optimal theta | |||
% % This function will return theta and the cost | |||
% [theta] = ... | |||
% fmincg (@(t)(lrCostFunction(t, X, (y == c), lambda)), ... | |||
% initial_theta, options); | |||
% | |||
options = optimset('GradObj', 'on', 'MaxIter', 50); | |||
for c = 1 : num_labels | |||
initial_theta = zeros(n + 1, 1); | |||
all_theta(c,:)= fmincg (@(t)(lrCostFunction(t, X, (y == c), lambda)), ... | |||
initial_theta, options); | |||
size(all_theta(c,:)) | |||
end | |||
%size(all_theta) | |||
%initial_theta = zeros(n + 1, num_labels); | |||
%all_theta= fmincg (@(t)(lrCostFunction(t, X, y, lambda)), ... | |||
% initial_theta, options); | |||
% ========================================================================= | |||
end |
@@ -1,37 +0,0 @@ | |||
function p = predict(Theta1, Theta2, X) | |||
%PREDICT Predict the label of an input given a trained neural network | |||
% p = PREDICT(Theta1, Theta2, X) outputs the predicted label of X given the | |||
% trained weights of a neural network (Theta1, Theta2) | |||
% Useful values | |||
m = size(X, 1); | |||
num_labels = size(Theta2, 1); | |||
% You need to return the following variables correctly | |||
p = zeros(size(X, 1), 1); | |||
X = [ones(m,1), X]; | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Complete the following code to make predictions using | |||
% your learned neural network. You should set p to a | |||
% vector containing labels between 1 to num_labels. | |||
% | |||
% Hint: The max function might come in useful. In particular, the max | |||
% function can also return the index of the max element, for more | |||
% information see 'help max'. If your examples are in rows, then, you | |||
% can use max(A, [], 2) to obtain the max for each row. | |||
% | |||
a2 = sigmoid(X * Theta1'); | |||
a2 = [ones(size(a2,1), 1), a2]; | |||
p = sigmoid(a2 *Theta2'); | |||
[temp_p,p] = max(p, [], 2); | |||
% ========================================================================= | |||
end |
@@ -1,44 +0,0 @@ | |||
function p = predictOneVsAll(all_theta, X) | |||
%PREDICT Predict the label for a trained one-vs-all classifier. The labels | |||
%are in the range 1..K, where K = size(all_theta, 1). | |||
% p = PREDICTONEVSALL(all_theta, X) will return a vector of predictions | |||
% for each example in the matrix X. Note that X contains the examples in | |||
% rows. all_theta is a matrix where the i-th row is a trained logistic | |||
% regression theta vector for the i-th class. You should set p to a vector | |||
% of values from 1..K (e.g., p = [1; 3; 1; 2] predicts classes 1, 3, 1, 2 | |||
% for 4 examples) | |||
m = size(X, 1); | |||
num_labels = size(all_theta, 1); | |||
% You need to return the following variables correctly | |||
p = zeros(size(X, 1), 1); | |||
% Add ones to the X data matrix | |||
X = [ones(m, 1) X]; | |||
% ====================== YOUR CODE HERE ====================== | |||
% Instructions: Complete the following code to make predictions using | |||
% your learned logistic regression parameters (one-vs-all). | |||
% You should set p to a vector of predictions (from 1 to | |||
% num_labels). | |||
% | |||
% Hint: This code can be done all vectorized using the max function. | |||
% In particular, the max function can also return the index of the | |||
% max element, for more information see 'help max'. If your examples | |||
% are in rows, then, you can use max(A, [], 2) to obtain the max | |||
% for each row. | |||
% | |||
p = X * all_theta'; | |||
[temp_p,p] = max(p, [], 2); | |||
%p(find(p == 10)) = 0; | |||
% ========================================================================= | |||
end |
@@ -1,6 +0,0 @@ | |||
function g = sigmoid(z) | |||
%SIGMOID Compute sigmoid functoon | |||
% J = SIGMOID(z) computes the sigmoid of z. | |||
g = 1.0 ./ (1.0 + exp(-z)); | |||
end |
@@ -1,56 +0,0 @@ | |||
function submit() | |||
addpath('./lib'); | |||
conf.assignmentSlug = 'multi-class-classification-and-neural-networks'; | |||
conf.itemName = 'Multi-class Classification and Neural Networks'; | |||
conf.partArrays = { ... | |||
{ ... | |||
'1', ... | |||
{ 'lrCostFunction.m' }, ... | |||
'Regularized Logistic Regression', ... | |||
}, ... | |||
{ ... | |||
'2', ... | |||
{ 'oneVsAll.m' }, ... | |||
'One-vs-All Classifier Training', ... | |||
}, ... | |||
{ ... | |||
'3', ... | |||
{ 'predictOneVsAll.m' }, ... | |||
'One-vs-All Classifier Prediction', ... | |||
}, ... | |||
{ ... | |||
'4', ... | |||
{ 'predict.m' }, ... | |||
'Neural Network Prediction Function' ... | |||
}, ... | |||
}; | |||
conf.output = @output; | |||
submitWithConfiguration(conf); | |||
end | |||
function out = output(partId, auxdata) | |||
% Random Test Cases | |||
X = [ones(20,1) (exp(1) * sin(1:1:20))' (exp(0.5) * cos(1:1:20))']; | |||
y = sin(X(:,1) + X(:,2)) > 0; | |||
Xm = [ -1 -1 ; -1 -2 ; -2 -1 ; -2 -2 ; ... | |||
1 1 ; 1 2 ; 2 1 ; 2 2 ; ... | |||
-1 1 ; -1 2 ; -2 1 ; -2 2 ; ... | |||
1 -1 ; 1 -2 ; -2 -1 ; -2 -2 ]; | |||
ym = [ 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 ]'; | |||
t1 = sin(reshape(1:2:24, 4, 3)); | |||
t2 = cos(reshape(1:2:40, 4, 5)); | |||
if partId == '1' | |||
[J, grad] = lrCostFunction([0.25 0.5 -0.5]', X, y, 0.1); | |||
out = sprintf('%0.5f ', J); | |||
out = [out sprintf('%0.5f ', grad)]; | |||
elseif partId == '2' | |||
out = sprintf('%0.5f ', oneVsAll(Xm, ym, 4, 0.1)); | |||
elseif partId == '3' | |||
out = sprintf('%0.5f ', predictOneVsAll(t1, Xm)); | |||
elseif partId == '4' | |||
out = sprintf('%0.5f ', predict(t1, t2, Xm)); | |||
end | |||
end |
@@ -1,15 +0,0 @@ | |||
# Created by Octave 4.2.0, Sun Nov 27 12:41:13 2016 GMT <unknown@unknown> | |||
# name: email | |||
# type: sq_string | |||
# elements: 1 | |||
# length: 17 | |||
scruel@vip.qq.com | |||
# name: token | |||
# type: sq_string | |||
# elements: 1 | |||
# length: 16 | |||
CPfDADNFz0Hd0Qgk | |||
@@ -1,50 +0,0 @@ | |||
function checkNNGradients(lambda) | |||
%CHECKNNGRADIENTS Creates a small neural network to check the | |||
%backpropagation gradients | |||
% CHECKNNGRADIENTS(lambda) Creates a small neural network to check the | |||
% backpropagation gradients, it will output the analytical gradients | |||
% produced by your backprop code and the numerical gradients (computed | |||
% using computeNumericalGradient). These two gradient computations should | |||
% result in very similar values. | |||
% | |||
if ~exist('lambda', 'var') || isempty(lambda) | |||
lambda = 0; | |||
end | |||
input_layer_size = 3; | |||
hidden_layer_size = 5; | |||
num_labels = 3; | |||
m = 5; | |||
% We generate some 'random' test data | |||
Theta1 = debugInitializeWeights(hidden_layer_size, input_layer_size); | |||
Theta2 = debugInitializeWeights(num_labels, hidden_layer_size); | |||
% Reusing debugInitializeWeights to generate X | |||
X = debugInitializeWeights(m, input_layer_size - 1); | |||
y = 1 + mod(1:m, num_labels)'; | |||
% Unroll parameters | |||
nn_params = [Theta1(:) ; Theta2(:)]; | |||
% Short hand for cost function | |||
costFunc = @(p) nnCostFunction(p, input_layer_size, hidden_layer_size, ... | |||
num_labels, X, y, lambda); | |||
[cost, grad] = costFunc(nn_params); | |||
numgrad = computeNumericalGradient(costFunc, nn_params); | |||
% Visually examine the two gradient computations. The two columns | |||
% you get should be very similar. | |||
disp([numgrad grad]); | |||
fprintf(['The above two columns you get should be very similar.\n' ... | |||
'(Left-Your Numerical Gradient, Right-Analytical Gradient)\n\n']); | |||
% Evaluate the norm of the difference between two solutions. | |||
% If you have a correct implementation, and assuming you used EPSILON = 0.0001 | |||
% in computeNumericalGradient.m, then diff below should be less than 1e-9 | |||
diff = norm(numgrad-grad)/norm(numgrad+grad); | |||
fprintf(['If your backpropagation implementation is correct, then \n' ... | |||
'the relative difference will be small (less than 1e-9). \n' ... | |||
'\nRelative Difference: %g\n'], diff); | |||
end |
@@ -1,29 +0,0 @@ | |||
function numgrad = computeNumericalGradient(J, theta) | |||
%COMPUTENUMERICALGRADIENT Computes the gradient using "finite differences" | |||
%and gives us a numerical estimate of the gradient. | |||
% numgrad = COMPUTENUMERICALGRADIENT(J, theta) computes the numerical | |||
% gradient of the function J around theta. Calling y = J(theta) should | |||
% return the function value at theta. | |||
% Notes: The following code implements numerical gradient checking, and | |||
% returns the numerical gradient.It sets numgrad(i) to (a numerical | |||
% approximation of) the partial derivative of J with respect to the | |||
% i-th input argument, evaluated at theta. (i.e., numgrad(i) should | |||
% be the (approximately) the partial derivative of J with respect | |||
% to theta(i).) | |||
% | |||
numgrad = zeros(size(theta)); | |||
perturb = zeros(size(theta)); | |||
e = 1e-4; | |||
for p = 1:numel(theta) | |||
% Set perturbation vector | |||
perturb(p) = e; | |||
loss1 = J(theta - perturb); | |||
loss2 = J(theta + perturb); | |||
% Compute Numerical Gradient | |||
numgrad(p) = (loss2 - loss1) / (2*e); | |||
perturb(p) = 0; | |||
end | |||
end |
@@ -1,22 +0,0 @@ | |||
function W = debugInitializeWeights(fan_out, fan_in) | |||
%DEBUGINITIALIZEWEIGHTS Initialize the weights of a layer with fan_in | |||
%incoming connections and fan_out outgoing connections using a fixed | |||
%strategy, this will help you later in debugging | |||
% W = DEBUGINITIALIZEWEIGHTS(fan_in, fan_out) initializes the weights | |||
% of a layer with fan_in incoming connections and fan_out outgoing | |||
% connections using a fix set of values | |||
% | |||
% Note that W should be set to a matrix of size(1 + fan_in, fan_out) as | |||
% the first row of W handles the "bias" terms | |||
% | |||
% Set W to zeros | |||
W = zeros(fan_out, 1 + fan_in); | |||
% Initialize W using "sin", this ensures that W is always of the same | |||
% values and will be useful for debugging | |||
W = reshape(sin(1:numel(W)), size(W)) / 10; | |||
% ========================================================================= | |||
end |
@@ -1,59 +0,0 @@ | |||
function [h, display_array] = displayData(X, example_width) | |||
%DISPLAYDATA Display 2D data in a nice grid | |||
% [h, display_array] = DISPLAYDATA(X, example_width) displays 2D data | |||
% stored in X in a nice grid. It returns the figure handle h and the | |||
% displayed array if requested. | |||
% Set example_width automatically if not passed in | |||
if ~exist('example_width', 'var') || isempty(example_width) | |||
example_width = round(sqrt(size(X, 2))); | |||
end | |||
% Gray Image | |||
colormap(gray); | |||
% Compute rows, cols | |||
[m n] = size(X); | |||
example_height = (n / example_width); | |||
% Compute number of items to display | |||
display_rows = floor(sqrt(m)); | |||
display_cols = ceil(m / display_rows); | |||
% Between images padding | |||
pad = 1; | |||
% Setup blank display | |||
display_array = - ones(pad + display_rows * (example_height + pad), ... | |||
pad + display_cols * (example_width + pad)); | |||
% Copy each example into a patch on the display array | |||
curr_ex = 1; | |||
for j = 1:display_rows | |||
for i = 1:display_cols | |||
if curr_ex > m, | |||
break; | |||
end | |||
% Copy the patch | |||
% Get the max value of the patch | |||
max_val = max(abs(X(curr_ex, :))); | |||
display_array(pad + (j - 1) * (example_height + pad) + (1:example_height), ... | |||
pad + (i - 1) * (example_width + pad) + (1:example_width)) = ... | |||
reshape(X(curr_ex, :), example_height, example_width) / max_val; | |||
curr_ex = curr_ex + 1; | |||
end | |||
if curr_ex > m, | |||
break; | |||
end | |||
end | |||
% Display Image | |||
h = imagesc(display_array, [-1 1]); | |||
% Do not show axis | |||
axis image off | |||
drawnow; | |||
end |
@@ -1,250 +0,0 @@ | |||
%% Machine Learning Online Class - Exercise 4 Neural Network Learning | |||
% Instructions | |||
% ------------ | |||
% | |||
% This file contains code that helps you get started on the | |||
% linear exercise. You will need to complete the following functions | |||
% in this exericse: | |||
% | |||
% sigmoidGradient.m | |||
% randInitializeWeights.m | |||
% nnCostFunction.m | |||
% | |||
% For this exercise, you will not need to change any code in this file, | |||
% or any other files other than those mentioned above. | |||
% | |||
%% Initialization | |||
clear ; close all; clc | |||
%% Setup the parameters you will use for this exercise | |||
input_layer_size = 400; % 20x20 Input Images of Digits | |||
hidden_layer_size = 25; % 25 hidden units | |||
num_labels = 10; % 10 labels, from 1 to 10 | |||
% (note that we have mapped "0" to label 10) | |||
%% =========== Part 1: Loading and Visualizing Data ============= | |||
% We start the exercise by first loading and visualizing the dataset. | |||
% You will be working with a dataset that contains handwritten digits. | |||
% | |||
% Load Training Data | |||
fprintf('Loading and Visualizing Data ...\n') | |||
load('ex4data1.mat'); | |||
m = size(X, 1); | |||
% Randomly select 100 data points to display | |||
sel = randperm(size(X, 1)); | |||
sel = sel(1:100); | |||
displayData(X(sel, :)); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% ================ Part 2: Loading Parameters ================ | |||
% In this part of the exercise, we load some pre-initialized | |||
% neural network parameters. | |||
fprintf('\nLoading Saved Neural Network Parameters ...\n') | |||
% Load the weights into variables Theta1 and Theta2 | |||
load('ex4weights.mat'); | |||
% Unroll parameters | |||
nn_params = [Theta1(:) ; Theta2(:)]; | |||
%% ================ Part 3: Compute Cost (Feedforward) ================ | |||
% To the neural network, you should first start by implementing the | |||
% feedforward part of the neural network that returns the cost only. You | |||
% should complete the code in nnCostFunction.m to return cost. After | |||
% implementing the feedforward to compute the cost, you can verify that | |||
% your implementation is correct by verifying that you get the same cost | |||
% as us for the fixed debugging parameters. | |||
% | |||
% We suggest implementing the feedforward cost *without* regularization | |||
% first so that it will be easier for you to debug. Later, in part 4, you | |||
% will get to implement the regularized cost. | |||
% | |||
fprintf('\nFeedforward Using Neural Network ...\n') | |||
% Weight regularization parameter (we set this to 0 here). | |||
lambda = 0; | |||
J = nnCostFunction(nn_params, input_layer_size, hidden_layer_size, ... | |||
num_labels, X, y, lambda); | |||
fprintf(['Cost at parameters (loaded from ex4weights): %f '... | |||
'\n(this value should be about 0.287629)\n'], J); | |||
fprintf('\nProgram paused. Press enter to continue.\n'); | |||
pause; | |||
%% =============== Part 4: Implement Regularization =============== | |||
% Once your cost function implementation is correct, you should now | |||
% continue to implement the regularization with the cost. | |||
% | |||
fprintf('\nChecking Cost Function (w/ Regularization) ... \n') | |||
% Weight regularization parameter (we set this to 1 here). | |||
lambda = 1; | |||
J = nnCostFunction(nn_params, input_layer_size, hidden_layer_size, ... | |||
num_labels, X, y, lambda); | |||
fprintf(['Cost at parameters (loaded from ex4weights): %f '... | |||
'\n(this value should be about 0.383770)\n'], J); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% ================ Part 5: Sigmoid Gradient ================ | |||
% Before you start implementing the neural network, you will first | |||
% implement the gradient for the sigmoid function. You should complete the | |||
% code in the sigmoidGradient.m file. | |||
% | |||
fprintf('\nEvaluating sigmoid gradient...\n') | |||
g = sigmoidGradient([1 -0.5 0 0.5 1]); | |||
fprintf('Sigmoid gradient evaluated at [1 -0.5 0 0.5 1]:\n '); | |||
fprintf('%f ', g); | |||
fprintf('\n\n'); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% ================ Part 6: Initializing Pameters ================ | |||
% In this part of the exercise, you will be starting to implment a two | |||
% layer neural network that classifies digits. You will start by | |||
% implementing a function to initialize the weights of the neural network | |||
% (randInitializeWeights.m) | |||
fprintf('\nInitializing Neural Network Parameters ...\n') | |||
initial_Theta1 = randInitializeWeights(input_layer_size, hidden_layer_size); | |||
initial_Theta2 = randInitializeWeights(hidden_layer_size, num_labels); | |||
% Unroll parameters | |||
initial_nn_params = [initial_Theta1(:) ; initial_Theta2(:)]; | |||
%% =============== Part 7: Implement Backpropagation =============== | |||
% Once your cost matches up with ours, you should proceed to implement the | |||
% backpropagation algorithm for the neural network. You should add to the | |||
% code you've written in nnCostFunction.m to return the partial | |||
% derivatives of the parameters. | |||
% | |||
fprintf('\nChecking Backpropagation... \n'); | |||
% Check gradients by running checkNNGradients | |||
checkNNGradients; | |||
fprintf('\nProgram paused. Press enter to continue.\n'); | |||
pause; | |||
%% =============== Part 8: Implement Regularization =============== | |||
% Once your backpropagation implementation is correct, you should now | |||
% continue to implement the regularization with the cost and gradient. | |||
% | |||
fprintf('\nChecking Backpropagation (w/ Regularization) ... \n') | |||
% Check gradients by running checkNNGradients | |||
lambda = 3; | |||
checkNNGradients(lambda); | |||
% Also output the costFunction debugging values | |||
debug_J = nnCostFunction(nn_params, input_layer_size, ... | |||
hidden_layer_size, num_labels, X, y, lambda); | |||
fprintf(['\n\nCost at (fixed) debugging parameters (w/ lambda = 10): %f ' ... | |||
'\n(this value should be about 0.576051)\n\n'], debug_J); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% =================== Part 8: Training NN =================== | |||
% You have now implemented all the code necessary to train a neural | |||
% network. To train your neural network, we will now use "fmincg", which | |||
% is a function which works similarly to "fminunc". Recall that these | |||
% advanced optimizers are able to train our cost functions efficiently as | |||
% long as we provide them with the gradient computations. | |||
% | |||
fprintf('\nTraining Neural Network... \n') | |||
% After you have completed the assignment, change the MaxIter to a larger | |||
% value to see how more training helps. | |||
options = optimset('MaxIter', 400); | |||
% You should also try different values of lambda | |||
lambda = 1; | |||
% Create "short hand" for the cost function to be minimized | |||
costFunction = @(p) nnCostFunction(p, ... | |||
input_layer_size, ... | |||
hidden_layer_size, ... | |||
num_labels, X, y, lambda); | |||
% Now, costFunction is a function that takes in only one argument (the | |||
% neural network parameters) | |||
[nn_params, cost] = fmincg(costFunction, initial_nn_params, options); | |||
% Obtain Theta1 and Theta2 back from nn_params | |||
disp("test") | |||
Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), ... | |||
hidden_layer_size, (input_layer_size + 1)); | |||
Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), ... | |||
num_labels, (hidden_layer_size + 1)); | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
%% ================= Part 9: Visualize Weights ================= | |||
% You can now "visualize" what the neural network is learning by | |||
% displaying the hidden units to see what features they are capturing in | |||
% the data. | |||
fprintf('\nVisualizing Neural Network... \n') | |||
displayData(Theta1(:, 2:end)); | |||
fprintf('\nProgram paused. Press enter to continue.\n'); | |||
pause; | |||
%% ================= Part 10: Implement Predict ================= | |||
% After training the neural network, we would like to use it to predict | |||
% the labels. You will now implement the "predict" function to use the | |||
% neural network to predict the labels of the training set. This lets | |||
% you compute the training set accuracy. | |||
pred = predict(Theta1, Theta2, X); | |||
fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100); | |||
% Randomly permute examples | |||
rp = randperm(m); | |||
for i = 1:m | |||
% Display | |||
fprintf('\nDisplaying Example Image\n'); | |||
displayData(X(rp(i), :)); | |||
pred = predict(Theta1, Theta2, X(rp(i),:)); | |||
fprintf('\nNeural Network Prediction: %d (digit %d)\n', pred, mod(pred, 10)); | |||
% Pause | |||
fprintf('Program paused. Press enter to continue.\n'); | |||
pause; | |||
end |