123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <title>Xkcd Data Visualization</title>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <!-- favicon (by default flask only serves from static) -->
- <link rel="shortcut icon" href="static/favicons/favicon.ico">
- <link rel="apple-touch-icon" sizes="180x180" href="static/favicons/apple-touch-icon.png">
- <link rel="icon" type="image/png" sizes="32x32" href="static/favicons/favicon-32x32.png">
- <link rel="icon" type="image/png" sizes="16x16" href="static/favicons/favicon-16x16.png">
- <link rel="manifest" href="static/favicons/site.webmanifest">
- <meta name="msapplication-TileColor" content="#00aba9">
- <meta name="theme-color" content="#ffffff">
- <!-- Patrick Hand font -->
- <link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Patrick+Hand" />
- <!-- Latest compiled and minified CSS -->
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
- <!-- jQuery library -->
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
- <!-- popper.min.js for Popovers -->
- <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
- <!-- Latest compiled JavaScript -->
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
- <!-- custom stylesheet -->
- <link rel="stylesheet" href="static/styles.css">
- </head>
- <body>
- <header class="box">
- <h1>Xkcd Data Visualization</h1>
- <h4>Similar comics are clustered together!</h4>
- </header>
- <main>
- <div class="container">
- <div class="row row-no-gutters">
- <div class="col-sm-6">
- <section class="box" id="featureDistributionMenu" style="padding-left: 20px;">
- <h3>
- Feature Distribution Menu
- <button type="button" class="btn btn-outline-secondary" data-container="body" data-toggle="popover" data-placement="bottom"
- title="Feature Distribution Menu"
- data-content='
- <strong>select a feature to see the distribution of all the comics with that feature</strong>
- <ul style="text-align:center;">
- <li>
- <h4>selection list</h4>
- <p>select feature by clicking</p>
- <p>on pc, search by typing first letter or using find tool on menu</p>
- </li>
- <li>
- <h4>select multiple</h4>
- <p>windows: ctrl+click</p>
- <p>mac: cmd+click</p>
- </li>
- <li>
- <h4>select consecutive</h4>
- <p>on pc: shift+click</p>
- </li>
- </ul>
- '
- data-html="true">
- <img src="static/glyphicons/info.svg" class="info-icon">
- </button>
- </h3>
- <div style="display: flex;">
- <div style="flex: auto;">
- <h3>{{num_features}} Features</h3>
- <select id="select-featureDistribution" size="20" multiple></select>
- </div>
- <div style="flex: auto;">
- <div style="padding-left: 20px;">
- <h3>Selected Features:</h3>
- <div style="text-align: left;" id="selected-featureDistribution" class="box"></div>
- <h3 id="overlapnum-featureDistribution">comics containing multiple of the selected features: </h3>
- <br>
- <button id="button-clear-featureDistribution" type="button">Clear Selection</button>
- </div>
- </div>
- </div>
- </section>
- </div>
- <div class="col-sm-6">
- <section class="box" id="featureDistribution">
- <h3>Feature Distribution
- <button type="button" class="btn btn-outline-secondary" data-container="body" data-toggle="popover" data-placement="bottom"
- title="Feature Distribution"
- data-content='
- <strong>tsne-embedding of comic relations where similar comics are closer together</strong>
- <ul style="text-align:center;">
- <li>
- <div class="tooltip-key">hover on point</div>
- <p>populate tooltip with comic title</p>
- </li>
- <li>
- <h4>color: orange</h4>
- <p>comic has one of the selected features</p>
- </li>
- <li>
- <h4>color: black</h4>
- <p>comic has multiple of the selected features</p>
- </li>
- <li>
- <h4>color: blue</h4>
- <p>comic has none of the selected features</p>
- </li>
- <li>
- <h4>color: red</h4>
- <p>comic picked on click, show details in picked comic panel</p>
- </li>
- <li>
- <h4>brush points</h4>
- <p>click and drag on scatterplot to zoom in</p>
- </li>
- <li>
- <h4>double / triple click on graph</h4>
- <p>zoom out</p>
- </li>
- </ul>
- '
- data-html="true">
- <img src="static/glyphicons/info.svg" class="info-icon">
- </button>
- </h3>
- <div id="chart-featureDistribution"></div>
- </section>
- </div>
- </div>
- </div>
- <div class="container">
- <div class="row row-no-gutters">
- <div class="col-sm-6">
- <section class="box" id="barchart">
- <h3>TFIDF of Top Words in Selected Comics
- <button type="button" class="btn btn-outline-secondary" data-container="body" data-toggle="popover" data-placement="bottom"
- title="TFIDF of Top Words in Selected Comics"
- data-content='
- <strong>compare selected comic's most important words & summed TFIDF (importance) scores</strong>
- <ul style="text-align:center;">
- <li>
- <h4>color: red</h4>
- <p>picked comic's TFIDF value</p>
- </li>
- <li>
- <h4>color: orange</h4>
- <p>selected comic group's summed TFIDF value</p>
- </li>
- <li>
- <h4>color: blue</h4>
- <p>word's total TFIDF score</p>
- </li>
- <li>
- <h4>checkbox</h4>
- <p>hide/show group's TFIDF bar, adjust axis</p>
- </li>
- </ul>
- '
- data-html="true">
- <img src="static/glyphicons/info.svg" class="info-icon">
- </button>
- </h3>
- <div>
- <input type="checkbox" class="checkbox-barchart" id="checkbox-barchart-picked" value="picked" checked>
- <label for="checkbox-barchart-picked">Picked (1)</label>
- <input type="checkbox" class="checkbox-barchart" id="checkbox-barchart-selected" value="selected" checked>
- <label for="checkbox-barchart-selected" id="checkbox-barchart-selected-label">Selected ()</label>
- <input type="checkbox" class="checkbox-barchart" id="checkbox-barchart-all" value="all" checked>
- <label for="checkbox-barchart-all">All ({{num_comics}})</label>
- </div>
- <div id="chart-barchart"></div>
- </section>
- </div>
- <div class="col-sm-6">
- <section class="box" id="scatterplot">
- <h3>TFIDF to LSA to TSNE Comic Relations
- <button type="button" class="btn btn-outline-secondary" data-container="body" data-toggle="popover" data-placement="bottom"
- title="TFIDF to LSA to TSNE Comic Relations"
- data-content='
- <strong>tsne-embedding of comic relations where similar comics are closer together</strong>
- <ul style="text-align:center;">
- <li>
- <div class="tooltip-key">hover on point</div>
- <p>populate tooltip with comic serial number and title</p>
- </li>
- <li>
- <h4>color: red</h4>
- <p>comic picked on click, show details in picked comic panel</p>
- </li>
- <li>
- <h4>color: orange</h4>
- <p>comic selected on brush, brush empty area to clear</p>
- </li>
- <li>
- <h4>color: blue</h4>
- <p>unselected comic</p>
- </li>
- <li>
- <h4>input area</h4>
- <p>pick specific comic by serial number</p>
- </li>
- <li>
- <h4>brush points</h4>
- <p>click and drag on scatterplot to select and zoom in</p>
- </li>
- <li>
- <h4>double / triple click on graph</h4>
- <p>zoom out</p>
- </li>
- </ul>
- '
- data-html="true">
- <img src="static/glyphicons/info.svg" class="info-icon">
- </button>
- </h3>
- <div class="input-group">
- <span class="input-group-addon">Pick Comic 1-{{num_comics}}</span>
- <input class="form-control" type="number" id="form-scatterplot-picked" min="1" max={{num_comics}} step="1">
- </div>
- <div id="chart-scatterplot"></div>
- </section>
- </div>
- </div>
- </div>
- <div class="container">
- <div class="row row-no-gutters">
- <div class="col-sm-6">
- <section id="pictureDiv" class="box">
- <h3>Picked Comic Info
- <button type="button" class="btn btn-outline-secondary" data-container="body" data-toggle="popover" data-placement="bottom"
- title="Picked Comic Info"
- data-content='<strong>see picked comic's title, image, and alt-text</strong>'
- data-html="true">
- <img src="static/glyphicons/info.svg" class="info-icon">
- </button>
- </h3>
- <p id="xkcdImageTitle"> 221: Random Number </p>
- <img id="xkcdImage" alt="221: Random Number"
- src="https://www.explainxkcd.com/wiki/images/f/fe/random_number.png"
- style='height: 100%; width: 100%; object-fit: contain'>
- <p id="xkcdImageAltText"> Alt Text </p>
- </section>
- </div>
- <div class="col-sm-6">
- <section class="box" style="text-align:left;">
- <h3>Process</h3>
- <ol style="text-align:left;">
- <li>scrape comics transcript, title, and alt-text from explainxkcd.com</li>
- <li>clean data by removing domain-specific stop-words (e.g. character names), lemminize and stem words (e.g. “chocolates”, “chocolatey”, “choco” all count as the root word, “chocolate”)</li>
- <li>represent each of the {{num_comics}} comic as a {{num_features}}-dim text vector of term-frequency x inverse document frequency (tf-idf) scores</li>
- <li>reduce the effects of synonymy and polysemy, and reduce the feature space from 7000 unique words to 50 feature by perform latent semantic analysis with truncated svd</li>
- <li>create 2d embedding of document relations with t-sne that shows similar comics located closer together</li>
- <li>build interactive, reactive data analysis web application with d3.js, bootstrap, and flask</li>
- </ol>
- <h3>Background Information on Xkcd Comics</h3>
- <p>
- xkcd comics are "A webcomic of romance, sarcasm, math, and language"
- (xkcd slogan). These comics are licensed under a Creative Commons
- Attribution-NonCommercial 2.5 License, and their transcripts are available
- on www.explainxkcd.com (xkcd comic's wiki). This web application uses
- the first {{num_comics}} comics as data source.
- </p>
- </section>
- </div>
- </div>
- </div>
- </main>
- <footer class="box">
- <p>
- Gati Aher, April 2020 |
- <a href="https://github.com/GatiAher/Xkcd_Data_Visualization">
- <img src="static/glyphicons/mark-github.svg" class="github-icon">
- </a>
- </p>
- </footer>
- <script src="https://d3js.org/d3.v4.min.js"></script>
- <script src="static/chart.js"></script>
- <script src="static/scatterplot.js"></script>
- <script src="static/barchart.js"></script>
- <script src="static/general.js"></script>
- <script>
- var comic_data = {{ return_comic_data.comic_data | safe }};
- var feature_names = {{ return_feature_names.feature_names | safe }};
- // add features to feature distribution menu
- for (const idx in feature_names) {
- $('#select-featureDistribution').append($('<option>', {value:idx, text:feature_names[idx]}));
- }
- var featureScatterplot = new Scatterplot("featureDistribution",
- selectOnBrushFlag=false, pickOnClickFlag=true,
- pickOnFormFlag=false, selectOnSelectMenuFlag=true);
- featureScatterplot.updateAndDraw(comic_data);
- var scatterplot = new Scatterplot("scatterplot");
- scatterplot.updateAndDraw(comic_data);
- var barchart = new Barchart("barchart");
- // initial state of feature selection menu
- $("#select-featureDistribution").val(["3301", "3849"]);
- $('#selected-featureDistribution').text("number (200), random (71)");
- requestFeatureDistribution(["3301", "3849"]);
- // initial coloring of selected dots
- scatterplot.scatter.selectAll("circle")
- .filter(function(d) { return dataStore.selected_sn.includes(d.sn); })
- .classed("dot-selected", true);
- // initial coloring of picked dot
- scatterplot.scatter.selectAll("circle")
- .filter(function(d) { return d.sn == dataStore.picked_sn })
- .classed("dot-picked", true);
- // initial state of pick elements
- generalPick("221: Random Number",
- "RFC 1149.5 specifies 4 as the standard IEEE-vetted random number.",
- "https://www.explainxkcd.com/wiki/images/f/fe/random_number.png", 221);
- // initial state of select elements
- generalSelect(dataStore.selected_sn);
- // BUG: call again to fix incomplete draw barchart
- requestBarchartData();
- // add clear feature to clear selection button
- $("#button-clear-featureDistribution").click(function(){
- $("#select-featureDistribution option:selected").prop("selected", false);
- $('#selected-featureDistribution').text("");
- requestFeatureDistribution([]);
- });
- // initialize all popovers
- $(function () {
- $('[data-toggle="popover"]').popover()
- });
- </script>
- </body>
- </html>
|