├── .gitignore ├── CNAME ├── README.md ├── css ├── footer.css ├── loader.css └── main.css ├── data └── acclab_data_innovation.csv ├── favicon.ico ├── imgs ├── branding │ ├── UNDP_Acc_Labs_All_Partners_horiz_white.png │ ├── UNDP_accelerator_labs_logo_vertical_color_RGB.png │ └── UNDP_accelerator_labs_logo_vertical_white.png ├── map │ ├── ai_intervention_areas.ai │ └── ai_intervention_areas.svg └── stats │ ├── area.png │ ├── data_and_applications.png │ ├── data_and_applications.svg │ ├── data_and_applications_colors.png │ ├── data_and_applications_colors.svg │ ├── data_and_applications_colors_dark.png │ ├── data_and_applications_colors_dark.svg │ ├── data_and_applications_colors_light.png │ ├── data_and_applications_colors_light.svg │ ├── datasources.png │ ├── sankey_20240402.png │ ├── sankey_20240402.svg │ └── technique.png ├── index.html ├── js ├── Array.prototype.extensions.js ├── d3.prototype.extensions.js └── sankey.js ├── notebooks ├── .ipynb_checkpoints │ └── descriptive_analysis-checkpoint.ipynb └── descriptive_analysis.ipynb ├── requirements.txt └── signals.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | env/ 3 | imgs/stats/sankey_20240402_* 4 | *.ai 5 | imgs/solutions_mapped/ -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | data-innovation.sdg-innovation-commons.org -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mainstreaming data innovation through the UNDP Accelerator Labs Network 2 | 3 | - [Download the data](https://github.com/UNDP-Accelerator-Labs/AI-map/blob/main/data/acclab_data_innovation.csv) 4 | 5 | ![Areas x datasources x labs](/imgs/stats/sankey_20240402.png) 6 | *Main data sources and application areas per lab* 7 | 8 | Over the past four years, the [UNDP Accelerator Labs Network](https://www.undp.org/acceleratorlabs) has been pushing for the mainstreaming of data innovation in sustainable development practice. Here we take stock of these efforts and highlight a certain convergence between computational techniques, datasources, and application areas. Note the work of the labs is action oriented. Other application areas and convergences undoubtably exist, typically in academic work. The purpose of this compilation is to highlight the application readiness of these techniques x datasources for specific development application areas around the world. 9 | 10 | The focus is intentionally reductive. It is on data innovation "projects". It should be noted however, that these are all part of broader portfolios of interventions. Overall, the UNDP Accelerator Labs Network sees data innovation a means to an end, not as an objective in itself. 11 | 12 | The next frontier for many of these projects is to establish data collaboratives to ensure their sustainability. More to come on this soon… 13 | 14 | ## Descriptive analysis 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 |
Computational techniqueMain datasourceAreaApplicationLab
Feature detectionDrone imageryAgriculture and pastoralismCrop disease detectionCameroon
Cabo Verde
Satellite imageryPollution and waste managementDump site detectionGuatemala
Serbia
Vietnam
Plastic waste detection in river systemsThe Philippines
Brick kiln detectionIndia
Environmental monitoringMine detectionBolivia
Land cover and use classificationSatellite imageryAgriculture and pastoralismDetection of sustained grazing areas over timeSomalia
Detection of sustained dry croplands over timeNiger
Detection of forest boundaries over timeEcuador
Multilayer map generationIndia
Disaster risk managementFlood detectionMauritania
Landslide detectionKyrgyzstan
Topic analysis and classificationOnline reviewsTourismTopic analysis of toursit reviewsJordan
Sentiment analysis of tourist reviewsMalawi
Tanzania
Social media postsGenderGender-related toxic speech detectionKyrgyzstan
Uruguay
MisinformationJordan
Generative AIPre-trained text modelOperations supportR script generation for simple, baseline data analyses and visualizationsGuatemala
EducationPersonalized ducational material generationCameroon
Pre-trained text model + political speechesDemocratic governanceUnified political speech generationArgentina
Pre-trained image modelGenderAnalysis of gender stereotypes in STEM fieldsSerbia
Pre-trained image model + urban and vegetation photosUrban developmentGreen urbanism image generation during public consultationsNorth Macedonia
Causal analysisLinkedIn profilesGenderGender inequality in the workplaceSerbia
157 | 158 | *Note we do not cover initiatives like crowdmapping here, as these are covered by the collective intelligence work of the labs.* 159 | 160 | Remote sensing data, whether low quality satellite imagery of high resolution drone imagery, is the most commonly used data source in the Accelerator Labs Network. This is likely due in part to the relative simplicity of accessing imagery and the maturity of the computational techniques. 161 | 162 | We also see a trend in applicaion areas for this type of data. Agriculture and pastoralism, and pollution and waste management are most common across labs, often trying to detect features in the imagery, like the aggregation of solid waste or crop diseases, or for deriving labd cover and land use maps, and vegetation indices. 163 | 164 | We also see a trend across several labs on the use of online posts, typically to travel sites, to understand sub-national toursim dynamics. 165 | 166 | -------------------------------------------------------------------------------- /css/footer.css: -------------------------------------------------------------------------------- 1 | footer { 2 | position: relative; 3 | background-color: #0468B1; 4 | background: linear-gradient(180deg, #005687 0%, #0468B1 30%, #32BEE1 100%); 5 | color: #fff; 6 | display: flex; 7 | flex-wrap: wrap; 8 | justify-content: space-between; 9 | font-family: Arial, sans-serif; 10 | font-size: 0.8rem; 11 | z-index: 10000; 12 | } 13 | 14 | .footer-row { 15 | display: flex; 16 | flex-wrap: wrap; 17 | justify-content: space-between; 18 | width: 100%; 19 | margin-bottom: 1rem; 20 | } 21 | 22 | .footer-img { 23 | max-width: 100%; 24 | height: auto; 25 | } 26 | 27 | .footer-column h3 { 28 | font-weight: bold; 29 | font-size: 14px; 30 | margin: calc(67px - 45px) 0 0 0; 31 | text-transform: uppercase; 32 | } 33 | 34 | .footer-column .outer .logo { 35 | display: block; 36 | height: 125px; 37 | margin: 0 auto 15px auto; 38 | } 39 | .footer-column .outer small { 40 | display: block; 41 | font-size: 12px; 42 | text-align: center; 43 | } 44 | .footer-column .inner { 45 | padding: 45px 45px 0px 45px; 46 | } 47 | .footer-column .inner ul { 48 | margin: 15px 0 0 0; 49 | padding: 0; 50 | } 51 | .footer-column .inner ul li{ 52 | font-size: 14px; 53 | list-style: none; 54 | margin-bottom: 0.5em; 55 | } 56 | .footer-column .inner a { 57 | color: #fff; 58 | font-weight: normal; 59 | } 60 | .footer-column .inner .social-media-links li { 61 | display: inline-block; 62 | font-size: 20px; 63 | margin: 0 10px 0 0; 64 | color: #fff; 65 | } 66 | 67 | .footer-column:not(.center) { 68 | flex: 1 1 0; 69 | } 70 | .footer-column.left { 71 | .inner { 72 | padding-top: 30px; 73 | } 74 | } 75 | .footer-column.center { 76 | width: calc(300px * 3 + 15px * 2); 77 | padding: 0 15px; 78 | } 79 | .footer-column.right { 80 | } 81 | 82 | .footer-row.signature { 83 | padding: 0 45px; 84 | } 85 | .footer-row.signature .inner p { 86 | color: #005687; 87 | } 88 | -------------------------------------------------------------------------------- /css/loader.css: -------------------------------------------------------------------------------- 1 | /* CREDIT: https://loading.io/css/ */ 2 | .lds-ripple { 3 | display: block; 4 | position: fixed; 5 | width: 80px; 6 | height: 80px; 7 | left: calc(50% - 40px); 8 | top: calc(50% - 40px); 9 | } 10 | .lds-ripple div { 11 | position: absolute; 12 | border: 4px solid #FFC10E; 13 | opacity: 1; 14 | border-radius: 50%; 15 | animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite; 16 | } 17 | .lds-ripple div:nth-child(2) { 18 | animation-delay: -0.5s; 19 | } 20 | @keyframes lds-ripple { 21 | 0% { 22 | top: 36px; 23 | left: 36px; 24 | width: 0; 25 | height: 0; 26 | opacity: 0; 27 | } 28 | 4.9% { 29 | top: 36px; 30 | left: 36px; 31 | width: 0; 32 | height: 0; 33 | opacity: 0; 34 | } 35 | 5% { 36 | top: 36px; 37 | left: 36px; 38 | width: 0; 39 | height: 0; 40 | opacity: 1; 41 | } 42 | 100% { 43 | top: 0px; 44 | left: 0px; 45 | width: 72px; 46 | height: 72px; 47 | opacity: 0; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap'); 2 | 3 | /* 4 | $c-dark-blue: #005687; 5 | $c-mid-blue: #0468B1; 6 | $c-mid-blue-semi: rgba(4,104,177,.75); 7 | $c-light-blue: #32BEE1; 8 | 9 | $c-dark-red: #A51E41; 10 | $c-mid-red: #FA1C26; 11 | $c-light-red: #F03C8C; 12 | 13 | $c-dark-green: #418246; 14 | $c-mid-green: #61B233; 15 | $c-light-green: #B4DC28; 16 | 17 | $c-dark-yellow: #FA7814; 18 | $c-mid-yellow: #FFC10E; 19 | $c-light-yellow: #FFF32A; 20 | 21 | $c-dark-grey: #000000; 22 | $c-mid-grey: #646464; 23 | $c-light-grey: #969696; 24 | 25 | $c-light-2: #e5e5e5; 26 | */ 27 | html { 28 | height: 100%; 29 | } 30 | 31 | body { 32 | height: 100%; 33 | padding: 0; 34 | margin: 0; 35 | font-family: 'Noto Sans'; 36 | } 37 | 38 | header { 39 | /*display: block; 40 | width: 100%; 41 | height: 30px;*/ 42 | position: fixed; 43 | top: 0; 44 | flex: 0 1 0; 45 | display: block; 46 | width: 100%; 47 | height: 30px; 48 | z-index: 1000; 49 | background-color: #005687; 50 | } 51 | header a { 52 | line-height: 26px; 53 | margin: 0 30px; 54 | float: right; 55 | } 56 | #logo { 57 | position: absolute; 58 | top: 30px; 59 | left: 0; 60 | pointer-events: none; 61 | } 62 | #logo img { 63 | height: 125px; 64 | margin-bottom: 30px; 65 | } 66 | #logo h1 { 67 | margin: 0 0 5px 105px; 68 | line-height: 1.2em; 69 | word-spacing: 100vw; 70 | color: #005687; 71 | } 72 | #logo h1 .light { 73 | color: #0468B1; 74 | font-weight: normal; 75 | } 76 | #logo h2 { 77 | margin: 0 0 0 105px; 78 | line-height: 1.3em; 79 | word-spacing: 100vw; 80 | color: $c-mid-green; 81 | font-weight: normal; 82 | } 83 | 84 | 85 | .inactive { 86 | pointer-events: none; 87 | } 88 | 89 | section { 90 | min-height: 100vh; 91 | width: 100%; 92 | } 93 | section.hx2 { 94 | height: 200vh; 95 | } 96 | section.hx5 { 97 | height: 500vh; 98 | } 99 | section.dark { 100 | background-color: #393939; 101 | } 102 | section.padded { 103 | padding: 300px 0; 104 | box-sizing: border-box; 105 | } 106 | section .inner { 107 | position: relative; 108 | max-width: 1080px; 109 | height: 100%; 110 | min-height: 100vh; 111 | margin: auto; 112 | display: flex; 113 | justify-content: center; 114 | align-items: center; 115 | box-sizing: border-box; 116 | } 117 | .inner.float { 118 | height: auto !important; 119 | min-height: 100vh; 120 | z-index: 100; 121 | } 122 | .sticky { 123 | position: sticky !important; 124 | top: 0; 125 | height: auto !important; 126 | min-height: 100vh; 127 | } 128 | .sticky.block { 129 | display: block !important; 130 | } 131 | .sticky svg { 132 | height: auto !important; 133 | } 134 | .col-spread { 135 | position: absolute; 136 | height: 100%; 137 | display: flex; 138 | flex-direction: column; 139 | justify-content: space-between; 140 | padding: 50px 0 90px 0; 141 | box-sizing: border-box; 142 | } 143 | .col-spread.left { 144 | left: -50px; 145 | } 146 | .col-spread.right { 147 | left: calc(100% - 50px); 148 | } 149 | .colx2 { 150 | display: grid; 151 | column-count: 2; 152 | column-gap: 15px; 153 | grid-template-columns: 1fr 25%; 154 | } 155 | p.instruction { 156 | font-size: 10px; 157 | color: #FFF; 158 | min-width: 200px; 159 | } 160 | 161 | .lead { 162 | font-size: 20px; 163 | line-height: 1.4em; 164 | } 165 | .small { 166 | font-size: 12px; 167 | line-height: 1.3em; 168 | } 169 | .blue { 170 | color: #005687; 171 | } 172 | h3.graphic-title { 173 | border-left: 4px solid #969696; 174 | color: #969696; 175 | font-size: 12px; 176 | padding-left: 8px; 177 | } 178 | .wobble { 179 | animation: wobble 2s ease infinite; 180 | } 181 | @keyframes wobble { 182 | 0% { 183 | transform: translateX(0); 184 | } 185 | 15% { 186 | transform: translateX(-25px); 187 | } 188 | 30% { 189 | transform: translateX(20px); 190 | } 191 | 45% { 192 | transform: translateX(-10px); 193 | } 194 | 60% { 195 | transform: translateX(5px); 196 | } 197 | 75% { 198 | transform: translateX(0); 199 | } 200 | 100% { 201 | transform: translateX(0); 202 | } 203 | } 204 | .container { 205 | display: flex; 206 | width: 100%; 207 | height: calc(100% - 30px); 208 | } 209 | .btn-row { 210 | display: block; 211 | position: absolute; 212 | top: 30; 213 | width: 100%; 214 | text-align: center; 215 | } 216 | .btn-row button { 217 | background: transparent; 218 | border: none; 219 | color: #FA7814; 220 | outline: none; 221 | padding: 5px 10px; 222 | cursor: pointer; 223 | font-size: 14px; 224 | } 225 | .btn-row button.active { 226 | background: #FA7814; 227 | color: #FFF; 228 | } 229 | .left-col { 230 | flex: 1 1 0; 231 | } 232 | .right-col { 233 | flex: 0 1 0; 234 | background-color: #005687; 235 | transition: flex .5s; 236 | color: #FFF; 237 | overflow: auto; 238 | } 239 | .right-col .inner { 240 | padding: 0 4em 2em 4em; 241 | } 242 | h1 { 243 | /* text-transform: uppercase;*/ 244 | color: #005687; 245 | } 246 | h1.main-title { 247 | text-align: center; 248 | font-size: 36px; 249 | line-height: 1.2em; 250 | margin-bottom: 0; 251 | } 252 | h1.main-title small { 253 | font-size: 20px; 254 | line-height: 1.3em; 255 | } 256 | h1.main-title .light { 257 | font-weight: normal; 258 | color: #0468B1; 259 | } 260 | h2.sub-title { 261 | margin-top: 0; 262 | font-weight: normal; 263 | } 264 | h3.entry-title { 265 | margin-bottom: 0; 266 | } 267 | h3 small { 268 | font-size: 14px; 269 | font-weight: normal; 270 | text-decoration: underline; 271 | } 272 | small.contributor, 273 | small.location { 274 | display: block; 275 | } 276 | small.location { 277 | margin-bottom: 1em; 278 | } 279 | div.entry { 280 | padding: 2rem 0; 281 | border-bottom: 1px solid #FFF; 282 | } 283 | div.tag { 284 | display: inline; 285 | font-size: 12px; 286 | padding: 2px 5px; 287 | border: 1px solid #FFF; 288 | border-radius: 5px; 289 | margin: 5px 5px 5px 0; 290 | } 291 | a { 292 | margin-bottom: 1em; 293 | color: #B4DC28; 294 | /* font-size: 18px;*/ 295 | outline: none; 296 | } 297 | 298 | svg { 299 | width: 100%; 300 | height: 100%; 301 | } 302 | .node text { 303 | pointer-events: none; 304 | text-anchor: middle; 305 | } 306 | circle.bg { 307 | cursor: pointer; 308 | fill: #FFF; 309 | } 310 | circle.outline { 311 | fill: none; 312 | stroke: #000; 313 | } 314 | 315 | .orbit, 316 | .orbit { 317 | opacity: 0; 318 | fill: none; 319 | stroke: #000; 320 | stroke-width: 1; 321 | } 322 | .orbit.primary { 323 | stroke-width: 2; 324 | } 325 | .node.primary { 326 | font-weight: bold; 327 | font-size: 24px; 328 | } 329 | .node.primary text { 330 | text-transform: uppercase; 331 | } 332 | .leaf text { 333 | text-transform: lowercase !important; 334 | } 335 | .node.primary circle.outline { 336 | stroke-width: 3; 337 | } 338 | .node.primary line.underline { 339 | stroke: #000; 340 | stroke-width: 2; 341 | } 342 | .node.secondary line.underline { 343 | stroke: #000; 344 | stroke-width: 1; 345 | } 346 | .node.tech:hover > circle:not(.bg), 347 | .node.tech:hover > line { 348 | stroke: #A51E41; 349 | } 350 | .node.tech:hover > text { 351 | fill: #A51E41; 352 | } 353 | .node.tech .leaf:hover circle:not(.bg), 354 | .node.tech .leaf:hover line { 355 | stroke: #FA1C26; 356 | } 357 | .node.tech .leaf:hover > text { 358 | fill: #FA1C26; 359 | } 360 | .node.policy:hover > circle:not(.bg), 361 | .node.policy:hover > line { 362 | stroke: #005687; 363 | } 364 | .node.policy:hover > text { 365 | fill: #005687; 366 | } 367 | .node.policy .leaf:hover circle:not(.bg), 368 | .node.policy .leaf:hover line { 369 | stroke: #0468B1; 370 | } 371 | .node.policy .leaf:hover text { 372 | fill: #0468B1; 373 | } 374 | .node.application:hover > circle:not(.bg), 375 | .node.application:hover > line, 376 | .node.application.active > circle:not(.bg), 377 | .node.application.active > line { 378 | stroke: #418246; 379 | } 380 | .node.application:hover > text, 381 | .node.application.active > text { 382 | fill: #418246; 383 | } 384 | .node.application .leaf:hover circle:not(.bg), 385 | .node.application .leaf:hover line, 386 | .node.application .leaf.active circle:not(.bg), 387 | .node.application .leaf.active line { 388 | stroke: #61B233; 389 | } 390 | .node.application .leaf:hover text, 391 | .node.application .leaf.active text { 392 | fill: #61B233; 393 | } 394 | .node.secondary { 395 | font-weight: medium; 396 | font-size: 24px; 397 | } 398 | .node rect.bg { 399 | fill: #FFF; 400 | pointer-events: none; 401 | } 402 | .leaf { 403 | font-weight: bold; 404 | font-size: 18px; 405 | } 406 | .node text, 407 | .leaf text { 408 | opacity: 0; 409 | } 410 | g.title text { 411 | font-weight: bold; 412 | font-size: 24px; 413 | opacity: 0; 414 | } 415 | g.title text .emph { 416 | font-size: 36px; 417 | } 418 | path.connection.dim { 419 | /* stroke: #e5e5e5 !important;*/ 420 | stroke: #646464 !important; 421 | stroke-opacity: .25 !important; 422 | } 423 | g.base.dim text { 424 | /* fill: #e5e5e5 !important;*/ 425 | fill: #646464 !important; 426 | fill-opacity: .25 !important; 427 | } 428 | -------------------------------------------------------------------------------- /data/acclab_data_innovation.csv: -------------------------------------------------------------------------------- 1 | Technique,Aggregate datasource,Datasource,Area,Application,Lab,Link,UNDP region,Note 2 | Object detection,Earth observation,Drone imagery,Precision agriculture and pastoralism,Crop disease detection,Cameroon,https://www.undp.org/cameroon/blog/will-drone-and-artificial-intelligence-help-increase-income-cameroonian-cocoa-planters,RBA, 3 | Object detection,Image data,Photo/ video,Precision agriculture and pastoralism,Crop disease detection,Cabo verde,,RBA, 4 | Object detection,Image data,Photo/ video,Precision agriculture and pastoralism,Pest control,Zimbabwe,https://www.undp.org/acceleratorlabs/publications/labs-20-evolving-global-research-and-development-capability-sdgs,RBA, 5 | Object detection,Earth observation,Satellite imagery,Pollution,Dump site detection,Guatemala,,RBLAC, 6 | Object detection,Earth observation,Satellite imagery,Pollution,Dump site detection,Serbia,https://www.undp.org/serbia/blog/can-artificial-intelligence-and-satellite-images-help-make-our-rivers-free-waste,RBEC,Low accuracy because of lack of training data 7 | Object detection,Earth observation,Satellite imagery,Pollution,Dump site detection,Vietnam,https://www.undp.org/vietnam/blog/remote-sensing-smart-city-solution-municipal-waste-management,RBAP, 8 | Object detection,Earth observation,Satellite imagery,Pollution,Plastic waste detection in river systems,The Philippines,https://www.undp.org/philippines/blog/experiment-satellite-remote-sensing-plastic-waste-pasig-river,RBAP, 9 | Object detection,Earth observation,Satellite imagery,Pollution,Brick kiln detection,India,https://www.undp.org/india/blog/how-geoai-platform-helping-target-brick-kiln-hotspots-air-pollution,RBAP, 10 | Object detection,Earth observation,Satellite imagery,Environmental monitorig,Mine detection,Bolivia,https://learningplans.sdg-innovation-commons.org/en/edit/pad?id=2060&source=1895&display=adjacent-source,RBLAC, 11 | "Land use/ land cover classification, and vegetation indices",Earth observation,Satellite imagery,Precision agriculture and pastoralism,Detection of sustained grazing areas over time ,Somalia,,RBAS, 12 | "Land use/ land cover classification, and vegetation indices",Earth observation,Satellite imagery,Precision agriculture and pastoralism,Detection of sustained dry croplands over time,Niger,,RBA, 13 | "Land use/ land cover classification, and vegetation indices",Earth observation,Satellite imagery,Precision agriculture and pastoralism,Detection of forest boundaries over time,Ecuador,,RBLAC, 14 | "Land use/ land cover classification, and vegetation indices",Earth observation,Satellite imagery,Precision agriculture and pastoralism,Multilayer map generation for agriculture,India,https://dicra.undp.org.in/,RBAP, 15 | "Land use/ land cover classification, and vegetation indices",Earth observation,Satellite imagery,Disaster risk management,Flood detection,Mauritania,,RBA, 16 | "Land use/ land cover classification, and vegetation indices",Earth observation,Satellite imagery,Disaster risk management,Landslide detection,Kyrgyzstan,,RBEC,Lack of training data 17 | Text classification,Online posts,Online reviews,Tourism,Topic analysis of tourist reviews,Jordan,https://public.tableau.com/app/profile/mohtaz.younes/viz/SentimentAnalysisofTourisminJordanonTripAdvisor/Main?publish=yes,RBAS, 18 | Text classification,Online posts,Online reviews,Tourism,Sentiment analysis of toursit reviews,Malawi,,RBA, 19 | Text classification,Online posts,Online reviews,Tourism,Sentiment analysis of toursit reviews,Tanzania,https://www.undp.org/tanzania/blog/re-thinking-tourism-zanzibar-how-artificial-intelligence-creating-value-industry,RBA, 20 | Text classification,Online posts,Social media posts,Misinformation,Misinformation on Covid19,Tanzania,https://www.undp.org/tanzania/blog/using-artificial-intelligence-tackle-infodemic-tanzania,RBA, 21 | Text classification,Online posts,Social media posts,Gender,Gender-related toxic speech detection,Kyrgyzstan,,RBEC, 22 | Text classification,Online posts,Social media posts,Gender,Gender-related toxic speech detection,Uruguay,,RBLAC, 23 | Text classification,Online posts,Social media posts,Misinformation,???,Jordan,https://learningplans.sdg-innovation-commons.org/en/edit/pad?id=2039&source=1917&display=adjacent-source,RBAS, 24 | Generative AI,Synthetic data,Pre-trained text model,Operations support,"R script generation for simple, baseline data analyses and visualizations",Guatemala,https://chat.openai.com/share/7c1972d8-a36d-4b79-8730-4a361d13d2da,RBLAC, 25 | Generative AI,Synthetic data,Pre-trained text model,Education,Personalized ducational material generation,Cameroon,https://learningplans.sdg-innovation-commons.org/en/edit/pad?id=1996&source=1928&display=adjacent-source,RBA, 26 | Generative AI,Synthetic data,Pre-trained text model + political speeches,Democratic governance,Unified political speech generation,Argentina,https://www.undp.org/es/argentina/ai-argentine-intelligence,RBLAC, 27 | Generative AI,Synthetic data,Pre-trained image model,Gender,Analysis of gender stereotypes in STEM fields,Serbia,https://www.undp.org/serbia/blog/reproducing-inequality-how-ai-image-generators-show-biases-against-women-stem,RBEC, 28 | Generative AI,Synthetic data,Pre-trained image model + urban and vegetation photos,Urbanism,Green urbanism image generation during public consultations,North Macedonia,,RBEC, 29 | Predictive modelling,Network data,Linked profiles,Gender,Gender inequality in the workplace,Serbia,,RBEC, 30 | Generative AI,Synthetic data,Pre-trained text model + political speeches,Urbanism,Intergenerational urban planning,Panama,https://www.linkedin.com/feed/update/urn:li:activity:7208501007826178050?updateEntityUrn=urn%3Ali%3Afs_feedUpdate%3A%28V2%2Curn%3Ali%3Aactivity%3A7208501007826178050%29,RBLAC, -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/favicon.ico -------------------------------------------------------------------------------- /imgs/branding/UNDP_Acc_Labs_All_Partners_horiz_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/branding/UNDP_Acc_Labs_All_Partners_horiz_white.png -------------------------------------------------------------------------------- /imgs/branding/UNDP_accelerator_labs_logo_vertical_color_RGB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/branding/UNDP_accelerator_labs_logo_vertical_color_RGB.png -------------------------------------------------------------------------------- /imgs/branding/UNDP_accelerator_labs_logo_vertical_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/branding/UNDP_accelerator_labs_logo_vertical_white.png -------------------------------------------------------------------------------- /imgs/map/ai_intervention_areas.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/map/ai_intervention_areas.ai -------------------------------------------------------------------------------- /imgs/map/ai_intervention_areas.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 17 | 18 | 19 | 20 | 21 | TECH 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | models 30 | 31 | 32 | 33 | 34 | 35 | data 36 | 37 | 38 | 39 | 40 | 41 | 42 | production 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | POLICY 51 | 52 | 53 | 54 | 55 | 56 | 57 | enabling 58 | 59 | 60 | 61 | 62 | 63 | 64 | constraining 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | APPLICATION 75 | 76 | 77 | 78 | 79 | 80 | critical 81 | 82 | 83 | 84 | 85 | 86 | analytic 87 | 88 | 89 | 90 | 91 | 92 | creative 93 | 94 | 95 | 96 | 97 | 98 | ? 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | Infrastructure 108 | 109 | 110 | 111 | 112 | 113 | Business 114 | 115 | 116 | 117 | AIpossible areas of intervention 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /imgs/stats/area.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/stats/area.png -------------------------------------------------------------------------------- /imgs/stats/data_and_applications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/stats/data_and_applications.png -------------------------------------------------------------------------------- /imgs/stats/data_and_applications.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 15 | 16 | Agriculture and pastoralism 17 | Pollution and waste management 18 | Environmental monitorig 19 | Disaster risk management 20 | Trousim 21 | Gender 22 | Misinformation 23 | Operations support 24 | Education 25 | Democratic governance 26 | Urban development 27 | Remote sensing 28 | Online posts 29 | Pre-trained AI models 30 | Network data 31 | Cameroon 32 | Cabo verde 33 | Guatemala 34 | Serbia 35 | Vietnam 36 | The Philipines 37 | India 38 | Bolivia 39 | Somalia 40 | Niger 41 | Ecuador 42 | Mauritania 43 | Kyrgyzstan 44 | Jordan 45 | Malawi 46 | Tanzania 47 | Uruguay 48 | Guatmala 49 | Argentina 50 | North Macedonia 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /imgs/stats/data_and_applications_colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/stats/data_and_applications_colors.png -------------------------------------------------------------------------------- /imgs/stats/data_and_applications_colors.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 20 | Agriculture 21 | and pastoralism 22 | Democratic governance 23 | Disaster 24 | r 25 | isk management 26 | Education 27 | Environmental 28 | monitorig 29 | Gender 30 | Misinformation 31 | Operations support 32 | Pollution and waste 33 | management 34 | Tourism 35 | Urban 36 | development 37 | Network data 38 | Online posts 39 | Pre-trained AI models 40 | Remote sensing 41 | Argentina 42 | Bolivia 43 | Cabo verde 44 | Cameroon 45 | Ecuador 46 | Guatemala 47 | India 48 | Jordan 49 | Kyrgyzstan 50 | Malawi 51 | Mauritania 52 | Niger 53 | North 54 | Macedonia 55 | Serbia 56 | Somalia 57 | Tanzania 58 | The 59 | Philipines 60 | Uruguay 61 | Vietnam 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /imgs/stats/data_and_applications_colors_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/stats/data_and_applications_colors_dark.png -------------------------------------------------------------------------------- /imgs/stats/data_and_applications_colors_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 26 | 27 | 28 | 29 | Agriculture 30 | and pastoralism 31 | Democratic governance 32 | Disaster 33 | r 34 | isk management 35 | Education 36 | Environmental 37 | monitorig 38 | Gender 39 | Misinformation 40 | Operations support 41 | Pollution and waste 42 | management 43 | Tourism 44 | Urban 45 | development 46 | Network data 47 | Online posts 48 | Pre-trained AI models 49 | Remote sensing 50 | Argentina 51 | Bolivia 52 | Cabo verde 53 | Cameroon 54 | Ecuador 55 | Guatemala 56 | India 57 | Jordan 58 | Kyrgyzstan 59 | Malawi 60 | Mauritania 61 | Niger 62 | North 63 | Macedonia 64 | Serbia 65 | Somalia 66 | Tanzania 67 | The 68 | Philipines 69 | Uruguay 70 | Vietnam 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /imgs/stats/data_and_applications_colors_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/stats/data_and_applications_colors_light.png -------------------------------------------------------------------------------- /imgs/stats/data_and_applications_colors_light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 25 | Agriculture 26 | and pastoralism 27 | Democratic governance 28 | Disaster 29 | r 30 | isk management 31 | Education 32 | Environmental 33 | monitorig 34 | Gender 35 | Misinformation 36 | Operations support 37 | Pollution and waste 38 | management 39 | Tourism 40 | Urban 41 | development 42 | Network data 43 | Online posts 44 | Pre-trained AI models 45 | Remote sensing 46 | Argentina 47 | Bolivia 48 | Cabo verde 49 | Cameroon 50 | Ecuador 51 | Guatemala 52 | India 53 | Jordan 54 | Kyrgyzstan 55 | Malawi 56 | Mauritania 57 | Niger 58 | North 59 | Macedonia 60 | Serbia 61 | Somalia 62 | Tanzania 63 | The 64 | Philipines 65 | Uruguay 66 | Vietnam 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /imgs/stats/datasources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/stats/datasources.png -------------------------------------------------------------------------------- /imgs/stats/sankey_20240402.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/stats/sankey_20240402.png -------------------------------------------------------------------------------- /imgs/stats/sankey_20240402.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | Earth observation 198 | DATA SOURCE 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | Network data 241 | Online posts 242 | Synthetic data 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | Feature detection 265 | Generative AI 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | Text classification 309 | *LULC: Land use/land cover 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | Education 357 | Gender 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | Pollution 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | Tourism 436 | Urbanism 437 | Argentina 438 | LAB/COUNTRY 439 | Bolivia 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | Cameroon 452 | Ecuador 453 | Guatemala 454 | India 455 | Jordan 456 | Kyrgyzstan 457 | Malawi 458 | Mauritania 459 | Niger 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | Serbia 477 | Somalia 478 | Tanzania 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | Uruguay 495 | Vietnam 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | -------------------------------------------------------------------------------- /imgs/stats/technique.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UNDP-Accelerator-Labs/AI-map/50dccccfa57a512626ef4198b9f47cad87ef19c9/imgs/stats/technique.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 26 |
27 | 28 |
29 |
30 | 35 |

36 | UNDP Accelerator Labs
37 | Towards
38 | mainstreaming
39 | data innovation
40 | for sustainable
41 | development
42 |

43 | 44 |
45 |
46 |
47 |
48 |
49 |

50 | 51 | Over the past four years, the UNDP Accelerator Labs Network has been pushing the mainstreaming of data innovation* inside and outside UNDP. Here, we take stock of these efforts, focusing specifically on work that leverages existing, third-party data, and includes some form of advanced computational technique—as opposed to work that focuses on more manual means of inputting and analyzing "new" data, like Collective Intelligence. The work is action oriented, rather than (solely) research oriented, meaning it is not focused on pushing the limits of data innovation, but rather on its integration into practice. 52 | 53 |

54 | The interactive graphic below highlights exemplar applications from around the world. It is a living document, meaning we plan to update it regularly. 55 |

56 |

57 | *We refer to data innovation as the use of unusual data sources and advanced computational techniques for sustainable development practice. We prefer the terms "unusual data sources" and "advanced computational techniques" over "big (or new) data" and "Artificial Intelligence (AI)", as we believe that the prior more adequately reflect the situated notions of resource and tool, while the latter are, in our opinion, generally confounded by the current hype around Generative AI. We see data innovation as a means to an end, not an end in itself. 58 |

59 |
60 |
61 |
62 |
63 |
64 | 65 |
66 |
67 |
68 |

DATA SOURCE

69 |

COMPUTATIONAL
TECHNIQUE

70 |

APPLICATION
AREA

71 |

LAB/COUNTRY

72 |
73 |
74 |
75 |
76 |

77 |

Hover over the diagram to highlight connections

78 |

← Click on the Lab/Country to read more

79 |
80 |
81 |
82 | 83 |
84 |
85 |
86 |

87 | The Accelerator Labs “work out loud”, meaning they continuously publish updates on their work, whether through blogs or action learning plans and reflections. Here, we sample 29 projects from 21 different Labs using these sources of information, looking for terms like “data innovation”, “unusual data”, “big data”, “data science”, “machine learning”, “artificial intelligence”, and “AI”. 88 |

89 | We code each project as a geographically situated triptych of data source—computational technique—application area. Our intention is to uncover convergences that might suggest maturity of given data innovation techniques. Note that we use relatively high-level descriptive classes for our coding to facilitate aggregation. For example, we characterize computational techniques as “object detection” or “text classification”, rather than by specific types of classification or of machine learning models. 90 |

91 | Read more about this work in our blog post: Dismantling the AI Monolith for Sustainable Development – Part 1: Observations on Our Use of Data and Computing 92 |

93 | Find all source materials on Github. 94 |

95 |
96 |
97 | 98 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /js/Array.prototype.extensions.js: -------------------------------------------------------------------------------- 1 | Array.prototype.filterInPlace = function (condition, thisArg) { 2 | let jx = 0; 3 | this.forEach((el, ix) => { 4 | if (condition.call(thisArg, el, ix, this)) { 5 | if (ix !== jx) { 6 | this[jx] = el; 7 | } 8 | jx += 1; 9 | } 10 | }); 11 | this.length = jx; 12 | return this; 13 | }; 14 | Array.prototype.flat = function () { 15 | return [].concat.apply([], this); 16 | }; 17 | Array.prototype.flatObj = function () { 18 | // FLATTEN OBJECT: https://stackoverflow.com/questions/31136422/flatten-array-with-objects-into-1-object 19 | return Object.assign.apply(Object, this); 20 | }; 21 | Array.prototype.fillNaN = function (key, value) { 22 | if (!value) value = 0; 23 | if (!key) { 24 | return this.map((v) => (isNaN(v) || v == null ? value : v)); 25 | } else { 26 | return this.map((v) => { 27 | if (isNaN(v[key]) || v[key] == null) v[key] = value; 28 | return v; 29 | }); 30 | } 31 | }; 32 | Array.prototype.sum = function (key) { 33 | if (this.length === 0) return 0; 34 | if (!key) { 35 | return this.reduce((accumulator, value) => accumulator + value); 36 | } else { 37 | return this.reduce((accumulator, value) => { 38 | const obj = {}; 39 | obj[key] = accumulator[key] + value[key]; 40 | return obj; 41 | })[key]; 42 | } 43 | }; 44 | Array.prototype.max = function (key, onkey) { 45 | const max = this.sort((a, b) => { 46 | if (key) return b[key] - a[key]; 47 | else return b - a; 48 | })[0]; 49 | if (onkey) return max[key]; 50 | else return max; 51 | }; 52 | Array.prototype.mean = function (key) { 53 | return this.sum(key) / this.length; 54 | }; 55 | Array.prototype.variance = function (key) { 56 | if (this.length === 0) throw new Error('no values'); 57 | const mean = this.mean(key); 58 | if (!key) return this.map((d) => Math.pow(d - mean, 2)).sum() / this.length; 59 | else return this.map((d) => Math.pow(d[key] - mean, 2)).sum() / this.length; 60 | }; 61 | Array.prototype.sd = function (key) { 62 | if (this.length === 0) throw new Error('no values'); 63 | return Math.sqrt(this.variance(key)); 64 | }; 65 | Array.prototype.nest = function (key, keep) { 66 | // THIS IS NOT QUITE THE SAME FUNCTION AS IN distances.js, THIS MORE CLOSELY RESEMBLES d3.nest 67 | const arr = []; 68 | this.forEach((d) => { 69 | const groupby = typeof key === 'function' ? key(d) : d[key]; 70 | if (!arr.find((c) => c.key === groupby)) { 71 | if (keep) { 72 | const obj = {}; 73 | obj.key = groupby; 74 | obj.values = [d]; 75 | obj.count = 1; 76 | if (Array.isArray(keep)) keep.forEach((k) => (obj[k] = d[k])); 77 | else obj[keep] = d[keep]; 78 | arr.push(obj); 79 | } else arr.push({ key: groupby, values: [d], count: 1 }); 80 | } else { 81 | arr.find((c) => c.key === groupby).values.push(d); 82 | arr.find((c) => c.key === groupby).count++; 83 | } 84 | }); 85 | return arr; 86 | }; 87 | Array.prototype.dotProduct = function (V2) { 88 | // USED IN distances.cosine 89 | return this.map((v1, i) => { 90 | const v2 = V2[i]; 91 | return v1 * v2; 92 | }).sum(); 93 | }; 94 | Array.prototype.matrixMultiplication = function (V) { 95 | return this.map((row) => { 96 | return [ 97 | row 98 | .map((c, j) => { 99 | return c * V[j]; 100 | }) 101 | .sum(), 102 | ]; 103 | }); 104 | }; 105 | Array.prototype.intersection = function (V2) { 106 | const intersection = []; 107 | this.sort(); 108 | V2.sort(); 109 | for (let i = 0; i < this.length; i += 1) { 110 | if (V2.indexOf(this[i]) !== -1) { 111 | intersection.push(this[i]); 112 | } 113 | } 114 | return intersection; 115 | }; 116 | Array.prototype.diff = function (V2) { 117 | const diff = []; 118 | this.forEach((d) => { 119 | if (!V2.includes(d)) diff.push(d); 120 | }); 121 | V2.forEach((d) => { 122 | if (!this.includes(d)) diff.push(d); 123 | }); 124 | return diff; 125 | }; 126 | Array.prototype.union = function (V) { 127 | V.forEach((d) => { 128 | if (this.indexOf(d) === -1) this.push(d); 129 | }); 130 | return this; 131 | }; 132 | Array.prototype.unique = function (key, onkey) { 133 | const arr = []; 134 | this.forEach((d) => { 135 | if (!key) { 136 | if (arr.indexOf(d) === -1) arr.push(d); 137 | } else { 138 | if (onkey) { 139 | if (arr.map((c) => c).indexOf(d[key]) === -1) arr.push(d[key]); 140 | } else { 141 | if (typeof key === 'function') { 142 | if (arr.map((c) => key(c)).indexOf(key(d)) === -1) arr.push(d); 143 | } else { 144 | if (arr.map((c) => c[key]).indexOf(d[key]) === -1) arr.push(d); 145 | } 146 | } 147 | } 148 | }); 149 | return arr; 150 | }; 151 | Array.prototype.group = function (key, keep) { 152 | const arr = []; 153 | this.forEach((d) => { 154 | if (!key) { 155 | if (arr.map((c) => c.key).indexOf(d) === -1) 156 | arr.push({ key: d, count: 1 }); 157 | else arr.find((c) => c.key === d).count += 1; 158 | } else { 159 | if (arr.map((c) => c.key).indexOf(d[key]) === -1) { 160 | const obj = {}; 161 | obj.key = d[key]; 162 | obj.count = 1; 163 | if (keep) obj[keep] = [d[keep]]; 164 | arr.push(obj); 165 | } else { 166 | const obj = arr.find((c) => c.key === d[key]); 167 | obj.count += 1; 168 | if (keep) obj[keep].push(d[keep]); 169 | } 170 | } 171 | }); 172 | arr.forEach((d) => (d.p = d.count / this.length)); 173 | return arr; 174 | }; 175 | Array.prototype.zip = function (V2) { 176 | return this.map((d, i) => [d, V2[i]]); 177 | }; 178 | Array.prototype.multizip = function (arr) { 179 | return this.map((d, i) => { 180 | const zip = [d]; 181 | arr.forEach((c) => zip.push(c[i])); 182 | return zip; 183 | }); 184 | }; 185 | Array.prototype.last = function () { 186 | return this[this.length - 1]; 187 | }; 188 | Array.prototype.chunk = function (size) { 189 | const groups = []; 190 | for (let i = 0; i < this.length; i += size) { 191 | groups.push(this.slice(i, i + size)); 192 | } 193 | return groups; 194 | }; 195 | Array.prototype.median = function () { 196 | this.sort((a, b) => a - b); 197 | const half = Math.floor(this.length / 2); 198 | return this[half]; 199 | }; 200 | Array.prototype.shuffle = function () { 201 | let currentIndex = this.length; 202 | let temporaryValue; 203 | let randomIndex; 204 | 205 | while (0 !== currentIndex) { 206 | randomIndex = Math.floor(Math.random() * currentIndex); 207 | currentIndex -= 1; 208 | temporaryValue = this[currentIndex]; 209 | this[currentIndex] = this[randomIndex]; 210 | this[randomIndex] = temporaryValue; 211 | } 212 | return this; 213 | }; 214 | Array.prototype.duplicates = function (key, onkey) { 215 | const arr = []; 216 | this.forEach((d, i) => { 217 | if (!key) { 218 | if (i === 0) arr.push(d); 219 | else if (arr.indexOf(d) !== -1) arr.push(d); 220 | } else { 221 | if (onkey) { 222 | if (i === 0) arr.push(d[key]); 223 | else if (arr.map((c) => c).indexOf(d[key]) !== -1) arr.push(d[key]); 224 | } else { 225 | if (i === 0) arr.push(d); 226 | if (arr.map((c) => c[key]).indexOf(d[key]) !== -1) arr.push(d); 227 | } 228 | } 229 | }); 230 | return arr; 231 | }; 232 | -------------------------------------------------------------------------------- /js/d3.prototype.extensions.js: -------------------------------------------------------------------------------- 1 | const staticElement = function (_sel, _method, _element, _class) { 2 | return _sel[typeof _method === 'object' ? _method[0] : _method](_element, typeof _method === 'object' ? _method[1] : null) 3 | .attr('class', _class) 4 | } 5 | const dynamicElement = function (_sel, _method, _element, _class, _data, _key) { // THIS REPLACES DOMnode 6 | const node = _sel.selectAll(_class ? `${_element.replace(/xhtml:/g, '')}.${_class.replace(/\s/g, '.')}` : `${_element.replace(/xhtml:/g, '')}`) 7 | .data(_data ? (typeof _data === 'function' ? d => _data(d) : _data) : d => [d], 8 | (d, i) => _key ? (typeof _key === 'function' ? _key(d) : d[_key]) : i) 9 | node.exit().remove() 10 | return node.enter() 11 | [typeof _method === 'object' ? _method[0] : _method](_element, typeof _method === 'object' ? _method[1] : null) 12 | .attr('class', _class ? _class : null) 13 | .merge(node) 14 | } 15 | 16 | d3.selection.prototype.insertElem = function (_before, _element, _class) { 17 | return new staticElement(this, ['insert', _before], _element, _class ? _class : null) 18 | } 19 | d3.selection.prototype.insertElems = function (_before, _element, _class, _data, _key) { 20 | return new dynamicElement(this, ['insert', _before], _element, _class ? _class : null, _data, _key) 21 | } 22 | d3.selection.prototype.addElem = function (_element, _class) { 23 | return new staticElement(this, 'append', _element, _class ? _class : null) 24 | } 25 | d3.selection.prototype.addElems = function (_element, _class, _data, _key) { 26 | return new dynamicElement(this, 'append', _element.trim(), _class ? _class.trim() : null, _data, _key) 27 | } 28 | d3.selection.prototype.findAncestor = function (_target) { 29 | if (!this.node().classList || this.node().nodeName === 'BODY') return null 30 | if (this.classed(_target) || this.node().nodeName === _target?.toUpperCase()) return this 31 | return d3.select(this.node().parentNode)?.findAncestor(_target); 32 | } 33 | d3.selection.prototype.hasAncestor = function (_target) { 34 | if (this.node().nodeName === 'BODY') return false 35 | if (typeof _target === 'string') { 36 | if (this.classed(_target) || this.node().nodeName === _target?.toUpperCase()) return true 37 | } else { 38 | if (this.node() === _target) return true 39 | } 40 | return d3.select(this.node().parentNode)?.hasAncestor(_target); 41 | } 42 | d3.selection.prototype.moveToFront = function() { 43 | return this.each(function(){ 44 | this.parentNode.appendChild(this) 45 | }) 46 | } 47 | d3.selection.prototype.moveToBack = function() { 48 | // CREDIT: https://stackoverflow.com/questions/14167863/how-can-i-bring-a-circle-to-the-front-with-d3 49 | return this.each(function() { 50 | const firstChild = this.parentNode.firstChild 51 | if (firstChild) { 52 | this.parentNode.insertBefore(this, firstChild) 53 | } 54 | }) 55 | } 56 | d3.selection.prototype.toggleClass = function (_class) { 57 | return this.classed(_class, !this.classed(_class)) 58 | } 59 | // https://stackoverflow.com/questions/25405359/how-can-i-select-last-child-in-d3-js 60 | d3.selection.prototype.last = function() { 61 | return d3.select(this.nodes()[this.size() - 1]) 62 | } -------------------------------------------------------------------------------- /js/sankey.js: -------------------------------------------------------------------------------- 1 | const basecolors = { 2 | 'dark-blue': '#005687', 3 | 'mid-blue': '#0468b1', 4 | 'light-blue': '#32bee1', 5 | 'dark-red': '#a51e41', 6 | 'mid-red': '#fa1c26', 7 | 'light-red': '#f03c8c', 8 | 'dark-green': '#418246', 9 | 'mid-green': '#61b233', 10 | 'light-green': '#b4dc28', 11 | 'dark-yellow': '#fa7814', 12 | 'mid-yellow': '#ffc10e', 13 | 'light-yellow': '#fff32a', 14 | 'dark-grey': '#000000', 15 | 'mid-grey': '#646464', 16 | 'light-grey': '#969696', 17 | 'light-2': '#e5e5e5', 18 | } 19 | const colors = [ 20 | basecolors['mid-blue'], 21 | basecolors['mid-yellow'], 22 | basecolors['light-red'], 23 | basecolors['light-green'], 24 | basecolors['light-yellow'] 25 | ] 26 | 27 | const offsetFirstRow = false 28 | 29 | function setupSVG (kwargs) { 30 | const { width, height } = kwargs 31 | const svg = d3.select('svg') 32 | .attrs({ 33 | 'x': 0, 34 | 'y':0, 35 | 'viewBox': `0 0 ${width} ${height}`, 36 | 'preserveAspectRatio': 'xMidYMid meet' 37 | }) 38 | return svg 39 | } 40 | 41 | function findBestTextDisplay (svg, text, maxwidth) { 42 | const terms = text.split(' '); 43 | const lines = []; 44 | let start = 0; 45 | let end = 1; 46 | 47 | function getWidth (terms, start, end, maxwidth) { 48 | const txt = svg.addElems('text', 'dummy hide') 49 | .text(terms.slice(start, end)); 50 | const { width } = txt.node().getBBox(); 51 | txt.remove() 52 | if (width < maxwidth && end < terms.length) { 53 | return getWidth(terms, start, end + 1, maxwidth); 54 | } else { 55 | return [start, end] 56 | } 57 | } 58 | 59 | if (end === terms.length) return terms 60 | else { 61 | while (end <= terms.length) { 62 | const bounds = getWidth(terms, start, end, maxwidth); 63 | start = bounds[0]; 64 | end = bounds[1]; 65 | const line = terms.slice(start, end); 66 | lines.push(line.join(' ')) 67 | 68 | start = end; 69 | end = end + 1; 70 | } 71 | } 72 | 73 | return lines; 74 | } 75 | 76 | function drawSankey () { 77 | const { clientWidth: cw, clientHeight: ch, offsetWidth: ow, offsetHeight: oh } = d3.select('body').node() 78 | const width = Math.min(cw ?? ow, 1080) //Math.round(Math.min(cw ?? ow, ch ?? oh)) 79 | const height = ch ?? oh //width 80 | const padding = 60 81 | const edit_layout = true 82 | 83 | const svg = setupSVG({ width, height }) 84 | 85 | d3.csv('data/acclab_data_innovation.csv') 86 | .then(data => { 87 | const levels = ['Aggregate datasource', 'Technique', 'Area', 'Lab']//.reverse() 88 | 89 | const lists = levels.map(d => { 90 | return { 91 | key: d, 92 | values: data.unique(d, true).sort((a, b) => a?.localeCompare(b)) 93 | } 94 | }) 95 | 96 | const x = levels.map((d, i) => { 97 | return d3.scaleLinear() 98 | .range([padding, width - padding]) 99 | .domain([0, lists.find(c => c.key === d).values.length + 2]) 100 | }) 101 | 102 | const y = d3.scaleLinear() 103 | .range([padding * 1.5, height - padding * 2]) 104 | .domain([0, levels.length - 1]) 105 | 106 | 107 | let hierarchy = [] 108 | levels.forEach((d, i) => { 109 | if (i > 0) { 110 | const prev = levels[i - 1] 111 | const nest = data.nest(c => `${c[prev]}---${c[d]}`) 112 | nest.forEach(c => { 113 | const sources = lists.find(c => c.key === prev).values 114 | const targets = lists.find(c => c.key === d).values 115 | 116 | c.source = c.key.split('---')[0] 117 | c.target = c.key.split('---')[1] 118 | 119 | let x1 = x[levels.indexOf(prev)](sources.indexOf(c.source) + 1) 120 | let x2 = x[levels.indexOf(d)](targets.indexOf(c.target) + 1) 121 | let y1 = levels.indexOf(prev) % 3 === 0 ? y(levels.indexOf(prev)) : y(levels.indexOf(prev)) + 10 122 | let y2 = levels.indexOf(d) % 3 === 0 ? y(levels.indexOf(d)) : y(levels.indexOf(d)) - 15 123 | 124 | if (offsetFirstRow) { 125 | if (i - 1 === 0) { 126 | if (sources.indexOf(c.source) % 2 !== 0) y1 -= 35 127 | } else if (i % 3 === 0) { 128 | if (targets.indexOf(c.target) % 2 !== 0) y2 += 45 129 | } 130 | } else { 131 | if (i % 3 === 0) { 132 | if (targets.indexOf(c.target) % 2 !== 0) y2 += 45 133 | } 134 | } 135 | 136 | c.from = [x1, y1] 137 | c.q1 = [x1, y1 + (y2 - y1) / 2] 138 | c.q2 = [x2, y1 + (y2 - y1) / 2] 139 | c.to = [x2, y2] 140 | c.level = d 141 | c.level_id = i 142 | }) 143 | hierarchy.push(nest) 144 | } 145 | }) 146 | hierarchy = hierarchy.flat() 147 | 148 | const w = d3.scaleLinear() 149 | .domain([1, d3.max(hierarchy, d => d.count)]) 150 | .range([1, 10]) 151 | 152 | svg.addElems('path', 'connection', hierarchy) 153 | .attr('d', d => `M ${d.from.join(' ')} C ${d.q1.join(' ')}, ${d.q2.join(' ')}, ${d.to.join(' ')}`) 154 | .styles({ 155 | 'stroke': d => { 156 | const { values } = lists.find(c => c.key === 'Aggregate datasource') 157 | if (values.includes(d.values[0]['Aggregate datasource'])) return colors[values.indexOf(d.values[0]['Aggregate datasource'])] 158 | else if (values.includes(d.target)) return colors[values.indexOf(d.target)] 159 | 160 | },'fill': 'none', 161 | 'stroke-width': d => w(d.count), 162 | 'stroke-linecap': 'round', 163 | 'stroke-opacity': .5 164 | }) 165 | /*.on('mouseover', function () { 166 | const sel = d3.select(this); 167 | highlight(sel); 168 | }).on('mouseout', _ => { 169 | resetHighlight(); 170 | })*/ 171 | 172 | const rows = svg.addElems('g', 'level', levels) 173 | .attr('transform', (d, i) => `translate(${[0, y(i)]})`) 174 | const base = rows.addElems('g', 'base', d => { 175 | const entries = lists.find(c => c.key === d).values 176 | return entries.map(c => { 177 | const obj = {} 178 | obj.level = levels.indexOf(d) 179 | obj.value = c 180 | return obj 181 | }) 182 | }).attr('transform', (d, i) => { 183 | let y = 0 184 | 185 | if (offsetFirstRow) { 186 | if (d.level === 0) { 187 | if (i % 2 !== 0) y = -45 188 | else y = -15 189 | } else if (d.level % 3 === 0) { 190 | if (i % 2 !== 0) y = 60 191 | else y = 15 192 | } 193 | } else { 194 | if (d.level === 0) { 195 | y = -15 196 | } else if (d.level % 3 === 0) { 197 | if (i % 2 !== 0) y = 60 198 | else y = 15 199 | } 200 | } 201 | 202 | return `translate(${[x[d.level](i + 1), y]})` 203 | }) 204 | 205 | const multiline = true 206 | if (multiline) { 207 | base.addElems('text') 208 | .styles({ 209 | 'text-anchor': 'middle', 210 | 'font-face': 'Noto Sans', 211 | 'font-size': '12px', 212 | 'fill': basecolors['light-2'], 213 | 'cursor': d => d.level === levels.length - 1 ? 'pointer' : null, 214 | }).addElems('tspan', 'line', d => { 215 | const maxwidth = (width - padding * 2) / (Math.max(...x[d.level].domain()) + 2); 216 | const lines = findBestTextDisplay(svg, d.value, maxwidth); 217 | return lines 218 | }).attrs({ 219 | 'x': 0, 220 | 'dy': (d, i) => i === 0 ? 0 : 12 * 1.3, 221 | }).text(d => d) 222 | } else { 223 | base.addElems('text') 224 | .styles({ 225 | 'text-anchor': 'middle', 226 | 'font-face': 'Noto Sans', 227 | 'font-size': '12px', 228 | 'fill': basecolors['light-2'], 229 | 'cursor': d => d.level === levels.length - 1 ? 'pointer' : null, 230 | }).text(d => d.value) 231 | .on('mouseover', function (d) { 232 | const connection = d3.selectAll('path.connection').filter(c => c.target === d.value); 233 | highlight(connection); 234 | }).on('mouseout', _ => { 235 | resetHighlight(); 236 | }) 237 | } 238 | 239 | base.each(function () { 240 | const sel = d3.select(this) 241 | const text = sel.select('text') 242 | const { width: txt_width, height: txt_height } = text.node().getBBox(); 243 | 244 | sel.addElems('rect', 'interaction-padding') 245 | .attrs({ 246 | 'width': txt_width + 50, 247 | 'height': txt_height + 30, 248 | 'x': -(txt_width + 50) / 2, 249 | 'y': -(txt_height + 30) / 2, 250 | }).styles({ 251 | 'fill': 'transparent', 252 | // 'stroke': 'orange', 253 | 'cursor': 'pointer', 254 | }) 255 | }).on('mouseover', function (d) { 256 | const connection = d3.selectAll('path.connection').filter(c => c.source === d.value || c.target === d.value); 257 | highlight(connection); 258 | }).on('mouseout', function () { 259 | const { toElement } = d3.event; 260 | if (!d3.select(toElement)?.hasAncestor(this)) resetHighlight(); 261 | }).on('click', function (d) { 262 | if (d.level !== levels.length - 1) return false 263 | 264 | const sel = d3.select(this).moveToFront(); 265 | const text = sel.select('text').moveToFront(); 266 | const parentLevel = d3.select(this).findAncestor('level').moveToFront(); 267 | const { width: txt_width, height: txt_height } = text.node().getBBox(); 268 | const { left } = text.node().getBoundingClientRect(); 269 | const { value, level } = d 270 | const paths = data.filter(c => { 271 | return c[levels[level]] === value 272 | }).map((c, j) => { 273 | return { label: levels.reduce((acc, val, idx) => { 274 | if (idx < levels.length - 1) { 275 | if (c[val].length > 15) return acc += `${c[val].slice(0, 15)}…—`; 276 | else return acc += `${c[val]}—`; 277 | } else { 278 | if (c[val].length > 15) return acc += `${c[val].slice(0, 15)}…`; 279 | else return acc += `${c[val]}`; 280 | } 281 | }, '🔗 '), datasource: c['Aggregate datasource'], link: c['Link'], line: j } 282 | }).filter(c => c.link?.length) 283 | 284 | const bubble = sel.addElems('g', 'bubble', paths.length ? [paths] : []) 285 | const labels = bubble.addElems('text') 286 | .styles({ 287 | 'text-anchor': 'start', 288 | 'font-face': 'Noto Sans', 289 | 'font-size': '12px', 290 | // 'stroke': d => { 291 | // const { values } = lists.find(c => c.key === 'Aggregate datasource') 292 | // if (values.includes(d.values[0]['Aggregate datasource'])) return colors[values.indexOf(d.values[0]['Aggregate datasource'])] 293 | // else if (values.includes(d.target)) return colors[values.indexOf(d.target)] 294 | 295 | // }, 296 | }) 297 | labels.addElems('a', 'link', c => c) 298 | .attrs({ 299 | 'xlink:href': c => c.link, 300 | 'target': '_blank', 301 | }) 302 | .addElems('tspan', 'link') 303 | .attrs({ 304 | 'x': 0, 305 | 'dy': c => c.line === 0 ? 0 : 12 * 1.7, 306 | }).styles({ 307 | 'fill': c => { 308 | const { values } = lists.find(c => c.key === 'Aggregate datasource'); 309 | return colors[values.indexOf(c.datasource)]; 310 | } 311 | }).html(c => c.label) 312 | // .on('mouseover', c => { 313 | // console.log(c) 314 | // }); 315 | 316 | if (labels.size()) { 317 | const { width: bubble_w, height: bubble_h } = labels.node().getBBox(); 318 | 319 | bubble.insertElems('text', 'rect', 'interaction-padding') 320 | .attrs({ 321 | 'width': bubble_w + 50, 322 | 'height': bubble_h + 50, 323 | 'x': -25, 324 | 'y': (-bubble_h / paths.length) - 25, 325 | }).styles({ 326 | 'fill': 'transparent', 327 | // 'stroke': 'orange', 328 | }); 329 | bubble.insertElems('text', 'rect', 'label-bg') 330 | .attrs({ 331 | 'width': bubble_w + 27, 332 | 'height': bubble_h + 27, 333 | 'x': -10, 334 | 'y': (-bubble_h / paths.length) - 7, 335 | }).styles({ 336 | 'fill': '#FFF' 337 | }); 338 | bubble.attr('transform', _ => { 339 | let x = (bubble_w + txt_width / 2 + 30) * -1 340 | let y = 0 341 | if (left <= width / 2) x = txt_width / 2 + 30 342 | if (paths.length > 1) y = -bubble_h * .25 343 | return `translate(${[x, y]})` 344 | }); 345 | } 346 | }) 347 | 348 | function highlight (sel) { 349 | const d = sel.data(); 350 | let level_id = d.unique('level_id', true)[0]; 351 | let source = d.unique('source', true); 352 | let target = d.unique('target', true); 353 | 354 | const highlights = d.map(c => c.values) 355 | .flat() 356 | .map(c => { 357 | const connections = [] 358 | const arr = levels.map((b, k) => { return { level: k, value: c[b] } }) 359 | arr.forEach(b => { 360 | if (b.level > 0) { 361 | arr.filter(a => a.level === b.level - 1) 362 | .forEach(a => { 363 | connections.push(`${a.value}---${b.value}`) 364 | }) 365 | } 366 | }) 367 | return { nodes: arr.map(a => a.value), connections } 368 | }) 369 | const nodesToHighlight = highlights.map(c => c.nodes).flat().unique() 370 | const connectionsToHighlight = highlights.map(c => c.connections).flat().unique() 371 | 372 | // sel.classed('highlight', true) 373 | // .classed('dim', false) 374 | // .moveToFront(); 375 | 376 | d3.selectAll('path.connection') 377 | .classed('highlight', c => connectionsToHighlight.includes(c.key)) 378 | .classed('dim', c => !connectionsToHighlight.includes(c.key)); 379 | 380 | d3.selectAll('g.base') 381 | .classed('highlight', c => nodesToHighlight.includes(c.value)) 382 | .classed('dim', c => !nodesToHighlight.includes(c.value)); 383 | } 384 | function resetHighlight () { 385 | d3.selectAll('path.connection, g.base') 386 | .classed('highlight dim', false); 387 | d3.selectAll('g.bubble').remove(); 388 | } 389 | 390 | }).catch(err => console.log(err)) 391 | } 392 | 393 | 394 | document.addEventListener('DOMContentLoaded', drawSankey) -------------------------------------------------------------------------------- /notebooks/.ipynb_checkpoints/descriptive_analysis-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 5 6 | } 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==4.2.0 2 | appnope==0.1.3 3 | argon2-cffi==23.1.0 4 | argon2-cffi-bindings==21.2.0 5 | arrow==1.3.0 6 | asttokens==2.4.1 7 | async-lru==2.0.4 8 | attrs==23.2.0 9 | Babel==2.14.0 10 | beautifulsoup4==4.12.3 11 | bleach==6.1.0 12 | certifi==2023.11.17 13 | cffi==1.16.0 14 | charset-normalizer==3.3.2 15 | comm==0.2.1 16 | contourpy==1.2.0 17 | cycler==0.12.1 18 | debugpy==1.8.0 19 | decorator==5.1.1 20 | defusedxml==0.7.1 21 | exceptiongroup==1.2.0 22 | executing==2.0.1 23 | fastjsonschema==2.19.1 24 | fonttools==4.47.2 25 | fqdn==1.5.1 26 | idna==3.6 27 | ipykernel==6.29.0 28 | ipython==8.20.0 29 | ipywidgets==8.1.1 30 | isoduration==20.11.0 31 | jedi==0.19.1 32 | Jinja2==3.1.3 33 | json5==0.9.14 34 | jsonpointer==2.4 35 | jsonschema==4.21.1 36 | jsonschema-specifications==2023.12.1 37 | jupyter==1.0.0 38 | jupyter-console==6.6.3 39 | jupyter-events==0.9.0 40 | jupyter-lsp==2.2.2 41 | jupyter_client==8.6.0 42 | jupyter_core==5.7.1 43 | jupyter_server==2.12.5 44 | jupyter_server_terminals==0.5.2 45 | jupyterlab==4.0.11 46 | jupyterlab-widgets==3.0.9 47 | jupyterlab_pygments==0.3.0 48 | jupyterlab_server==2.25.2 49 | kiwisolver==1.4.5 50 | MarkupSafe==2.1.4 51 | matplotlib==3.8.2 52 | matplotlib-inline==0.1.6 53 | mistune==3.0.2 54 | nbclient==0.9.0 55 | nbconvert==7.14.2 56 | nbformat==5.9.2 57 | nest-asyncio==1.6.0 58 | notebook==7.0.7 59 | notebook_shim==0.2.3 60 | numpy==1.26.3 61 | overrides==7.6.0 62 | packaging==23.2 63 | pandas==2.2.0 64 | pandocfilters==1.5.1 65 | parso==0.8.3 66 | pexpect==4.9.0 67 | pillow==10.2.0 68 | platformdirs==4.1.0 69 | prometheus-client==0.19.0 70 | prompt-toolkit==3.0.43 71 | psutil==5.9.8 72 | ptyprocess==0.7.0 73 | pure-eval==0.2.2 74 | pycparser==2.21 75 | Pygments==2.17.2 76 | pyparsing==3.1.1 77 | python-dateutil==2.8.2 78 | python-json-logger==2.0.7 79 | pytz==2023.3.post1 80 | PyYAML==6.0.1 81 | pyzmq==25.1.2 82 | qtconsole==5.5.1 83 | QtPy==2.4.1 84 | referencing==0.32.1 85 | requests==2.31.0 86 | rfc3339-validator==0.1.4 87 | rfc3986-validator==0.1.1 88 | rpds-py==0.17.1 89 | Send2Trash==1.8.2 90 | six==1.16.0 91 | sniffio==1.3.0 92 | soupsieve==2.5 93 | stack-data==0.6.3 94 | terminado==0.18.0 95 | tinycss2==1.2.1 96 | tomli==2.0.1 97 | tornado==6.4 98 | traitlets==5.14.1 99 | types-python-dateutil==2.8.19.20240106 100 | typing_extensions==4.9.0 101 | tzdata==2023.4 102 | uri-template==1.3.0 103 | urllib3==2.1.0 104 | wcwidth==0.2.13 105 | webcolors==1.13 106 | webencodings==0.5.1 107 | websocket-client==1.7.0 108 | widgetsnbextension==4.0.9 109 | -------------------------------------------------------------------------------- /signals.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 24 | 25 | 26 | 27 | 28 |
29 | Contribute 30 | 31 |
32 | 33 |
34 | 39 |
40 | 42 | 43 | 44 | 45 | 46 | 47 | AI 48 | (possible) areas 49 | of intervention 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
58 |
59 |
60 |
61 | 144 | 145 | 532 | 533 | --------------------------------------------------------------------------------