├── LICENSE
├── README.md
├── api
├── annotator
│ └── m_table_annotation.py
├── lookup
│ └── m_mtabes.py
└── utilities
│ └── m_iw.py
├── data
└── semtab
│ ├── 0A2WQW7B.csv
│ ├── 2T_10.zip
│ ├── atable.zip
│ ├── atable_2.zip
│ ├── atable_3.zip
│ ├── mytables.zip
│ └── tables.zip
├── docs
├── mtab.md
└── mtabes.md
├── interface
├── static
│ ├── images
│ │ ├── MTabESSemTab2T.png
│ │ ├── MTabESSemTabR1.png
│ │ ├── MTabESSemTabR2.png
│ │ ├── MTabESSemTabR3.png
│ │ ├── MTabESSemTabR4.png
│ │ ├── logo_mtab_1.png
│ │ ├── logo_mtab_2.png
│ │ ├── logo_mtab_3.png
│ │ ├── logo_mtab_4.png
│ │ └── mtab_pic.png
│ └── others
│ │ ├── mytables.json
│ │ └── mytables.zip
└── templates
│ └── md.html
├── requirements.txt
├── results.zip
├── run_2t.py
└── static
├── images
├── MTabESSemTab2T.png
├── MTabESSemTabR1.png
├── MTabESSemTabR2.png
├── MTabESSemTabR3.png
├── MTabESSemTabR4.png
├── logo_mtab_1.png
├── logo_mtab_2.png
├── logo_mtab_3.png
├── logo_mtab_4.png
├── mtab_pic.png
├── semtab2019.png
├── semtab2020.png
└── semtab2021.png
└── others
├── 0AJSJYAL.xltx
├── mytables.json
├── mytables.zip
├── mytables_ntar.json
├── mytables_ntar.zip
└── semtab2021
├── biotable
└── .gitkeep
└── hardtable
└── .gitkeep
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Phuc Nguyen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ---
4 |
5 | MTab: Entity Search and Table Annotation with Knowledge Graphs (Wikidata, Wikipedia and DBpedia)
6 |
7 | ### Demo
8 | - Demo (Teaser): https://youtu.be/sr-zxH5JUjw
9 | - Demonstration Video: https://youtu.be/0ibTWeObWaA
10 | - Entity Search: https://mtab.kgraph.jp/mtabes
11 | - Table Annotation: https://mtab.kgraph.jp/mtab
12 |
13 |
14 | ### API usage
15 | - Entity Search: [MTabES](docs/mtabes.md)
16 | - Request Example: [entity search](api/lookup/m_mtabes.py)
17 | - Table Annotation: [MTab](docs/mtab.md)
18 | - Request Example: [table annotation](api/annotator/m_table_annotation.py)
19 | - Running Table Annotation on Tough Tables (2T) dataset:
20 | - Running Scripts: [run 2t](https://github.com/phucty/mtab_tool/blob/master/run_2t.py)
21 |
22 | ### Source code:
23 | - Development code: https://github.com/phucty/mtab_dev
24 |
25 | ### Other works:
26 | - [MTab4D](https://github.com/phucty/mtab4dbpedia): Table Annotation with DBpedia
27 | - [WikiDB](https://github.com/phucty/wikidb): Build a DB (key-value store - LMDB style) from Wikidata dump, offline access Wikidata, fast boolean search
28 |
29 | ### References
30 | - Phuc Nguyen, Ikuya Yamada, Natthawut Kertkeidkachorn, Ryutaro Ichise, Hideaki Takeda, SemTab 2021: Tabular Data Annotation with MTab Tool. [[video](https://www.youtube.com/watch?v=j-l3poE0Ktc)]
31 |
32 | - Phuc Nguyen, Ikuya Yamada, Natthawut Kertkeidkachorn, Ryutaro Ichise, Hideaki Takeda, Demonstration of MTab: Tabular Data Annotation with Knowledge Graphs. [[video](https://youtu.be/0ibTWeObWaA)]
33 |
34 | - Phuc Nguyen, Hideaki Takeda, MTab: Tabular Data Annotation, NII Open House June 2021. [[video](https://youtu.be/1ByffPp2alg?t=3269)]
35 |
36 | - Phuc Nguyen, Ikuya Yamada, Hideaki Takeda, [MTabES: Entity Search with Keyword Search, Fuzzy Search, and Entity Popularities](https://drive.google.com/file/d/10Tl0Qd5gxFSiCsnSjJbvRSUiDXW-Kifn/view?usp=sharing), In The 35th Annual Conference of the Japanese Society for Artificial Intelligence (JSAI), 2021. [[video](https://drive.google.com/file/d/1gYSP619HcMT-sE6iD3LiQeRtZw9UZTWQ/view?usp=sharing)]
37 |
38 |
39 | - Phuc Nguyen, Ikuya Yamada, Natthawut Kertkeidkachorn, Ryutaro Ichise, Hideaki Takeda, [MTab4Wikidata at SemTab 2020: Tabular Data Annotation with Wikidata](http://ceur-ws.org/Vol-2775/paper9.pdf), In SemTab@ISWC, 2020. [[video](https://drive.google.com/file/d/1vz-6nkc9t6MQZYzgg-PZNLs-9TT86wRD/view?usp=sharing)]
40 |
41 |
42 | - Phuc Nguyen, Natthawut Kertkeidkachorn, Ryutaro Ichise, Hideaki Takeda [MTab: Matching Tabular Data to Knowledge Graph using Probability Models](http://ceur-ws.org/Vol-2553/paper2.pdf), In SemTab@ISWC, 2019, [[slides](http://www.cs.ox.ac.uk/isg/challenges/sem-tab/2019/slides/MTab.pptx)]
43 |
44 |
45 | ### Awards:
46 |
47 | - 1st prize at SemTab 2021 (usability track). [Results](https://www.cs.ox.ac.uk/isg/challenges/sem-tab/2021/index.html#results)
48 |
49 |
50 |
51 | - 1st prize at SemTab 2020 (tabular data to Wikidata matching). [Results](http://www.cs.ox.ac.uk/isg/challenges/sem-tab/2020/results.html)
52 |
53 |
54 | - 1st prize at SemTab 2019 (tabular data to DBpedia matching). [Results](http://www.cs.ox.ac.uk/isg/challenges/sem-tab/2019/results.html)
55 |
56 |
57 | ### Citing
58 |
59 | If you find MTab tool useful in your work, and you want to cite our work, please use the following referencee:
60 | ```
61 | @inproceedings{2021_mtab4wikidata,
62 | author = {Phuc Nguyen and
63 | Ikuya Yamada and
64 | Natthawut Kertkeidkachorn and
65 | Ryutaro Ichise and
66 | Hideaki Takeda},
67 | title = {SemTab 2021: Tabular Data Annotation with MTab Tool},
68 | booktitle = {SemTab@ISWC 2021},
69 | series = {{CEUR} Workshop Proceedings},
70 | volume = {3103},
71 | pages = {92--101},
72 | publisher = {CEUR-WS.org},
73 | year = {2021},
74 | url = {http://ceur-ws.org/Vol-3103/paper8.pdf},
75 | }
76 | ```
77 |
78 |
79 | ### Contact
80 | Phuc Nguyen (`phucnt@nii.ac.jp`)
81 |
--------------------------------------------------------------------------------
/api/annotator/m_table_annotation.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | from collections import defaultdict
4 | from contextlib import closing
5 | from datetime import timedelta
6 | from time import time, sleep
7 | from multiprocessing import Pool
8 |
9 | import requests
10 | from requests.packages.urllib3.util.retry import Retry
11 | from requests.adapters import HTTPAdapter
12 | from tqdm import tqdm
13 |
14 | from api.utilities import m_iw
15 |
16 | # Request config
17 | LIMIT_TIME_OUT = 7200 # 2h: 7200 - 24h: 86400 -3days:259200
18 | LIMIT_RETRIES = 3
19 |
20 |
21 | class MTab(object):
22 | def __init__(self):
23 | self.F_MTAB = "https://mtab.app/api/v1.1/mtab"
24 | # self.F_MTAB = "http://localhost:5000/api/v1.1/mtab"
25 |
26 | self.session = requests.Session()
27 | retries = Retry(
28 | total=LIMIT_RETRIES,
29 | backoff_factor=1,
30 | status_forcelist=[500, 502, 503, 504],
31 | )
32 | self.session.mount("https://", HTTPAdapter(max_retries=retries))
33 | self.session.mount("http://", HTTPAdapter(max_retries=retries))
34 |
35 | def _request(self, func_name, query_args, retries=3, message=""):
36 | responds = defaultdict()
37 | if retries == 0:
38 | print(message)
39 | return responds
40 | try:
41 | # _responds = requests.post(func_name, json=query_args, timeout=self.TIME_OUT)
42 | _responds = self.session.post(
43 | func_name, json=query_args, timeout=LIMIT_TIME_OUT
44 | )
45 | if _responds.status_code == 200:
46 | responds = _responds.json()
47 | if not responds or (
48 | responds.get("status") == "Error" and not responds.get("message")
49 | ):
50 | sleep(300)
51 | return self._request(
52 | func_name,
53 | query_args,
54 | retries - 1,
55 | message=f"Error: Retry {retries-1}",
56 | )
57 | except Exception as message:
58 | if func_name == self.F_MTAB and query_args.get("table_name"):
59 | args_info = func_name + ": " + query_args.get("table_name")
60 | else:
61 | args_info = func_name
62 | sleep(300)
63 | return self._request(
64 | func_name, query_args, retries - 1, message=f"\n{message} - {args_info}"
65 | )
66 | return responds
67 |
68 | def get_table_annotation(
69 | self,
70 | table_content,
71 | table_name="",
72 | predict_target=False,
73 | tar_cea=None,
74 | tar_cta=None,
75 | tar_cpa=None,
76 | search_mode="a",
77 | search_limit=50,
78 | debug=False,
79 | ):
80 | query_args = {
81 | "table_name": table_name,
82 | "table": table_content,
83 | "predict_target": predict_target,
84 | "tar_cea": tar_cea,
85 | "tar_cta": tar_cta,
86 | "tar_cpa": tar_cpa,
87 | "search_mode": search_mode,
88 | "search_limit": search_limit,
89 | "debug": debug,
90 | }
91 | responds = self._request(self.F_MTAB, query_args)
92 | return responds
93 |
94 |
95 | def example_table_annotation():
96 | mtab_api = MTab()
97 |
98 | # Table file
99 | dir_table = "/Users/phucnguyen/Downloads/0AJSJYAL.xltx"
100 | # dir_table = f"/Users/phucnguyen/git/dprofile/data/tables/wikitable_1.xlsx"
101 | table_name = os.path.splitext(os.path.basename(dir_table))[0]
102 | table_content = m_iw.load_table(dir_table)
103 |
104 | # Run 1: Let MTab predict annotation targets
105 | responds_auto = mtab_api.get_table_annotation(
106 | table_content,
107 | table_name=table_name,
108 | predict_target=True, # Set this is True
109 | search_mode="a", # Using aggregation search
110 | search_limit=100, # candidate entity generation limit
111 | debug=True, # return all candidates, and their confidence scores in CEA tasks
112 | )
113 |
114 | print(json.dumps(responds_auto, indent=2))
115 |
116 | # Run 2: provide annotation targets
117 |
118 | # Annotation targets
119 | # tar_cea = [
120 | # [1, 0],
121 | # [2, 0],
122 | # [3, 0],
123 | # [4, 0],
124 | # [5, 0],
125 | # [6, 0],
126 | # [7, 0],
127 | # [8, 0],
128 | # [9, 0],
129 | # [10, 0],
130 | # ]
131 | # tar_cta = [0]
132 | # tar_cpa = [[0, 1], [0, 2]]
133 | #
134 | # responds = mtab_api.get_table_annotation(
135 | # table_content,
136 | # table_name=table_name,
137 | # tar_cea=tar_cea,
138 | # tar_cta=tar_cta,
139 | # tar_cpa=tar_cpa,
140 | # search_mode="a",
141 | # )
142 | # print(responds)
143 |
144 |
145 | if __name__ == "__main__":
146 | example_table_annotation()
147 |
--------------------------------------------------------------------------------
/api/lookup/m_mtabes.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from time import time
3 | from requests.packages.urllib3.util.retry import Retry
4 | from requests.adapters import HTTPAdapter
5 |
6 |
7 | class MTabES(object):
8 | def __init__(self):
9 | self.URL = "https://mtab.app/api/v1/search"
10 | self.session = requests.Session()
11 | retries = Retry(total=5,
12 | backoff_factor=1,
13 | status_forcelist=[500, 502, 503, 504])
14 | self.session.mount('https://', HTTPAdapter(max_retries=retries))
15 | self.session.mount('http://', HTTPAdapter(max_retries=retries))
16 |
17 | def get(self, query_value, limit=20, mode="a", lang="en", expensive=0, info=0):
18 | query_args = {
19 | "q": query_value,
20 | "limit": limit,
21 | "m": mode,
22 | "lang": lang,
23 | "info": info,
24 | "expensive": expensive
25 | }
26 | start = time()
27 | responds = []
28 | if not query_value:
29 | return [], time() - start
30 | try:
31 | # tmp_responds = requests.get(self.URL, params=query_args)
32 | tmp_responds = self.session.get(self.URL, params=query_args)
33 | if tmp_responds.status_code == 200:
34 | tmp_responds = tmp_responds.json()
35 | if tmp_responds.get("hits"):
36 | if info:
37 | responds = [[r["id"], r["score"], r["label"], r["des"]] for r in tmp_responds["hits"]]
38 | else:
39 | responds = [[r["id"], r["score"]] for r in tmp_responds["hits"]]
40 | except Exception as message:
41 | print(f"\n{message}\n{str(query_args)}")
42 | run_time = time() - start
43 | return responds, run_time
44 |
45 |
46 | if __name__ == "__main__":
47 | mtab_es = MTabES()
48 | queries = [
49 | "Sweden",
50 | "TV-Browser",
51 | "hideaki takeda",
52 | "HIdeki Tedaka",
53 | "2MASS J10540655-0031018",
54 | "Tokyo",
55 | "武田英明",
56 | "Град Скопјее",
57 | "Préfecture de Kanagawa",
58 | "Paulys Realenzyklopädie der klassischen Altertumswissenschaft",
59 | "La gran bretaña",
60 | "제주 유나이티드 FC",
61 | "অ্যাটলেটিকো ডি কলকাতা",
62 | "Nguyễn Ái Quốc",
63 | "ホー・チ・ミン",
64 | ]
65 | modes = ["a"] # "a", "b", "f"
66 | lang_opts = ["en"] # "en", "all"
67 | expensive_opts = [0] # 0, 1
68 | info = 1 # get entity information
69 | for query in queries:
70 | for mode in modes:
71 | for lang in lang_opts:
72 | for expensive in expensive_opts:
73 | responds, run_time = mtab_es.get(query, limit=20, mode=mode, lang=lang, expensive=expensive, info=info)
74 | print(f"\n[{lang}|{mode}|{expensive}] About {len(responds)} results in {run_time:.4f} seconds | {query}")
75 |
76 | if info:
77 | for i, (r, s, l, d) in enumerate(responds[:3]):
78 | print(f"{i + 1:2}. {s:.4f} - {r}[{l}] - {d}")
79 | else:
80 | for i, (r, s) in enumerate(responds[:3]):
81 | print(f"{i+1:2}. {s:.4f} - {r}[]")
82 |
83 |
84 | # Responds
85 | # [en|a|0] About 20 results in 0.3921 seconds | Sweden
86 | # 1. 0.2856 - Q34[Sweden] - sovereign state in northern Europe
87 | # 2. 0.2831 - Q424644[Sweden] - Wikimedia disambiguation page
88 | # 3. 0.2830 - Q37437749[Sweden] - family name
89 | #
90 | # [en|a|0] About 20 results in 0.1395 seconds | TV-Browser
91 | # 1. 0.5289 - Q1715028[TV-Browser] - electronic program guide (tv, radio)
92 | # 2. 0.1183 - Q399128[Browser] - Wikimedia disambiguation page
93 | # 3. 0.1183 - Q11334456[Browser] - None
94 | #
95 | # [en|a|0] About 20 results in 0.0937 seconds | hideaki takeda
96 | # 1. 0.6209 - Q2330082[Hideaki Takeda] - Japanese association football player
97 | # 2. 0.6209 - Q57886243[Hideaki Takeda] - informatics researcher, National Institute of Informatics, Japan
98 | # 3. 0.1058 - Q15719495[Hideaki] - male given name
99 | #
100 | # [en|a|0] About 20 results in 0.0650 seconds | HIdeki Tedaka
101 | # 1. 0.4108 - Q4924099[Hideki Todaka] - Japanese boxer
102 | # 2. 0.2360 - Q5752358[Hideki] - male given name
103 | # 3. 0.2359 - Q52319792[Hideki] - Japanese mangaka
104 | #
105 | # [en|a|0] About 20 results in 0.2180 seconds | 2MASS J10540655-0031018
106 | # 1. 0.4934 - Q222120[2MASS J00540655-0031018] - brown dwarf
107 | # 2. 0.2285 - Q87130330[TYC 4151-458-1] - None
108 | # 3. 0.0419 - Q89756929[TYC 5033-427-1] - None
109 | #
110 | # [en|a|0] About 20 results in 0.2050 seconds | Tokyo
111 | # 1. 0.2843 - Q1490[Tokyo] - capital and most populous prefecture of Japan
112 | # 2. 0.2833 - Q396867[Tokyo] - Wikimedia disambiguation page
113 | # 3. 0.2833 - Q65120889[Tokyo] - None
114 | #
115 | # [en|a|0] About 20 results in 0.2326 seconds | 武田英明
116 | # 1. 0.3100 - Q2330082[Hideaki Takeda] - Japanese association football player
117 | # 2. 0.3100 - Q57886243[Hideaki Takeda] - informatics researcher, National Institute of Informatics, Japan
118 | # 3. 0.0857 - Q433473[Hideaki Yanagida] - Japanese sport wrestler
119 | #
120 | # [en|a|0] About 20 results in 0.1653 seconds | Град Скопјее
121 | # 1. 0.4790 - Q2575820[Greater Skopje] - administrative division within the Republic of Macedonia constituted of 10 municipalities
122 | # 2. 0.0783 - Q515[city] - large permanent human settlement
123 | # 3. 0.0775 - Q1500094[grad] - place name element meaning 'town'
124 | #
125 | # [en|a|0] About 14 results in 0.3231 seconds | Préfecture de Kanagawa
126 | # 1. 0.4818 - Q127513[Kanagawa Prefecture] - prefecture of Japan
127 | # 2. 0.1015 - Q161454[Kagawa Prefecture] - prefecture of Japan
128 | # 3. 0.0771 - Q22800853[Q22800853] - Wikimedia template
129 | #
130 | # [en|a|0] About 20 results in 0.1574 seconds | Paulys Realenzyklopädie der klassischen Altertumswissenschaft
131 | # 1. 0.4548 - Q1138524[Paulys Realenzyklopädie der klassischen Altertumswissenschaft] - extensive and comprehensive German encyclopedia of classical scholarship
132 | # 2. 0.0009 - Q19250471[Mesembria (Pauly-Wissowa)] - cross-reference in Paulys Realencyclopädie der classischen Altertumswissenschaft (RE)
133 | # 3. 0.0005 - Q47459707[Paulys Realencyclopädie der classischen Altertumswissenschaft] - document published in 1997
134 | #
135 | # [en|a|0] About 19 results in 0.1409 seconds | La gran bretaña
136 | # 1. 0.5792 - Q2841[Bogota] - capital city of Colombia
137 | # 2. 0.0804 - Q145[United Kingdom] - country in Western Europe
138 | # 3. 0.0776 - Q23666[Great Britain] - island in the North Atlantic off the north-west coast of continental Europe
139 | #
140 | # [en|a|0] About 15 results in 0.1555 seconds | 제주 유나이티드 FC
141 | # 1. 0.4472 - Q482617[Jeju United FC] - football club in South Korea
142 | # 2. 0.0873 - Q12223270[Template:Jeju United FC] - Wikimedia template
143 | # 3. 0.0321 - Q8565398[Category:Jeju United FC] - Wikimedia category
144 | #
145 | # [en|a|0] About 20 results in 0.1284 seconds | অ্যাটলেটিকো ডি কলকাতা
146 | # 1. 0.5787 - Q16836329[ATK] - association football club
147 | # 2. 0.0771 - Q22003383[D.D Bhawalkar] - Indian Optical Physicist
148 | # 3. 0.0105 - Q14221200[North Kolkata] - Northern parts and some suburbs of the city of joy kolkata
149 | #
150 | # [en|a|0] About 20 results in 0.1098 seconds | Nguyễn Ái Quốc
151 | # 1. 0.4461 - Q36014[Ho Chi Minh] - Vietnamese communist leader and Chairman of the Workers' Party of Vietnam (1890-1969)
152 | # 2. 0.4455 - Q12901199[Q12901199] - None
153 | # 3. 0.4455 - Q10742909[Q10742909] - None
154 | #
155 | # [en|a|0] About 20 results in 0.0746 seconds | ホー・チ・ミン
156 | # 1. 0.4446 - Q36014[Ho Chi Minh] - Vietnamese communist leader and Chairman of the Workers' Party of Vietnam (1890-1969)
157 | # 2. 0.0967 - Q874234[Ho Chi Minh Mausoleum] - None
158 | # 3. 0.0771 - Q7410171[Category:Ho Chi Minh] - Wikimedia category
159 |
--------------------------------------------------------------------------------
/api/utilities/m_iw.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import fnmatch
3 | import os
4 | import pandas
5 | import numpy as np
6 | import petl as petl
7 |
8 |
9 | def create_dir(file_dir):
10 | """Create a directory
11 |
12 | Args:
13 | file_dir (str): file directory
14 | """
15 | folder_dir = os.path.dirname(file_dir)
16 | if not os.path.exists(folder_dir):
17 | os.makedirs(folder_dir)
18 |
19 |
20 | def load_object_csv(file_name, encoding="utf8"):
21 | content = []
22 | if os.path.exists(file_name):
23 | with open(file_name, "r", encoding=encoding, errors="ignore") as f:
24 | reader = csv.reader(f, delimiter=",")
25 | for r in reader:
26 | row_norm = []
27 | for c in r:
28 | row_norm.append(c)
29 | content.append(row_norm)
30 | return content
31 |
32 |
33 | def save_object_csv(file_name, rows):
34 | create_dir(file_name)
35 | temp_file = "%s.temp" % file_name
36 | with open(temp_file, "w") as f:
37 | try:
38 | writer = csv.writer(f, delimiter=",", quotechar='"', quoting=csv.QUOTE_ALL)
39 | for r in rows:
40 | if (
41 | isinstance(r, list)
42 | or isinstance(r, tuple)
43 | or isinstance(r, np.ndarray)
44 | ):
45 | writer.writerow(r)
46 | else:
47 | writer.writerow([r])
48 | except Exception as message:
49 | print(message)
50 | if os.path.exists(file_name):
51 | os.remove(file_name)
52 | os.rename(temp_file, file_name)
53 |
54 |
55 | def get_files_from_dir_subdir(folder_path, extension="*"):
56 | all_files = []
57 | for root, _, file_dirs in os.walk(folder_path):
58 | for file_dir in fnmatch.filter(file_dirs, "*.%s" % extension):
59 | if ".DS_Store" not in file_dir:
60 | all_files.append(os.path.join(root, file_dir))
61 | return all_files
62 |
63 |
64 | def get_files_from_dir(
65 | folder_path, extension="*", limit_reader=-1, is_sort=False, reverse=False
66 | ):
67 | all_file_dirs = get_files_from_dir_subdir(folder_path, extension)
68 |
69 | if is_sort:
70 | file_with_size = [(f, os.path.getsize(f)) for f in all_file_dirs]
71 | file_with_size.sort(key=lambda f: f[1], reverse=reverse)
72 | all_file_dirs = [f for f, _ in file_with_size]
73 | if limit_reader < 0:
74 |
75 | limit_reader = len(all_file_dirs)
76 | return all_file_dirs[:limit_reader]
77 |
78 |
79 | def get_encoding(source, method="charamel"):
80 | result = "utf-8"
81 | if os.path.isfile(source):
82 | with open(source, "rb") as file_open:
83 | # Read all content --> make sure about the file encoding
84 | file_content = file_open.read()
85 |
86 | # predict encoding
87 | if method == "charamel":
88 | try:
89 | import charamel
90 |
91 | charamel.Detector()
92 | encoding_detector = charamel.Detector()
93 | detector = encoding_detector.detect(file_content)
94 | if detector:
95 | result = detector.value
96 | except Exception as message:
97 | print(message)
98 | pass
99 | else:
100 | detector = chardet.detect(file_content)
101 | if detector["encoding"]:
102 | result = detector["encoding"]
103 | return result
104 |
105 |
106 | def load_table(dir_table):
107 | def parse_xml_table(source):
108 | tables_xml = pandas.read_html(source)
109 | if tables_xml:
110 | return [tables_xml[0].columns.values.tolist()] + tables_xml[
111 | 0
112 | ].values.tolist()
113 | else:
114 | return None
115 |
116 | table_obj = None
117 | encoding = get_encoding(dir_table)
118 | file_ext = os.path.splitext(dir_table)[1][1:]
119 | if file_ext == "csv":
120 | table_obj = load_object_csv(dir_table, encoding=encoding)
121 | elif file_ext == "tsv":
122 | table_obj = petl.fromtsv(dir_table, encoding=encoding)
123 | elif file_ext == "txt":
124 | table_obj = petl.fromtext(dir_table, encoding=encoding)
125 | elif file_ext == "xls":
126 | table_obj = petl.fromxls(dir_table, encoding=encoding)
127 | elif file_ext in ["xlsm", "xlsb", "xltx", "xlsx", "xlt", "xltm"]:
128 | table_obj = petl.fromxlsx(dir_table)
129 | elif file_ext == "xml":
130 | table_obj = parse_xml_table(dir_table)
131 | cells = []
132 | if table_obj:
133 | for row in table_obj:
134 | row_norm = []
135 | for col in row:
136 | tmp_cell = str(col)
137 | # tmp_cell = ul.norm_text(str(col), punctuations=True, lower=False)
138 | # tmp_date = ul.get_date(tmp_cell)
139 | # if tmp_date:
140 | # tmp_cell = tmp_date
141 | row_norm.append(tmp_cell)
142 | if row_norm:
143 | # row = ftfy.fix_text(row)
144 | cells.append(row_norm)
145 |
146 | return cells
147 |
--------------------------------------------------------------------------------
/data/semtab/0A2WQW7B.csv:
--------------------------------------------------------------------------------
1 | col0,col1,col2
2 | We've#the Zenith Toyer A,300.29999999999995,21.042
3 | Ritz-Carltoo Toronto,209.5902,18.981
4 | Yingli ower,285.85499999999996,20.019999999999996
5 | Ccnterra Tower,175.761,17.91
6 | Nauru Hose,191.9,19.88
7 | Heast Tower,182.546,21.020999999999997
8 | Mlami Tower,192.91,19.038
9 | Torse Cepsa,250.0381,19.0
10 | Dltus Skyscraer,125.62499999999999,18.036
11 | Seat of he European Central Bank,184.075,18.162
12 |
--------------------------------------------------------------------------------
/data/semtab/2T_10.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/data/semtab/2T_10.zip
--------------------------------------------------------------------------------
/data/semtab/atable.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/data/semtab/atable.zip
--------------------------------------------------------------------------------
/data/semtab/atable_2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/data/semtab/atable_2.zip
--------------------------------------------------------------------------------
/data/semtab/atable_3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/data/semtab/atable_3.zip
--------------------------------------------------------------------------------
/data/semtab/mytables.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/data/semtab/mytables.zip
--------------------------------------------------------------------------------
/data/semtab/tables.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/data/semtab/tables.zip
--------------------------------------------------------------------------------
/docs/mtab.md:
--------------------------------------------------------------------------------
1 | MTab: Tabular Data Annotation
2 | ===========
3 | ---
4 |
5 | ### News:
6 | - To be expected: Data analysis, and QA for table data.
7 | - 2021/06/04 - Address the run time error of big table annotation. Solution: only process 1000 cells of tables as the default setting. However, you can adjust the parameter "limit" as your need by adding "?limit=1000" of the API. We also set the timeout limit of our API up to 3 days.
8 | - 2021/02/23 - API is online at https://mtab.app. This API is optimized and running on Mac mini M1.
9 |
10 | ### Features:
11 | - Semantic Annotation with knowledge graphs: Wikidata, Wikipedia, DBpedia
12 | - Annotate table cells with entities
13 | - Annotate table attributes (columns) with entity types, or classes. Currently, the tool supports table attributes as table columns.
14 | - Annotate the relation between table attributes (columns) with properties (relations, or predicates).
15 | - Structure Annotation:
16 | - Table type prediction: matrix, relational, layout (under development)
17 | - Header detection
18 | - Core attribute (subject column, or primary key) detection
19 | - basic stats including number of rows, columns, cells.
20 | - data types (under development)
21 | - languages (under development)
22 | - Good for table interpretation, data integration, and knowledge discovery.
23 |
24 | ### Interface:
25 | https://mtab.app/mtab
26 |
27 | ### API URL:
28 | https://mtab.app/api/v1/mtab
29 |
30 | ### Usage:
31 | Users can send table files (in CSV, Excel, TSV format) to the tool and get the annotations.
32 |
33 | **Note: We do not keep your data. After processing your tables, we will delete your data immediately.**
34 |
35 | - Due to the efficiency issue, the API will do annotation only the first 1000 rows of the input table.However, you can adjust the API parameter as “limit=1000”. Maybe you can change it to 1 million if you have 1 million rows in your table, but it will take more time to do annotation. For example:
36 | ```bash
37 | % curl -X POST -F file=@"YOUR_FILE_LOCATION/YOUR_TABLE.xltx" https://mtab.app/api/v1/mtab?limit=1000000
38 | ```
39 |
40 |
41 | ### Annotate a table:
42 | Annotate a table in the Excel format [0AJSJYAL.xltx](https://github.com/phucty/mtab_tool/blob/master/static/others/0AJSJYAL.xltx)
43 |
44 | ```bash
45 | % curl -X POST -F file=@"YOUR_FILE_LOCATION/0AJSJYAL.xltx" https://mtab.app/api/v1/mtab
46 | ```
47 |
48 | Expected Answer:
49 | ```json
50 | {
51 | "n_tables": 1,
52 | "status": "Success",
53 | "tables": [
54 | {
55 | "name": "0AJSJYAL",
56 | "run_time": 0.8414499759674072,
57 | "semantic": {
58 | "cea": [
59 | {
60 | "annotation": {
61 | "dbpedia": "http://dbpedia.org/resource/Newport,_Arkansas",
62 | "desc": "city in Arkansas, USA",
63 | "label": "Newport",
64 | "wikidata": "http://www.wikidata.org/entity/Q79414",
65 | "wikipedia": "http://en.wikipedia.org/wiki/Newport,_Arkansas"
66 | },
67 | "target": [
68 | 1,
69 | 0
70 | ]
71 | },
72 | {
73 | "annotation": {
74 | "dbpedia": "http://dbpedia.org/resource/Thomas_(2001_film)",
75 | "desc": "2001 film by Raffaele Mertes",
76 | "label": "Thomas",
77 | "wikidata": "http://www.wikidata.org/entity/Q2421872",
78 | "wikipedia": "http://en.wikipedia.org/wiki/Thomas_(2001_film)"
79 | },
80 | "target": [
81 | 2,
82 | 0
83 | ]
84 | },
85 | {
86 | "annotation": {
87 | "dbpedia": "http://dbpedia.org/resource/8082_Haynes",
88 | "desc": "asteroid",
89 | "label": "8082 Haynes",
90 | "wikidata": "http://www.wikidata.org/entity/Q533244",
91 | "wikipedia": "http://en.wikipedia.org/wiki/8082_Haynes"
92 | },
93 | "target": [
94 | 3,
95 | 0
96 | ]
97 | },
98 | {
99 | "annotation": {
100 | "desc": "family name",
101 | "label": "Lampitt",
102 | "wikidata": "http://www.wikidata.org/entity/Q37468695"
103 | },
104 | "target": [
105 | 4,
106 | 0
107 | ]
108 | },
109 | {
110 | "annotation": {
111 | "dbpedia": "http://dbpedia.org/resource/Solanki",
112 | "desc": "family name",
113 | "label": "Solanki",
114 | "wikidata": "http://www.wikidata.org/entity/Q37521226",
115 | "wikipedia": "http://en.wikipedia.org/wiki/Solanki"
116 | },
117 | "target": [
118 | 5,
119 | 0
120 | ]
121 | },
122 | {
123 | "annotation": {
124 | "dbpedia": "http://dbpedia.org/resource/Weston,_Colorado",
125 | "desc": "unincorporated community in Colorado",
126 | "label": "Weston",
127 | "wikidata": "http://www.wikidata.org/entity/Q7989353",
128 | "wikipedia": "http://en.wikipedia.org/wiki/Weston,_Colorado"
129 | },
130 | "target": [
131 | 6,
132 | 0
133 | ]
134 | }
135 | ],
136 | "cpa": [],
137 | "cta": [
138 | {
139 | "annotation": [
140 | {
141 | "dbpedia": "http://dbpedia.org/resource/Human_settlement",
142 | "desc": "community of any size, in which people live",
143 | "label": "human settlement",
144 | "wikidata": "http://www.wikidata.org/entity/Q486972",
145 | "wikipedia": "http://en.wikipedia.org/wiki/Human_settlement"
146 | },
147 | {
148 | "dbpedia": "http://dbpedia.org/resource/Surname",
149 | "desc": "part of a naming scheme for individuals, used in many cultures worldwide",
150 | "label": "family name",
151 | "wikidata": "http://www.wikidata.org/entity/Q101352",
152 | "wikipedia": "http://en.wikipedia.org/wiki/Surname"
153 | }
154 | ],
155 | "target": 0
156 | }
157 | ]
158 | },
159 | "status": "Success",
160 | "structure": {
161 | "cells": 37,
162 | "columns": 7,
163 | "core_attribute": 0,
164 | "encoding": "utf-8",
165 | "headers": [
166 | 0
167 | ],
168 | "r_cells": 0.7551020408163265,
169 | "rows": 7,
170 | "table type": "vertical relation"
171 | },
172 | "table_cells": [
173 | [
174 | "col0",
175 | "col1",
176 | "col2",
177 | "col3",
178 | "col4",
179 | "col5",
180 | "col6"
181 | ],
182 | [
183 | "Newport",
184 | "31",
185 | "8",
186 | "95",
187 | "2",
188 | "-",
189 | "-"
190 | ],
191 | [
192 | "Thomas",
193 | "30",
194 | "5",
195 | "98",
196 | "2",
197 | "-",
198 | "-"
199 | ],
200 | [
201 | "Haynes",
202 | "25",
203 | "8",
204 | "68",
205 | "2",
206 | "-",
207 | "-"
208 | ],
209 | [
210 | "Lampitt",
211 | "29.4",
212 | "10",
213 | "73",
214 | "3",
215 | "-",
216 | "-"
217 | ],
218 | [
219 | "Solanki",
220 | "19",
221 | "4",
222 | "76",
223 | "1",
224 | "-",
225 | "-"
226 | ],
227 | [
228 | "Weston",
229 | "1",
230 | "0",
231 | "1",
232 | "0",
233 | "-",
234 | "-"
235 | ]
236 | ]
237 | }
238 | ]
239 | }
240 | ```
241 |
242 |
243 | ### Annotate multiple tables:
244 | Note:
245 | - Please do not send more than 100 tables for one request to avoid data transmission corruption. (We only process 100 tables per request).
246 | - Please put your tables in a folder named tables and compress like this file [mytables.zip](https://github.com/phucty/mtab_tool/blob/master/static/others/mytables.zip). (We only accept a compressed file in zip format to speed up data transmission)
247 | ```
248 | mytable.zip
249 | |-- tables (folder)
250 | | |--table_1.csv
251 | | |--table_2.csv
252 | | |--...
253 | ```
254 | **Command:**
255 | ```bash
256 | % curl -X POST -F file=@"YOUR_FILE_LOCATION/mytables.zip" https://mtab.app/api/v1/mtab
257 | ```
258 |
259 | **Expected Answer:**
260 | Refer to the [mytables.json](https://github.com/phucty/mtab_tool/blob/master/static/others/mytables.json) as the full answers
261 |
262 |
263 | ### Annotate multiple tables with targets (CEA, CTA, and CPA as [SemTab challenge](https://www.cs.ox.ac.uk/isg/challenges/sem-tab/)):
264 | Note:
265 | The format of the compressed file like [mytables_ntar.zip](https://github.com/phucty/mtab_tool/blob/master/static/others/mytables_ntar.zip).
266 | ```
267 | mytable_ntar.zip
268 | |-- tables (folder)
269 | | |--table_1.csv
270 | | |--table_2.csv
271 | | |--...
272 | |-- cea.csv (Cell annotation targets in the format of [table ID, row index, column index])
273 | |-- cta.csv (Column annotation targets in the format of [table ID, column index])
274 | |-- cpa.csv (The relation between two columns in the format of [table ID, column 1, column 2]
275 | ```
276 |
277 | **Command:**
278 | ```bash
279 | % curl -X POST -F file=@"YOUR_ZIP_FILE_LOCATION/mytables_ntar.zip" https://mtab.app/api/v1/mtab
280 | ```
281 | **Expected Answer:**
282 |
283 | Refer to the [mytables_ntar.json](https://github.com/phucty/mtab_tool/blob/master/static/others/mytables_ntar.json) as the full answers
284 |
285 | ### Other Examples:
286 | #### Table Annotation
287 |
288 |
289 | #### Data correction:
290 | Input: Tabular data
291 |
292 | | col0 | col1 | col2 | col3 |
293 | |-------------------------|----------|------------|------------|
294 | | 2MASS J10540655-0031018 | -5.7 | 19.3716366 | 13.6356351 |
295 | | 2MASS J0464841+0715177 | -2.77475 | 26.671236 | 11.8187551 |
296 | | 2MAS J08351104+2006371 | 72.216 | 3.7242888 | 128.151961 |
297 | | 2MASS J08330994+186328 | -6.993 | 6.0962562 | 127.649963 |
298 |
299 | Output:
300 |
301 | | [star](http://www.wikidata.org/entity/Q523) | [radial velocity](http://www.wikidata.org/prop/direct/P2216) | [parallax](http://www.wikidata.org/prop/direct/P2214) | [right ascension](http://www.wikidata.org/prop/direct/P6257) |
302 | |-------------------------|-----------------|----------|--------------------|
303 | | [2MASS J00540655-0031018](http://www.wikidata.org/entity/Q222120) | -5.70 | 19.2561 | 13.52741580209200 |
304 | | [2MASS J00464841+0715177](http://www.wikidata.org/entity/Q222110) | -2.75 | 26.6180 | 11.70173767885790 |
305 | | [2MASS J08351104+2006371](http://www.wikidata.org/entity/Q78611172) | 72 | 3.6984 | 128.79594070217040 |
306 | | [2MASS J08330994+1806328](http://www.wikidata.org/entity/Q78610810) | -7 | 6.1146 | 128.29142004157090 |
--------------------------------------------------------------------------------
/docs/mtabes.md:
--------------------------------------------------------------------------------
1 | MTabES: Entity Search
2 | ===========
3 | ---
4 |
5 | ### Features:
6 | - The indexed database (entity labels) is a combination of the three Knowledge Graphs: Wikidata, Wikipedia, and DBpedia, including entity labels, aliases, other names, redirect entity labels, and disambiguation entities. There are 249,388,985 labels, 91,216,260 entities at 2021/01/01.
7 | - Multilingual support.
8 | - Work well with noisy text such as misspelling or abbreviation
9 | - Can be used for the tasks of entity search or entity-based OCR post-processing.
10 |
11 |
12 | ### Interface:
13 | https://mtab.app/mtabes
14 |
15 | ### API URL:
16 | https://mtab.app/api/v1/search
17 |
18 | ### Parameter:
19 | - q: search query. This parameter is required.
20 | - limit: maximum number of relevant entities to return. The value should be from 1 to 1000. The default value is 20.
21 | - m: one of three value [b, f, a]. The default value is a.
22 | - b: keywords search with BM25 (hyper-parameters: b=0.75, k1=1.2).
23 | - f: fuzzy search with an edit-distance (Damerau–Levenshtein distance).
24 | - a: the weighted aggregation of keyword search and fuzzy search. This model yields slightly better performance (1-3 % accuracy improvement) than fuzzy search.
25 |
26 | - info: one of two value [0, 1]. The default value is 0.
27 | - 0: do not return entity labels, description, mapping URLs of DBpedia and Wikipedia.
28 | - 1: return entity labels, description, mapping URLs of DBpedia and Wikipedia.
29 | - expensive: one of two value [0, 1]. The default value is 0.
30 | - 0: efficiency mode. Perform early stopping in the fuzzy search.
31 | - 1: Brute-force search. This mode could slightly improve search performance (improve 1-2% accuracy), but it might take a long time to get answers (about ten times longer than the efficiency mode).
32 | ### Examples:
33 | Searching a query of "2MASS J10540655-0031018".
34 |
35 | Note that: At 2021/01/01, we could not get any answer by using the standard lookup (Wikidata, Wikipedia, DBpedia, or Google Search)
36 |
37 | **Command:**
38 | ```bash
39 | % curl -X GET "https://mtab.app/api/v1/search?limit=3&m=a&info=1&q=2MASS%20J10540655-0031018"
40 | ```
41 | Expected Answer:
42 | ```json
43 | {
44 | "hits": [
45 | {
46 | "des": "brown dwarf",
47 | "id": "Q222120",
48 | "label": "2MASS J00540655-0031018",
49 | "score": 0.39831033397179416,
50 | "wd": "http://www.wikidata.org/entity/Q222120"
51 | },
52 | {
53 | "des": null,
54 | "id": "Q87130330",
55 | "label": "TYC 4151-458-1",
56 | "score": 0.23949881593395422,
57 | "wd": "http://www.wikidata.org/entity/Q87130330"
58 | },
59 | {
60 | "des": null,
61 | "id": "Q89756929",
62 | "label": "TYC 5033-427-1",
63 | "score": 0.043365759204671825,
64 | "wd": "http://www.wikidata.org/entity/Q89756929"
65 | }
66 | ],
67 | "run_time": 1.1118018627166748,
68 | "status": "Success",
69 | "total": "3"
70 | }
71 | ```
72 | **MTabES Benchmarking:**
73 |
74 | - SemTab 2020 Round 1
75 |
76 |
77 |
78 | [comment]: <> ()
79 | - SemTab 2020 Round 2
80 |
81 |
82 |
83 | [comment]: <> ()
84 | - SemTab 2020 Round 3
85 |
86 |
87 |
88 | [comment]: <> ()
89 | - SemTab 2020 Round 4
90 |
91 |
92 |
93 | [comment]: <> ()
94 | - Tough Tables
95 |
96 |
97 |
98 | [comment]: <> ()
--------------------------------------------------------------------------------
/interface/static/images/MTabESSemTab2T.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/MTabESSemTab2T.png
--------------------------------------------------------------------------------
/interface/static/images/MTabESSemTabR1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/MTabESSemTabR1.png
--------------------------------------------------------------------------------
/interface/static/images/MTabESSemTabR2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/MTabESSemTabR2.png
--------------------------------------------------------------------------------
/interface/static/images/MTabESSemTabR3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/MTabESSemTabR3.png
--------------------------------------------------------------------------------
/interface/static/images/MTabESSemTabR4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/MTabESSemTabR4.png
--------------------------------------------------------------------------------
/interface/static/images/logo_mtab_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/logo_mtab_1.png
--------------------------------------------------------------------------------
/interface/static/images/logo_mtab_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/logo_mtab_2.png
--------------------------------------------------------------------------------
/interface/static/images/logo_mtab_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/logo_mtab_3.png
--------------------------------------------------------------------------------
/interface/static/images/logo_mtab_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/logo_mtab_4.png
--------------------------------------------------------------------------------
/interface/static/images/mtab_pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/images/mtab_pic.png
--------------------------------------------------------------------------------
/interface/static/others/mytables.json:
--------------------------------------------------------------------------------
1 | {
2 | "n_tables": 2,
3 | "status": "Success",
4 | "tables": [
5 | {
6 | "file_name": "0CF12YZK.csv",
7 | "run_time": 28.576568126678467,
8 | "semantic": {
9 | "cea": [
10 | {
11 | "annotation": {
12 | "dbpedia": "http://dbpedia.org/resource/Price,_Utah",
13 | "wikidata": "http://www.wikidata.org/entity/Q482891",
14 | "wikipedia": "http://en.wikipedia.org/wiki/Price,_Utah"
15 | },
16 | "target": [
17 | 1,
18 | 0
19 | ]
20 | },
21 | {
22 | "annotation": {
23 | "dbpedia": "http://dbpedia.org/resource/Amguid_crater",
24 | "wikidata": "http://www.wikidata.org/entity/Q248727",
25 | "wikipedia": "http://en.wikipedia.org/wiki/Amguid_crater"
26 | },
27 | "target": [
28 | 2,
29 | 0
30 | ]
31 | },
32 | {
33 | "annotation": {
34 | "dbpedia": "http://dbpedia.org/resource/Zucchius_(crater)",
35 | "wikidata": "http://www.wikidata.org/entity/Q227650",
36 | "wikipedia": "http://en.wikipedia.org/wiki/Zucchius_(crater)"
37 | },
38 | "target": [
39 | 3,
40 | 0
41 | ]
42 | },
43 | {
44 | "annotation": {
45 | "dbpedia": "http://dbpedia.org/resource/Capella",
46 | "wikidata": "http://www.wikidata.org/entity/Q12970",
47 | "wikipedia": "http://en.wikipedia.org/wiki/Capella"
48 | },
49 | "target": [
50 | 4,
51 | 0
52 | ]
53 | },
54 | {
55 | "annotation": {
56 | "dbpedia": "http://dbpedia.org/resource/Gaudibert_(crater)",
57 | "wikidata": "http://www.wikidata.org/entity/Q211287",
58 | "wikipedia": "http://en.wikipedia.org/wiki/Gaudibert_(crater)"
59 | },
60 | "target": [
61 | 5,
62 | 0
63 | ]
64 | },
65 | {
66 | "annotation": {
67 | "dbpedia": "http://dbpedia.org/resource/Thales_(crater)",
68 | "wikidata": "http://www.wikidata.org/entity/Q201509",
69 | "wikipedia": "http://en.wikipedia.org/wiki/Thales_(crater)"
70 | },
71 | "target": [
72 | 6,
73 | 0
74 | ]
75 | },
76 | {
77 | "annotation": {
78 | "wikidata": "http://www.wikidata.org/entity/Q697934"
79 | },
80 | "target": [
81 | 7,
82 | 0
83 | ]
84 | },
85 | {
86 | "annotation": {
87 | "dbpedia": "http://dbpedia.org/resource/Lagrange_(crater)",
88 | "wikidata": "http://www.wikidata.org/entity/Q195032",
89 | "wikipedia": "http://en.wikipedia.org/wiki/Lagrange_(crater)"
90 | },
91 | "target": [
92 | 8,
93 | 0
94 | ]
95 | },
96 | {
97 | "annotation": {
98 | "dbpedia": "http://dbpedia.org/resource/Regiomontanus_(crater)",
99 | "wikidata": "http://www.wikidata.org/entity/Q175368",
100 | "wikipedia": "http://en.wikipedia.org/wiki/Regiomontanus_(crater)"
101 | },
102 | "target": [
103 | 9,
104 | 0
105 | ]
106 | },
107 | {
108 | "annotation": {
109 | "dbpedia": "http://dbpedia.org/resource/De_Gasparis_(crater)",
110 | "wikidata": "http://www.wikidata.org/entity/Q168113",
111 | "wikipedia": "http://en.wikipedia.org/wiki/De_Gasparis_(crater)"
112 | },
113 | "target": [
114 | 10,
115 | 0
116 | ]
117 | },
118 | {
119 | "annotation": {
120 | "dbpedia": "http://dbpedia.org/resource/Adams_(lunar_crater)",
121 | "wikidata": "http://www.wikidata.org/entity/Q166188",
122 | "wikipedia": "http://en.wikipedia.org/wiki/Adams_(lunar_crater)"
123 | },
124 | "target": [
125 | 11,
126 | 0
127 | ]
128 | },
129 | {
130 | "annotation": {
131 | "dbpedia": "http://dbpedia.org/resource/Gardnos_crater",
132 | "wikidata": "http://www.wikidata.org/entity/Q164971",
133 | "wikipedia": "http://en.wikipedia.org/wiki/Gardnos_crater"
134 | },
135 | "target": [
136 | 12,
137 | 0
138 | ]
139 | },
140 | {
141 | "annotation": {
142 | "dbpedia": "http://dbpedia.org/resource/Diophantus_(crater)",
143 | "wikidata": "http://www.wikidata.org/entity/Q164095",
144 | "wikipedia": "http://en.wikipedia.org/wiki/Diophantus_(crater)"
145 | },
146 | "target": [
147 | 13,
148 | 0
149 | ]
150 | },
151 | {
152 | "annotation": {
153 | "dbpedia": "http://dbpedia.org/resource/Agrippa_(crater)",
154 | "wikidata": "http://www.wikidata.org/entity/Q153150",
155 | "wikipedia": "http://en.wikipedia.org/wiki/Agrippa_(crater)"
156 | },
157 | "target": [
158 | 14,
159 | 0
160 | ]
161 | },
162 | {
163 | "annotation": {
164 | "dbpedia": "http://dbpedia.org/resource/Agatharchides_(crater)",
165 | "wikidata": "http://www.wikidata.org/entity/Q153140",
166 | "wikipedia": "http://en.wikipedia.org/wiki/Agatharchides_(crater)"
167 | },
168 | "target": [
169 | 15,
170 | 0
171 | ]
172 | },
173 | {
174 | "annotation": {
175 | "dbpedia": "http://dbpedia.org/resource/Cavendish_(crater)",
176 | "wikidata": "http://www.wikidata.org/entity/Q143729",
177 | "wikipedia": "http://en.wikipedia.org/wiki/Cavendish_(crater)"
178 | },
179 | "target": [
180 | 16,
181 | 0
182 | ]
183 | },
184 | {
185 | "annotation": {
186 | "dbpedia": "http://dbpedia.org/resource/Mersenius_(crater)",
187 | "wikidata": "http://www.wikidata.org/entity/Q143365",
188 | "wikipedia": "http://en.wikipedia.org/wiki/Mersenius_(crater)"
189 | },
190 | "target": [
191 | 17,
192 | 0
193 | ]
194 | },
195 | {
196 | "annotation": {
197 | "dbpedia": "http://dbpedia.org/resource/Zagut_(crater)",
198 | "wikidata": "http://www.wikidata.org/entity/Q140418",
199 | "wikipedia": "http://en.wikipedia.org/wiki/Zagut_(crater)"
200 | },
201 | "target": [
202 | 18,
203 | 0
204 | ]
205 | },
206 | {
207 | "annotation": {
208 | "dbpedia": "http://dbpedia.org/resource/Hausen_(crater)",
209 | "wikidata": "http://www.wikidata.org/entity/Q134149",
210 | "wikipedia": "http://en.wikipedia.org/wiki/Hausen_(crater)"
211 | },
212 | "target": [
213 | 19,
214 | 0
215 | ]
216 | },
217 | {
218 | "annotation": {
219 | "dbpedia": "http://dbpedia.org/resource/Abulfeda_(crater)",
220 | "wikidata": "http://www.wikidata.org/entity/Q133615",
221 | "wikipedia": "http://en.wikipedia.org/wiki/Abulfeda_(crater)"
222 | },
223 | "target": [
224 | 20,
225 | 0
226 | ]
227 | },
228 | {
229 | "annotation": {
230 | "wikidata": "http://www.wikidata.org/entity/Q22239279"
231 | },
232 | "target": [
233 | 21,
234 | 0
235 | ]
236 | },
237 | {
238 | "annotation": {
239 | "dbpedia": "http://dbpedia.org/resource/Anděl_(crater)",
240 | "wikidata": "http://www.wikidata.org/entity/Q130049",
241 | "wikipedia": "http://en.wikipedia.org/wiki/Anděl_(crater)"
242 | },
243 | "target": [
244 | 22,
245 | 0
246 | ]
247 | },
248 | {
249 | "annotation": {
250 | "dbpedia": "http://dbpedia.org/resource/Aristoteles_(crater)",
251 | "wikidata": "http://www.wikidata.org/entity/Q128108",
252 | "wikipedia": "http://en.wikipedia.org/wiki/Aristoteles_(crater)"
253 | },
254 | "target": [
255 | 23,
256 | 0
257 | ]
258 | },
259 | {
260 | "annotation": {
261 | "dbpedia": "http://dbpedia.org/resource/Aristillus_(crater)",
262 | "wikidata": "http://www.wikidata.org/entity/Q128041",
263 | "wikipedia": "http://en.wikipedia.org/wiki/Aristillus_(crater)"
264 | },
265 | "target": [
266 | 24,
267 | 0
268 | ]
269 | },
270 | {
271 | "annotation": {
272 | "dbpedia": "http://dbpedia.org/resource/Harpalus_(crater)",
273 | "wikidata": "http://www.wikidata.org/entity/Q128035",
274 | "wikipedia": "http://en.wikipedia.org/wiki/Harpalus_(crater)"
275 | },
276 | "target": [
277 | 25,
278 | 0
279 | ]
280 | },
281 | {
282 | "annotation": {
283 | "dbpedia": "http://dbpedia.org/resource/Eudoxus_(lunar_crater)",
284 | "wikidata": "http://www.wikidata.org/entity/Q128013",
285 | "wikipedia": "http://en.wikipedia.org/wiki/Eudoxus_(lunar_crater)"
286 | },
287 | "target": [
288 | 26,
289 | 0
290 | ]
291 | },
292 | {
293 | "annotation": {
294 | "dbpedia": "http://dbpedia.org/resource/Laroin",
295 | "wikidata": "http://www.wikidata.org/entity/Q198121",
296 | "wikipedia": "http://en.wikipedia.org/wiki/Laroin"
297 | },
298 | "target": [
299 | 27,
300 | 0
301 | ]
302 | },
303 | {
304 | "annotation": {
305 | "dbpedia": "http://dbpedia.org/resource/Philolaus_(crater)",
306 | "wikidata": "http://www.wikidata.org/entity/Q116169",
307 | "wikipedia": "http://en.wikipedia.org/wiki/Philolaus_(crater)"
308 | },
309 | "target": [
310 | 28,
311 | 0
312 | ]
313 | },
314 | {
315 | "annotation": {
316 | "dbpedia": "http://dbpedia.org/resource/Mouche",
317 | "wikidata": "http://www.wikidata.org/entity/Q18411720",
318 | "wikipedia": "http://en.wikipedia.org/wiki/Mouche"
319 | },
320 | "target": [
321 | 29,
322 | 0
323 | ]
324 | },
325 | {
326 | "annotation": {
327 | "dbpedia": "http://dbpedia.org/resource/Pascal_(crater)",
328 | "wikidata": "http://www.wikidata.org/entity/Q115739",
329 | "wikipedia": "http://en.wikipedia.org/wiki/Pascal_(crater)"
330 | },
331 | "target": [
332 | 30,
333 | 0
334 | ]
335 | },
336 | {
337 | "annotation": {
338 | "dbpedia": "http://dbpedia.org/resource/Plato_(crater)",
339 | "wikidata": "http://www.wikidata.org/entity/Q115383",
340 | "wikipedia": "http://en.wikipedia.org/wiki/Plato_(crater)"
341 | },
342 | "target": [
343 | 31,
344 | 0
345 | ]
346 | },
347 | {
348 | "annotation": {
349 | "dbpedia": "http://dbpedia.org/resource/Abel_(disambiguation)",
350 | "wikidata": "http://www.wikidata.org/entity/Q224167",
351 | "wikipedia": "http://en.wikipedia.org/wiki/Abel_(disambiguation)"
352 | },
353 | "target": [
354 | 32,
355 | 0
356 | ]
357 | },
358 | {
359 | "annotation": {
360 | "dbpedia": "http://dbpedia.org/resource/Abul_Wafa_(crater)",
361 | "wikidata": "http://www.wikidata.org/entity/Q115062",
362 | "wikipedia": "http://en.wikipedia.org/wiki/Abul_Wafa_(crater)"
363 | },
364 | "target": [
365 | 33,
366 | 0
367 | ]
368 | },
369 | {
370 | "annotation": {
371 | "dbpedia": "http://dbpedia.org/resource/Saussure_(crater)",
372 | "wikidata": "http://www.wikidata.org/entity/Q74583",
373 | "wikipedia": "http://en.wikipedia.org/wiki/Saussure_(crater)"
374 | },
375 | "target": [
376 | 34,
377 | 0
378 | ]
379 | },
380 | {
381 | "annotation": {
382 | "dbpedia": "http://dbpedia.org/resource/Longomontanus_(crater)",
383 | "wikidata": "http://www.wikidata.org/entity/Q73533",
384 | "wikipedia": "http://en.wikipedia.org/wiki/Longomontanus_(crater)"
385 | },
386 | "target": [
387 | 35,
388 | 0
389 | ]
390 | },
391 | {
392 | "annotation": {
393 | "dbpedia": "http://dbpedia.org/resource/Orontius_(crater)",
394 | "wikidata": "http://www.wikidata.org/entity/Q64067",
395 | "wikipedia": "http://en.wikipedia.org/wiki/Orontius_(crater)"
396 | },
397 | "target": [
398 | 36,
399 | 0
400 | ]
401 | },
402 | {
403 | "annotation": {
404 | "dbpedia": "http://dbpedia.org/resource/Esclangon_(crater)",
405 | "wikidata": "http://www.wikidata.org/entity/Q63694",
406 | "wikipedia": "http://en.wikipedia.org/wiki/Esclangon_(crater)"
407 | },
408 | "target": [
409 | 37,
410 | 0
411 | ]
412 | },
413 | {
414 | "annotation": {
415 | "dbpedia": "http://dbpedia.org/resource/Kepler_(band)",
416 | "wikidata": "http://www.wikidata.org/entity/Q6393189",
417 | "wikipedia": "http://en.wikipedia.org/wiki/Kepler_(band)"
418 | },
419 | "target": [
420 | 38,
421 | 0
422 | ]
423 | },
424 | {
425 | "annotation": {
426 | "wikidata": "http://www.wikidata.org/entity/Q45550018"
427 | },
428 | "target": [
429 | 39,
430 | 0
431 | ]
432 | },
433 | {
434 | "annotation": {
435 | "dbpedia": "http://dbpedia.org/resource/Daguerre_(crater)",
436 | "wikidata": "http://www.wikidata.org/entity/Q1157392",
437 | "wikipedia": "http://en.wikipedia.org/wiki/Daguerre_(crater)"
438 | },
439 | "target": [
440 | 40,
441 | 0
442 | ]
443 | },
444 | {
445 | "annotation": {
446 | "wikidata": "http://www.wikidata.org/entity/Q1057579"
447 | },
448 | "target": [
449 | 41,
450 | 0
451 | ]
452 | },
453 | {
454 | "annotation": {
455 | "dbpedia": "http://dbpedia.org/resource/Cyrillus_(crater)",
456 | "wikidata": "http://www.wikidata.org/entity/Q1148824",
457 | "wikipedia": "http://en.wikipedia.org/wiki/Cyrillus_(crater)"
458 | },
459 | "target": [
460 | 42,
461 | 0
462 | ]
463 | },
464 | {
465 | "annotation": {
466 | "dbpedia": "http://dbpedia.org/resource/Curtius_(crater)",
467 | "wikidata": "http://www.wikidata.org/entity/Q1145827",
468 | "wikipedia": "http://en.wikipedia.org/wiki/Curtius_(crater)"
469 | },
470 | "target": [
471 | 43,
472 | 0
473 | ]
474 | },
475 | {
476 | "annotation": {
477 | "dbpedia": "http://dbpedia.org/resource/Crüger_(crater)",
478 | "wikidata": "http://www.wikidata.org/entity/Q1142589",
479 | "wikipedia": "http://en.wikipedia.org/wiki/Crüger_(crater)"
480 | },
481 | "target": [
482 | 44,
483 | 0
484 | ]
485 | }
486 | ],
487 | "cpa": [
488 | {
489 | "annotation": {
490 | "wikidata": "http://www.wikidata.org/prop/direct/P4511"
491 | },
492 | "target": [
493 | 0,
494 | 1
495 | ]
496 | },
497 | {
498 | "annotation": {
499 | "wikidata": "http://www.wikidata.org/prop/direct/P2386"
500 | },
501 | "target": [
502 | 0,
503 | 2
504 | ]
505 | }
506 | ],
507 | "cta": [
508 | {
509 | "annotation": {
510 | "dbpedia": "http://dbpedia.org/resource/Impact_crater",
511 | "wikidata": "http://www.wikidata.org/entity/Q55818",
512 | "wikipedia": "http://en.wikipedia.org/wiki/Impact_crater"
513 | },
514 | "target": 0
515 | }
516 | ]
517 | },
518 | "structure": {
519 | "columns": 3,
520 | "core_attribute": 0,
521 | "header": [
522 | 0
523 | ],
524 | "missing ratio": 0,
525 | "row": 45,
526 | "table type": "vertical relation"
527 | },
528 | "table_id": "0CF12YZK"
529 | },
530 | {
531 | "file_name": "K0PM5GMK.csv",
532 | "run_time": 17.138594150543213,
533 | "semantic": {
534 | "cea": [
535 | {
536 | "annotation": {
537 | "wikidata": "http://www.wikidata.org/entity/Q32094061"
538 | },
539 | "target": [
540 | 1,
541 | 0
542 | ]
543 | },
544 | {
545 | "annotation": {
546 | "wikidata": "http://www.wikidata.org/entity/Q244822"
547 | },
548 | "target": [
549 | 1,
550 | 1
551 | ]
552 | },
553 | {
554 | "annotation": {
555 | "dbpedia": "http://dbpedia.org/resource/Spain",
556 | "wikidata": "http://www.wikidata.org/entity/Q29",
557 | "wikipedia": "http://en.wikipedia.org/wiki/Spain"
558 | },
559 | "target": [
560 | 1,
561 | 2
562 | ]
563 | },
564 | {
565 | "annotation": {
566 | "wikidata": "http://www.wikidata.org/entity/Q30302686"
567 | },
568 | "target": [
569 | 1,
570 | 3
571 | ]
572 | },
573 | {
574 | "annotation": {
575 | "wikidata": "http://www.wikidata.org/entity/Q27966457"
576 | },
577 | "target": [
578 | 2,
579 | 0
580 | ]
581 | },
582 | {
583 | "annotation": {
584 | "dbpedia": "http://dbpedia.org/resource/Blue",
585 | "wikidata": "http://www.wikidata.org/entity/Q1088",
586 | "wikipedia": "http://en.wikipedia.org/wiki/Blue"
587 | },
588 | "target": [
589 | 2,
590 | 1
591 | ]
592 | },
593 | {
594 | "annotation": {
595 | "dbpedia": "http://dbpedia.org/resource/Czechoslovakia",
596 | "wikidata": "http://www.wikidata.org/entity/Q33946",
597 | "wikipedia": "http://en.wikipedia.org/wiki/Czechoslovakia"
598 | },
599 | "target": [
600 | 2,
601 | 2
602 | ]
603 | },
604 | {
605 | "annotation": {
606 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
607 | },
608 | "target": [
609 | 2,
610 | 3
611 | ]
612 | },
613 | {
614 | "annotation": {
615 | "wikidata": "http://www.wikidata.org/entity/Q27089347"
616 | },
617 | "target": [
618 | 3,
619 | 0
620 | ]
621 | },
622 | {
623 | "annotation": {
624 | "dbpedia": "http://dbpedia.org/resource/Yellow",
625 | "wikidata": "http://www.wikidata.org/entity/Q943",
626 | "wikipedia": "http://en.wikipedia.org/wiki/Yellow"
627 | },
628 | "target": [
629 | 3,
630 | 1
631 | ]
632 | },
633 | {
634 | "annotation": {
635 | "dbpedia": "http://dbpedia.org/resource/Peru",
636 | "wikidata": "http://www.wikidata.org/entity/Q419",
637 | "wikipedia": "http://en.wikipedia.org/wiki/Peru"
638 | },
639 | "target": [
640 | 3,
641 | 2
642 | ]
643 | },
644 | {
645 | "annotation": {
646 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
647 | },
648 | "target": [
649 | 3,
650 | 3
651 | ]
652 | },
653 | {
654 | "annotation": {
655 | "wikidata": "http://www.wikidata.org/entity/Q7382095"
656 | },
657 | "target": [
658 | 4,
659 | 0
660 | ]
661 | },
662 | {
663 | "annotation": {
664 | "dbpedia": "http://dbpedia.org/resource/Blue",
665 | "wikidata": "http://www.wikidata.org/entity/Q1088",
666 | "wikipedia": "http://en.wikipedia.org/wiki/Blue"
667 | },
668 | "target": [
669 | 4,
670 | 1
671 | ]
672 | },
673 | {
674 | "annotation": {
675 | "dbpedia": "http://dbpedia.org/resource/Russia",
676 | "wikidata": "http://www.wikidata.org/entity/Q159",
677 | "wikipedia": "http://en.wikipedia.org/wiki/Russia"
678 | },
679 | "target": [
680 | 4,
681 | 2
682 | ]
683 | },
684 | {
685 | "annotation": {
686 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
687 | },
688 | "target": [
689 | 4,
690 | 3
691 | ]
692 | },
693 | {
694 | "annotation": {
695 | "wikidata": "http://www.wikidata.org/entity/Q5718706"
696 | },
697 | "target": [
698 | 5,
699 | 0
700 | ]
701 | },
702 | {
703 | "annotation": {
704 | "dbpedia": "http://dbpedia.org/resource/Yellow",
705 | "wikidata": "http://www.wikidata.org/entity/Q943",
706 | "wikipedia": "http://en.wikipedia.org/wiki/Yellow"
707 | },
708 | "target": [
709 | 5,
710 | 1
711 | ]
712 | },
713 | {
714 | "annotation": {
715 | "dbpedia": "http://dbpedia.org/resource/Spain",
716 | "wikidata": "http://www.wikidata.org/entity/Q29",
717 | "wikipedia": "http://en.wikipedia.org/wiki/Spain"
718 | },
719 | "target": [
720 | 5,
721 | 2
722 | ]
723 | },
724 | {
725 | "annotation": {
726 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
727 | },
728 | "target": [
729 | 5,
730 | 3
731 | ]
732 | },
733 | {
734 | "annotation": {
735 | "wikidata": "http://www.wikidata.org/entity/Q5718562"
736 | },
737 | "target": [
738 | 6,
739 | 0
740 | ]
741 | },
742 | {
743 | "annotation": {
744 | "dbpedia": "http://dbpedia.org/resource/Yellow",
745 | "wikidata": "http://www.wikidata.org/entity/Q943",
746 | "wikipedia": "http://en.wikipedia.org/wiki/Yellow"
747 | },
748 | "target": [
749 | 6,
750 | 1
751 | ]
752 | },
753 | {
754 | "annotation": {
755 | "dbpedia": "http://dbpedia.org/resource/Spain",
756 | "wikidata": "http://www.wikidata.org/entity/Q29",
757 | "wikipedia": "http://en.wikipedia.org/wiki/Spain"
758 | },
759 | "target": [
760 | 6,
761 | 2
762 | ]
763 | },
764 | {
765 | "annotation": {
766 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
767 | },
768 | "target": [
769 | 6,
770 | 3
771 | ]
772 | },
773 | {
774 | "annotation": {
775 | "wikidata": "http://www.wikidata.org/entity/Q5558049"
776 | },
777 | "target": [
778 | 7,
779 | 0
780 | ]
781 | },
782 | {
783 | "annotation": {
784 | "dbpedia": "http://dbpedia.org/resource/Yellow",
785 | "wikidata": "http://www.wikidata.org/entity/Q943",
786 | "wikipedia": "http://en.wikipedia.org/wiki/Yellow"
787 | },
788 | "target": [
789 | 7,
790 | 1
791 | ]
792 | },
793 | {
794 | "annotation": {
795 | "dbpedia": "http://dbpedia.org/resource/Spain",
796 | "wikidata": "http://www.wikidata.org/entity/Q29",
797 | "wikipedia": "http://en.wikipedia.org/wiki/Spain"
798 | },
799 | "target": [
800 | 7,
801 | 2
802 | ]
803 | },
804 | {
805 | "annotation": {
806 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
807 | },
808 | "target": [
809 | 7,
810 | 3
811 | ]
812 | },
813 | {
814 | "annotation": {
815 | "wikidata": "http://www.wikidata.org/entity/Q24942296"
816 | },
817 | "target": [
818 | 8,
819 | 0
820 | ]
821 | },
822 | {
823 | "annotation": {
824 | "dbpedia": "http://dbpedia.org/resource/Green",
825 | "wikidata": "http://www.wikidata.org/entity/Q3133",
826 | "wikipedia": "http://en.wikipedia.org/wiki/Green"
827 | },
828 | "target": [
829 | 8,
830 | 1
831 | ]
832 | },
833 | {
834 | "annotation": {
835 | "dbpedia": "http://dbpedia.org/resource/Spain",
836 | "wikidata": "http://www.wikidata.org/entity/Q29",
837 | "wikipedia": "http://en.wikipedia.org/wiki/Spain"
838 | },
839 | "target": [
840 | 8,
841 | 2
842 | ]
843 | },
844 | {
845 | "annotation": {
846 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
847 | },
848 | "target": [
849 | 8,
850 | 3
851 | ]
852 | },
853 | {
854 | "annotation": {
855 | "wikidata": "http://www.wikidata.org/entity/Q24942285"
856 | },
857 | "target": [
858 | 9,
859 | 0
860 | ]
861 | },
862 | {
863 | "annotation": {
864 | "dbpedia": "http://dbpedia.org/resource/Blue",
865 | "wikidata": "http://www.wikidata.org/entity/Q1088",
866 | "wikipedia": "http://en.wikipedia.org/wiki/Blue"
867 | },
868 | "target": [
869 | 9,
870 | 1
871 | ]
872 | },
873 | {
874 | "annotation": {
875 | "dbpedia": "http://dbpedia.org/resource/Spain",
876 | "wikidata": "http://www.wikidata.org/entity/Q29",
877 | "wikipedia": "http://en.wikipedia.org/wiki/Spain"
878 | },
879 | "target": [
880 | 9,
881 | 2
882 | ]
883 | },
884 | {
885 | "annotation": {
886 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
887 | },
888 | "target": [
889 | 9,
890 | 3
891 | ]
892 | },
893 | {
894 | "annotation": {
895 | "wikidata": "http://www.wikidata.org/entity/Q4485721"
896 | },
897 | "target": [
898 | 10,
899 | 0
900 | ]
901 | },
902 | {
903 | "annotation": {
904 | "dbpedia": "http://dbpedia.org/resource/Red",
905 | "wikidata": "http://www.wikidata.org/entity/Q3142",
906 | "wikipedia": "http://en.wikipedia.org/wiki/Red"
907 | },
908 | "target": [
909 | 10,
910 | 1
911 | ]
912 | },
913 | {
914 | "annotation": {
915 | "dbpedia": "http://dbpedia.org/resource/German_Reich",
916 | "wikidata": "http://www.wikidata.org/entity/Q41304",
917 | "wikipedia": "http://en.wikipedia.org/wiki/Weimar_Republic"
918 | },
919 | "target": [
920 | 10,
921 | 2
922 | ]
923 | },
924 | {
925 | "annotation": {
926 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
927 | },
928 | "target": [
929 | 10,
930 | 3
931 | ]
932 | },
933 | {
934 | "annotation": {
935 | "wikidata": "http://www.wikidata.org/entity/Q11698194"
936 | },
937 | "target": [
938 | 11,
939 | 0
940 | ]
941 | },
942 | {
943 | "annotation": {
944 | "dbpedia": "http://dbpedia.org/resource/Green",
945 | "wikidata": "http://www.wikidata.org/entity/Q3133",
946 | "wikipedia": "http://en.wikipedia.org/wiki/Green"
947 | },
948 | "target": [
949 | 11,
950 | 1
951 | ]
952 | },
953 | {
954 | "annotation": {
955 | "dbpedia": "http://dbpedia.org/resource/Malta",
956 | "wikidata": "http://www.wikidata.org/entity/Q233",
957 | "wikipedia": "http://en.wikipedia.org/wiki/Malta"
958 | },
959 | "target": [
960 | 11,
961 | 2
962 | ]
963 | },
964 | {
965 | "annotation": {
966 | "wikidata": "http://www.wikidata.org/entity/Q30302686"
967 | },
968 | "target": [
969 | 11,
970 | 3
971 | ]
972 | },
973 | {
974 | "annotation": {
975 | "dbpedia": "http://dbpedia.org/resource/Flag_of_the_People's_Liberation_Army",
976 | "wikidata": "http://www.wikidata.org/entity/Q10872945",
977 | "wikipedia": "http://en.wikipedia.org/wiki/Flag_of_the_People's_Liberation_Army"
978 | },
979 | "target": [
980 | 12,
981 | 0
982 | ]
983 | },
984 | {
985 | "annotation": {
986 | "dbpedia": "http://dbpedia.org/resource/Red",
987 | "wikidata": "http://www.wikidata.org/entity/Q3142",
988 | "wikipedia": "http://en.wikipedia.org/wiki/Red"
989 | },
990 | "target": [
991 | 12,
992 | 1
993 | ]
994 | },
995 | {
996 | "annotation": {
997 | "dbpedia": "http://dbpedia.org/resource/China",
998 | "wikidata": "http://www.wikidata.org/entity/Q148",
999 | "wikipedia": "http://en.wikipedia.org/wiki/China"
1000 | },
1001 | "target": [
1002 | 12,
1003 | 2
1004 | ]
1005 | },
1006 | {
1007 | "annotation": {
1008 | "wikidata": "http://www.wikidata.org/entity/Q20970435"
1009 | },
1010 | "target": [
1011 | 12,
1012 | 3
1013 | ]
1014 | },
1015 | {
1016 | "annotation": {
1017 | "wikidata": "http://www.wikidata.org/entity/Q11913350"
1018 | },
1019 | "target": [
1020 | 13,
1021 | 0
1022 | ]
1023 | },
1024 | {
1025 | "annotation": {
1026 | "dbpedia": "http://dbpedia.org/resource/Yellow",
1027 | "wikidata": "http://www.wikidata.org/entity/Q943",
1028 | "wikipedia": "http://en.wikipedia.org/wiki/Yellow"
1029 | },
1030 | "target": [
1031 | 13,
1032 | 1
1033 | ]
1034 | },
1035 | {
1036 | "annotation": {
1037 | "dbpedia": "http://dbpedia.org/resource/Czech_Republic",
1038 | "wikidata": "http://www.wikidata.org/entity/Q213",
1039 | "wikipedia": "http://en.wikipedia.org/wiki/Czech_Republic"
1040 | },
1041 | "target": [
1042 | 13,
1043 | 2
1044 | ]
1045 | },
1046 | {
1047 | "annotation": {
1048 | "wikidata": "http://www.wikidata.org/entity/Q20970430"
1049 | },
1050 | "target": [
1051 | 13,
1052 | 3
1053 | ]
1054 | },
1055 | {
1056 | "annotation": {
1057 | "wikidata": "http://www.wikidata.org/entity/Q1006483"
1058 | },
1059 | "target": [
1060 | 14,
1061 | 0
1062 | ]
1063 | },
1064 | {
1065 | "annotation": {
1066 | "dbpedia": "http://dbpedia.org/resource/Red",
1067 | "wikidata": "http://www.wikidata.org/entity/Q3142",
1068 | "wikipedia": "http://en.wikipedia.org/wiki/Red"
1069 | },
1070 | "target": [
1071 | 14,
1072 | 1
1073 | ]
1074 | },
1075 | {
1076 | "annotation": {
1077 | "dbpedia": "http://dbpedia.org/resource/Weimar_Republic",
1078 | "wikidata": "http://www.wikidata.org/entity/Q183",
1079 | "wikipedia": "http://en.wikipedia.org/wiki/Germany"
1080 | },
1081 | "target": [
1082 | 14,
1083 | 2
1084 | ]
1085 | },
1086 | {
1087 | "annotation": {
1088 | "wikidata": "http://www.wikidata.org/entity/Q30302686"
1089 | },
1090 | "target": [
1091 | 14,
1092 | 3
1093 | ]
1094 | },
1095 | {
1096 | "annotation": {
1097 | "dbpedia": "http://dbpedia.org/resource/Flag_of_the_Armenian_Soviet_Socialist_Republic",
1098 | "wikidata": "http://www.wikidata.org/entity/Q877603",
1099 | "wikipedia": "http://en.wikipedia.org/wiki/Flag_of_the_Armenian_Soviet_Socialist_Republic"
1100 | },
1101 | "target": [
1102 | 15,
1103 | 0
1104 | ]
1105 | },
1106 | {
1107 | "annotation": {
1108 | "dbpedia": "http://dbpedia.org/resource/Blue",
1109 | "wikidata": "http://www.wikidata.org/entity/Q1088",
1110 | "wikipedia": "http://en.wikipedia.org/wiki/Blue"
1111 | },
1112 | "target": [
1113 | 15,
1114 | 1
1115 | ]
1116 | },
1117 | {
1118 | "annotation": {
1119 | "dbpedia": "http://dbpedia.org/resource/Armenian_Soviet_Socialist_Republic",
1120 | "wikidata": "http://www.wikidata.org/entity/Q132856",
1121 | "wikipedia": "http://en.wikipedia.org/wiki/Armenian_Soviet_Socialist_Republic"
1122 | },
1123 | "target": [
1124 | 15,
1125 | 2
1126 | ]
1127 | },
1128 | {
1129 | "annotation": {
1130 | "wikidata": "http://www.wikidata.org/entity/Q30302657"
1131 | },
1132 | "target": [
1133 | 15,
1134 | 3
1135 | ]
1136 | },
1137 | {
1138 | "annotation": {
1139 | "dbpedia": "http://dbpedia.org/resource/Flag_of_Piedmont",
1140 | "wikidata": "http://www.wikidata.org/entity/Q1094206",
1141 | "wikipedia": "http://en.wikipedia.org/wiki/Flag_of_Piedmont"
1142 | },
1143 | "target": [
1144 | 16,
1145 | 0
1146 | ]
1147 | },
1148 | {
1149 | "annotation": {
1150 | "dbpedia": "http://dbpedia.org/resource/Blue",
1151 | "wikidata": "http://www.wikidata.org/entity/Q1088",
1152 | "wikipedia": "http://en.wikipedia.org/wiki/Blue"
1153 | },
1154 | "target": [
1155 | 16,
1156 | 1
1157 | ]
1158 | },
1159 | {
1160 | "annotation": {
1161 | "dbpedia": "http://dbpedia.org/resource/Italy",
1162 | "wikidata": "http://www.wikidata.org/entity/Q38",
1163 | "wikipedia": "http://en.wikipedia.org/wiki/Italy"
1164 | },
1165 | "target": [
1166 | 16,
1167 | 2
1168 | ]
1169 | },
1170 | {
1171 | "annotation": {
1172 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
1173 | },
1174 | "target": [
1175 | 16,
1176 | 3
1177 | ]
1178 | },
1179 | {
1180 | "annotation": {
1181 | "dbpedia": "http://dbpedia.org/resource/Transnistria",
1182 | "wikidata": "http://www.wikidata.org/entity/Q907112",
1183 | "wikipedia": "http://en.wikipedia.org/wiki/Transnistria"
1184 | },
1185 | "target": [
1186 | 17,
1187 | 0
1188 | ]
1189 | },
1190 | {
1191 | "annotation": {
1192 | "dbpedia": "http://dbpedia.org/resource/Green",
1193 | "wikidata": "http://www.wikidata.org/entity/Q3133",
1194 | "wikipedia": "http://en.wikipedia.org/wiki/Green"
1195 | },
1196 | "target": [
1197 | 17,
1198 | 1
1199 | ]
1200 | },
1201 | {
1202 | "annotation": {
1203 | "dbpedia": "http://dbpedia.org/resource/Moldova",
1204 | "wikidata": "http://www.wikidata.org/entity/Q217",
1205 | "wikipedia": "http://en.wikipedia.org/wiki/Moldova"
1206 | },
1207 | "target": [
1208 | 17,
1209 | 2
1210 | ]
1211 | },
1212 | {
1213 | "annotation": {
1214 | "wikidata": "http://www.wikidata.org/entity/Q30302657"
1215 | },
1216 | "target": [
1217 | 17,
1218 | 3
1219 | ]
1220 | },
1221 | {
1222 | "annotation": {
1223 | "dbpedia": "http://dbpedia.org/resource/Flag_of_Crimea",
1224 | "wikidata": "http://www.wikidata.org/entity/Q225489",
1225 | "wikipedia": "http://en.wikipedia.org/wiki/Flag_of_Crimea"
1226 | },
1227 | "target": [
1228 | 18,
1229 | 0
1230 | ]
1231 | },
1232 | {
1233 | "annotation": {
1234 | "dbpedia": "http://dbpedia.org/resource/Blue",
1235 | "wikidata": "http://www.wikidata.org/entity/Q1088",
1236 | "wikipedia": "http://en.wikipedia.org/wiki/Blue"
1237 | },
1238 | "target": [
1239 | 18,
1240 | 1
1241 | ]
1242 | },
1243 | {
1244 | "annotation": {
1245 | "dbpedia": "http://dbpedia.org/resource/Russia",
1246 | "wikidata": "http://www.wikidata.org/entity/Q159",
1247 | "wikipedia": "http://en.wikipedia.org/wiki/Russia"
1248 | },
1249 | "target": [
1250 | 18,
1251 | 2
1252 | ]
1253 | },
1254 | {
1255 | "annotation": {
1256 | "wikidata": "http://www.wikidata.org/entity/Q30302657"
1257 | },
1258 | "target": [
1259 | 18,
1260 | 3
1261 | ]
1262 | },
1263 | {
1264 | "annotation": {
1265 | "dbpedia": "http://dbpedia.org/resource/Flag_of_Guernsey",
1266 | "wikidata": "http://www.wikidata.org/entity/Q158591",
1267 | "wikipedia": "http://en.wikipedia.org/wiki/Flag_of_Guernsey"
1268 | },
1269 | "target": [
1270 | 19,
1271 | 0
1272 | ]
1273 | },
1274 | {
1275 | "annotation": {
1276 | "dbpedia": "http://dbpedia.org/resource/Red",
1277 | "wikidata": "http://www.wikidata.org/entity/Q3142",
1278 | "wikipedia": "http://en.wikipedia.org/wiki/Red"
1279 | },
1280 | "target": [
1281 | 19,
1282 | 1
1283 | ]
1284 | },
1285 | {
1286 | "annotation": {
1287 | "dbpedia": "http://dbpedia.org/resource/Guernsey",
1288 | "wikidata": "http://www.wikidata.org/entity/Q25230",
1289 | "wikipedia": "http://en.wikipedia.org/wiki/Bailiwick_of_Guernsey"
1290 | },
1291 | "target": [
1292 | 19,
1293 | 2
1294 | ]
1295 | },
1296 | {
1297 | "annotation": {
1298 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
1299 | },
1300 | "target": [
1301 | 19,
1302 | 3
1303 | ]
1304 | },
1305 | {
1306 | "annotation": {
1307 | "dbpedia": "http://dbpedia.org/resource/Flag_of_Saba",
1308 | "wikidata": "http://www.wikidata.org/entity/Q429900",
1309 | "wikipedia": "http://en.wikipedia.org/wiki/Flag_of_Saba"
1310 | },
1311 | "target": [
1312 | 20,
1313 | 0
1314 | ]
1315 | },
1316 | {
1317 | "annotation": {
1318 | "dbpedia": "http://dbpedia.org/resource/Yellow",
1319 | "wikidata": "http://www.wikidata.org/entity/Q943",
1320 | "wikipedia": "http://en.wikipedia.org/wiki/Yellow"
1321 | },
1322 | "target": [
1323 | 20,
1324 | 1
1325 | ]
1326 | },
1327 | {
1328 | "annotation": {
1329 | "dbpedia": "http://dbpedia.org/resource/Kingdom_of_the_Netherlands",
1330 | "wikidata": "http://www.wikidata.org/entity/Q55",
1331 | "wikipedia": "http://en.wikipedia.org/wiki/Netherlands"
1332 | },
1333 | "target": [
1334 | 20,
1335 | 2
1336 | ]
1337 | },
1338 | {
1339 | "annotation": {
1340 | "wikidata": "http://www.wikidata.org/entity/Q20970431"
1341 | },
1342 | "target": [
1343 | 20,
1344 | 3
1345 | ]
1346 | }
1347 | ],
1348 | "cpa": [
1349 | {
1350 | "annotation": {
1351 | "wikidata": "http://www.wikidata.org/prop/direct/P462"
1352 | },
1353 | "target": [
1354 | 0,
1355 | 1
1356 | ]
1357 | },
1358 | {
1359 | "annotation": {
1360 | "wikidata": "http://www.wikidata.org/prop/direct/P17"
1361 | },
1362 | "target": [
1363 | 0,
1364 | 2
1365 | ]
1366 | },
1367 | {
1368 | "annotation": {
1369 | "wikidata": "http://www.wikidata.org/prop/direct/P2061"
1370 | },
1371 | "target": [
1372 | 0,
1373 | 3
1374 | ]
1375 | }
1376 | ],
1377 | "cta": [
1378 | {
1379 | "annotation": {
1380 | "dbpedia": "http://dbpedia.org/resource/Flag",
1381 | "wikidata": "http://www.wikidata.org/entity/Q14660",
1382 | "wikipedia": "http://en.wikipedia.org/wiki/Flag"
1383 | },
1384 | "target": 0
1385 | },
1386 | {
1387 | "annotation": {
1388 | "dbpedia": "http://dbpedia.org/resource/Color",
1389 | "wikidata": "http://www.wikidata.org/entity/Q1075",
1390 | "wikipedia": "http://en.wikipedia.org/wiki/Color"
1391 | },
1392 | "target": 1
1393 | },
1394 | {
1395 | "annotation": {
1396 | "wikidata": "http://www.wikidata.org/entity/Q20970434"
1397 | },
1398 | "target": 3
1399 | }
1400 | ]
1401 | },
1402 | "structure": {
1403 | "columns": 4,
1404 | "core_attribute": 0,
1405 | "header": [
1406 | 0
1407 | ],
1408 | "missing ratio": 0,
1409 | "row": 21,
1410 | "table type": "vertical relation"
1411 | },
1412 | "table_id": "K0PM5GMK"
1413 | }
1414 | ]
1415 | }
--------------------------------------------------------------------------------
/interface/static/others/mytables.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/interface/static/others/mytables.zip
--------------------------------------------------------------------------------
/interface/templates/md.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% block title %}{{ md_title }}{% endblock %}
3 | {% block content %}
4 | {{ md_content | safe }}
5 | {% endblock %}
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | charamel == 1.0.0
2 | numpy == 1.19.2
3 | pandas == 1.1.5
4 | petl == 1.7.4
5 | requests == 2.27.1
6 | openpyxl
7 |
--------------------------------------------------------------------------------
/results.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/results.zip
--------------------------------------------------------------------------------
/run_2t.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import fnmatch
3 | import json
4 | import os
5 | import signal
6 | import urllib
7 | from collections import defaultdict, Counter
8 | from contextlib import closing
9 | from datetime import timedelta
10 | from math import pi
11 | from multiprocessing import Pool
12 | from time import time, sleep
13 |
14 | import chardet
15 | import matplotlib.pyplot as plt
16 | import numpy
17 | import pandas
18 | import petl
19 | import requests
20 | from contextlib2 import contextmanager
21 | from requests.adapters import HTTPAdapter
22 | from requests.packages.urllib3.util.retry import Retry
23 | from tqdm import tqdm
24 |
25 | import m_config as cf
26 |
27 | DOMAIN = "https://mtab.app"
28 |
29 | DIR_ROOT = "/Users/phucnguyen/git/mtab"
30 |
31 | # Dataset Directories
32 | DIR_TABLES = DIR_ROOT + "/data/tables/{challenge}/{data_name}/tables"
33 |
34 | # Target files
35 | DIR_CEA_TAR = DIR_ROOT + "/data/tables/{challenge}/{data_name}/cea.csv"
36 | DIR_CTA_TAR = DIR_ROOT + "/data/tables/{challenge}/{data_name}/cta.csv"
37 | DIR_CPA_TAR = DIR_ROOT + "/data/tables/{challenge}/{data_name}/cpa.csv"
38 |
39 |
40 | DIR_CEA_GT = DIR_ROOT + "/data/tables/{challenge}/{data_name}/gt/CEA_2T_WD_gt.csv"
41 |
42 | # Result files
43 | DIR_CEA_RES = DIR_ROOT + "/results/{challenge}/{data_name}/{source}/cea.csv"
44 | DIR_CTA_RES = DIR_ROOT + "/results/{challenge}/{data_name}/{source}/cta.csv"
45 | DIR_CPA_RES = DIR_ROOT + "/results/{challenge}/{data_name}/{source}/cpa.csv"
46 |
47 |
48 | # Request config
49 | LIMIT_TIME_OUT = 259200 # 2h: 7200 1D: 86400 3D:259200
50 | LIMIT_RETRIES = 3
51 |
52 |
53 | @contextmanager
54 | def time_limit(seconds):
55 | def signal_handler(signum, frame):
56 | raise Exception("Timed out!")
57 |
58 | signal.signal(signal.SIGALRM, signal_handler)
59 | signal.alarm(seconds)
60 | try:
61 | yield
62 | finally:
63 | signal.alarm(0)
64 |
65 |
66 | def create_dir(file_dir):
67 | """Create a directory
68 |
69 | Args:
70 | file_dir (str): file directory
71 | """
72 | folder_dir = os.path.dirname(file_dir)
73 | if not os.path.exists(folder_dir):
74 | os.makedirs(folder_dir)
75 |
76 |
77 | def load_object_csv(file_name, encoding="utf8"):
78 | content = []
79 | if os.path.exists(file_name):
80 | with open(file_name, "r", encoding=encoding, errors="ignore") as f:
81 | reader = csv.reader(f, delimiter=",")
82 | for r in reader:
83 | row_norm = []
84 | for c in r:
85 | row_norm.append(c)
86 | content.append(row_norm)
87 | return content
88 |
89 |
90 | def save_object_csv(file_name, rows):
91 | create_dir(file_name)
92 | temp_file = "%s.temp" % file_name
93 | with open(temp_file, "w") as f:
94 | try:
95 | writer = csv.writer(f, delimiter=",", quotechar='"', quoting=csv.QUOTE_ALL)
96 | for r in rows:
97 | if (
98 | isinstance(r, list)
99 | or isinstance(r, tuple)
100 | or isinstance(r, numpy.ndarray)
101 | ):
102 | writer.writerow(r)
103 | else:
104 | writer.writerow([r])
105 | except Exception as message:
106 | print(message)
107 | if os.path.exists(file_name):
108 | os.remove(file_name)
109 | os.rename(temp_file, file_name)
110 |
111 |
112 | def get_files_from_dir_subdir(folder_path, extension="*"):
113 | all_files = []
114 | for root, _, file_dirs in os.walk(folder_path):
115 | for file_dir in fnmatch.filter(file_dirs, "*.%s" % extension):
116 | if ".DS_Store" not in file_dir:
117 | all_files.append(os.path.join(root, file_dir))
118 | return all_files
119 |
120 |
121 | def get_files_from_dir(
122 | folder_path, extension="*", limit_reader=-1, is_sort=False, reverse=False
123 | ):
124 | all_file_dirs = get_files_from_dir_subdir(folder_path, extension)
125 |
126 | if is_sort:
127 | file_with_size = [(f, os.path.getsize(f)) for f in all_file_dirs]
128 | file_with_size.sort(key=lambda f: f[1], reverse=reverse)
129 | all_file_dirs = [f for f, _ in file_with_size]
130 | if limit_reader < 0:
131 |
132 | limit_reader = len(all_file_dirs)
133 | return all_file_dirs[:limit_reader]
134 |
135 |
136 | def get_encoding(source, method="charamel"):
137 | result = "utf-8"
138 | if os.path.isfile(source):
139 | with open(source, "rb") as file_open:
140 | # Read all content --> make sure about the file encoding
141 | file_content = file_open.read()
142 |
143 | # predict encoding
144 | if method == "charamel":
145 | try:
146 | import charamel
147 |
148 | charamel.Detector()
149 | encoding_detector = charamel.Detector()
150 | detector = encoding_detector.detect(file_content)
151 | if detector:
152 | result = detector.value
153 | except Exception as message:
154 | print(message)
155 | pass
156 | else:
157 | detector = chardet.detect(file_content)
158 | if detector["encoding"]:
159 | result = detector["encoding"]
160 | return result
161 |
162 |
163 | def load_table(dir_table):
164 | def parse_xml_table(source):
165 | tables_xml = pandas.read_html(source)
166 | if tables_xml:
167 | return [tables_xml[0].columns.values.tolist()] + tables_xml[
168 | 0
169 | ].values.tolist()
170 | else:
171 | return None
172 |
173 | table_obj = None
174 | encoding = get_encoding(dir_table)
175 | file_ext = os.path.splitext(dir_table)[1][1:]
176 | if file_ext == "csv":
177 | table_obj = load_object_csv(dir_table, encoding=encoding)
178 | elif file_ext == "tsv":
179 | table_obj = petl.fromtsv(dir_table, encoding=encoding)
180 | elif file_ext == "txt":
181 | table_obj = petl.fromtext(dir_table, encoding=encoding)
182 | elif file_ext == "xls":
183 | table_obj = petl.fromxls(dir_table, encoding=encoding)
184 | elif file_ext in ["xlsm", "xlsb", "xltx", "xlsx", "xlt", "xltm"]:
185 | table_obj = petl.fromxlsx(dir_table)
186 | elif file_ext == "xml":
187 | table_obj = parse_xml_table(dir_table)
188 | cells = []
189 | if table_obj:
190 | for row in table_obj:
191 | row_norm = []
192 | for col in row:
193 | tmp_cell = str(col)
194 | # tmp_cell = ul.norm_text(str(col), punctuations=True, lower=False)
195 | # tmp_date = ul.get_date(tmp_cell)
196 | # if tmp_date:
197 | # tmp_cell = tmp_date
198 | row_norm.append(tmp_cell)
199 | if row_norm:
200 | # row = ftfy.fix_text(row)
201 | cells.append(row_norm)
202 |
203 | return cells
204 |
205 |
206 | TABLE_CATEGORIES = {
207 | "ALL": ([""], []),
208 | "CTRL_WIKI": (["WIKI"], ["NOISE2"]),
209 | "CTRL_DBP": (["CTRL", "DBP"], ["NOISE2"]),
210 | "CTRL_NOISE2": (["CTRL", "NOISE2"], []),
211 | "TOUGH_T2D": (["T2D"], ["NOISE2"]),
212 | "TOUGH_HOMO": (["HOMO"], ["SORTED", "NOISE2"]),
213 | "TOUGH_MISC": (["MISC"], ["NOISE2"]),
214 | "TOUGH_MISSP": (["MISSP"], ["NOISE1", "NOISE2"]),
215 | "TOUGH_SORTED": (["SORTED"], ["NOISE2"]),
216 | "TOUGH_NOISE1": (["NOISE1"], []),
217 | "TOUGH_NOISE2": (["TOUGH", "NOISE2"], []),
218 | }
219 |
220 |
221 | def _is_table_in_cat(x, whitelist, blacklist):
222 | b = True
223 | for i in whitelist:
224 | if not (b and (i in x)):
225 | return False
226 | for e in blacklist:
227 | if not (b and (e not in x)):
228 | return False
229 | return True
230 |
231 |
232 | def precision_score(correct_cells, annotated_cells):
233 | """
234 | Precision = (# correctly annotated cells) / (# annotated cells)
235 | :param correct_cells:
236 | :param annotated_cells:
237 | :return:
238 | """
239 | return (
240 | float(len(correct_cells)) / len(annotated_cells)
241 | if len(annotated_cells) > 0
242 | else 0.0
243 | )
244 |
245 |
246 | def recall_score(correct_cells, gt_cell_ent):
247 | """
248 | Recall = (# correctly annotated cells) / (# target cells)
249 | :param correct_cells:
250 | :param gt_cell_ent:
251 | :return:
252 | """
253 | return float(len(correct_cells)) / len(gt_cell_ent.keys())
254 |
255 |
256 | def f1_score(precision, recall):
257 | """
258 | F1 Score = (2 * Precision * Recall) / (Precision + Recall)
259 | :param precision:
260 | :param recall:
261 | :return:
262 | """
263 | return (
264 | (2 * precision * recall) / (precision + recall)
265 | if (precision + recall) > 0
266 | else 0.0
267 | )
268 |
269 |
270 | def _get_radar_plot(scores, title):
271 | categories = list(scores.keys())
272 | N = len(categories)
273 | angles = [n / float(N) * 2 * pi for n in range(N)]
274 | angles += angles[:1]
275 |
276 | f = plt.figure()
277 | ax = plt.subplot(111, polar=True)
278 | ax.set_theta_offset(pi / 2)
279 | ax.set_theta_direction(-1)
280 |
281 | plt.xticks(angles[:-1], categories)
282 | ax.set_rlabel_position(0)
283 | plt.yticks([0.25, 0.5, 0.75], ["0.25", "0.50", "0.75"], color="grey", size=7)
284 | plt.ylim(0, 1)
285 |
286 | values = list(map(lambda x: x["f1"], scores.values()))
287 | values += values[:1]
288 | ax.plot(angles, values, linewidth=1, linestyle="solid", label="f1")
289 | ax.fill(angles, values, "b", alpha=0.1)
290 | for angle, value in zip(angles, values):
291 | ax.annotate(
292 | round(value, 2), (angle, value), size=8, weight="bold", ha="center", c="b"
293 | )
294 |
295 | values = list(map(lambda x: x["precision"], scores.values()))
296 | values += values[:1]
297 | ax.plot(angles, values, linewidth=1, linestyle="solid", label="precision")
298 | ax.fill(angles, values, "r", alpha=0.1)
299 |
300 | values = list(map(lambda x: x["recall"], scores.values()))
301 | values += values[:1]
302 | ax.plot(angles, values, linewidth=1, linestyle="solid", label="recall")
303 | ax.fill(angles, values, "g", alpha=0.1)
304 |
305 | plt.legend(loc="upper right", bbox_to_anchor=(0.1, 0.1))
306 | plt.title(title, size=11, y=1.1)
307 |
308 | return f
309 |
310 |
311 | def _write_df(
312 | df, filename, drop=True, strip=True, index=False, header=True, quoting=csv.QUOTE_ALL
313 | ):
314 | if drop:
315 | df = df.drop_duplicates()
316 | if strip:
317 | df = df.apply(lambda x: x.str.strip() if x.dtype == "object" else x)
318 | df.to_csv(filename, index=index, header=header, quoting=quoting)
319 |
320 |
321 | def score_cea(gs_file, submission_file):
322 | scores = {}
323 | gt = pandas.read_csv(
324 | gs_file,
325 | delimiter=",",
326 | names=["tab_id", "col_id", "row_id", "entity"],
327 | dtype={"tab_id": str, "col_id": str, "row_id": str, "entity": str},
328 | keep_default_na=False,
329 | )
330 | sub = pandas.read_csv(
331 | submission_file,
332 | delimiter=",",
333 | names=["tab_id", "col_id", "row_id", "entity"],
334 | dtype={"tab_id": str, "col_id": str, "row_id": str, "entity": str},
335 | keep_default_na=False,
336 | )
337 |
338 | gt = gt.to_dict("records")
339 | sub = sub.to_dict("records")
340 |
341 | gt_cell_ent = dict()
342 | gt_cell_ent_orig = dict()
343 | for row in gt:
344 | cell = "%s %s %s" % (row["tab_id"], row["col_id"], row["row_id"])
345 | gt_cell_ent[cell] = urllib.parse.unquote(row["entity"]).lower().split(" ")
346 | gt_cell_ent_orig[cell] = row["entity"].split(" ")
347 |
348 | gt_cell_ent[cell] = [i.replace(cf.WD, "") for i in gt_cell_ent[cell]]
349 | gt_cell_ent_orig[cell] = [i.replace(cf.WD, "") for i in gt_cell_ent_orig[cell]]
350 |
351 | correct_cells, wrong_cells, annotated_cells = set(), list(), set()
352 | for row in sub:
353 | cell = "%s %s %s" % (row["tab_id"], row["col_id"], row["row_id"])
354 | if cell in gt_cell_ent:
355 | if cell in annotated_cells:
356 | raise Exception("Duplicate cells in the submission file")
357 | else:
358 | annotated_cells.add(cell)
359 |
360 | annotation = urllib.parse.unquote(row["entity"]).lower()
361 | if annotation in gt_cell_ent[cell]:
362 | correct_cells.add(cell)
363 | else:
364 | wrong_cells.append(
365 | {
366 | "table": row["tab_id"],
367 | "col": int(row["col_id"]),
368 | "row": int(row["row_id"]),
369 | "actual": row["entity"],
370 | "target": " ".join(gt_cell_ent_orig[cell]),
371 | }
372 | )
373 |
374 | for cat in TABLE_CATEGORIES:
375 | include, exclude = TABLE_CATEGORIES[cat]
376 | c_cells = {x for x in correct_cells if _is_table_in_cat(x, include, exclude)}
377 | a_cells = {x for x in annotated_cells if _is_table_in_cat(x, include, exclude)}
378 | g_cells = dict(
379 | filter(
380 | lambda elem: _is_table_in_cat(elem[0], include, exclude),
381 | gt_cell_ent.items(),
382 | )
383 | )
384 | if len(g_cells) > 0:
385 | precision = precision_score(c_cells, a_cells)
386 | recall = recall_score(c_cells, g_cells)
387 | f1 = f1_score(precision, recall)
388 | scores[cat] = {
389 | "precision": precision,
390 | "recall": recall,
391 | "f1": f1,
392 | "correct": len(c_cells),
393 | "gt": len(g_cells),
394 | "submit": len(a_cells),
395 | }
396 |
397 | return scores
398 |
399 |
400 | class MTab(object):
401 | def __init__(self):
402 | self.F_MTAB = f"{DOMAIN}/api/v1.1/mtab"
403 |
404 | self.session = requests.Session()
405 | retries = Retry(
406 | total=LIMIT_RETRIES,
407 | backoff_factor=1,
408 | status_forcelist=[500, 502, 503, 504],
409 | )
410 | self.session.mount("https://", HTTPAdapter(max_retries=retries))
411 | self.session.mount("http://", HTTPAdapter(max_retries=retries))
412 |
413 | def _request(self, func_name, query_args, retries=3, message=""):
414 | responds = defaultdict()
415 | if retries == 0:
416 | print(message)
417 | return responds
418 | try:
419 | # _responds = requests.post(func_name, json=query_args, timeout=self.TIME_OUT)
420 | _responds = self.session.post(
421 | func_name, json=query_args, timeout=LIMIT_TIME_OUT
422 | )
423 | if _responds.status_code == 200:
424 | responds = _responds.json()
425 | if not responds or (
426 | responds.get("status") == "Error" and not responds.get("message")
427 | ):
428 | sleep(300)
429 | return self._request(
430 | func_name,
431 | query_args,
432 | retries - 1,
433 | message=f"Error: Retry {retries-1}",
434 | )
435 | except Exception as message:
436 | if func_name == self.F_MTAB and query_args.get("table_name"):
437 | args_info = func_name + ": " + query_args.get("table_name")
438 | else:
439 | args_info = func_name
440 | sleep(300)
441 | return self._request(
442 | func_name, query_args, retries - 1, message=f"\n{message} - {args_info}"
443 | )
444 | return responds
445 |
446 | def get_table_annotation(self, args):
447 | try:
448 | with time_limit(LIMIT_TIME_OUT):
449 | responds = self._request(self.F_MTAB, args)
450 | except Exception as message:
451 | print(message)
452 | responds = self.get_table_annotation(args)
453 | return responds
454 |
455 |
456 | def pool_table_annotation(args):
457 | responds = {}
458 | map_row_index = args.pop("map_row_index")
459 | try:
460 | mtab_api = MTab()
461 | responds = mtab_api.get_table_annotation(args)
462 | except Exception as message:
463 | print(message)
464 | responds.update({"status": "Error", "message": message})
465 |
466 | # overloading - try 10 times, 5s / a sleep
467 | if (not responds or responds["status"] == "Error") and args.get("sleep", 0) < 50:
468 | sleep(5)
469 | args.update({"sleep": args.get("sleep", 0) + 5})
470 | print(args.get("sleep", 0))
471 | return pool_table_annotation(args)
472 |
473 | if responds.get("semantic") and responds["semantic"].get("cea"):
474 | responds["semantic"]["cea"] = [
475 | [map_row_index[r], c, a] for r, c, a in responds["semantic"]["cea"]
476 | ]
477 | return args, responds
478 |
479 |
480 | def load_resources(
481 | challenge="semtab2020",
482 | data_name="2T",
483 | search_mode="a",
484 | table_limit=0,
485 | search_limit=50,
486 | search_expensive=False,
487 | chunk_size=200,
488 | chunk_limit=0,
489 | ):
490 | dir_folder_tables = DIR_TABLES.format(challenge=challenge, data_name=data_name)
491 |
492 | # Load tables
493 | dir_tables = get_files_from_dir(dir_folder_tables, is_sort=True, reverse=True)
494 |
495 | if table_limit:
496 | dir_tables = dir_tables[:table_limit]
497 |
498 | # Matching targets
499 | tar_cea, tar_cta, tar_cpa = defaultdict(list), defaultdict(list), defaultdict(list)
500 |
501 | # Load targets
502 | dir_tar_cea = DIR_CEA_TAR.format(challenge=challenge, data_name=data_name)
503 | dir_tar_cta = DIR_CTA_TAR.format(challenge=challenge, data_name=data_name)
504 | dir_tar_cpa = DIR_CPA_TAR.format(challenge=challenge, data_name=data_name)
505 | # Load target cea
506 | for line in load_object_csv(dir_tar_cea):
507 | table_name, row_i, col_i = line[:3]
508 | tar_cea[table_name].append([row_i, col_i])
509 |
510 | # Load target cta
511 | for line in load_object_csv(dir_tar_cta):
512 | table_name, col_i = line[:2]
513 | tar_cta[table_name].append(col_i)
514 |
515 | # Load target cpa
516 | for line in load_object_csv(dir_tar_cpa):
517 | table_name, col_i1, col_i2 = line[:3]
518 | tar_cpa[table_name].append([col_i1, col_i2])
519 |
520 | # Create input args in chunks
521 | args = []
522 | total_cea = 0
523 | for dir_table in dir_tables:
524 | table_name = os.path.splitext(os.path.basename(dir_table))[0]
525 | table_content = load_object_csv(dir_table)
526 | chunk_tar_cea = tar_cea.get(table_name)
527 | lines = {row_i for row_i, col_i in chunk_tar_cea}
528 | lines = sorted(list(lines), key=lambda x: int(x))
529 | buff_table = []
530 | buff_line = set()
531 | buff_line_map = {}
532 | buff_line_map_inverse = {}
533 | count_tar = 0
534 | for line in lines:
535 | line = int(line)
536 | buff_line.add(line)
537 | buff_line_map[line] = len(buff_table)
538 | buff_line_map_inverse[len(buff_table)] = line
539 | buff_table.append(table_content[line])
540 | if len(buff_line) == chunk_size or line == int(lines[-1]):
541 | chunks_tar_cea_obj = [
542 | [str(buff_line_map[int(row_i)]), col_i]
543 | for row_i, col_i in chunk_tar_cea
544 | if int(row_i) in buff_line
545 | ]
546 | args_obj = {
547 | "table": buff_table,
548 | "table_name": table_name,
549 | "tar_cea": chunks_tar_cea_obj,
550 | "tar_cta": tar_cta.get(table_name),
551 | "tar_cpa": tar_cpa.get(table_name),
552 | "search_mode": search_mode,
553 | "search_limit": search_limit,
554 | "search_expensive": search_expensive,
555 | "map_row_index": buff_line_map_inverse,
556 | }
557 | count_tar += len(chunks_tar_cea_obj)
558 | args.append(args_obj)
559 | buff_line = set()
560 | buff_table = []
561 | buff_line_map = {}
562 | buff_line_map_inverse = {}
563 | if count_tar != len(chunk_tar_cea):
564 | print("Missing targets: " + table_name)
565 | total_cea += count_tar
566 | if chunk_limit:
567 | args = args[:chunk_limit]
568 |
569 | total_tables = len(dir_tables)
570 |
571 | return args, total_cea, total_tables
572 |
573 |
574 | def m_call_run_semtab(
575 | challenge="semtab2020",
576 | data_name="2T",
577 | n_thread=1,
578 | search_mode="a",
579 | table_limit=0,
580 | search_limit=50,
581 | search_expensive=False,
582 | chunk_size=200,
583 | chunk_limit=0,
584 | ):
585 | start = time()
586 | args, total_cea, total_tables = load_resources(
587 | challenge,
588 | data_name,
589 | search_mode,
590 | table_limit,
591 | search_limit,
592 | search_expensive,
593 | chunk_size,
594 | chunk_limit,
595 | )
596 | # Call MTab
597 | res_cea, res_cta, res_cpa = (
598 | defaultdict(Counter),
599 | defaultdict(Counter),
600 | defaultdict(Counter),
601 | )
602 | # Save annotation files
603 | domain = "online"
604 |
605 | dir_cea_res = DIR_CEA_RES.format(
606 | challenge=challenge, data_name=data_name, source=domain
607 | )
608 | dir_cta_res = DIR_CTA_RES.format(
609 | challenge=challenge, data_name=data_name, source=domain
610 | )
611 | dir_cpa_res = DIR_CPA_RES.format(
612 | challenge=challenge, data_name=data_name, source=domain
613 | )
614 |
615 | def save_final_result(dir_res_obj, res_obj):
616 | res_cea_final = []
617 | for key, values in res_obj.items():
618 | res_cea_final.append(list(key) + [max(values, key=values.get)])
619 | res_cea_final.sort(key=lambda x: x[0])
620 | save_object_csv(dir_res_obj, res_cea_final)
621 | return res_cea_final
622 |
623 | p_bar = tqdm(total=total_cea)
624 | processed_tables = set()
625 | with closing(Pool(processes=n_thread)) as p:
626 | for input_args, output_args in p.imap_unordered(pool_table_annotation, args):
627 | processed_tables.add(input_args["table_name"])
628 | p_bar.update(len(input_args["tar_cea"]))
629 | p_bar.set_description(
630 | desc=f"{len(processed_tables)}/{total_tables}. "
631 | + input_args["table_name"]
632 | )
633 | if not output_args or output_args["status"] == "Error":
634 | if output_args.get("message"):
635 | print(output_args.get("message"))
636 | else:
637 | print(
638 | "Error: Could not get POST input, please retry again. (The server is overloading now)"
639 | )
640 | continue
641 | if not output_args.get("semantic"):
642 | continue
643 | if output_args["semantic"].get("cea"):
644 | for r, c, a in output_args["semantic"]["cea"]:
645 | res_cea[(output_args["table_name"], r, c)][a] += len(
646 | input_args["tar_cea"]
647 | )
648 |
649 | if output_args["semantic"].get("cta"):
650 | for c, a in output_args["semantic"]["cta"]:
651 | res_cta[(output_args["table_name"], c)][a[0]] += len(
652 | input_args["tar_cea"]
653 | )
654 | if output_args["semantic"].get("cpa"):
655 | for c1, c2, a in output_args["semantic"]["cpa"]:
656 | res_cpa[(output_args["table_name"], c1, c2)][a[0]] += len(
657 | input_args["tar_cea"]
658 | )
659 |
660 | save_final_result(dir_cea_res, res_cea)
661 | save_final_result(dir_cta_res, res_cta)
662 | save_final_result(dir_cpa_res, res_cpa)
663 | p_bar.close()
664 |
665 | save_final_result(dir_cea_res, res_cea)
666 | save_final_result(dir_cta_res, res_cta)
667 | save_final_result(dir_cpa_res, res_cpa)
668 |
669 | print(f"Run time: {str(timedelta(seconds=round(time() - start)))}")
670 |
671 |
672 | if __name__ == "__main__":
673 | challenge = "semtab2020"
674 | data_name = "2T"
675 | domain = "online"
676 |
677 | m_call_run_semtab(
678 | challenge=challenge,
679 | data_name=data_name,
680 | n_thread=4,
681 | table_limit=0,
682 | search_mode="a",
683 | search_limit=100,
684 | search_expensive=True,
685 | chunk_size=200,
686 | chunk_limit=0,
687 | )
688 | scores = score_cea(
689 | DIR_CEA_GT.format(challenge=challenge, data_name=data_name),
690 | DIR_CEA_RES.format(challenge=challenge, data_name=data_name, source=domain),
691 | )
692 | print(json.dumps(scores, indent=4))
693 |
694 |
695 | """
696 | 180/180. Z4M8AT89: 100%|██████████████████████████████████████| 667244/667244 [21:53:57<00:00, 8.46it/s]
697 | {
698 | "ALL": {
699 | "precision": 0.8954061559997541,
700 | "recall": 0.8953726073220591,
701 | "f1": 0.8953893813466541,
702 | "correct": 597432,
703 | "gt": 667244,
704 | "submit": 667219
705 | }
706 | }
707 | """
708 |
--------------------------------------------------------------------------------
/static/images/MTabESSemTab2T.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/MTabESSemTab2T.png
--------------------------------------------------------------------------------
/static/images/MTabESSemTabR1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/MTabESSemTabR1.png
--------------------------------------------------------------------------------
/static/images/MTabESSemTabR2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/MTabESSemTabR2.png
--------------------------------------------------------------------------------
/static/images/MTabESSemTabR3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/MTabESSemTabR3.png
--------------------------------------------------------------------------------
/static/images/MTabESSemTabR4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/MTabESSemTabR4.png
--------------------------------------------------------------------------------
/static/images/logo_mtab_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/logo_mtab_1.png
--------------------------------------------------------------------------------
/static/images/logo_mtab_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/logo_mtab_2.png
--------------------------------------------------------------------------------
/static/images/logo_mtab_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/logo_mtab_3.png
--------------------------------------------------------------------------------
/static/images/logo_mtab_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/logo_mtab_4.png
--------------------------------------------------------------------------------
/static/images/mtab_pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/mtab_pic.png
--------------------------------------------------------------------------------
/static/images/semtab2019.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/semtab2019.png
--------------------------------------------------------------------------------
/static/images/semtab2020.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/semtab2020.png
--------------------------------------------------------------------------------
/static/images/semtab2021.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/images/semtab2021.png
--------------------------------------------------------------------------------
/static/others/0AJSJYAL.xltx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/others/0AJSJYAL.xltx
--------------------------------------------------------------------------------
/static/others/mytables.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/others/mytables.zip
--------------------------------------------------------------------------------
/static/others/mytables_ntar.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phucty/mtab_tool/c4642017d6c8b23453d7695c162fb5711b87a683/static/others/mytables_ntar.zip
--------------------------------------------------------------------------------
/static/others/semtab2021/biotable/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/static/others/semtab2021/hardtable/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------