1. 程式人生 > >基於jupyter lab搭建網頁程式設計環境並新增自定義python kernel和matlab kernel以及plotly的使用

基於jupyter lab搭建網頁程式設計環境並新增自定義python kernel和matlab kernel以及plotly的使用

> 內容轉載自[我的部落格](https://blog.whuzfb.cn/blog/2020/08/02/install_jupyter_lab/) [TOC] ## 說明 即使該系統有使用者`zfb`、`root`、`test`、`ubuntu`等,下面介紹的步驟隻影響本使用者,既不需要`root`許可權,也不會對其他使用者造成影響(開機自啟的`service`檔案需要`root`使用者編輯和設定開機自啟,之後就不需要操作了) ## 1. 建立虛擬環境jupyter ```bash # 安裝venv sudo apt-get install python3-venv # 建立虛擬環境,名稱為jupyter python3 -m venv jupyter ``` ## 2. 安裝nodejs(用於jupyterlab安裝擴充套件) ```bash # 下載nvm用於管理npm、nodejs環境 wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash # 重新啟動即可使用nvm命令 # nvm ls-remote 列出nodejs所有可用版本 # nvm install 10.10.0 安裝nodejs 10.10.0版本 # 安裝nodejs最新版本 nvm install node ``` 把nvm環境`bin`資料夾放入`PATH`,即在`~/.bashrc`新增一行內容,必須把自己路徑放在前面,避免先搜尋到`/usr/local/bin`目錄: ```bash export PATH=/home/zfb/.nvm/versions/node/v14.5.0/bin:${PATH} ``` ## 3. 安裝pip包 ```bash # 啟用虛擬環境jupyter source jupyter/bin/activate # 在虛擬環境jupyter中安裝jupyterlab和nodejs pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jupyterlab npm nodejs ``` ## 4. 使用jupyterlab 先把python虛擬環境`jupyter`的`bin`資料夾放入`PATH`,即在`~/.bashrc`新增一行內容,必須把自己路徑放在前面,避免先搜尋到`/usr/local/bin`目錄: ```bash export PATH=/home/zfb/jupyter/bin:${PATH} ``` 在命令列輸入`jupyter lab`即可在本地埠開啟(不需要啟用虛擬環境),可以通過命令`which jupyter`得到`/home/zfb/jupyter/bin/jupyter`結果 在jupyterlab執行期間,可以通過命令`jupyter notebook list`檢視當前執行的jupyter例項 列出當前已安裝的擴充套件:`jupyter labextension list` 解除安裝某個擴充套件:`jupyter labextension uninstall my-extension-name` 檢視jupyter的kernel:`jupyter kernelspec list` 注意:`http://127.0.0.1:8888/lab`是jupyterlab的地址;`http://127.0.0.1:8888/tree`是傳統jupyter notebook的地址 ## 5. 配置jupyterlab 在終端輸入以下命令生成加密祕鑰: ```bash # 啟用虛擬環境jupyter source jupyter/bin/activate # 密碼設定為123456,此命令輸出密碼的sha1結果,用於下一步配置檔案token python -c "from notebook.auth import passwd;print(passwd('123456'))" ``` 在命令列輸入`jupyter lab --generate-config`,則會生成檔案`/home/zfb/.jupyter/jupyter_notebook_config.py`,開啟該檔案,修改以下內容: ```python c.NotebookApp.allow_remote_access = True c.NotebookApp.ip = '0.0.0.0' c.NotebookApp.notebook_dir = '/home/zfb/jp_data/' c.NotebookApp.open_browser = False c.NotebookApp.password = 'sha1:10d130e9bad7:b73d9821f96ccc4f42b2071b5dc46f2357373da3' c.NotebookApp.port = 8888 ``` 安裝擴充套件時如果找不到node,那麼需要確保它在PATH,然後手動啟動jupyter lab,**不要使用service啟動**即可在瀏覽器點選install安裝 ## 6. 開機自啟jupyter 切換root使用者(zfb使用者不能執行sudo命令),建立檔案jupyter-zfb.service,內容如下: ```ini [Unit] Description=Auto start jupyter lab Service for web After=network.target [Service] Type=simple # Type=forking # PIDFile=/var/pid/master.pid # 如果是在為其他使用者配置jupyterlab,這裡填對應的使用者名稱 User=zfb Restart=on-failure RestartSec=10s WorkingDirectory=/home/zfb/jupyter ExecStart=/home/zfb/jupyter/bin/jupyter lab # ExecReload=/home/zfb/jupyter/bin/jupyter lab [Install] WantedBy=multi-user.target ``` 然後依次執行下面命令: ```bash # 複製jupyter-zfb.service檔案到指定目錄 sudo cp ./jupyter-zfb.service /etc/systemd/system/ # 設定jupyter-zfb開機自啟 systemctl enable jupyter-zfb.service # 過載service檔案 sudo systemctl daemon-reload # 檢視所有的開機自啟項 systemctl list-unit-files --type=service|grep enabled # 手動開啟jupyter-zfb服務 service jupyter-zfb start # 檢視jupyter-zfb服務的執行狀態 service jupyter-zfb status # 停止jupyter-zfb服務 service jupyter-zfb stop ``` 檢視服務狀態的輸出如下: ```txt root1@my-Server:~$ service jupyter-zfb status ● jupyter-zfb.service - Auto start jupyter lab Service for web Loaded: loaded (/etc/systemd/system/jupyter-zfb.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2020-07-19 23:59:44 CST; 3s ago Main PID: 19426 (jupyter-lab) Tasks: 1 (limit: 7372) CGroup: /system.slice/jupyter-zfb.service └─19426 /home/zfb/jupyter/bin/python3 /home/zfb/jupyter/bin/jupyter-lab Jul 19 23:59:44 my-Server systemd[1]: Started Auto start jupyter lab Service for web. Jul 19 23:59:44 my-Server jupyter[19426]: [I 23:59:44.704 LabApp] JupyterLab extension loaded from /home/zfb/ Jul 19 23:59:44 my-Server jupyter[19426]: [I 23:59:44.704 LabApp] JupyterLab application directory is /home/z Jul 19 23:59:44 my-Server jupyter[19426]: [I 23:59:44.706 LabApp] Serving notebooks from local directory: /ho Jul 19 23:59:44 my-Server jupyter[19426]: [I 23:59:44.706 LabApp] The Jupyter Notebook is running at: Jul 19 23:59:44 my-Server jupyter[19426]: [I 23:59:44.706 LabApp] http://my-Server:8888/ Jul 19 23:59:44 my-Server jupyter[19426]: [I 23:59:44.706 LabApp] Use Control-C to stop this server and shut root1@my-Server:~$ ``` **問題**:service執行,則一旦安裝擴充套件之後重新開啟,擴充套件處就顯示500 Internal Server Error;但是直接執行在控制檯無問題;nohup jupyter lab &也無問題;screen也無問題 ## 6. 開機自啟和nohup執行 建立檔案`startjupyterlab.sh`並分配執行許可權: ```bash #!/bin/bash # 後臺執行,重定向錯誤日誌,匯出pid到檔案 # nohup會免疫HUP訊號,>>表示追加模式 /usr/bin/nohup /home/zfb/jupyter/bin/jupyter lab >> /home/zfb/jupyter/log/jupyterlab.log 2>&1 & echo $! > /home/zfb/jupyter/run_jupyter.pid ``` ubuntu 18.04不再使用`inited`管理系統,改用`systemd`,原本簡單方便的`/etc/rc.local`檔案已經沒有了。systemd預設讀取`/etc/systemd/system/`下的配置檔案,該目錄下的檔案會連結`/lib/systemd/system/`下的檔案,一般系統安裝完`/lib/systemd/system/`下會有`rc-local.service`檔案,即我們需要的配置檔案,裡面有寫到`rc.local`的啟動順序和行為,檔案內容如下`cat /lib/systemd/system/rc-local.service` ```ini # SPDX-License-Identifier: LGPL-2.1+ # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # This unit gets pulled automatically into multi-user.target by # systemd-rc-local-generator if /etc/rc.local is executable. [Unit] Description=/etc/rc.local Compatibility Documentation=man:systemd-rc-local-generator(8) ConditionFileIsExecutable=/etc/rc.local After=network.target [Service] Type=forking ExecStart=/etc/rc.local start TimeoutSec=0 RemainAfterExit=yes GuessMainPID=no ``` `systemctl status rc-local`可以檢視當前是否有`rc-local`這個服務,如果沒有則需要建立`ln -fs /lib/systemd/system/rc-local.service /etc/systemd/system/rc-local.service`。設定開機啟動並執行服務可以看到如下輸出: ```bash zfb@my-Server:~$ service rc-local status ● rc-local.service - /etc/rc.local Compatibility Loaded: loaded (/lib/systemd/system/rc-local.service; static; vendor preset: enabled) Drop-In: /lib/systemd/system/rc-local.service.d └─debian.conf Active: inactive (dead) Condition: start condition failed at Mon 2020-07-20 14:39:15 CST; 2s ago └─ ConditionFileIsExecutable=/etc/rc.local was not met Docs: man:systemd-rc-local-generator(8) zfb@ny-Server:~$ ``` 然後執行以下操作: ```bash # 建立檔案 sudo vim /etc/rc.local # 新增內容 # #!/bin/bash # # su - zfb -c "/bin/bash /home/zfb/startjupyterlab.sh" # 新增執行許可權 sudo chmod +x /etc/rc.local ``` 執行`service rc-local start`即可啟動服務,`service rc-local status`檢視執行狀態 **日誌分割**:然後建立檔案`/etc/logrotate.d/jupyter-zfb`: ```txt su zfb zfb /home/zfb/jupyter/log/jupyterlab.log{ weekly minsize 10M rotate 10 missingok dateext notifempty sharedscripts postrotate if [ -f /home/zfb/jupyter/run_jupyter.pid ]; then /bin/kill -9 `cat /home/zfb/jupyter/run_jupyter.pid` fi /usr/bin/nohup /home/zfb/jupyter/bin/jupyter lab >> /home/zfb/jupyter/log/jupyterlab.log 2>&1 & echo $! > /home/zfb/jupyter/run_jupyter.pid endscript } ``` 執行命令`logrotate -dvf /etc/logrotate.d/jupyter-zfb`可以檢視每次輪詢的輸出 * `d`表示只是顯示,並不實際執行 * `v`表示顯示詳細資訊 * `f`表示即使不滿足條件也強制執行一次 ## 7. 新增其他python環境的kernel 在不啟用任何環境的終端,建立新的虛擬環境py36(最後把它新增到jupyter的kernel) ```bash # 建立新的虛擬環境py36 python3 -m venv py36 # 啟用新虛擬環境py36 source py36/bin/activate # 為新環境安裝需要的庫 # pip install -i https://pypi.tuna.tsinghua.edu.cn/simple # 為虛擬環境安裝kernel pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ipykernel # 將此虛擬環境配置到jupyter的kernel中,此命令返回 # Installed kernelspec kernel_py36 in /home/zfb/.local/share/jupyter/kernels/kernel_py36 # 若不指定--user,則會提示許可權不足,因為預設安裝到/usr/local/share/jupyter python -m ipykernel install --name kernel_py36 --user # 啟動jupyterlab,此時可以看到已經有兩個kernel可供切換(jupyter、kernel_py36) jupyter lab ``` 刪除某個kernel:`jupyter kernelspec remove kernel_py36` ## 8. 新增matlab的kernel 啟用虛擬環境`jupyter`(jupyterlab被安裝在此虛擬環境),然後安裝matlab_kernal,再切換到matlab的安裝目錄`extern/engines/python/`,執行`setup.py`檔案,具體步驟的命令如下: ```bash # 啟用虛擬環境jupyter source jupyter/bin/activate # 在虛擬環境jupyter安裝matlab_kernel pip install matlab_kernel # 若不指定--user,則會提示許可權不足 python -m matlab_kernel install --user # 切換到matlab安裝目錄的extern/engines/python/,然後執行命令 python setup.py install # --build-base="/home/zfb/build" install --prefix="/home/zfb/jupyter/lib/python3.6/site-packages" # 此時執行jupyter kernelspec list即可看到如下輸出 # Available kernels: # matlab /home/zfb/jupyter/share/jupyter/kernels/matlab # python3 /home/zfb/jupyter/share/jupyter/kernels/python3 ``` 保證最後`/home/zfb/jupyter/lib/python3.6/site-packages/`資料夾下有`matlab`資料夾和`matlab_kernel`資料夾: ```txt matlab ├── engine │ ├── _arch.txt │ ├── basefuture.py │ ├── engineerror.py │ ├── enginehelper.py │ ├── enginesession.py │ ├── fevalfuture.py │ ├── futureresult.py │ ├── __init__.py │ ├── matlabengine.py │ ├── matlabfuture.py │ └── __pycache__ │ ├── basefuture.cpython-36.pyc │ ├── engineerror.cpython-36.pyc │ ├── enginehelper.cpython-36.pyc │ ├── enginesession.cpython-36.pyc │ ├── fevalfuture.cpython-36.pyc │ ├── futureresult.cpython-36.pyc │ ├── __init__.cpython-36.pyc │ ├── matlabengine.cpython-36.pyc │ └── matlabfuture.cpython-36.pyc ├── __init__.py ├── _internal │ ├── __init__.py │ ├── mlarray_sequence.py │ ├── mlarray_utils.py │ └── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── mlarray_sequence.cpython-36.pyc │ └── mlarray_utils.cpython-36.pyc ├── mlarray.py ├── mlexceptions.py └── __pycache__ ├── __init__.cpython-36.pyc ├── mlarray.cpython-36.pyc └── mlexceptions.cpython-36.pyc 5 directories, 31 files matlab_kernel ├── check.py ├── __init__.py ├── kernel.json ├── kernel.py ├── __main__.py ├── matlab │ ├── engine │ │ ├── _arch.txt │ │ ├── basefuture.py │ │ ├── engineerror.py │ │ ├── enginehelper.py │ │ ├── enginesession.py │ │ ├── fevalfuture.py │ │ ├── futureresult.py │ │ ├── __init__.py │ │ ├── matlabengine.py │ │ ├── matlabfuture.py │ │ └── __pycache__ │ │ ├── basefuture.cpython-36.pyc │ │ ├── engineerror.cpython-36.pyc │ │ ├── enginehelper.cpython-36.pyc │ │ ├── enginesession.cpython-36.pyc │ │ ├── fevalfuture.cpython-36.pyc │ │ ├── futureresult.cpython-36.pyc │ │ ├── __init__.cpython-36.pyc │ │ ├── matlabengine.cpython-36.pyc │ │ └── matlabfuture.cpython-36.pyc │ ├── __init__.py │ ├── _internal │ │ ├── __init__.py │ │ ├── mlarray_sequence.py │ │ ├── mlarray_utils.py │ │ └── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── mlarray_sequence.cpython-36.pyc │ │ └── mlarray_utils.cpython-36.pyc │ ├── mlarray.py │ ├── mlexceptions.py │ └── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── mlarray.cpython-36.pyc │ └── mlexceptions.cpython-36.pyc ├── matlabengineforpython-R2020a-py3.6.egg-info └── __pycache__ ├── check.cpython-36.pyc ├── __init__.cpython-36.pyc ├── kernel.cpython-36.pyc └── __main__.cpython-36.pyc 7 directories, 41 files ``` 可以參考[連結1](https://am111.readthedocs.io/en/latest/jmatlab_install.html)和[連結2](https://www.mathworks.com/help/matlab/matlab_external/install-the-matlab-engine-for-python.html) ## 9. 使用frp內網穿透 騰訊雲主機的`frps.ini`新增一行: ```ini # 不需要和frpc.ini一致 vhost_http_port = 8888 ``` 執行jupyterlab的伺服器的`frpc.ini`新增一個部分: ```conf [web] type = http local_port = 8888 custom_domains = lab.example.cn ``` 如果要使用frp內網穿透的同時又給它設定域名,則域名解析記錄新增一條名稱為lab的A記錄到騰訊雲主機的IP(frps),在騰訊雲主機再新增一個nginx項: ```txt server{ listen 80; # 如果需要ssl,參考https://blog.whuzfb.cn/blog/2020/07/07/web_https/ # listen 443 ssl; # include ssl/whuzfb.cn.ssl.conf; # 此時支援http與https server_name lab.example.cn; access_log /home/ubuntu/frp_linux_amd64/log/access_jupyter.log; error_log /home/ubuntu/frp_linux_amd64/log/error_jupyter.log; # 防止jupyter儲存檔案時413 Request Entity Too Large # client_max_body_size 50m; 0表示關閉檢測 client_max_body_size 0; location /{ proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; proxy_buffering off; proxy_pass http://127.0.0.1:8888; } location ~* /(api/kernels/[^/]+/(channels|iopub|shell|stdin)|terminals/websocket)/? { proxy_pass http://127.0.0.1:8888; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # WebSocket support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # ------- 舊方法:還是有部分報錯/api/kernels err_too_many_redirects --------- # # 必須有,否則請求/api/kernels/ 的狀態碼都是400 # location /api/kernels/ { # proxy_pass http://127.0.0.1:8888; # proxy_set_header Host $host; # # websocket support # proxy_http_version 1.1; # proxy_set_header Upgrade "websocket"; # proxy_set_header Connection "Upgrade"; # proxy_read_timeout 86400; # } # # 必須有,否則請求/terminals/ 的狀態碼都是400 # location /terminals/ { # proxy_pass http://127.0.0.1:8888; # proxy_set_header Host $host; # # websocket support # proxy_http_version 1.1; # proxy_set_header Upgrade "websocket"; # proxy_set_header Connection "Upgrade"; # proxy_read_timeout 86400; # } } ``` ## 10. VSCode連線jupyter 由於jupyterlab可以執行在本地指定埠,所以可以通過IP和埠在客戶自己瀏覽器進行遠端開發(保證遠端伺服器的`jupyter lab`開機自啟服務),這在區域網內很方便,但是對於沒有公網IP的話,就無法使用此功能 好在VSCode可以直接開啟遠端jupyter,具體操作如下 * 在客戶本地機器安裝`Remote Development`三件套外掛,然後選擇`Remote-SSH: Connect to host`,可以在本地提前建立配置檔案(`C:\Users\zfb\.ssh\config`或者`C:\ProgramData\ssh\ssh_config`),內容類似: ```conf # 第一個遠端機器 Host mylab HostName 54.33.135.211 Port 22 User ubuntu ``` * 根據提示輸入遠端伺服器的密碼即可連線成功,然後在遠端伺服器安裝`Python`、`Pylance`、`IntelliCode`這三個外掛,開啟遠端伺服器的資料夾,建立一個副檔名為`ipynb`的檔案,然後VSCode會自動提示選擇Python版本(既可以選擇系統的,也可以根據路徑選擇某個虛擬環境裡面的),接著VSCode會自動連線Kernel,使用者可以在右上角檢視當前Kernel的狀態或者切換Kernel ## 11. ssh連線jupyter在本地開啟 在瀏覽器使用遠端ip:port的方法,則伺服器必須有公網,而且還費流量,另一種方法,ssh連線,然後埠對映 伺服器1:處於內網,已安裝frpc,使用者名稱為zfb,已安裝配置好jupyterlab,執行在8888埠 雲主機2:處於公網,ip為56.78.12.34,已安裝frps,使用者名稱為ubuntu,僅用於伺服器的內網穿透,埠7001為伺服器1提供ssh轉發 執行以下命令,把使用者3的電腦的本地埠8080繫結到伺服器1的埠8888: `ssh -p 7001 -NL localhost:8080:localhost:8888 [email protected]` 此時在使用者3的本機開啟網址`http://127.0.0.1:8080`即可訪問伺服器1的jupyterlab ## 12. matplotlib安裝 首先在虛擬環境jupyter安裝matplotlib庫和ipympl庫,後者用於顯示可互動圖形 ```bash # 啟用虛擬環境jupyter source jupyter/bin/activate # 在虛擬環境jupyter安裝matlab_kernel pip install -i https://pypi.tuna.tsinghua.edu.cn/simple matplotlib ipympl ``` 重新開啟瀏覽器會提示rebuild,點選確定。等待build成功然後點選reload即可正常使用此外掛,如下程式碼 ```python %matplotlib widget import pandas as pd import numpy as np import matplotlib from matplotlib import pyplot as plt ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000)) ts = ts.cumsum() df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=['A', 'B', 'C', 'D']) df = df.cumsum() df.plot() plt.legend(loc='best') plt.title('我是中文') ``` 如果中文亂碼,則[糾正中文亂碼](https://blog.whuzfb.cn/blog/2020/07/02/matplotlib_tricks) ## 13. 使用plotly顯示python程式繪製的圖片 使用方法見[官網](https://plotly.com/python/getting-started),python的使用不需要key和使用者名稱,直接用就行 ## 14. 使用plotly顯示matlab的圖片 詳細使用方法見[官網教程](https://plotly.com/matlab/getting-started/)。註冊plotly的[chart-studio](https://chart-studio.plotly.com/Auth/login/)賬號,然後在個人賬戶的`setting`點選`api keys`,選擇`Regenerate key`,記住這個key和自己的使用者名稱。然後下載[壓縮包](https://github.com/plotly/MATLAB-Online/archive/master.zip)並解壓,開啟matlab,輸入 ```txt >> cd ~/plotly-graphing-library-for-matlab-master/ >> plotlysetup('DemoAccount', 'lr1c44zw81') % 回車,剩下的內容都是自動執行 Adding Plotly to MATLAB toolbox directory ... Done Welcome to Plotly! If you are new to Plotly please enter: >> plotlyhelp to get started! ``` 此時會建立檔案`~/.plotly/.credentials`,裡面已經儲存使用者名稱和key(注意該使用者需要有`toolbox`的寫入許可權) 然後在jupyterlab寫: ```matlab [X,Y,Z] = peaks; contour(X,Y,Z,20); % 個人使用者還是用離線模式吧,否則只能建立100個圖,還必須是公開分享 getplotlyoffline('https://cdn.plot.ly/plotly-latest.min.js') fig2plotly(gcf, 'offline', true) ``` 該命令會在當前目錄生成一個html檔案,雙擊開啟即可 **注意:** 如果發現在其他目錄無法使用`fig2plotly`函式,則可能是上一步驟,將plotly新增到Matlab工具箱出現了問題。可以自己手動將其複製到指定工具箱路徑,或者直接把`plotly-graphing-library-for-matlab-master`資料夾的絕對路徑新增到`Matlab PATH` ## 15. 使用plotly繪製matlab的包含ColorBar的圖片 如果正在使用新版Matlab(R2019a以後),在`.m`檔案中如果使用`colorbar`函式,則在呼叫plotly時候可能會遇到報錯 ```txt Insufficient number of outputs from right hand side of equal sign to satisfy assignment. Error in findColorbarAxis (line 8) colorbarAxis = obj.State.Axis(colorbarAxisIndex).Handle; Error in plotlyfig/update (line 557) colorbarAxis = findColorbarAxis(obj, handle(cols(c))); Error in plotlyfig (line 208) obj.update; Error in fig2plotly (line 44) p = plotlyfig(varargin{:}); ``` 參考[連結](https://github.com/plotly/plotly-graphing-library-for-matlab/pull/146),於是開啟檔案`findColorBarAxis.m`: ```bash # 若Matlab的Plotly工具箱安裝位置為/home/Polyspace/R2020a/toolbox/plotly sudo vi /home/Polyspace/R2020a/toolbox/plotly/plotlyfig_auz/helpers/findColorBarAxis.m ``` 整個檔案內容替換為如下: ```matlab function colorbarAxis = findColorbarAxis(obj,colorbarHandle) if isHG2 colorbarAxisIndex = find(arrayfun(@(x)(isequal(getappdata(x.Handle,'ColorbarPeerHandle'),colorbarHandle)),obj.State.Axis)); % If the above returns empty then we are on a more recent Matlab % release where the appdata entry is called LayoutPeers if isempty(colorbarAxisIndex) colorbarAxisIndex = find(arrayfun(@(x)(isequal(getappdata(x.Handle,'LayoutPeers'),colorbarHandle)),obj.State.Axis)); end else colorbarAxisIndex = find(arrayfun(@(x)(isequal(getappdata(x.Handle,'LegendColorbarInnerList'),colorbarHandle) + ... isequal(getappdata(x.Handle,'LegendColorbarOuterList'),colorbarHandle)),obj.State.Axis)); end colorbarAxis = obj.State.Axis(colorbarAxisIndex).Handle;