| @@ -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 | |||