deck.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. # Licensed to the Apache Software Foundation (ASF) under one
  2. # or more contributor license agreements. See the NOTICE file
  3. # distributed with this work for additional information
  4. # regarding copyright ownership. The ASF licenses this file
  5. # to you under the Apache License, Version 2.0 (the
  6. # "License"); you may not use this file except in compliance
  7. # with the License. You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing,
  12. # software distributed under the License is distributed on an
  13. # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. # KIND, either express or implied. See the License for the
  15. # specific language governing permissions and limitations
  16. # under the License.
  17. # pylint: disable=too-many-statements
  18. import json
  19. from superset import db
  20. from superset.models.dashboard import Dashboard
  21. from superset.models.slice import Slice
  22. from .helpers import get_slice_json, merge_slice, TBL, update_slice_ids
  23. COLOR_RED = {"r": 205, "g": 0, "b": 3, "a": 0.82}
  24. POSITION_JSON = """\
  25. {
  26. "CHART-3afd9d70": {
  27. "meta": {
  28. "chartId": 66,
  29. "width": 6,
  30. "height": 50
  31. },
  32. "type": "CHART",
  33. "id": "CHART-3afd9d70",
  34. "children": []
  35. },
  36. "CHART-2ee7fa5e": {
  37. "meta": {
  38. "chartId": 67,
  39. "width": 6,
  40. "height": 50
  41. },
  42. "type": "CHART",
  43. "id": "CHART-2ee7fa5e",
  44. "children": []
  45. },
  46. "CHART-201f7715": {
  47. "meta": {
  48. "chartId": 68,
  49. "width": 6,
  50. "height": 50
  51. },
  52. "type": "CHART",
  53. "id": "CHART-201f7715",
  54. "children": []
  55. },
  56. "CHART-d02f6c40": {
  57. "meta": {
  58. "chartId": 69,
  59. "width": 6,
  60. "height": 50
  61. },
  62. "type": "CHART",
  63. "id": "CHART-d02f6c40",
  64. "children": []
  65. },
  66. "CHART-2673431d": {
  67. "meta": {
  68. "chartId": 70,
  69. "width": 6,
  70. "height": 50
  71. },
  72. "type": "CHART",
  73. "id": "CHART-2673431d",
  74. "children": []
  75. },
  76. "CHART-85265a60": {
  77. "meta": {
  78. "chartId": 71,
  79. "width": 6,
  80. "height": 50
  81. },
  82. "type": "CHART",
  83. "id": "CHART-85265a60",
  84. "children": []
  85. },
  86. "CHART-2b87513c": {
  87. "meta": {
  88. "chartId": 72,
  89. "width": 6,
  90. "height": 50
  91. },
  92. "type": "CHART",
  93. "id": "CHART-2b87513c",
  94. "children": []
  95. },
  96. "GRID_ID": {
  97. "type": "GRID",
  98. "id": "GRID_ID",
  99. "children": [
  100. "ROW-a7b16cb5",
  101. "ROW-72c218a5",
  102. "ROW-957ba55b",
  103. "ROW-af041bdd"
  104. ]
  105. },
  106. "HEADER_ID": {
  107. "meta": {
  108. "text": "deck.gl Demo"
  109. },
  110. "type": "HEADER",
  111. "id": "HEADER_ID"
  112. },
  113. "ROOT_ID": {
  114. "type": "ROOT",
  115. "id": "ROOT_ID",
  116. "children": [
  117. "GRID_ID"
  118. ]
  119. },
  120. "ROW-72c218a5": {
  121. "meta": {
  122. "background": "BACKGROUND_TRANSPARENT"
  123. },
  124. "type": "ROW",
  125. "id": "ROW-72c218a5",
  126. "children": [
  127. "CHART-d02f6c40",
  128. "CHART-201f7715"
  129. ]
  130. },
  131. "ROW-957ba55b": {
  132. "meta": {
  133. "background": "BACKGROUND_TRANSPARENT"
  134. },
  135. "type": "ROW",
  136. "id": "ROW-957ba55b",
  137. "children": [
  138. "CHART-2673431d",
  139. "CHART-85265a60"
  140. ]
  141. },
  142. "ROW-a7b16cb5": {
  143. "meta": {
  144. "background": "BACKGROUND_TRANSPARENT"
  145. },
  146. "type": "ROW",
  147. "id": "ROW-a7b16cb5",
  148. "children": [
  149. "CHART-3afd9d70",
  150. "CHART-2ee7fa5e"
  151. ]
  152. },
  153. "ROW-af041bdd": {
  154. "meta": {
  155. "background": "BACKGROUND_TRANSPARENT"
  156. },
  157. "type": "ROW",
  158. "id": "ROW-af041bdd",
  159. "children": [
  160. "CHART-2b87513c"
  161. ]
  162. },
  163. "DASHBOARD_VERSION_KEY": "v2"
  164. }"""
  165. def load_deck_dash() -> None:
  166. print("Loading deck.gl dashboard")
  167. slices = []
  168. tbl = db.session.query(TBL).filter_by(table_name="long_lat").first()
  169. slice_data = {
  170. "spatial": {"type": "latlong", "lonCol": "LON", "latCol": "LAT"},
  171. "color_picker": COLOR_RED,
  172. "datasource": "5__table",
  173. "granularity_sqla": None,
  174. "groupby": [],
  175. "mapbox_style": "mapbox://styles/mapbox/light-v9",
  176. "multiplier": 10,
  177. "point_radius_fixed": {"type": "metric", "value": "count"},
  178. "point_unit": "square_m",
  179. "min_radius": 1,
  180. "max_radius": 250,
  181. "row_limit": 5000,
  182. "time_range": " : ",
  183. "size": "count",
  184. "time_grain_sqla": None,
  185. "viewport": {
  186. "bearing": -4.952916738791771,
  187. "latitude": 37.78926922909199,
  188. "longitude": -122.42613341901688,
  189. "pitch": 4.750411100577438,
  190. "zoom": 12.729132798697304,
  191. },
  192. "viz_type": "deck_scatter",
  193. }
  194. print("Creating Scatterplot slice")
  195. slc = Slice(
  196. slice_name="Scatterplot",
  197. viz_type="deck_scatter",
  198. datasource_type="table",
  199. datasource_id=tbl.id,
  200. params=get_slice_json(slice_data),
  201. )
  202. merge_slice(slc)
  203. slices.append(slc)
  204. slice_data = {
  205. "point_unit": "square_m",
  206. "row_limit": 5000,
  207. "spatial": {"type": "latlong", "lonCol": "LON", "latCol": "LAT"},
  208. "mapbox_style": "mapbox://styles/mapbox/dark-v9",
  209. "granularity_sqla": None,
  210. "size": "count",
  211. "viz_type": "deck_screengrid",
  212. "time_range": "No filter",
  213. "point_radius": "Auto",
  214. "color_picker": {"a": 1, "r": 14, "b": 0, "g": 255},
  215. "grid_size": 20,
  216. "viewport": {
  217. "zoom": 14.161641703941438,
  218. "longitude": -122.41827069521386,
  219. "bearing": -4.952916738791771,
  220. "latitude": 37.76024135844065,
  221. "pitch": 4.750411100577438,
  222. },
  223. "point_radius_fixed": {"type": "fix", "value": 2000},
  224. "datasource": "5__table",
  225. "time_grain_sqla": None,
  226. "groupby": [],
  227. }
  228. print("Creating Screen Grid slice")
  229. slc = Slice(
  230. slice_name="Screen grid",
  231. viz_type="deck_screengrid",
  232. datasource_type="table",
  233. datasource_id=tbl.id,
  234. params=get_slice_json(slice_data),
  235. )
  236. merge_slice(slc)
  237. slices.append(slc)
  238. slice_data = {
  239. "spatial": {"type": "latlong", "lonCol": "LON", "latCol": "LAT"},
  240. "row_limit": 5000,
  241. "mapbox_style": "mapbox://styles/mapbox/streets-v9",
  242. "granularity_sqla": None,
  243. "size": "count",
  244. "viz_type": "deck_hex",
  245. "time_range": "No filter",
  246. "point_radius_unit": "Pixels",
  247. "point_radius": "Auto",
  248. "color_picker": {"a": 1, "r": 14, "b": 0, "g": 255},
  249. "grid_size": 40,
  250. "extruded": True,
  251. "viewport": {
  252. "latitude": 37.789795085160335,
  253. "pitch": 54.08961642447763,
  254. "zoom": 13.835465702403654,
  255. "longitude": -122.40632230075536,
  256. "bearing": -2.3984797349335167,
  257. },
  258. "point_radius_fixed": {"type": "fix", "value": 2000},
  259. "datasource": "5__table",
  260. "time_grain_sqla": None,
  261. "groupby": [],
  262. }
  263. print("Creating Hex slice")
  264. slc = Slice(
  265. slice_name="Hexagons",
  266. viz_type="deck_hex",
  267. datasource_type="table",
  268. datasource_id=tbl.id,
  269. params=get_slice_json(slice_data),
  270. )
  271. merge_slice(slc)
  272. slices.append(slc)
  273. slice_data = {
  274. "spatial": {"type": "latlong", "lonCol": "LON", "latCol": "LAT"},
  275. "row_limit": 5000,
  276. "mapbox_style": "mapbox://styles/mapbox/satellite-streets-v9",
  277. "granularity_sqla": None,
  278. "size": "count",
  279. "viz_type": "deck_grid",
  280. "point_radius_unit": "Pixels",
  281. "point_radius": "Auto",
  282. "time_range": "No filter",
  283. "color_picker": {"a": 1, "r": 14, "b": 0, "g": 255},
  284. "grid_size": 120,
  285. "extruded": True,
  286. "viewport": {
  287. "longitude": -122.42066918995666,
  288. "bearing": 155.80099696026355,
  289. "zoom": 12.699690845482069,
  290. "latitude": 37.7942314882596,
  291. "pitch": 53.470800300695146,
  292. },
  293. "point_radius_fixed": {"type": "fix", "value": 2000},
  294. "datasource": "5__table",
  295. "time_grain_sqla": None,
  296. "groupby": [],
  297. }
  298. print("Creating Grid slice")
  299. slc = Slice(
  300. slice_name="Grid",
  301. viz_type="deck_grid",
  302. datasource_type="table",
  303. datasource_id=tbl.id,
  304. params=get_slice_json(slice_data),
  305. )
  306. merge_slice(slc)
  307. slices.append(slc)
  308. polygon_tbl = (
  309. db.session.query(TBL).filter_by(table_name="sf_population_polygons").first()
  310. )
  311. slice_data = {
  312. "datasource": "11__table",
  313. "viz_type": "deck_polygon",
  314. "slice_id": 41,
  315. "granularity_sqla": None,
  316. "time_grain_sqla": None,
  317. "time_range": " : ",
  318. "line_column": "contour",
  319. "metric": {
  320. "aggregate": "SUM",
  321. "column": {
  322. "column_name": "population",
  323. "description": None,
  324. "expression": None,
  325. "filterable": True,
  326. "groupby": True,
  327. "id": 1332,
  328. "is_dttm": False,
  329. "optionName": "_col_population",
  330. "python_date_format": None,
  331. "type": "BIGINT",
  332. "verbose_name": None,
  333. },
  334. "expressionType": "SIMPLE",
  335. "hasCustomLabel": True,
  336. "label": "Population",
  337. "optionName": "metric_t2v4qbfiz1_w6qgpx4h2p",
  338. "sqlExpression": None,
  339. },
  340. "line_type": "json",
  341. "linear_color_scheme": "oranges",
  342. "mapbox_style": "mapbox://styles/mapbox/light-v9",
  343. "viewport": {
  344. "longitude": -122.43388541747726,
  345. "latitude": 37.752020331384834,
  346. "zoom": 11.133995608594631,
  347. "bearing": 37.89506450385642,
  348. "pitch": 60,
  349. "width": 667,
  350. "height": 906,
  351. "altitude": 1.5,
  352. "maxZoom": 20,
  353. "minZoom": 0,
  354. "maxPitch": 60,
  355. "minPitch": 0,
  356. "maxLatitude": 85.05113,
  357. "minLatitude": -85.05113,
  358. },
  359. "reverse_long_lat": False,
  360. "fill_color_picker": {"r": 3, "g": 65, "b": 73, "a": 1},
  361. "stroke_color_picker": {"r": 0, "g": 122, "b": 135, "a": 1},
  362. "filled": True,
  363. "stroked": False,
  364. "extruded": True,
  365. "multiplier": 0.1,
  366. "point_radius_fixed": {
  367. "type": "metric",
  368. "value": {
  369. "aggregate": None,
  370. "column": None,
  371. "expressionType": "SQL",
  372. "hasCustomLabel": None,
  373. "label": "Density",
  374. "optionName": "metric_c5rvwrzoo86_293h6yrv2ic",
  375. "sqlExpression": "SUM(population)/SUM(area)",
  376. },
  377. },
  378. "js_columns": [],
  379. "js_data_mutator": "",
  380. "js_tooltip": "",
  381. "js_onclick_href": "",
  382. "legend_format": ".1s",
  383. "legend_position": "tr",
  384. }
  385. print("Creating Polygon slice")
  386. slc = Slice(
  387. slice_name="Polygons",
  388. viz_type="deck_polygon",
  389. datasource_type="table",
  390. datasource_id=polygon_tbl.id,
  391. params=get_slice_json(slice_data),
  392. )
  393. merge_slice(slc)
  394. slices.append(slc)
  395. slice_data = {
  396. "datasource": "10__table",
  397. "viz_type": "deck_arc",
  398. "slice_id": 42,
  399. "granularity_sqla": None,
  400. "time_grain_sqla": None,
  401. "time_range": " : ",
  402. "start_spatial": {
  403. "type": "latlong",
  404. "latCol": "LATITUDE",
  405. "lonCol": "LONGITUDE",
  406. },
  407. "end_spatial": {
  408. "type": "latlong",
  409. "latCol": "LATITUDE_DEST",
  410. "lonCol": "LONGITUDE_DEST",
  411. },
  412. "row_limit": 5000,
  413. "mapbox_style": "mapbox://styles/mapbox/light-v9",
  414. "viewport": {
  415. "altitude": 1.5,
  416. "bearing": 8.546256357301871,
  417. "height": 642,
  418. "latitude": 44.596651438714254,
  419. "longitude": -91.84340711201104,
  420. "maxLatitude": 85.05113,
  421. "maxPitch": 60,
  422. "maxZoom": 20,
  423. "minLatitude": -85.05113,
  424. "minPitch": 0,
  425. "minZoom": 0,
  426. "pitch": 60,
  427. "width": 997,
  428. "zoom": 2.929837070560775,
  429. },
  430. "color_picker": {"r": 0, "g": 122, "b": 135, "a": 1},
  431. "stroke_width": 1,
  432. }
  433. print("Creating Arc slice")
  434. slc = Slice(
  435. slice_name="Arcs",
  436. viz_type="deck_arc",
  437. datasource_type="table",
  438. datasource_id=db.session.query(TBL).filter_by(table_name="flights").first().id,
  439. params=get_slice_json(slice_data),
  440. )
  441. merge_slice(slc)
  442. slices.append(slc)
  443. slice_data = {
  444. "datasource": "12__table",
  445. "slice_id": 43,
  446. "viz_type": "deck_path",
  447. "time_grain_sqla": None,
  448. "time_range": " : ",
  449. "line_column": "path_json",
  450. "line_type": "json",
  451. "row_limit": 5000,
  452. "mapbox_style": "mapbox://styles/mapbox/light-v9",
  453. "viewport": {
  454. "longitude": -122.18885402582598,
  455. "latitude": 37.73671752604488,
  456. "zoom": 9.51847667620428,
  457. "bearing": 0,
  458. "pitch": 0,
  459. "width": 669,
  460. "height": 1094,
  461. "altitude": 1.5,
  462. "maxZoom": 20,
  463. "minZoom": 0,
  464. "maxPitch": 60,
  465. "minPitch": 0,
  466. "maxLatitude": 85.05113,
  467. "minLatitude": -85.05113,
  468. },
  469. "color_picker": {"r": 0, "g": 122, "b": 135, "a": 1},
  470. "line_width": 150,
  471. "reverse_long_lat": False,
  472. "js_columns": ["color"],
  473. "js_data_mutator": "data => data.map(d => ({\n"
  474. " ...d,\n"
  475. " color: colors.hexToRGB(d.extraProps.color)\n"
  476. "}));",
  477. "js_tooltip": "",
  478. "js_onclick_href": "",
  479. }
  480. print("Creating Path slice")
  481. slc = Slice(
  482. slice_name="Path",
  483. viz_type="deck_path",
  484. datasource_type="table",
  485. datasource_id=db.session.query(TBL)
  486. .filter_by(table_name="bart_lines")
  487. .first()
  488. .id,
  489. params=get_slice_json(slice_data),
  490. )
  491. merge_slice(slc)
  492. slices.append(slc)
  493. slug = "deck"
  494. print("Creating a dashboard")
  495. title = "deck.gl Demo"
  496. dash = db.session.query(Dashboard).filter_by(slug=slug).first()
  497. if not dash:
  498. dash = Dashboard()
  499. dash.published = True
  500. js = POSITION_JSON
  501. pos = json.loads(js)
  502. update_slice_ids(pos, slices)
  503. dash.position_json = json.dumps(pos, indent=4)
  504. dash.dashboard_title = title
  505. dash.slug = slug
  506. dash.slices = slices
  507. db.session.merge(dash)
  508. db.session.commit()
  509. if __name__ == "__main__":
  510. load_deck_dash()