0%

绘制卫星的gantt图

以卫星高度计任务为例,绘制Gantt图,以展示过去、现在和未来的卫星任务时间轴。此类图形对于综述文章或者研究生开题报告有一定帮助。

甘特图(Gantt Chart)简介:它是条状图的一种流行类型,显示项目进度以及其他与时间相关的系统进展的内在关系随着时间进展的情况,是由亨利·甘特 (Henry Laurence Gantt) 于1910年开发出。在项目管理中,甘特图显示项目的终端元素的开始和结束,概要元素或终端元素的依赖关系。

工具

我们采用Python库plotlyplotly.express模块来绘制Gantt图。其优点是高度集成,节省代码,方便学习使用。

plotly.express可以绘制许多类型的图形,包含那些常见的不常见的、常用的不常用,如散点图、线条图、PIE图、Bar图、泡泡图、桑吉图、Sunburst图、Icicle图等等。详见:https://plotly.com/python/plotly-express/

数据格式

输入的数据格式采用pandas的DataFrame,内容包含任务名称、开始时间和结束时间。

1
2
3
4
5
df = pd.DataFrame([
dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28'),
dict(Task="Job B", Start='2009-03-05', Finish='2009-04-15'),
dict(Task="Job C", Start='2009-02-20', Finish='2009-05-30')
])

对于卫星任务,我们可以设置如下:

1
df = pd.DataFrame([dict(Satellite="TP", Start='1992-8-11', Finish='2005-12-31',Country="USA-FR")])

代码

Python全部绘图代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#Install Plotly
# pip install plotly

#Import required libraries
import plotly.express as px
import pandas as pd

#Create input data aggregated for each Satellite for each Country type
df = pd.DataFrame([
dict(Satellite="GEOSAT", Start='1985-3-1', Finish='1989-12-1',Country="USA"),
dict(Satellite="ERS-1", Start='1991-7-1', Finish='1995-6-1',Country="EU"),
dict(Satellite="TP", Start='1992-8-11', Finish='2005-12-31',Country="USA-FR"),
dict(Satellite="ERS-2", Start='1995-4-1', Finish='2002-6-1',Country="EU"),
dict(Satellite="GFO", Start='1998-5-1', Finish='2008-9-1',Country="USA"),
dict(Satellite="Jason-2", Start='2001-11-1', Finish='2013-7-1',Country="USA-FR"),
dict(Satellite="ENVISAT", Start='2002-3-1', Finish='2012-4-1',Country="EU"),
dict(Satellite="Icesat-1", Start='2003-1-1', Finish='2010-2-1',Country="USA"),
dict(Satellite="Jason-2", Start='2008-6-1', Finish='2019-10-1',Country="USA-FR"),
dict(Satellite="Cryosat-2", Start='2010-4-1', Finish='2024-4-1',Country="EU"),
dict(Satellite="HY-2A", Start='2011-8-1', Finish='2020-4-1',Country="CN"),
dict(Satellite="Saral", Start='2013-2-1', Finish='2022-12-31',Country="IN-FR"),
dict(Satellite="Sentinel-3A", Start='2016-2-1', Finish='2023-4-1',Country="EU"),
dict(Satellite="Jason-3", Start='2016-1-1', Finish='2022-4-1',Country="USA-FR"),
dict(Satellite="Sentinel-3B", Start='2018-4-1', Finish='2025-4-1',Country="EU"),
dict(Satellite="Sentinel-3C", Start='2024-4-1', Finish='2031-4-1',Country="EU"),
dict(Satellite="Sentinel-3D", Start='2028-4-1', Finish='2035-4-1',Country="EU"),
dict(Satellite="Icesat-2", Start='2018-9-1', Finish='2023-1-1',Country="USA"),
dict(Satellite="HY-2B", Start='2018-10-1', Finish='2023-4-1',Country="CN"),
dict(Satellite="HY-2C", Start='2020-9-1', Finish='2025-4-1',Country="CN"),
dict(Satellite="Sentinel-6 Michael Freilich", Start='2020-11-1', Finish='2027-1-1',Country="USA-FR"),
dict(Satellite="HY-2D", Start='2021-5-1', Finish='2026-4-1',Country="CN"),
dict(Satellite="HY-2E", Start='2022-5-1', Finish='2027-4-1',Country="CN"),
dict(Satellite="HY-2F", Start='2023-5-1', Finish='2028-4-1',Country="CN"),
dict(Satellite="HY-2G", Start='2024-5-1', Finish='2029-4-1',Country="CN"),
dict(Satellite="HY-2H", Start='2025-5-1', Finish='2030-4-1',Country="CN"),
dict(Satellite="SWOT", Start='2022-5-1', Finish='2026-4-1',Country="USA-FR"),
dict(Satellite="Sentinel-6B", Start='2025-1-1', Finish='2032-1-1',Country="USA-FR"),
dict(Satellite="COMPIRA", Start='2022-10-1', Finish='2026-1-1',Country="JP"),
])

#generate visualization
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Satellite", color = "Country",text ="Satellite",width=1000,height=800)
fig.update_yaxes(autorange="reversed")
fig.update_layout(showlegend=True,legend_x=0.89,legend_y=0.99)
fig.update_yaxes(title_text="Satellite")
fig.update_xaxes(title_text="Time")

fig.add_vline(x='2022-7-1',line_color="black",line_dash="dot",opacity=0.5)

fig.add_vrect(x0='2022-7-1', x1='2038-1-1',line_color="green",fillcolor="red", opacity=0.2,
annotation_text="", annotation_position="bottom left",
annotation=dict(font_size=20, font_family="Times New Roman"))


fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='LightPink')
fig.update_yaxes(nticks=30)
fig.update_yaxes(showgrid=False,showticklabels=False)
fig.show()

# Save fig
fig.write_image("fig_sat.pdf")
fig.write_image("fig_sat.png")

Jupyter Notebook版本的代码见:https://github.com/yangleir/RemoteSensing_paper/blob/main/fig1_gantt/gantt.ipynb

结果

通过上面的代码,我们绘制了Gantt图,通过卫星任务的国家和地区进行分组。此外,还添加了当前时间线,以及对未来时间区间做透明填充。

调整

这里暂不探讨一些绘图的细节,有兴趣的同学可以尝试修改下方的部分代码,False改为True

1
2
fig.update_yaxes(nticks=30)
fig.update_yaxes(showgrid=False,showticklabels=False)