未验证 提交 81e8949e 编写于 作者: R Rui,Lei 提交者: GitHub

Vis tool for master (#3473)

上级 5ed33ac4
......@@ -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
![image](https://user-images.githubusercontent.com/33376433/123763559-82074100-d8f6-11eb-9109-ead7e18f84b8.png)
<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:
![1](https://user-images.githubusercontent.com/33376433/123760377-5df63080-d8f3-11eb-8ca8-c93590f21bde.png)
![2](https://user-images.githubusercontent.com/33376433/123760402-63537b00-d8f3-11eb-9393-398c4204ccf1.png)
![3](https://user-images.githubusercontent.com/33376433/123760418-66e70200-d8f3-11eb-8701-437afd73ac4c.png)
![4](https://user-images.githubusercontent.com/33376433/123760424-69e1f280-d8f3-11eb-9f45-571496685a6e.png)
![5](https://user-images.githubusercontent.com/33376433/123760433-6cdce300-d8f3-11eb-8ecd-da04a475af41.png)
......@@ -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">
![image](https://user-images.githubusercontent.com/33376433/123763559-82074100-d8f6-11eb-9109-ead7e18f84b8.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)")
```
绘图结果:
![1](https://user-images.githubusercontent.com/33376433/123760377-5df63080-d8f3-11eb-8ca8-c93590f21bde.png)
![2](https://user-images.githubusercontent.com/33376433/123760402-63537b00-d8f3-11eb-9393-398c4204ccf1.png)
![3](https://user-images.githubusercontent.com/33376433/123760418-66e70200-d8f3-11eb-8701-437afd73ac4c.png)
![4](https://user-images.githubusercontent.com/33376433/123760424-69e1f280-d8f3-11eb-9f45-571496685a6e.png)
![5](https://user-images.githubusercontent.com/33376433/123760433-6cdce300-d8f3-11eb-8ecd-da04a475af41.png)
@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
#!/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
/*
* 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);
}
}
%
% 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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册