exsclaim 2.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. exsclaim-2.4.1/LICENSE +21 -0
  2. exsclaim-2.4.1/MANIFEST.in +31 -0
  3. exsclaim-2.4.1/PKG-INFO +167 -0
  4. exsclaim-2.4.1/README.md +77 -0
  5. exsclaim-2.4.1/exsclaim/README.md +13 -0
  6. exsclaim-2.4.1/exsclaim/__init__.py +17 -0
  7. exsclaim-2.4.1/exsclaim/__main__.py +187 -0
  8. exsclaim-2.4.1/exsclaim/api/__init__.py +5 -0
  9. exsclaim-2.4.1/exsclaim/api/__main__.py +965 -0
  10. exsclaim-2.4.1/exsclaim/api/config.py +8 -0
  11. exsclaim-2.4.1/exsclaim/api/middleware.py +165 -0
  12. exsclaim-2.4.1/exsclaim/api/models.py +174 -0
  13. exsclaim-2.4.1/exsclaim/api/routers/__init__.py +1 -0
  14. exsclaim-2.4.1/exsclaim/api/routers/v1.py +211 -0
  15. exsclaim-2.4.1/exsclaim/api/settings.py +18 -0
  16. exsclaim-2.4.1/exsclaim/caption.py +266 -0
  17. exsclaim-2.4.1/exsclaim/captions/__init__.py +2 -0
  18. exsclaim-2.4.1/exsclaim/captions/ollama_llms.py +87 -0
  19. exsclaim-2.4.1/exsclaim/captions/openai_llms.py +104 -0
  20. exsclaim-2.4.1/exsclaim/config.py +29 -0
  21. exsclaim-2.4.1/exsclaim/dashboard/__init__.py +1 -0
  22. exsclaim-2.4.1/exsclaim/dashboard/__main__.py +103 -0
  23. exsclaim-2.4.1/exsclaim/dashboard/assets/Argonnelablogo-White.png +0 -0
  24. exsclaim-2.4.1/exsclaim/dashboard/assets/Argonnelablogo.png +0 -0
  25. exsclaim-2.4.1/exsclaim/dashboard/assets/ExsclaimLogo-Black.png +0 -0
  26. exsclaim-2.4.1/exsclaim/dashboard/assets/ExsclaimLogo-Inverted.png +0 -0
  27. exsclaim-2.4.1/exsclaim/dashboard/assets/ExsclaimLogo.png +0 -0
  28. exsclaim-2.4.1/exsclaim/dashboard/assets/exsclaim.css +192 -0
  29. exsclaim-2.4.1/exsclaim/dashboard/assets/favicon.ico +0 -0
  30. exsclaim-2.4.1/exsclaim/dashboard/assets/recolor.py +50 -0
  31. exsclaim-2.4.1/exsclaim/dashboard/components/__init__.py +4 -0
  32. exsclaim-2.4.1/exsclaim/dashboard/components/api_client.py +61 -0
  33. exsclaim-2.4.1/exsclaim/dashboard/components/common.py +158 -0
  34. exsclaim-2.4.1/exsclaim/dashboard/components/homepage.py +35 -0
  35. exsclaim-2.4.1/exsclaim/dashboard/components/layout.py +605 -0
  36. exsclaim-2.4.1/exsclaim/dashboard/components/query.py +430 -0
  37. exsclaim-2.4.1/exsclaim/dashboard/components/resultpage.py +33 -0
  38. exsclaim-2.4.1/exsclaim/dashboard/config.py +5 -0
  39. exsclaim-2.4.1/exsclaim/db/__init__.py +2 -0
  40. exsclaim-2.4.1/exsclaim/db/models.py +261 -0
  41. exsclaim-2.4.1/exsclaim/db/postgres.py +177 -0
  42. exsclaim-2.4.1/exsclaim/exceptions.py +41 -0
  43. exsclaim-2.4.1/exsclaim/figure.py +439 -0
  44. exsclaim-2.4.1/exsclaim/figures/__init__.py +9 -0
  45. exsclaim-2.4.1/exsclaim/figures/classes.py +29 -0
  46. exsclaim-2.4.1/exsclaim/figures/config/scale_label_reader.json +169 -0
  47. exsclaim-2.4.1/exsclaim/figures/config/yolov3_default_master.cfg +34 -0
  48. exsclaim-2.4.1/exsclaim/figures/config/yolov3_default_subfig.cfg +34 -0
  49. exsclaim-2.4.1/exsclaim/figures/masks.py +28 -0
  50. exsclaim-2.4.1/exsclaim/figures/models/__init__.py +4 -0
  51. exsclaim-2.4.1/exsclaim/figures/models/crnn.py +188 -0
  52. exsclaim-2.4.1/exsclaim/figures/models/network.py +447 -0
  53. exsclaim-2.4.1/exsclaim/figures/models/yolo_layer.py +727 -0
  54. exsclaim-2.4.1/exsclaim/figures/models/yolov3.py +322 -0
  55. exsclaim-2.4.1/exsclaim/figures/scale/__init__.py +10 -0
  56. exsclaim-2.4.1/exsclaim/figures/scale/coco_eval.py +380 -0
  57. exsclaim-2.4.1/exsclaim/figures/scale/coco_utils.py +262 -0
  58. exsclaim-2.4.1/exsclaim/figures/scale/corpus.txt +50000 -0
  59. exsclaim-2.4.1/exsclaim/figures/scale/ctc.py +218 -0
  60. exsclaim-2.4.1/exsclaim/figures/scale/dataset.py +319 -0
  61. exsclaim-2.4.1/exsclaim/figures/scale/engine.py +182 -0
  62. exsclaim-2.4.1/exsclaim/figures/scale/evaluate_scale.py +457 -0
  63. exsclaim-2.4.1/exsclaim/figures/scale/label_reader_test.py +481 -0
  64. exsclaim-2.4.1/exsclaim/figures/scale/lm.py +57 -0
  65. exsclaim-2.4.1/exsclaim/figures/scale/process.py +79 -0
  66. exsclaim-2.4.1/exsclaim/figures/scale/scale_bar_model.py +223 -0
  67. exsclaim-2.4.1/exsclaim/figures/scale/train_label_reader.py +483 -0
  68. exsclaim-2.4.1/exsclaim/figures/scale/utils.py +286 -0
  69. exsclaim-2.4.1/exsclaim/figures/separator/__init__.py +1 -0
  70. exsclaim-2.4.1/exsclaim/figures/separator/process.py +264 -0
  71. exsclaim-2.4.1/exsclaim/figures/transformations.py +19 -0
  72. exsclaim-2.4.1/exsclaim/journal.py +1235 -0
  73. exsclaim-2.4.1/exsclaim/notifications.py +105 -0
  74. exsclaim-2.4.1/exsclaim/pdf.py +332 -0
  75. exsclaim-2.4.1/exsclaim/pipeline.py +754 -0
  76. exsclaim-2.4.1/exsclaim/tests/__init__.py +0 -0
  77. exsclaim-2.4.1/exsclaim/tests/accuarcy_test.py +162 -0
  78. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/ncomms5946_fig1.jpg +0 -0
  79. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/ncomms5946_fig2.jpg +0 -0
  80. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/ncomms5946_fig3.jpg +0 -0
  81. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/ncomms5946_fig4.jpg +0 -0
  82. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/ncomms5946_fig5.jpg +0 -0
  83. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/ncomms5946_fig6.jpg +0 -0
  84. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/ncomms5946_fig7.jpg +0 -0
  85. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/ncomms5946_fig8.jpg +0 -0
  86. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/ncomms5946_fig9.jpg +0 -0
  87. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/s41467-018-06211-3_fig1.jpg +0 -0
  88. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/s41467-018-06211-3_fig2.jpg +0 -0
  89. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/s41467-018-06211-3_fig3.jpg +0 -0
  90. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/s41467-018-06211-3_fig4.jpg +0 -0
  91. exsclaim-2.4.1/exsclaim/tests/data/images/pipeline/s41467-018-06211-3_fig5.jpg +0 -0
  92. exsclaim-2.4.1/exsclaim/tests/data/images/scale_bar_test_images/basic_figure.jpg +0 -0
  93. exsclaim-2.4.1/exsclaim/tests/data/images/scale_bar_test_images/blue_scale_labels.jpg +0 -0
  94. exsclaim-2.4.1/exsclaim/tests/data/images/scale_bar_test_images/no_scale_objects.jpg +0 -0
  95. exsclaim-2.4.1/exsclaim/tests/data/images/scale_bar_test_images/white_and_black_scale_objects.png +0 -0
  96. exsclaim-2.4.1/exsclaim/tests/data/images/scale_bar_test_images/white_scale_bars_no_labels.jpg +0 -0
  97. exsclaim-2.4.1/exsclaim/tests/data/images/scale_label_test_images/dark_text_no_apparent_space.jpg +0 -0
  98. exsclaim-2.4.1/exsclaim/tests/data/images/scale_label_test_images/red_text_low_quality.jpg +0 -0
  99. exsclaim-2.4.1/exsclaim/tests/data/images/scale_label_test_images/terrible_quality.jpg +0 -0
  100. exsclaim-2.4.1/exsclaim/tests/data/images/scale_label_test_images/unreadable.jpg +0 -0
  101. exsclaim-2.4.1/exsclaim/tests/data/images/scale_label_test_images/white_text_decimal.jpg +0 -0
  102. exsclaim-2.4.1/exsclaim/tests/data/images/scale_label_test_images/white_text_large_apparent_space.jpg +0 -0
  103. exsclaim-2.4.1/exsclaim/tests/data/images/scale_label_test_images/white_text_light_background_low_quality.jpg +0 -0
  104. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/ncomms11770.html +2176 -0
  105. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/ncomms1737.html +1118 -0
  106. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/ncomms5946.html +1408 -0
  107. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/s41467-018-06211-3.html +1244 -0
  108. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/s41557-020-0418-3.html +1304 -0
  109. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/s41598-020-77062-6.html +1793 -0
  110. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/s41929-019-0365-9.html +1137 -0
  111. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/srep01497.html +1112 -0
  112. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/srep23945.html +1201 -0
  113. exsclaim-2.4.1/exsclaim/tests/data/nature_articles/test_search.html +1743 -0
  114. exsclaim-2.4.1/exsclaim/tests/data/nature_closed_expected.json +5382 -0
  115. exsclaim-2.4.1/exsclaim/tests/data/nature_search.html +5338 -0
  116. exsclaim-2.4.1/exsclaim/tests/data/nature_test.json +15 -0
  117. exsclaim-2.4.1/exsclaim/tests/test_api.py +80 -0
  118. exsclaim-2.4.1/exsclaim/tests/test_figure.py +105 -0
  119. exsclaim-2.4.1/exsclaim/tests/test_journal.py +100 -0
  120. exsclaim-2.4.1/exsclaim/tests/test_pipeline.py +133 -0
  121. exsclaim-2.4.1/exsclaim/tool.py +361 -0
  122. exsclaim-2.4.1/exsclaim/utilities/__init__.py +6 -0
  123. exsclaim-2.4.1/exsclaim/utilities/boxes.py +69 -0
  124. exsclaim-2.4.1/exsclaim/utilities/download.py +48 -0
  125. exsclaim-2.4.1/exsclaim/utilities/files.py +13 -0
  126. exsclaim-2.4.1/exsclaim/utilities/logging.py +50 -0
  127. exsclaim-2.4.1/exsclaim/utilities/models.py +85 -0
  128. exsclaim-2.4.1/exsclaim/utilities/paths.py +38 -0
  129. exsclaim-2.4.1/exsclaim/version.py +1 -0
  130. exsclaim-2.4.1/exsclaim/version.pyi +7 -0
  131. exsclaim-2.4.1/exsclaim.egg-info/PKG-INFO +167 -0
  132. exsclaim-2.4.1/exsclaim.egg-info/SOURCES.txt +138 -0
  133. exsclaim-2.4.1/exsclaim.egg-info/dependency_links.txt +1 -0
  134. exsclaim-2.4.1/exsclaim.egg-info/entry_points.txt +2 -0
  135. exsclaim-2.4.1/exsclaim.egg-info/requires.txt +39 -0
  136. exsclaim-2.4.1/exsclaim.egg-info/top_level.txt +1 -0
  137. exsclaim-2.4.1/pyproject.toml +48 -0
  138. exsclaim-2.4.1/requirements.txt +58 -0
  139. exsclaim-2.4.1/setup.cfg +4 -0
  140. exsclaim-2.4.1/setup.py +54 -0
