This is an automated email from the ASF dual-hosted git repository.
haonan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 81e8949 Vis tool for master (#3473)
81e8949 is described below
commit 81e8949e1f54cbf7974e12788cff5ec58de1aba6
Author: Rui,Lei <[email protected]>
AuthorDate: Sat Jul 3 14:59:21 2021 +0800
Vis tool for master (#3473)
---
docs/SystemDesign/TsFile/Format.md | 228 ++++++++++++++--
docs/zh/SystemDesign/TsFile/Format.md | 228 ++++++++++++++--
.../tools/tsfileToolSet/print-tsfile-visdata.bat | 62 +++++
.../tools/tsfileToolSet/print-tsfile-visdata.sh | 48 ++++
.../iotdb/db/tools/vis/TsFileExtractVisdata.java | 170 ++++++++++++
.../main/java/org/apache/iotdb/db/tools/vis/vis.m | 290 +++++++++++++++++++++
6 files changed, 973 insertions(+), 53 deletions(-)
diff --git a/docs/SystemDesign/TsFile/Format.md
b/docs/SystemDesign/TsFile/Format.md
index d1b2d3a..ae3329e 100644
--- a/docs/SystemDesign/TsFile/Format.md
+++ b/docs/SystemDesign/TsFile/Format.md
@@ -56,13 +56,12 @@
- **Compressing Type Hardcode**
- 0: UNCOMPRESSED
- 1: SNAPPY
+ - 2: GZIP
+ - 3: LZO
+ - 4: SDT
+ - 5: PAA
+ - 6: PLA
- 7: LZ4
-- **TsDigest Statistics Type Hardcode**
- - 0: min_value
- - 1: max_value
- - 2: first_value
- - 3: last_value
- - 4: sum_value
### 1.2 TsFile Overview
@@ -255,11 +254,29 @@ A TsFile ends with a 6-byte magic string (`TsFile`).
Congratulations! You have finished the journey of discovering TsFile.
-### 1.3 TsFile Tool Set
+## 2. A TsFile Visualization Example
-#### 1.3.1 IoTDB Data Directory Overview Tool
+### v0.8
-After building the server, the startup script of this tool will appear under
the `server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet` directory.
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/65209576-2bd36000-dacb-11e9-9e43-49e0dd01274e.png">
+
+### v0.9 / 000001
+
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/69341240-26012300-0ca4-11ea-91a1-d516810cad44.png">
+
+### v0.10 / 000002
+
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/19167280/95296983-492cc500-08ac-11eb-9f66-c9c78401c61d.png">
+
+### v0.12 / 000003
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/123052025-f47aab80-d434-11eb-94c2-9b75429e5c54.png">
+
+
+## 3. TsFile Tool Set
+
+### 3.1 IoTDB Data Directory Overview Tool
+
+After building the server, the startup script of this tool will appear under
the `server\target\iotdb-server-{version}\tools\tsfileToolSet` directory.
Command:
@@ -278,10 +295,10 @@ For Linux or MacOs:
An example on Windows:
```
-D:\iotdb\server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet>.\print-iotdb-data-dir.bat
D:\\data\data
+D:\iotdb\server\target\iotdb-server-{version}\tools\tsfileToolSet>.\print-iotdb-data-dir.bat
D:\\data\data
|````````````````````````
Starting Printing the IoTDB Data Directory Overview
-|````````````````````````
+|````````````````````````
output save path:IoTDB_data_dir_overview.txt
TsFile data dir num:1
21:17:38.841 [main] WARN org.apache.iotdb.tsfile.common.conf.TSFileDescriptor
- Failed to find config file iotdb-engine.properties at classpath, use default
configuration
@@ -308,9 +325,9 @@ TsFile data dir num:1
-#### 1.3.2 TsFileResource Print Tool
+### 3.2 TsFileResource Print Tool
-After building the server, the startup script of this tool will appear under
the `server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet` directory.
+After building the server, the startup script of this tool will appear under
the `server\target\iotdb-server-{version}\tools\tsfileToolSet` directory.
Command:
@@ -329,19 +346,19 @@ For Linux or MacOs:
An example on Windows:
```shell
-D:\iotdb\server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet>.\print-tsfile-resource-files.bat
D:\data\data\sequence\root.vehicle
+D:\iotdb\server\target\iotdb-server-{version}\tools\tsfileToolSet>.\print-tsfile-resource-files.bat
D:\data\data\sequence\root.vehicle
|````````````````````````
Starting Printing the TsFileResources
-|````````````````````````
+|````````````````````````
12:31:59.861 [main] WARN org.apache.iotdb.db.conf.IoTDBDescriptor - Cannot
find IOTDB_HOME or IOTDB_CONF environment variable when loading config file
iotdb-engine.properties, use default configuration
analyzing D:\data\data\sequence\root.vehicle\1572496142067-101-0.tsfile ...
device root.vehicle.d0, start time 3000
(1970-01-01T08:00:03+08:00[GMT+08:00]), end time 100999
(1970-01-01T08:01:40.999+08:00[GMT+08:00])
analyzing the resource file finished.
```
-#### 1.3.3 TsFile Sketch Tool
+### 3.3 TsFile Sketch Tool
-After building the server, the startup script of this tool will appear under
the `server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet` directory.
+After building the server, the startup script of this tool will appear under
the `server\target\iotdb-server-{version}\tools\tsfileToolSet` directory.
Command:
@@ -364,7 +381,7 @@ For Linux or MacOs:
An example on macOS:
```shell
-/iotdb/server/target/iotdb-server-0.13.0-SNAPSHOT/tools/tsfileToolSet$
./print-tsfile-sketch.sh test.tsfile
+/iotdb/server/target/iotdb-server-{version}/tools/tsfileToolSet$
./print-tsfile-sketch.sh test.tsfile
|````````````````````````
Starting Printing the TsFile Sketch
|````````````````````````
@@ -581,20 +598,179 @@ file length: 33436
```
-#### 1.3.4 TsFileSequenceRead
+### 3.4 TsFileSequenceRead
You can also use `example/tsfile/org/apache/iotdb/tsfile/TsFileSequenceRead`
to sequentially print a TsFile's content.
-### 1.4 A TsFile Visualization Example
-#### v0.8
+### 3.5 Vis Tool
-<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/65209576-2bd36000-dacb-11e9-9e43-49e0dd01274e.png">
+Vis is a tool that visualizes the time layouts and cout aggregation of chunk
data in TsFiles. You can use this tool to facilitate debugging, check the
distribution of data, etc. Please feel free to play around with it, and let us
know your thoughts.
-#### v0.9 / 000001
+
-<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/69341240-26012300-0ca4-11ea-91a1-d516810cad44.png">
+- A single long narrow rectangle in the figure shows the visdata of a single
chunk in a TsFile.
+Visdata contains \[tsName, fileName, chunkId, startTime, endTime,
pointCountNum\].
+- The position of a rectangle on the x-axis is defined by the startTime and
endTime of the chunk data.
+- The position of a rectangle on the y-axis is defined simultaneously by
+ - (a)`showSpecific`: the specific set of time series to be plotted;
+ - (b) seqKey/unseqKey display policies: extract seqKey or unseqKey from
statisfied keys under
+ different display policies:
+ - b-1) unseqKey identifies tsName and fileName, so chunk data with the
same fileName and
+ tsName but different chunkIds are plotted on the same line.
+ - b-2) seqKey identifies tsName, so chunk data with the same tsName but
different fileNames
+ and chunkIds are plotted on the same line;
+ - (c)`isFileOrder`: sort seqKey&unseqKey according to `isFileOrder`, true to
sort
+ seqKeys&unseqKeys by fileName priority, false to sort seqKeys&unseqKeys by
tsName priority.
+ When multiple time series are displayed on a graph at the same time, this
parameter can provide
+ users with these two observation perspectives.
-#### v0.10 / 000002
+#### 3.5.1 How to run Vis
-<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/19167280/95296983-492cc500-08ac-11eb-9f66-c9c78401c61d.png">
+The source code contains two files: `TsFileExtractVisdata.java` and `vis.m`.
`TsFileExtractVisdata.java` extracts, from input tsfiles, necessary
visualization information, which is what `vis.m` needs to plot figures.
+
+Simply put, you first run `TsFileExtractVisdata.java` and then run `vis.m`.
+
+##### Step 1: run TsFileExtractVisdata.java
+
+`TsFileExtractVisdata.java` extracts visdata [tsName, fileName, chunkId,
startTime, endTime, pointCountNum] from every chunk of the input TsFiles and
write them to the specified output path.
+
+After building the server, the startup script of this tool will appear under
the `server\target\iotdb-server-{version}\tools\tsfileToolSet` directory.
+
+Command:
+
+For Windows:
+
+```
+.\print-tsfile-visdata.bat path1 seqIndicator1 path2 seqIndicator2 ... pathN
seqIndicatorN outputPath
+```
+
+For Linux or MacOs:
+
+```
+./print-tsfile-visdata.sh path1 seqIndicator1 path2 seqIndicator2 ... pathN
seqIndicatorN outputPath
+```
+
+Args: [`path1` `seqIndicator1` `path2` `seqIndicator2` ... `pathN`
`seqIndicatorN` `outputPath`]
+
+Details:
+
+- 2N+1 args in total.
+- `seqIndicator` should be 'true' or 'false' (not case sensitive). 'true'
means is the file is sequence, 'false' means the file is unsequence.
+- `Path` can be the full path of a tsfile or a directory path. If it is a
directory path, make sure that all tsfiles in this directory have the same
`seqIndicator`.
+- The input TsFiles should all be sealed. The handle of unsealed TsFile is
left as future work when in need.
+
+##### Step 2: run vis.m
+
+`vis.m` load visdata generated by `TsFileExtractVisdata`, and then plot
figures given the loaded visdata and two plot parameters: `showSpecific` and
`isFileOrder`.
+
+```matlab
+function [timeMap,countMap] = loadVisData(filePath,timestampUnit)
+% Load visdata generated by TsFileExtractVisdata.
+%
+% filePath: the path of visdata.
+% The format is [tsName,fileName,chunkId,startTime,endTime,pointCountNum].
+% `tsName` and `fileName` are string, the others are long value.
+% If the tsfile is unsequence file, `fileName` will contain "unseq" as an
+% indicator, which is guaranteed by TsFileExtractVisdata.
+%
+% timestampUnit(not case sensitive):
+% 'us' if the timestamp is microsecond, e.g., 1621993620816000
+% 'ms' if it is millisecond, e.g., 1621993620816
+% 's' if it is second, e.g., 1621993620
+%
+% timeMap: record the time range of every chunk.
+% Key [tsName][fileName][chunkId] identifies the only chunk. Value is
+% [startTime,endTime] of the chunk.
+%
+% countMap: record the point count number of every chunk. Key is the same
+% as that of timeMap. Value is pointCountNum.
+```
+
+```matlab
+function draw(timeMap,countMap,showSpecific,isFileOrder)
+% Plot figures given the loaded data and two plot parameters:
+% `showSpecific` and `isFileOrder`.
+%
+% process: 1) traverse `keys(timeMap)` to get the position arrangements on
+% the y axis dynamically, which is defined simultaneously by
+% (a)`showSpecific`: traverse `keys(timeMap)`, filter out keys
+% that don't statisfy `showSpecific`.
+% (b) seqKey/unseqKey display policies: extract seqKey or unseqKey
+% from statisfied keys under different display policies:
+% b-1) unseqKey identifies tsName and fileName, so chunk data
with the
+% same fileName and tsName but different chunkIds are
+% plotted on the same line.
+% b-2) seqKey identifies tsName, so chunk data with the same
tsName but
+% different fileNames and chunkIds are plotted on the same
+% line.
+% (c)`isFileOrder`: sort seqKey&unseqKey according to `isFileOrder`,
+% finally get the position arrangements on the y axis.
+% 2) traverse `keys(timeMap)` again, get startTime&endTime from
+% `treeMap` as positions on the x axis, combined with the
+% positions on the y axis from the last step, finish plot.
+%
+% timeMap,countMap: generated by loadVisData function.
+%
+% showSpecific: the specific set of time series to be plotted.
+% If showSpecific is empty{}, then all loaded time series
+% will be plotted.
+% Note: Wildcard matching is not supported now. In other
+% words, showSpecific only support full time series path
+% names.
+%
+% isFileOrder: true to sort seqKeys&unseqKeys by fileName priority, false
+% to sort seqKeys&unseqKeys by tsName priority.
+```
+
+
+#### 3.5.2 Examples
+
+##### Example 1
+
+Use the tsfiles written by `IoTDBLargeDataIT.insertData` with a little
modification: add `statement.execute("flush");` at the end of
`IoTDBLargeDataIT.insertData`.
+
+Step 1: run `TsFileExtractVisdata.java`
+
+```
+.\print-tsfile-visdata.bat data\sequence true data\unsequence false
D:\visdata1.csv
+```
+or equivalently:
+```
+.\print-tsfile-visdata.bat
data\sequence\root.vehicle\0\0\1622743492580-1-0.tsfile true
data\sequence\root.vehicle\0\0\1622743505092-2-0.tsfile true
data\sequence\root.vehicle\0\0\1622743505573-3-0.tsfile true
data\unsequence\root.vehicle\0\0\1622743505901-4-0.tsfile false D:\visdata1.csv
+```
+
+Step 2: run `vis.m`
+
+```matlab
+clear all;close all;
+
+% 1. load visdata generated by TsFileExtractVisdata
+filePath = 'D:\visdata1.csv';
+[timeMap,countMap] = loadVisData(filePath,'ms'); % mind the timestamp unit
+
+% 2. plot figures given the loaded data and two plot parameters:
+% `showSpecific` and `isFileOrder`
+draw(timeMap,countMap,{},false)
+title("draw(timeMap,countMap,\{\},false)")
+
+draw(timeMap,countMap,{},true)
+title("draw(timeMap,countMap,\{\},true)")
+
+draw(timeMap,countMap,{'root.vehicle.d0.s0'},false)
+title("draw(timeMap,countMap,{'root.vehicle.d0.s0'},false)")
+
+draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},false)
+title("draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},false)")
+
+draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},true)
+title("draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},true)")
+```
+
+Plot results:
+
+
+
+
+
+
diff --git a/docs/zh/SystemDesign/TsFile/Format.md
b/docs/zh/SystemDesign/TsFile/Format.md
index ec2517a..da897d8 100644
--- a/docs/zh/SystemDesign/TsFile/Format.md
+++ b/docs/zh/SystemDesign/TsFile/Format.md
@@ -55,13 +55,12 @@
- **压缩类型**
- 0: UNCOMPRESSED
- 1: SNAPPY
+ - 2: GZIP
+ - 3: LZO
+ - 4: SDT
+ - 5: PAA
+ - 6: PLA
- 7: LZ4
-- **预聚合信息**
- - 0: min_value
- - 1: max_value
- - 2: first_value
- - 3: last_value
- - 4: sum_value
### 1.2 TsFile 概述
@@ -257,11 +256,29 @@ TsFile 是以6个字节的magic string (`TsFile`) 作为结束。
恭喜您, 至此您已经完成了 TsFile 的探秘之旅,祝您玩儿的开心!
-### 1.3 TsFile工具集
+## 2 TsFile 的总览图
-#### 1.3.1 IoTDB Data Directory 快速概览工具
+### v0.8
-该工具的启动脚本会在编译 server 之后生成至
`server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet` 目录中。
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/65209576-2bd36000-dacb-11e9-9e43-49e0dd01274e.png">
+
+### v0.9 / 000001
+
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/69341240-26012300-0ca4-11ea-91a1-d516810cad44.png">
+
+### v0.10 / 000002
+
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/19167280/95296983-492cc500-08ac-11eb-9f66-c9c78401c61d.png">
+
+### v0.12 / 000003
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/123052025-f47aab80-d434-11eb-94c2-9b75429e5c54.png">
+
+
+## 3 TsFile工具集
+
+### 3.1 IoTDB Data Directory 快速概览工具
+
+该工具的启动脚本会在编译 server 之后生成至
`server\target\iotdb-server-{version}\tools\tsfileToolSet` 目录中。
使用方式:
@@ -280,10 +297,10 @@ For Linux or MacOs:
在Windows系统中的示例:
```
-D:\iotdb\server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet>.\print-iotdb-data-dir.bat
D:\\data\data
+D:\iotdb\server\target\iotdb-server-{version}\tools\tsfileToolSet>.\print-iotdb-data-dir.bat
D:\\data\data
|````````````````````````
Starting Printing the IoTDB Data Directory Overview
-|````````````````````````
+|````````````````````````
output save path:IoTDB_data_dir_overview.txt
TsFile data dir num:1
21:17:38.841 [main] WARN org.apache.iotdb.tsfile.common.conf.TSFileDescriptor
- Failed to find config file iotdb-engine.properties at classpath, use default
configuration
@@ -308,9 +325,9 @@ TsFile data dir num:1
|==============================================================
```
-#### 1.3.2 TsFileResource 打印工具
+### 3.2 TsFileResource 打印工具
-该工具的启动脚本会在编译 server 之后生成至
`server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet` 目录中。
+该工具的启动脚本会在编译 server 之后生成至
`server\target\iotdb-server-{version}\tools\tsfileToolSet` 目录中。
使用方式:
@@ -329,19 +346,19 @@ Linux or MacOs:
在Windows系统中的示例:
```
-D:\iotdb\server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet>.\print-tsfile-resource-files.bat
D:\data\data\sequence\root.vehicle
+D:\iotdb\server\target\iotdb-server-{version}\tools\tsfileToolSet>.\print-tsfile-resource-files.bat
D:\data\data\sequence\root.vehicle
|````````````````````````
Starting Printing the TsFileResources
-|````````````````````````
+|````````````````````````
12:31:59.861 [main] WARN org.apache.iotdb.db.conf.IoTDBDescriptor - Cannot
find IOTDB_HOME or IOTDB_CONF environment variable when loading config file
iotdb-engine.properties, use default configuration
analyzing D:\data\data\sequence\root.vehicle\1572496142067-101-0.tsfile ...
device root.vehicle.d0, start time 3000
(1970-01-01T08:00:03+08:00[GMT+08:00]), end time 100999
(1970-01-01T08:01:40.999+08:00[GMT+08:00])
analyzing the resource file finished.
```
-#### 1.3.3 TsFile 描述工具
+### 3.3 TsFile 描述工具
-该工具的启动脚本会在编译 server 之后生成至
`server\target\iotdb-server-0.13.0-SNAPSHOT\tools\tsfileToolSet` 目录中。
+该工具的启动脚本会在编译 server 之后生成至
`server\target\iotdb-server-{version}\tools\tsfileToolSet` 目录中。
使用方式:
@@ -364,10 +381,10 @@ Linux or MacOs:
在mac系统中的示例:
```
-/iotdb/server/target/iotdb-server-0.13.0-SNAPSHOT/tools/tsfileToolSet$
./print-tsfile-sketch.sh test.tsfile
+/iotdb/server/target/iotdb-server-{version}/tools/tsfileToolSet$
./print-tsfile-sketch.sh test.tsfile
|````````````````````````
Starting Printing the TsFile Sketch
-|````````````````````````
+|````````````````````````
TsFile path:test.tsfile
Sketch save path:TsFile_sketch_view.txt
-------------------------------- TsFile Sketch --------------------------------
@@ -580,20 +597,177 @@ file length: 33436
---------------------------------- TsFile Sketch End
----------------------------------
```
-#### 1.3.4 TsFileSequenceRead
+### 3.4 TsFileSequenceRead
您可以使用示例中的类 `example/tsfile/org/apache/iotdb/tsfile/TsFileSequenceRead` 顺序打印
TsFile 中的内容.
-### 1.4 TsFile 的总览图
+### 3.5 Vis Tool
-#### v0.8
+Vis是一个把TsFiles中的chunk数据的时间分布以及点数可视化的工具。你可以使用这个工具来帮助你debug,还可以用来观察数据分布等等。
+欢迎使用这个工具,在社区里交流你的想法。
-<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/65209576-2bd36000-dacb-11e9-9e43-49e0dd01274e.png">
+
-#### v0.9 / 000001
+- 图中的一个窄长矩形代表的是一个TsFile里的一个chunk,其可视化信息为\[tsName, fileName, chunkId,
startTime, endTime, pointCountNum\]。
+- 矩形在x轴上的位置是由该chunk的startTime和endTime决定的。
+- 矩形在y轴上的位置是由以下三项共同决定的:
+ - (a)`showSpecific`: 用户指定要显示的特定时间序列集合。
+ - (b) seqKey/unseqKey显示规则: 从满足特定时间序列集合的keys提取seqKey或unseqKey时采取不同的显示规则:
+ - b-1)
unseqKey识别tsName和fileName,因此有相同tsName和fileName但是不同chunkIds的chunk数据将绘制在同一行;
+ - b-2) seqKey识别tsName,因此有相同tsName但是不同fileNames和chunkIds的chunk数据将绘制在同一行,
+ -
(c)`isFileOrder`:根据`isFileOrder`对seqKey&unseqKey进行排序,true则以fileName优先的顺序排序,
+ false则以tsName优先的顺序排序。当在一张图上同时显示多条时间序列时,该参数将给用户提供这两种可选的观察视角。
-<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/33376433/69341240-26012300-0ca4-11ea-91a1-d516810cad44.png">
+#### 3.5.1 如何运行Vis
-#### v0.10 / 000002
+源数据包含两个文件:`TsFileExtractVisdata.java`和`vis.m`。
+`TsFileExtractVisdata.java`从输入的tsfile文件中提取必要的可视化信息,`vis.m`用这些信息来完成作图。
-<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto;
margin-right:auto; display:block;"
src="https://user-images.githubusercontent.com/19167280/95296983-492cc500-08ac-11eb-9f66-c9c78401c61d.png">
+简单说就是:先运行`TsFileExtractVisdata.java`然后再运行`vis.m`。
+
+##### 第一步:运行TsFileExtractVisdata.java
+
+`TsFileExtractVisdata.java`对输入的tsfiles的每一个chunk提取可视化信息[tsName, fileName,
chunkId, startTime, endTime, pointCountNum],
+并把这些信息保存到指定的输出文件里。
+
+该工具的启动脚本会在编译 server 之后生成至
`server\target\iotdb-server-{version}\tools\tsfileToolSet` 目录中。
+
+使用方式:
+
+Windows:
+
+```
+.\print-tsfile-visdata.bat path1 seqIndicator1 path2 seqIndicator2 ... pathN
seqIndicatorN outputPath
+```
+
+Linux or MacOs:
+
+```
+./print-tsfile-visdata.sh path1 seqIndicator1 path2 seqIndicator2 ... pathN
seqIndicatorN outputPath
+```
+
+参数: [`path1` `seqIndicator1` `path2` `seqIndicator2` ... `pathN`
`seqIndicatorN` `outputPath`]
+
+细节:
+
+- 一共2N+1个参数。
+- `seqIndicator`:'true'或者'false' (大小写不敏感). 'true'表示是顺序文件, 'false'表示是乱序文件。
+-
`Path`:可以是一个tsfile的全路径,也可以是一个文件夹路径。如果是文件夹路径,你需要确保这个文件夹下的所有tsfile文件的`seqIndicator`都是一样的。
+- 输入的所有TsFile文件必须是封好口的。处理未封口的文件留待未来有需要的情况再实现。
+
+##### 第二步:运行vis.m
+
+`vis.m`把`TsFileExtractVisdata`生成的visdata加载进来,然后基于visdata以及两个用户绘图参数`showSpecific`和`isFileOrder`来完成作图。
+
+```matlab
+function [timeMap,countMap] = loadVisData(filePath,timestampUnit)
+% Load visdata generated by TsFileExtractVisdata.
+%
+% filePath: the path of visdata.
+% The format is [tsName,fileName,chunkId,startTime,endTime,pointCountNum].
+% `tsName` and `fileName` are string, the others are long value.
+% If the tsfile is unsequence file, `fileName` will contain "unseq" as an
+% indicator, which is guaranteed by TsFileExtractVisdata.
+%
+% timestampUnit(not case sensitive):
+% 'us' if the timestamp is microsecond, e.g., 1621993620816000
+% 'ms' if it is millisecond, e.g., 1621993620816
+% 's' if it is second, e.g., 1621993620
+%
+% timeMap: record the time range of every chunk.
+% Key [tsName][fileName][chunkId] identifies the only chunk. Value is
+% [startTime,endTime] of the chunk.
+%
+% countMap: record the point count number of every chunk. Key is the same
+% as that of timeMap. Value is pointCountNum.
+```
+
+```matlab
+function draw(timeMap,countMap,showSpecific,isFileOrder)
+% Plot figures given the loaded data and two plot parameters:
+% `showSpecific` and `isFileOrder`.
+%
+% process: 1) traverse `keys(timeMap)` to get the position arrangements on
+% the y axis dynamically, which is defined simultaneously by
+% (a)`showSpecific`: traverse `keys(timeMap)`, filter out keys
+% that don't statisfy `showSpecific`.
+% (b) seqKey/unseqKey display policies: extract seqKey or unseqKey
+% from statisfied keys under different display policies:
+% b-1) unseqKey identifies tsName and fileName, so chunk data
with the
+% same fileName and tsName but different chunkIds are
+% plotted on the same line.
+% b-2) seqKey identifies tsName, so chunk data with the same
tsName but
+% different fileNames and chunkIds are plotted on the same
+% line.
+% (c)`isFileOrder`: sort seqKey&unseqKey according to `isFileOrder`,
+% finally get the position arrangements on the y axis.
+% 2) traverse `keys(timeMap)` again, get startTime&endTime from
+% `treeMap` as positions on the x axis, combined with the
+% positions on the y axis from the last step, finish plot.
+%
+% timeMap,countMap: generated by loadVisData function.
+%
+% showSpecific: the specific set of time series to be plotted.
+% If showSpecific is empty{}, then all loaded time series
+% will be plotted.
+% Note: Wildcard matching is not supported now. In other
+% words, showSpecific only support full time series path
+% names.
+%
+% isFileOrder: true to sort seqKeys&unseqKeys by fileName priority, false
+% to sort seqKeys&unseqKeys by tsName priority.
+```
+
+
+
+#### 3.5.2 例子
+
+##### 例1
+
+使用由`IoTDBLargeDataIT.insertData`写出的tsfiles。
+小修改:`IoTDBLargeDataIT.insertData`最后添加一条`statement.execute("flush");`指令。
+
+第一步:运行`TsFileExtractVisdata.java`
+
+```
+.\print-tsfile-visdata.bat data\sequence true data\unsequence false
D:\visdata1.csv
+```
+或者等价地:
+```
+.\print-tsfile-visdata.bat
data\sequence\root.vehicle\0\0\1622743492580-1-0.tsfile true
data\sequence\root.vehicle\0\0\1622743505092-2-0.tsfile true
data\sequence\root.vehicle\0\0\1622743505573-3-0.tsfile true
data\unsequence\root.vehicle\0\0\1622743505901-4-0.tsfile false D:\visdata1.csv
+```
+
+第二步:运行`vis.m`
+
+```matlab
+clear all;close all;
+
+% 1. load visdata generated by TsFileExtractVisdata
+filePath = 'D:\visdata1.csv';
+[timeMap,countMap] = loadVisData(filePath,'ms'); % mind the timestamp unit
+
+% 2. plot figures given the loaded data and two plot parameters:
+% `showSpecific` and `isFileOrder`
+draw(timeMap,countMap,{},false)
+title("draw(timeMap,countMap,\{\},false)")
+
+draw(timeMap,countMap,{},true)
+title("draw(timeMap,countMap,\{\},true)")
+
+draw(timeMap,countMap,{'root.vehicle.d0.s0'},false)
+title("draw(timeMap,countMap,{'root.vehicle.d0.s0'},false)")
+
+draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},false)
+title("draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},false)")
+
+draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},true)
+title("draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},true)")
+```
+
+绘图结果:
+
+
+
+
+
+
diff --git
a/server/src/assembly/resources/tools/tsfileToolSet/print-tsfile-visdata.bat
b/server/src/assembly/resources/tools/tsfileToolSet/print-tsfile-visdata.bat
new file mode 100644
index 0000000..43772b5
--- /dev/null
+++ b/server/src/assembly/resources/tools/tsfileToolSet/print-tsfile-visdata.bat
@@ -0,0 +1,62 @@
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+
+
+@echo off
+echo ````````````````````````
+echo Starting Printing the TsFile Visdata
+echo ````````````````````````
+
+if "%OS%" == "Windows_NT" setlocal
+
+pushd %~dp0..\..
+if NOT DEFINED IOTDB_HOME set IOTDB_HOME=%CD%
+popd
+
+if NOT DEFINED MAIN_CLASS set
MAIN_CLASS=org.apache.iotdb.db.tools.vis.TsFileExtractVisdata
+if NOT DEFINED JAVA_HOME goto :err
+
+@REM
-----------------------------------------------------------------------------
+@REM ***** CLASSPATH library setting *****
+@REM Ensure that any user defined CLASSPATH variables are not used on startup
+set CLASSPATH="%IOTDB_HOME%\lib\*"
+
+goto okClasspath
+
+:append
+set CLASSPATH=%CLASSPATH%;%1
+goto :eof
+
+@REM
-----------------------------------------------------------------------------
+:okClasspath
+
+"%JAVA_HOME%\bin\java" -cp "%CLASSPATH%" %MAIN_CLASS% %*
+
+goto finally
+
+
+:err
+echo JAVA_HOME environment variable must be set!
+pause
+
+
+@REM
-----------------------------------------------------------------------------
+:finally
+
+ENDLOCAL
\ No newline at end of file
diff --git
a/server/src/assembly/resources/tools/tsfileToolSet/print-tsfile-visdata.sh
b/server/src/assembly/resources/tools/tsfileToolSet/print-tsfile-visdata.sh
new file mode 100644
index 0000000..28b1241
--- /dev/null
+++ b/server/src/assembly/resources/tools/tsfileToolSet/print-tsfile-visdata.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+echo ---------------------
+echo Starting Printing the TsFile Sketch
+echo ---------------------
+
+if [ -z "${IOTDB_HOME}" ]; then
+ export IOTDB_HOME="$(cd "`dirname "$0"`"/../..; pwd)"
+fi
+
+if [ -n "$JAVA_HOME" ]; then
+ for java in "$JAVA_HOME"/bin/amd64/java "$JAVA_HOME"/bin/java; do
+ if [ -x "$java" ]; then
+ JAVA="$java"
+ break
+ fi
+ done
+else
+ JAVA=java
+fi
+
+CLASSPATH=""
+for f in ${IOTDB_HOME}/lib/*.jar; do
+ CLASSPATH=${CLASSPATH}":"$f
+done
+
+MAIN_CLASS=org.apache.iotdb.db.tools.vis.TsFileExtractVisdata
+
+"$JAVA" -cp "$CLASSPATH" "$MAIN_CLASS" "$@"
+exit $?
\ No newline at end of file
diff --git
a/server/src/main/java/org/apache/iotdb/db/tools/vis/TsFileExtractVisdata.java
b/server/src/main/java/org/apache/iotdb/db/tools/vis/TsFileExtractVisdata.java
new file mode 100644
index 0000000..ba2aa1b
--- /dev/null
+++
b/server/src/main/java/org/apache/iotdb/db/tools/vis/TsFileExtractVisdata.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.tools.vis;
+
+import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
+import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
+import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Extract, from input tsfiles, necessary visualization information, which is
what "vis.m" needs to
+ * plot figures.
+ *
+ * <p>Input: [path1 seqIndicator1 path2 seqIndicator2 ... pathN seqIndicatorN
outputPath]
+ *
+ * <p>Example: G:\\debug\\data\\sequence true G:\\debug\\data\\unsequence
false visdata.csv 2N+1
+ * args in total.
+ *
+ * <p>`seqIndicator` should be 'true' or 'false' (not case sensitive). 'true'
means is the file is
+ * sequence, 'false' means the file is unsequence.
+ *
+ * <p>`Path` can be the full path of a file or a directory path. If it is a
directory path, make
+ * sure that all files in this directory have the same seqIndicator.
+ *
+ * <p>All input TsFiles should be sealed. The handle of unsealed TsFile is
left as future work when
+ * in need.
+ *
+ * <p>Output content format: [tsName, fileName, chunkId, startTime, endTime,
pointCountNum]
+ *
+ * <p>`fileName`: If the tsfile is unsequence file, TsFileExtractVisdata will
make sure that the
+ * fileName contains "unseq" as an indicator which will be used by "vis.m".
+ *
+ * <p>NOTE: There is no version info stored in TsFileV3/IoTDBV0.12 any more.
As a result,
+ * TsFileExtractVisdata (1) will not extract version info as it does to
TsFileV2/IoTDBV0.11 and (2)
+ * will not use reader.selfCheck to get ChunkMetadata, which will be fetched
by reading metadata at
+ * the end of the TsFile instead. That means, the input TsFiles should all be
sealed. The handle of
+ * unsealed TsFile is left as future work when in need.
+ */
+public class TsFileExtractVisdata {
+
+ public static String seqFileNameSuffix = "(seque)";
+ public static String unseqFileNameSuffix = "(unseq)";
+
+ public static void main(String[] args) throws IOException {
+ int M = args.length;
+ if (M % 2 == 0) {
+ throw new IOException(
+ "2N+1 args should be:[path1 seqIndicator1 path2 seqIndicator2 "
+ + "... pathN seqIndicatorN outputPath]");
+ }
+ List<String> inputPathList = new ArrayList<>();
+ List<Boolean> seqIndicatorList = new ArrayList<>();
+ for (int i = 0; i < M - 1; i = i + 2) {
+ inputPathList.add(args[i]);
+ String indicator = args[i + 1].toLowerCase();
+ if (!indicator.equals("true") && !indicator.equals("false")) {
+ throw new IOException("seqIndicator should be 'true' or 'false' (not
case sensitive).");
+ }
+ seqIndicatorList.add(Boolean.parseBoolean(args[i + 1]));
+ }
+ String outputPath = args[M - 1];
+
+ try (PrintWriter pw = new PrintWriter(new FileWriter(outputPath))) {
+ int idx = 0;
+ for (String inputPath : inputPathList) {
+ boolean isSeq = seqIndicatorList.get(idx++);
+ List<String> filelist = new ArrayList<>();
+ filelist = getFile(inputPath, filelist); // get all tsfile paths under
the inputPath
+ for (String f : filelist) {
+ System.out.println(f); // note that this info need not be written to
outputFile
+ String fileNameForVis;
+ // Extract the file name from f, following the rule negotiated with
"vis.m".
+ // The rule is that if it is an unsequence tsfile, its extracted
fileName must contain
+ // "unseq".
+ // It's not a must for the extracted fileName of a sequence tsfile
to contain "seque", but
+ // good to do so.
+ File file = new File(f);
+ String fileName = file.getName();
+ if (isSeq) {
+ fileNameForVis = fileName + seqFileNameSuffix;
+ } else {
+ fileNameForVis = fileName + unseqFileNameSuffix;
+ }
+ // extract necessary vis info from the tsfile
+ try (TsFileSequenceReader reader = new TsFileSequenceReader(f)) {
+ // get all ChunkMetadatas at the end of the TsFile
+ for (String device : reader.getAllDevices()) {
+ Map<String, List<ChunkMetadata>> seriesMetaData =
+ reader.readChunkMetadataInDevice(device);
+ for (Map.Entry<String, List<ChunkMetadata>> series :
seriesMetaData.entrySet()) {
+ // chunkId is used by vis.m to differentiate different chunks
of the same timeseries
+ // in the same TsFile.
+ long chunkId = 0;
+ for (ChunkMetadata chunkMetadata : series.getValue()) {
+ String tsName = device + TsFileConstant.PATH_SEPARATOR +
series.getKey();
+ long startTime = chunkMetadata.getStartTime();
+ long endTime = chunkMetadata.getEndTime();
+ long pointCountNum =
chunkMetadata.getStatistics().getCount();
+ chunkId++;
+ printlnBoth(
+ pw,
+ String.format(
+ "%s,%s,%d,%d,%d,%d",
+ tsName, fileNameForVis, chunkId, startTime, endTime,
pointCountNum));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the list of paths of all tsfiles under the input path recursively.
+ *
+ * @param path can be the full path of a file or a directory path
+ * @param filelist
+ * @return the list of paths of all tsfiles under the input path
+ */
+ private static List<String> getFile(String path, List<String> filelist) {
+ File file = new File(path);
+ File[] array = file.listFiles();
+ if (array == null) {
+ filelist.add(path);
+ return filelist;
+ }
+ for (File value : array) {
+ if (value.isFile()) {
+ String filePath = value.getPath();
+ if (filePath.endsWith(TsFileConstant.TSFILE_SUFFIX)) {
+ // only include tsfiles
+ filelist.add(value.getPath());
+ }
+ } else if (value.isDirectory()) {
+ getFile(value.getPath(), filelist);
+ }
+ }
+ return filelist;
+ }
+
+ private static void printlnBoth(PrintWriter pw, String str) {
+ System.out.println(str);
+ pw.println(str);
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/tools/vis/vis.m
b/server/src/main/java/org/apache/iotdb/db/tools/vis/vis.m
new file mode 100644
index 0000000..44ec76f
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/tools/vis/vis.m
@@ -0,0 +1,290 @@
+ %
+ % Licensed to the Apache Software Foundation (ASF) under one
+ % or more contributor license agreements. See the NOTICE file
+ % distributed with this work for additional information
+ % regarding copyright ownership. The ASF licenses this file
+ % to you under the Apache License, Version 2.0 (the
+ % "License"); you may not use this file except in compliance
+ % with the License. You may obtain a copy of the License at
+ %
+ % http://www.apache.org/licenses/LICENSE-2.0
+ %
+ % Unless required by applicable law or agreed to in writing,
+ % software distributed under the License is distributed on an
+ % "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ % KIND, either express or implied. See the License for the
+ % specific language governing permissions and limitations
+ % under the License.
+ %
+
+clear all;close all;
+
+% 1. load visdata generated by TsFileExtractVisdata
+filePath = 'D:\visdata1.csv';
+[timeMap,countMap] = loadVisData(filePath,'ms'); % mind the timestamp unit
+
+% 2. plot figures given the loaded data and two plot parameters:
+% `showSpecific` and `isFileOrder`
+draw(timeMap,countMap,{},false)
+
+draw(timeMap,countMap,{},true)
+
+draw(timeMap,countMap,{'root.vehicle.d0.s0'},false)
+
+draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},false)
+
+draw(timeMap,countMap,{'root.vehicle.d0.s0','root.vehicle.d0.s1'},true)
+
+%% Functions
+function [timeMap,countMap] = loadVisData(filePath,timestampUnit)
+% Load visdata generated by TsFileExtractVisdata.
+%
+% filePath: the path of visdata.
+% The format is [tsName,fileName,chunkId,startTime,endTime,pointCountNum].
+% `tsName` and `fileName` are string, the others are long value.
+% If the tsfile is unsequence file, `fileName` will contain "unseq" as an
+% indicator, which is guaranteed by TsFileExtractVisdata.
+%
+% timestampUnit(not case sensitive):
+% 'us' if the timestamp is microsecond, e.g., 1621993620816000
+% 'ms' if it is millisecond, e.g., 1621993620816
+% 's' if it is second, e.g., 1621993620
+%
+% timeMap: record the time range of every chunk.
+% Key [tsName][fileName][chunkId] identifies the only chunk. Value is
+% [startTime,endTime] of the chunk.
+%
+% countMap: record the point count number of every chunk. Key is the same
+% as that of timeMap. Value is pointCountNum.
+
+ timeMap = containers.Map();
+ countMap = containers.Map();
+ A = readtable(filePath);
+ for i=1:1:size(A,1)
+ [timeMap,countMap]=addChunkTime(A{i,1}{1},A{i,2}{1},A{i,3},...
+ A{i,4},A{i,5},A{i,6},timestampUnit,timeMap,countMap);
+ end
+ disp(['loadVisData finished. ','load ',num2str(size(timeMap,1)),' chunks
in total'])
+end
+
+function [timeMap,countMap] = addChunkTime(tsName,fileName,chunkId,...
+ startTime,endTime,pointCountNum,timestampUnit,timeMap,countMap)
+% Used by loadVisData function.
+
+ % the key [tsName][fileName][chunkId] identifies the only chunk
+ key = ['[',tsName,'][', fileName,'][', num2str(chunkId),']'];
+
+ startTime = convertLongToDate(startTime,timestampUnit);
+ endTime = convertLongToDate(endTime,timestampUnit);
+ timeMap(key) = [startTime,endTime];
+
+ countMap(key) = pointCountNum;
+end
+
+function draw(timeMap,countMap,showSpecific,isFileOrder)
+% Plot figures given the loaded data and two plot parameters:
+% `showSpecific` and `isFileOrder`.
+%
+% process: 1) traverse `keys(timeMap)` to get the position arrangements on
+% the y axis dynamically, which is defined simultaneously by
+% (a)`showSpecific`: traverse `keys(timeMap)`, filter out keys
+% that don't statisfy `showSpecific`.
+% (b) seqKey/unseqKey display policies: extract seqKey or unseqKey
+% from statisfied keys under different display policies:
+% b-1) unseqKey identifies tsName and fileName, so chunk data
with the
+% same fileName and tsName but different chunkIds are
+% plotted on the same line.
+% b-2) seqKey identifies tsName, so chunk data with the same
tsName but
+% different fileNames and chunkIds are plotted on the same
+% line.
+% (c)`isFileOrder`: sort seqKey&unseqKey according to `isFileOrder`,
+% finally get the position arrangements on the y axis.
+% 2) traverse `keys(timeMap)` again, get startTime&endTime from
+% `treeMap` as positions on the x axis, combined with the
+% positions on the y axis from the last step, finish plot.
+%
+% timeMap,countMap: generated by loadVisData function.
+%
+% showSpecific: the specific set of time series to be plotted.
+% If showSpecific is empty{}, then all loaded time series
+% will be plotted.
+% Note: Wildcard matching is not supported now. In other
+% words, showSpecific only support full time series path
+% names.
+%
+% isFileOrder: true to sort seqKeys&unseqKeys by fileName priority, false
+% to sort seqKeys&unseqKeys by tsName priority.
+
+ % traverse `keys(timeMap)` to get the position arrangements on the y axis
dynamically
+
[yticklabelMap,allkeysBoolean]=get_yticklabelMaps(keys(timeMap),showSpecific,
isFileOrder);
+ disp('draw: get_yticklabelMaps finished')
+
+ % traverse `keys(timeMap)` again to plot
+ if all(allkeysBoolean(:)==false)
+ disp('no statisfied specific data')
+ return
+ end
+ figure,
+ m=1;
+ for k = keys(timeMap)
+ if ~allkeysBoolean(m)
+ m = m + 1; % don't forget this step
+ continue;
+ end
+ key = k{1};
+ % extract [tsName][fileName][chunkId] respectively
+ timeMapKeySplit=split(key,["[","]","]["]);
+ tsName = timeMapKeySplit{2};
+ fileName = timeMapKeySplit{4};
+ chunkId = timeMapKeySplit{6};
+ % get the positions on the x axis
+ timeRange = timeMap(key);
+ % get the positions on the y axis
+ if contains(key,'unseq') % unsequence tsfile
+ % unseqKey identifies tsName and fileName, so data with the
+ % same fileName and tsName but different chunkIds are
+ % ploteed on the same line.
+ if isFileOrder
+ % unseqKey is 'fileName/tsName'
+ yPos = yticklabelMap([fileName,'/',tsName]);
+ else
+ % unseqKey is 'tsName/fileName'
+ yPos = yticklabelMap([tsName,'/',fileName]);
+ end
+ % begin plot
+ plot(timeRange,[yPos,yPos],'LineWidth',8),hold on
+
text(timeRange(1),yPos-0.3,sprintf(num2str(countMap(key))),'FontSize',7),hold on
+
+ % chunkId is used to differentiate different chunks of the same
timeseries in the same TsFile.
+ %
text(timeRange(1),yPos+0.3,sprintf(['[',chunkId,']']),'FontSize',7),hold on
+
+ % add short vertical lines to the two ends of timeRange
+ plot([timeRange(1),timeRange(1)],[yPos,yPos+0.3]),hold on
+ plot([timeRange(2),timeRange(2)],[yPos,yPos+0.3]),hold on
+ m = m + 1;
+ else % sequence tsfile
+ % seqKey identifies tsName, so data with the same tsName but
+ % different fileNames and chunkIds are ploteed on the same
+ % line.
+ yPos = yticklabelMap(tsName);
+ % begin plot
+ plot(timeRange,[yPos,yPos],'LineWidth',8),hold on
+
text(timeRange(1),yPos-0.3,sprintf(num2str(countMap(key))),'FontSize',7),hold on
+ % add fileName text, since seqKey does not contain this information
+ text(timeRange(1),yPos+0.5,sprintf(fileName),'FontSize',7),hold on
+ % add short vertical lines to the two ends of timeRange
+ plot([timeRange(1),timeRange(1)],[yPos,yPos+0.3]),hold on
+ plot([timeRange(2),timeRange(2)],[yPos,yPos+0.3]),hold on
+ m = m + 1;
+ end
+ end
+ yticklabelRes = keys(yticklabelMap);
+ yticklabelNum = size(yticklabelRes,2);
+ yticks(1:1:yticklabelNum)
+ yticklabels(yticklabelRes)
+ xtickformat('yyyy-MM-dd HH:mm:ss.SSS')
+ ylim([0 yticklabelNum+1])
+ disp('draw finished')
+end
+
+function
[yticklabelMap,allkeysBoolean]=get_yticklabelMaps(allkeys,showSpecific,isFileOrder)
+% Used by draw function. Given two plot parameters: `showSpecific` and
+% `isFileOrder`,it dynamically generate the position arrangements on
+% the y axis.
+%
+% process: traverse `keys(timeMap)`, filter out keys that don't statisfy
+% `showSpecific`, extract seqKey or unseqKey from statisfied keys,
+% sort seqKey&unseqKey according to `isFileOrder` to get the position
+% arrangements on the y axis.
+%
+% allkeys: a 1*N cell array stores the keys of all loaded data. Key
+% [tsName][fileName][chunkId] identifies the only chunk.
+%
+% showSpecific: the specific set of time series to be plotted.
+% If showSpecific is empty{}, then all loaded time series
+% will be plotted.
+% Note: Wildcard matching is not supported now. In other
+% words, showSpecific only support full time series path
+% names.
+%
+% isFileOrder: true to sort seqKeys&unseqKeys by fileName
+% priority('fileName/tsName'), false to sort seqKeys&unseqKeys
+% by tsName priority ('tsName/fileName').
+%
+% yticklabelMap: seqKey/unseqKey->yPos, record the position arrangements on
+% the y axis.
+%
+% allkeysBoolean: save the filtered result of allkeys to avoid repeated
+% computation later in the draw function.
+
+ N=size(allkeys,2);
+ allkeysBoolean = ones(1,N);
+ m=1;
+ seqOrUnseqKeys = {};
+ for k = allkeys
+ key = k{1};
+ % extract [tsName][fileName][chunkId] respectively
+ timeMapKeySplit=split(key,["[","]","]["]);
+ tsName = timeMapKeySplit{2};
+ fileName = timeMapKeySplit{4};
+ % filter given showSpecific
+ if ~isempty(showSpecific)&&~any(strcmp(showSpecific,tsName))
+ % note that can not use "contains", because for example V1.C101
+ % containes V1.C1
+ allkeysBoolean(m)=false;
+ m = m + 1;
+ continue;
+ % Note: Wildcard matching is not supported now. In other
+ % words, showSpecific only support full time series path
+ % names.
+ end
+ allkeysBoolean(m)=true;
+ if contains(fileName,'unseq') %unsequence tsfile
+ if isFileOrder
+ unseqKey=[fileName,'/',tsName];
+ else
+ unseqKey=[tsName,'/', fileName];
+ end
+ if ~any(strcmp(seqOrUnseqKeys,unseqKey))
+ seqOrUnseqKeys{end+1}=unseqKey;
+ end
+ else %sequence tsfile
+ seqKey=tsName;
+ if ~any(strcmp(seqOrUnseqKeys,seqKey))
+ seqOrUnseqKeys{end+1}=seqKey;
+ end
+ end
+ m = m + 1;
+ end
+ seqOrUnseqKeys = sort(seqOrUnseqKeys);
+ yticklabelMap = containers.Map();
+ yposCurr = 1;
+ for yposKey = seqOrUnseqKeys
+ yticklabelMap(yposKey{1}) = yposCurr;
+ yposCurr = yposCurr + 1;
+ end
+end
+
+function t=convertLongToDate(timestamp,timestampUnit)
+% timestampUnit(not case sensitive):
+% 'us' if the timestamp is microsecond, e.g., 1621993620816000
+% 'ms' if it is millisecond, e.g., 1621993620816
+% 's' if it is second, e.g., 1621993620
+
+ timestampUnit = lower(timestampUnit);
+ if strcmp(timestampUnit,'us')
+ % microsecond, e.g., 1621993620816000
+ posix_timestamp = timestamp/1000/1000;
+ t=datetime(posix_timestamp,'convertfrom','posixtime', 'Format',
'yyyy-MM-dd HH:mm:ss.SSSSSS','TimeZone','local');
+ elseif strcmp(timestampUnit,'ms')
+ % millisecond, e.g., 1621993620816
+ posix_timestamp = timestamp/1000;
+ t=datetime(posix_timestamp,'convertfrom','posixtime', 'Format',
'yyyy-MM-dd HH:mm:ss.SSS','TimeZone','local');
+ elseif strcmp(timestampUnit,'s')
+ % second, e.g., 1621993620
+ posix_timestamp = timestamp;
+ t=datetime(posix_timestamp,'convertfrom','posixtime', 'Format',
'yyyy-MM-dd HH:mm:ss','TimeZone','local');
+ else
+ error('Wrong timestamp unit. It should be us/ms/s.')
+ end
+end