exsclaim-2.4.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 MaterialEyes
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.
@@ -0,0 +1,31 @@
1
+ include exsclaim/README.md
2
+
3
+ recursive-include exsclaim *.py
4
+ recursive-include exsclaim *.pyi
5
+
6
+ recursive-include exsclaim/api *.py
7
+ recursive-include exsclaim/api *.pyi
8
+
9
+ recursive-include exsclaim/dashboard *.py
10
+ recursive-include exsclaim/dashboard *.pyi
11
+
12
+ include exsclaim/figures/config/yolov3_default_master.cfg
13
+ include exsclaim/figures/config/yolov3_default_subfig.cfg
14
+ include exsclaim/figures/config/scale_label_reader.json
15
+ include exsclaim/figures/scale/corpus.txt
16
+
17
+ include exsclaim/tests/data/nature_test.json
18
+ include exsclaim/tests/data/images/pipeline/*
19
+ include exsclaim/tests/data/nature_articles/*
20
+ include exsclaim/tests/data/nature_search.html
21
+ include exsclaim/tests/data/images/scale_bar_test_images/*
22
+ include exsclaim/tests/data/images/scale_label_test_images/*
23
+ include exsclaim/tests/data/nature_closed_expected.json
24
+
25
+ include exsclaim/dashboard/assets/*.png
26
+ include exsclaim/dashboard/assets/*.ico
27
+ include exsclaim/dashboard/assets/*.css
28
+
29
+ include exsclaim/dashboard/components
30
+
31
+ include requirements.txt
@@ -0,0 +1,167 @@
1
+ Metadata-Version: 2.4
2
+ Name: exsclaim
3
+ Version: 2.4.1
4
+ Summary: EXSCLAIM! is a library for the automatic EXtraction, Separation, and Caption-based natural Language Annotation of IMages from scientific figures.
5
+ Author-email: "Eric Schwenker, Trevor Spreadbury, Weixin Jiang, Maria Chan, Len Washington III" <developer@materialeyes.org>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 MaterialEyes
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://exsclaim.materialeyes.org
29
+ Project-URL: Source, https://github.com/MaterialEyes/exsclaim2.0
30
+ Project-URL: Documentation, https://github.com/MaterialEyes/exsclaim2.0/wiki
31
+ Project-URL: Issues, https://github.com/MaterialEyes/exsclaim2.0/issues
32
+ Project-URL: Paper, https://arxiv.org/abs/2103.10631
33
+ Classifier: Development Status :: 4 - Beta
34
+ Classifier: Environment :: Console
35
+ Classifier: Environment :: Web Environment
36
+ Classifier: Framework :: Dash
37
+ Classifier: Framework :: FastAPI
38
+ Classifier: Intended Audience :: Science/Research
39
+ Classifier: License :: OSI Approved :: MIT License
40
+ Classifier: Operating System :: OS Independent
41
+ Classifier: Programming Language :: JavaScript
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Programming Language :: Python :: 3.13
45
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
46
+ Classifier: Topic :: Text Processing
47
+ Requires-Python: >=3.13.2
48
+ Description-Content-Type: text/markdown
49
+ License-File: LICENSE
50
+ Requires-Dist: loguru==0.7.3
51
+ Requires-Dist: numpy==2.2.6
52
+ Requires-Dist: opencv-contrib-python-headless==4.12.0.88
53
+ Requires-Dist: Pillow==11.3.0
54
+ Requires-Dist: ultralytics==8.3.170
55
+ Requires-Dist: aiohttp==3.12.15
56
+ Requires-Dist: httpx==0.28.1
57
+ Requires-Dist: brotli==1.1.0
58
+ Requires-Dist: selenium==4.34.2
59
+ Requires-Dist: selenium-stealth==1.0.6
60
+ Requires-Dist: urllib3==2.5.0
61
+ Requires-Dist: asyncpg==0.30.0
62
+ Requires-Dist: beautifulsoup4==4.13.4
63
+ Requires-Dist: soupsieve==2.7
64
+ Requires-Dist: deepdiff==8.5.0
65
+ Requires-Dist: pycocotools==2.0.10
66
+ Requires-Dist: pytz==2025.2
67
+ Requires-Dist: typing_extensions==4.14.0
68
+ Requires-Dist: PyYAML==6.0.2
69
+ Requires-Dist: pymupdf==1.26.3
70
+ Requires-Dist: torch==2.7.1
71
+ Requires-Dist: torchvision==0.22.1
72
+ Requires-Dist: pytorch-model-summary==0.1.2
73
+ Requires-Dist: ollama==0.5.1
74
+ Requires-Dist: openai==1.97.1
75
+ Requires-Dist: asksageclient==1.31
76
+ Requires-Dist: dash[async]==3.1.1
77
+ Requires-Dist: fastapi[standard]==0.116.1
78
+ Requires-Dist: pydantic==2.11.7
79
+ Requires-Dist: starlette==0.47.2
80
+ Requires-Dist: uvicorn==0.35.0
81
+ Requires-Dist: hypercorn==0.17.3
82
+ Requires-Dist: sqlmodel==0.0.24
83
+ Requires-Dist: sqlalchemy==2.0.42
84
+ Requires-Dist: pydantic_settings==2.10.1
85
+ Requires-Dist: uuid-utils==0.11.0
86
+ Requires-Dist: dash_bootstrap_components==2.0.3
87
+ Requires-Dist: gunicorn[gevent]==23.0.0
88
+ Requires-Dist: certifi==2025.7.14
89
+ Dynamic: license-file
90
+
91
+ # EXSCLAIM2.0: LLM-powered Automatic **EX**traction, **S**eparation, and **C**aption-based natural **L**anguage **A**nnotation of **IM**ages from scientific figures
92
+ [![License](https://img.shields.io/github/license/MaterialEyes/exsclaim2.0.svg?color=blue)](https://github.com/MaterialEyes/exsclaim2.0/blob/main/LICENSE)
93
+ [![Website](https://img.shields.io/website?url=https%3A%2F%2Fexsclaim-dev.materialeyes.org%2F&up_message=online&down_message=offline&down_color=red&label=Website)
94
+ ](https://exsclaim-dev.materialeyes.org)
95
+ [![Release](https://img.shields.io/github/release/MaterialEyes/exsclaim2.0.svg)](https://github.com/MaterialEyes/exsclaim2.0/releases)
96
+ [![DOI](https://zenodo.org/badge/DOI/10.48550/arXiv.2103.10631.svg)](https://arxiv.org/abs/2103.10631)
97
+
98
+ ## 🤔 Consider Collaboration
99
+
100
+ If you find this tool or any of its derived capabilities useful, please consider registering as a user of Center for Nanoscale Materials. We will keep you posted of latest developments, as well as opportunities for computational resources, relevant data, and collaboration. Please contact Maria Chan (mchan@anl.gov) for details.
101
+
102
+ ## Introduction to EXSCLAIM2.0
103
+
104
+ EXSCLAIM2.0 is a Python package combining EXSCLAIM! code with Large Language models (LLMs) that can be used for the automatic generation of datasets of labeled images from published papers.
105
+ There are four main steps:
106
+ 1. [JournalScraper](https://github.com/MaterialEyes/exsclaim2.0/wiki/JournalScraper): scrap journal websites, acquiring figures, captions, and metadata
107
+ 2. [CaptionDistributor](https://github.com/MaterialEyes/exsclaim2.0/wiki/CaptionDistributor): separate figure captions into the component chunks that refer to the figure's subfigures using LLMs and prompt engineering
108
+ 3. [FigureSeparator](https://github.com/MaterialEyes/exsclaim2.0/wiki/FigureSeparator): separate figures into subfigures, detect scale information, label, and type of image
109
+
110
+ ## Examples and tutorials
111
+ We provide several tutorials demonstrating how to use EXSCLAIM2.0:
112
+ 1. [Nature_exsclaim_search](/notebooks/1_Nature_exsclaim_search.ipynb): automatically scrapping data from literature and performing Named Entity Recognition (NER) on the extracted captions.
113
+ 2. [HTMLScraper](/notebooks/2_HTMLScraper.ipynb): automatically scrapping data from user provided HTML files
114
+ 3. [Microscopy_CLIP_retrieval](/notebooks/3_Microscopy_CLIP_retrieval.ipynb): Using Microscopy_CLIP to perform image-to-image and text-to-image retrieval on our multimodal microscopy dataset.
115
+
116
+
117
+ ## Installation
118
+ The guides to install EXSCLAIM through Pip, Git and Docker can be found within the [wiki](https://github.com/MaterialEyes/exsclaim2.0/wiki/Installation).
119
+ The guides include installing pre-compiled versions as well as building from the source code and then installing.
120
+
121
+ ### Using Exsclaim 2.0
122
+ ```python
123
+ from exsclaim import Pipeline
124
+ search_query = {
125
+ ...
126
+ }
127
+ results = Pipeline(search_query_json)
128
+ ```
129
+ where `search_query` is either a dictionary representing a valid JSON object, or a Pathlike string pointing towards a valid JSON file,
130
+ or
131
+ ```shell
132
+ python -m exsclaim query {path to json file holding search query}
133
+ ```
134
+ More extensive guides can be found within the [wiki](https://github.com/MaterialEyes/exsclaim2.0/wiki/Running-the-EXSCLAIM-Pipeline).
135
+
136
+ ### Using Docker Compose
137
+ To use Docker Compose to host the service, run the following commands in the base directory:
138
+ ```shell
139
+ docker compose build base
140
+ docker compose build {service(s) here}
141
+ docker compose up {service(s) here}
142
+ ```
143
+
144
+ ## Acknowledgements
145
+ This material is based upon work supported by Laboratory Directed Research and Development (LDRD) funding from Argonne National Laboratory, provided by the Director, Office of Science, of the U.S. Department of Energy under Contract No. DE-AC02-06CH11357
146
+
147
+ This work was performed at the Center for Nanoscale Materials, a U.S. Department of Energy Office of Science User Facility, and supported by the U.S. Department of Energy, Office of Science, under Contract No. DE-AC02-06CH11357.
148
+
149
+ We gratefully acknowledge the computing resources provided on Bebop, a high-performance computing cluster operated by the Laboratory Computing Resource Center at Argonne National Laboratory.
150
+
151
+ ## Citation
152
+ If you find EXSCLAIM! useful, please encourage its development by citing the following [paper](https://arxiv.org/abs/2103.10631) in your research:
153
+ ```
154
+ Schwenker, E., Jiang, W. Spreadbury, T., Ferrier N., Cossairt, O., Chan M.K.Y., EXSCLAIM! - An automated pipeline for the construction and
155
+ labeling of materials imaging datasets from scientific literature. arXiv e-prints (2021): arXiv-2103
156
+ ```
157
+
158
+ #### Bibtex
159
+ ```
160
+ @article{schwenker2021exsclaim,
161
+ title={EXSCLAIM! - An automated pipeline for the construction of labeled materials imaging datasets from literature},
162
+ author={Schwenker, Eric and Jiang, Weixin and Spreadbury, Trevor and Ferrier, Nicola and Cossairt, Oliver and Chan, Maria KY},
163
+ journal={arXiv e-prints},
164
+ pages={arXiv--2103},
165
+ year={2021}
166
+ }
167
+ ```
@@ -0,0 +1,77 @@
1
+ # EXSCLAIM2.0: LLM-powered Automatic **EX**traction, **S**eparation, and **C**aption-based natural **L**anguage **A**nnotation of **IM**ages from scientific figures
2
+ [![License](https://img.shields.io/github/license/MaterialEyes/exsclaim2.0.svg?color=blue)](https://github.com/MaterialEyes/exsclaim2.0/blob/main/LICENSE)
3
+ [![Website](https://img.shields.io/website?url=https%3A%2F%2Fexsclaim-dev.materialeyes.org%2F&up_message=online&down_message=offline&down_color=red&label=Website)
4
+ ](https://exsclaim-dev.materialeyes.org)
5
+ [![Release](https://img.shields.io/github/release/MaterialEyes/exsclaim2.0.svg)](https://github.com/MaterialEyes/exsclaim2.0/releases)
6
+ [![DOI](https://zenodo.org/badge/DOI/10.48550/arXiv.2103.10631.svg)](https://arxiv.org/abs/2103.10631)
7
+
8
+ ## 🤔 Consider Collaboration
9
+
10
+ If you find this tool or any of its derived capabilities useful, please consider registering as a user of Center for Nanoscale Materials. We will keep you posted of latest developments, as well as opportunities for computational resources, relevant data, and collaboration. Please contact Maria Chan (mchan@anl.gov) for details.
11
+
12
+ ## Introduction to EXSCLAIM2.0
13
+
14
+ EXSCLAIM2.0 is a Python package combining EXSCLAIM! code with Large Language models (LLMs) that can be used for the automatic generation of datasets of labeled images from published papers.
15
+ There are four main steps:
16
+ 1. [JournalScraper](https://github.com/MaterialEyes/exsclaim2.0/wiki/JournalScraper): scrap journal websites, acquiring figures, captions, and metadata
17
+ 2. [CaptionDistributor](https://github.com/MaterialEyes/exsclaim2.0/wiki/CaptionDistributor): separate figure captions into the component chunks that refer to the figure's subfigures using LLMs and prompt engineering
18
+ 3. [FigureSeparator](https://github.com/MaterialEyes/exsclaim2.0/wiki/FigureSeparator): separate figures into subfigures, detect scale information, label, and type of image
19
+
20
+ ## Examples and tutorials
21
+ We provide several tutorials demonstrating how to use EXSCLAIM2.0:
22
+ 1. [Nature_exsclaim_search](/notebooks/1_Nature_exsclaim_search.ipynb): automatically scrapping data from literature and performing Named Entity Recognition (NER) on the extracted captions.
23
+ 2. [HTMLScraper](/notebooks/2_HTMLScraper.ipynb): automatically scrapping data from user provided HTML files
24
+ 3. [Microscopy_CLIP_retrieval](/notebooks/3_Microscopy_CLIP_retrieval.ipynb): Using Microscopy_CLIP to perform image-to-image and text-to-image retrieval on our multimodal microscopy dataset.
25
+
26
+
27
+ ## Installation
28
+ The guides to install EXSCLAIM through Pip, Git and Docker can be found within the [wiki](https://github.com/MaterialEyes/exsclaim2.0/wiki/Installation).
29
+ The guides include installing pre-compiled versions as well as building from the source code and then installing.
30
+
31
+ ### Using Exsclaim 2.0
32
+ ```python
33
+ from exsclaim import Pipeline
34
+ search_query = {
35
+ ...
36
+ }
37
+ results = Pipeline(search_query_json)
38
+ ```
39
+ where `search_query` is either a dictionary representing a valid JSON object, or a Pathlike string pointing towards a valid JSON file,
40
+ or
41
+ ```shell
42
+ python -m exsclaim query {path to json file holding search query}
43
+ ```
44
+ More extensive guides can be found within the [wiki](https://github.com/MaterialEyes/exsclaim2.0/wiki/Running-the-EXSCLAIM-Pipeline).
45
+
46
+ ### Using Docker Compose
47
+ To use Docker Compose to host the service, run the following commands in the base directory:
48
+ ```shell
49
+ docker compose build base
50
+ docker compose build {service(s) here}
51
+ docker compose up {service(s) here}
52
+ ```
53
+
54
+ ## Acknowledgements
55
+ This material is based upon work supported by Laboratory Directed Research and Development (LDRD) funding from Argonne National Laboratory, provided by the Director, Office of Science, of the U.S. Department of Energy under Contract No. DE-AC02-06CH11357
56
+
57
+ This work was performed at the Center for Nanoscale Materials, a U.S. Department of Energy Office of Science User Facility, and supported by the U.S. Department of Energy, Office of Science, under Contract No. DE-AC02-06CH11357.
58
+
59
+ We gratefully acknowledge the computing resources provided on Bebop, a high-performance computing cluster operated by the Laboratory Computing Resource Center at Argonne National Laboratory.
60
+
61
+ ## Citation
62
+ If you find EXSCLAIM! useful, please encourage its development by citing the following [paper](https://arxiv.org/abs/2103.10631) in your research:
63
+ ```
64
+ Schwenker, E., Jiang, W. Spreadbury, T., Ferrier N., Cossairt, O., Chan M.K.Y., EXSCLAIM! - An automated pipeline for the construction and
65
+ labeling of materials imaging datasets from scientific literature. arXiv e-prints (2021): arXiv-2103
66
+ ```
67
+
68
+ #### Bibtex
69
+ ```
70
+ @article{schwenker2021exsclaim,
71
+ title={EXSCLAIM! - An automated pipeline for the construction of labeled materials imaging datasets from literature},
72
+ author={Schwenker, Eric and Jiang, Weixin and Spreadbury, Trevor and Ferrier, Nicola and Cossairt, Oliver and Chan, Maria KY},
73
+ journal={arXiv e-prints},
74
+ pages={arXiv--2103},
75
+ year={2021}
76
+ }
77
+ ```
@@ -0,0 +1,13 @@
1
+ ## EXSCLAIM Module
2
+
3
+ This directory contains the relevant code for the EXSCLAIM module, organized as follows:
4
+
5
+ - pipeline.py: Code for Pipeline class, which runs ExsclaimTool subclasses on Query JSONs.
6
+ - tool.py: Defines base ExsclaimTool class and CaptionDistributor and JournalScraper subclasses. Each ExsclaimTool class is initialized with a Query JSON and has methods to run the tool, update the exsclaim.json, and load any necessary models.
7
+ - figure.py: Defines FigureSeparator, a subclass of ExsclaimTool. Has methods to separate, classify, and read the labels of subfigures and to determine the scale of subfigures.
8
+ - caption.py: Defines useful functions used by CaptionDistributor.
9
+ - journal.py: Defines the JournalFamily class. Nature and ACS subfamilies are defined and other journal families can be added and used by JournalScraper.
10
+ - figures/: Additional modules for defining and training figure models.
11
+ - captions/: Additional modules for defining and training caption models.
12
+ - tests/: test files and sample data to check results.
13
+ - utilities/: Modules with functions that are useful across several modules
@@ -0,0 +1,17 @@
1
+ from .db import *
2
+ from .captions import *
3
+ from .figures import *
4
+ from .tests import *
5
+ from .utilities import *
6
+
7
+ from .exceptions import *
8
+ from .caption import *
9
+ from .figure import *
10
+ from .journal import *
11
+ from .notifications import *
12
+ from .pipeline import *
13
+ from .tool import *
14
+ from .version import version as __version__
15
+
16
+ from logging import getLogger, NullHandler
17
+ getLogger(__name__).addHandler(NullHandler())
@@ -0,0 +1,187 @@
1
+ from . import Pipeline, PipelineInterruptionException
2
+
3
+ try:
4
+ from . import __version__
5
+ except ImportError:
6
+ __version__ = None
7
+ from argparse import ArgumentParser
8
+ from atexit import register
9
+ from json import load
10
+ from os import PathLike, chmod
11
+ from os.path import splitext, isfile
12
+ from pathlib import Path
13
+ from shutil import make_archive
14
+
15
+
16
+ @register
17
+ def on_terminate():
18
+ import logging
19
+ logger = logging.getLogger(__name__)
20
+
21
+ for handler in logger.handlers:
22
+ handler.flush()
23
+
24
+ logging.shutdown()
25
+
26
+
27
+ async def run_pipeline(query=None, verbose:bool=False, compress:str=None, compress_location:str=None, journal_scraper:bool=False,
28
+ pdf_scraper:bool=False, caption_distributor:bool=False, figure_separator:bool=False, **kwargs):
29
+ if query is None:
30
+ raise ValueError("The search query is required.")
31
+
32
+ # if not any((journal_scraper, pdf_scraper, caption_distributor, figure_separator)):
33
+ # raise ValueError("You must run the pipeline with at least one tool.")
34
+
35
+ compress = compress or ""
36
+
37
+ path = Path(query).absolute()
38
+ if not path.exists():
39
+ raise ValueError(f"The search query file \"{path}\" does not exist.")
40
+
41
+ with open(path, "r") as f:
42
+ search_query = load(f)
43
+
44
+ if verbose:
45
+ if not search_query.get("logging", None):
46
+ search_query["logging"] = ["print"]
47
+
48
+ if "print" not in search_query["logging"]:
49
+ search_query["logging"].append("print")
50
+
51
+ pipeline = Pipeline(search_query)
52
+ try:
53
+ results = await pipeline.run(caption_distributor=caption_distributor, pdf_scraper=pdf_scraper,
54
+ journal_scraper=journal_scraper, figure_separator=figure_separator)
55
+
56
+ for handler in pipeline.logger.handlers:
57
+ handler.flush()
58
+
59
+ if compress:
60
+ name = search_query["name"]
61
+ save_location, _ = splitext(compress_location or str(pipeline.results_directory))
62
+ make_archive(save_location, compress, root_dir=str(pipeline.results_directory.parent), base_dir=name)
63
+
64
+ try:
65
+ chmod(save_location, 0o775)
66
+ print("Changed the permissions.")
67
+ except PermissionError:
68
+ print(f"Could not change the permissions of {save_location} to 775.")
69
+ pipeline.logger.warning(f"Could not change the permissions of {save_location} to 775.")
70
+
71
+ except PipelineInterruptionException as e:
72
+ pipeline.logger.exception("The pipeline could not successfully finish running.")
73
+ if hasattr(e, "errno"):
74
+ return e.errno
75
+ return -1
76
+
77
+ return 0
78
+
79
+
80
+ async def ui(dashboard_configuration:PathLike[str] = None, api_configuration:PathLike[str] = None, blocking:bool = False):
81
+ from signal import signal, SIGINT, SIGTERM, SIGQUIT
82
+ from subprocess import Popen
83
+
84
+ exsclaim_dir = Path(__file__).parent.resolve()
85
+
86
+ def get_configuration(configuration:PathLike[str], folder:str) -> str:
87
+ configuration = configuration or (exsclaim_dir / folder / "config.py")
88
+
89
+ if not isfile(configuration):
90
+ raise FileNotFoundError(f"The configuration file \"{configuration}\" does not exist.")
91
+
92
+ configuration = f"file:{configuration}"
93
+
94
+ return configuration
95
+
96
+ api_configuration = get_configuration(api_configuration, "api")
97
+ dashboard_configuration = get_configuration(dashboard_configuration, "dashboard")
98
+
99
+ api = Popen(["/usr/local/bin/hypercorn", "-c", api_configuration, "exsclaim.api:app"])
100
+ dashboard = Popen(["/usr/local/bin/gunicorn", "-c", dashboard_configuration, "exsclaim.dashboard:server"],
101
+ cwd=str(exsclaim_dir / "dashboard"))
102
+
103
+ if not blocking:
104
+ return 0
105
+
106
+ def signal_handler(*args):
107
+ dashboard.kill()
108
+ api.kill()
109
+ return 0
110
+
111
+ for sig in {SIGINT, SIGTERM, SIGQUIT}:
112
+ signal(sig, signal_handler)
113
+
114
+ api.wait()
115
+ dashboard.wait()
116
+ return 0
117
+
118
+
119
+ async def init_db():
120
+ from .db import Database
121
+ db = Database()
122
+ await db.initialize_database()
123
+
124
+
125
+ async def launch(args=None):
126
+ parser = ArgumentParser(prog="exsclaim")
127
+
128
+ parser.add_argument("-v", "--version", action="version",
129
+ version=f"EXSCLAIM v{__version__}" if __version__ is not None else "EXSCLAIM! version is currently unavailable.")
130
+
131
+ subparsers = parser.add_subparsers(dest="command", required=True)
132
+ query_subparser = subparsers.add_parser("query", help="The path to the JSON file holding the search query.")
133
+
134
+ query_subparser.add_argument("query", help="The path to the JSON file holding the search query.")
135
+ query_subparser.add_argument("--journal_scraper", "--journal", "-js", action="store_true")
136
+ query_subparser.add_argument("--pdf_scraper", "--pdf", "-ps", action="store_true")
137
+ query_subparser.add_argument("--caption_distributor", "--caption", "-cd", action="store_true")
138
+ query_subparser.add_argument("--figure_separator", "--figure", "-fs", action="store_true")
139
+ query_subparser.add_argument("--html_scraper", "-hs", action="store_true")
140
+ query_subparser.add_argument("--compress", "-c", choices=["zip", "tar", "gztar", "bztar", "xztar"], help="Compress the search results into a tar.gz file to save space. Deletes the original folder after compression.")
141
+ query_subparser.add_argument("--compress_location", "-cl", help="The location where the compressed search results will be stored.")
142
+ query_subparser.add_argument("--verbose", "-v", action="store_true")
143
+
144
+ view_subparser = subparsers.add_parser("ui", help="View search results from EXSCLAIM!")
145
+ view_subparser.add_argument("-dc", "--dashboard_configuration", help="The path to the gunicorn configuration file for the dashboard. Example at https://github.com/benoitc/gunicorn/blob/bacbf8aa5152b94e44aa5d2a94aeaf0318a85248/examples/example_config.py")
146
+ view_subparser.add_argument("-ac", "--api_configuration", help="The path to the gunicorn configuration file for the api.")
147
+ view_subparser.add_argument("-B", "--blocking", action="store_true", help="If the program should wait for the subprocesses to finish before closing.")
148
+
149
+ db_subparser = subparsers.add_parser("initialize_db", help="Initializes the PostgreSQL database.")
150
+
151
+ for subparser in (query_subparser, view_subparser):
152
+ subparser.add_argument("--force_ollama", action="store_true", help="Fails if EXSCLAIM can't connect to the Ollama API.")
153
+
154
+ args = vars(parser.parse_args(args))
155
+
156
+ if "force_ollama" in args:
157
+ if args["force_ollama"]:
158
+ from .captions.ollama_llms import Ollama
159
+ Ollama.available_models(silent_fail=False)
160
+
161
+ del args["force_ollama"]
162
+
163
+ exit_code = None
164
+ match args["command"]:
165
+ case "query":
166
+ exit_code = await run_pipeline(**args)
167
+ case "ui":
168
+ del args["command"]
169
+ exit_code = await ui(**args)
170
+ case "initialize_db":
171
+ exit_code = await init_db()
172
+ case "train":
173
+ ...
174
+
175
+ return exit_code
176
+
177
+
178
+ def main(args=None):
179
+ from asyncio import run
180
+ exit_code = run(launch(args))
181
+
182
+ if exit_code is not None:
183
+ exit(exit_code)
184
+
185
+
186
+ if __name__ == "__main__":
187
+ main()
@@ -0,0 +1,5 @@
1
+ from .models import *
2
+ from .settings import Settings
3
+ from .__main__ import *
4
+
5
+ settings = Settings()