<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Hatem Hassan 👨‍💻☕️💻🌺😎</title>
    <description>The latest articles on Forem by Hatem Hassan 👨‍💻☕️💻🌺😎 (@iammowgoud).</description>
    <link>https://forem.com/iammowgoud</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F64864%2Fe223af06-b26f-4efd-b6a1-9943b4e1d03e.png</url>
      <title>Forem: Hatem Hassan 👨‍💻☕️💻🌺😎</title>
      <link>https://forem.com/iammowgoud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/iammowgoud"/>
    <language>en</language>
    <item>
      <title>That time I built a tool that helps 1000 CS students every month</title>
      <dc:creator>Hatem Hassan 👨‍💻☕️💻🌺😎</dc:creator>
      <pubDate>Tue, 07 Jan 2020 22:52:39 +0000</pubDate>
      <link>https://forem.com/iammowgoud/that-time-i-built-a-tool-that-helps-1000-cs-students-every-month-22lp</link>
      <guid>https://forem.com/iammowgoud/that-time-i-built-a-tool-that-helps-1000-cs-students-every-month-22lp</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://iammowgoud.com/blog/that-time-i-built-quine-mccluskey/"&gt;personal blog&lt;/a&gt; (better formatting)&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; I built an online tool in 2013 at AUC that gets ~1000 visits a month from students all over the world and is mentioned in a couple of reputable universities slides including Columbia University.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://quinemccluskey.com/"&gt;Website&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;7 years ago, while I was pursuing my bachelor's of Computer Engineering at &lt;a href="https://www.aucegypt.edu/"&gt;The American University in Cairo&lt;/a&gt;, I had a course called Digital Design, which in retrospect I think was supposed to be called &lt;a href="https://en.wikipedia.org/wiki/Digital_electronics"&gt;Digital Electronics&lt;/a&gt; but who am I to name courses!!&lt;br&gt;
The course had nothing to do with design in the common known sense; it was mainly about the design of electronic logic gates to build processors and basic computer systems.&lt;/p&gt;

&lt;p&gt;Part of the course was studying the Quine McCluskey algorithm and learning how it works, then the semester project was building a calculator to solve for it in C++.&lt;/p&gt;

&lt;p&gt;Luckily after finishing the assignment I checked the domain name &lt;code&gt;quinemccluskey.com&lt;/code&gt; and to my surprise, it was available 😯😯&lt;/p&gt;

&lt;p&gt;I immediately bought the domain name and started converting my C++ program to a website using my limited knowledge of PHP at the time. I also used one of the earliest versions of  Bootstrap for styling. Please don't judge the UI, it was 2013 😅&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;a href="http://quinemccluskey.com/"&gt;Quine Mccluskey Calculator&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Adoption
&lt;/h1&gt;

&lt;p&gt;After publishing the website, I connected it to &lt;a href="https://marketingplatform.google.com/about/analytics/"&gt;Google Analytics&lt;/a&gt; then I posted the link on several social media websites and added it to the Quine Mccluskey &lt;a href="https://en.wikipedia.org/wiki/Quine%E2%80%93McCluskey_algorithm"&gt;Wikipedia page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since this algorithm is a standard topic taught in most CS and Electronics undergraduate programs around the world, it had a relatively wide demand across students all over the world.&lt;/p&gt;

&lt;p&gt;Looking at Google Analytics data we can see that over the &lt;strong&gt;&lt;em&gt;past 6 years&lt;/em&gt;&lt;/strong&gt;, almost &lt;strong&gt;&lt;em&gt;50k users&lt;/em&gt;&lt;/strong&gt; visited the website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cUYT8Ojz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/total-visitors.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cUYT8Ojz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/total-visitors.png" alt="Total visitors" width="880" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also there's a &lt;em&gt;28 day average of **943 "Active Users":&lt;/em&gt;**&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nSaXzgYk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/active-users.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nSaXzgYk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/active-users.png" alt='Google defines an Active Users as "The number of unique users who had at least one session within a 28-day period."' width="880" height="327"&gt;&lt;/a&gt;&lt;br&gt;
Google defines an Active Users as "The number of unique users who had at least one session within a 28-day period."&lt;/p&gt;

&lt;h3&gt;
  
  
  Did you notice any patterns in the visitors timeline?
&lt;/h3&gt;

&lt;p&gt;That's because students usually use the tool during the &lt;strong&gt;&lt;em&gt;assignment&lt;/em&gt;&lt;/strong&gt; period or the &lt;strong&gt;&lt;em&gt;Midterms season&lt;/em&gt;&lt;/strong&gt;, which is usually in November or March depending on the semester.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gs4ZhJ4---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/peaks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gs4ZhJ4---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/peaks.png" alt="Users seasonality" width="880" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Where do those visitors come from?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oma_q-w0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/geo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oma_q-w0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/geo.png" alt="Geographical sources" width="880" height="316"&gt;&lt;/a&gt;&lt;br&gt;
Geographically we can see that the heavy load is coming from the &lt;strong&gt;US&lt;/strong&gt; and &lt;strong&gt;India&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gO3d3rz6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/educational.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gO3d3rz6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/educational.png" alt="Sources including '.edu'" width="452" height="544"&gt;&lt;/a&gt;&lt;br&gt;
It's also worth noting that doing a simple search in the sources datatable we can find visitors coming from these universities internal systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Texas State University (USA)&lt;/li&gt;
&lt;li&gt;MSA (Egypt)&lt;/li&gt;
&lt;li&gt;Auburn University (USA)&lt;/li&gt;
&lt;li&gt;National Ilan University (Taiwan)&lt;/li&gt;
&lt;li&gt;Hunan Normal University (China)&lt;/li&gt;
&lt;li&gt;Ming Chuan University (Taiwan)&lt;/li&gt;
&lt;li&gt;Columbia University (USA)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What is Quine Mccluskey?
&lt;/h1&gt;

&lt;p&gt;In the world of digital logic design, everything is a logical function that can be boiled down to one of the basic arithmetic operations: addition, subtraction, multiplication or division.&lt;/p&gt;

&lt;p&gt;Even the most complex processes like image/video processing or machine learning algorithms are converted at the very low level to these simple arithmetic operations so it can run through the physical &lt;a href="https://en.wikipedia.org/wiki/Logic_gate"&gt;gates&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Flip-flop_(electronics)"&gt;flip-flops&lt;/a&gt; inside the processor/GPU card.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Processor_design"&gt;Earlier in computing history&lt;/a&gt;, engineers used to design and build such processors manually by finding out how to map a real problem to a series of &lt;a href="https://en.wikipedia.org/wiki/Boolean_function"&gt;boolean functions&lt;/a&gt; that outputs the correct result when electricity runs through the processing board.&lt;/p&gt;

&lt;p&gt;Theoretically a boolean function is an equation that can be represented in multiple ways; however, there should be one &lt;strong&gt;&lt;em&gt;optimal&lt;/em&gt;&lt;/strong&gt; way to implement it. Here comes the process of &lt;a href="https://en.wikipedia.org/wiki/Logic_optimization"&gt;&lt;strong&gt;Logic Optimization&lt;/strong&gt;&lt;/a&gt;. One of the most straightforward ways to optimiza boolean functions is the &lt;a href="https://en.wikipedia.org/wiki/Quine%E2%80%93McCluskey_algorithm"&gt;Quine–McCluskey algorithm&lt;/a&gt;, which serves the same purpose as the &lt;a href="https://en.wikipedia.org/wiki/Karnaugh_map"&gt;K-maps&lt;/a&gt; method but for more variables.&lt;/p&gt;

&lt;p&gt;Quine-McCluskey is a tabular and tedious method based on the concept of &lt;a href="https://en.wiktionary.org/wiki/prime_implicant"&gt;prime implicants&lt;/a&gt;. A prime implicant is a product or sum term, which can’t be further reduced by combining with any other terms of the given Boolean function.&lt;/p&gt;

&lt;p&gt;Basically you have to do the following 6 steps to simplify a Boolean Function using Quine–McCluskey.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I omitted explaining the "don't care" notion for simplicity but you can read about it in depth &lt;a href="https://www.lions.odu.edu/~rljones/310/homework/Chap3/EET310_Ch3_G_QM_Dont_Care.pdf"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2avXnBVL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/step-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2avXnBVL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/step-1.png" alt="Step 1: Arranging min terms" width="502" height="854"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 1:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
List down all of the &lt;a href="https://en.wiktionary.org/wiki/minterm"&gt;minterms&lt;/a&gt; in ascending order in &lt;strong&gt;&lt;em&gt;binary representation&lt;/em&gt;&lt;/strong&gt;, then group them by the number of &lt;strong&gt;1&lt;/strong&gt;s in each.&lt;br&gt;
This should create a maximum of &lt;strong&gt;n+1&lt;/strong&gt; groups for &lt;strong&gt;n&lt;/strong&gt; minterms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 2:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Compare the minterms in each group with the group after it. If there is a change in only one bit position, replace that one bit with ‘_’.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4P4ZbNK5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/step-2-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4P4ZbNK5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/step-2-3.png" alt="Steps 2 &amp;amp; 3: Comparisons" width="880" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 3:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Repeat Step 2 with the First Comparison results to come up with the &lt;strong&gt;&lt;em&gt;prime implicants&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 4:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Create the prime implicants &lt;strong&gt;&lt;em&gt;coverage table&lt;/em&gt;&lt;/strong&gt;. Prime implicants are be placed in rows and min terms are placed in columns.&lt;br&gt;
Then cross out (&lt;strong&gt;&lt;em&gt;X&lt;/em&gt;&lt;/strong&gt;) the cells which correspond to a min term that is covered with a prime implicant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6sifLpy3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/step-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6sifLpy3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/step-4.png" alt="Step 4: Prime implicants" width="880" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 5:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Now we need to get the &lt;strong&gt;&lt;em&gt;Essential Prime Implicants&lt;/em&gt;&lt;/strong&gt;. An Essential Prime Implicant is a minterm that is covered by &lt;strong&gt;&lt;em&gt;only one&lt;/em&gt;&lt;/strong&gt; prime implicant. These essential prime implicants are the &lt;em&gt;pre-final&lt;/em&gt; form the simplified Boolean function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VvbnS4x7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/step-5-6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VvbnS4x7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/step-5-6.png" alt="Reducing the prime implicants table" width="880" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 6:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Reduce by removing the row of each essential prime implicant and the columns corresponding to the min terms that are covered in that essential prime implicant.&lt;/p&gt;

&lt;p&gt;Repeat Step 5 for prime implicants till all min terms of given Boolean function are completed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wsyV7KBL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/final.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wsyV7KBL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/quine/final.png" alt="Final result" width="756" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>electronics</category>
      <category>engineering</category>
      <category>php</category>
      <category>web</category>
    </item>
    <item>
      <title>Fullstack NLP: Building &amp; Deploying End-to-end Fake News Classifier</title>
      <dc:creator>Hatem Hassan 👨‍💻☕️💻🌺😎</dc:creator>
      <pubDate>Sat, 07 Dec 2019 10:44:09 +0000</pubDate>
      <link>https://forem.com/iammowgoud/fullstack-nlp-building-deploying-end-to-end-fake-news-classifier-56fb</link>
      <guid>https://forem.com/iammowgoud/fullstack-nlp-building-deploying-end-to-end-fake-news-classifier-56fb</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://iammowgoud.com/blog/fullstack-nlp-building-and-deploying-end-to-end-fake-news-classifier/"&gt;personal blog&lt;/a&gt; (better formatting)&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; This is a tutorial on building the API+UI of NLP text classification web application and deploying it to production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection"&gt;Github&lt;/a&gt; | &lt;a href="https://fakenewsservice-ih2ql4rjjq-ew.a.run.app/notebook"&gt;Notebook&lt;/a&gt; | &lt;a href="https://fakenewsservice-ih2ql4rjjq-ew.a.run.app/"&gt;Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The classification model used is by no mean accurate and it's definitely overfitted over the training dataset. The focus of this post is implementing the fullstack web application. &lt;a href="https://www.fastcompany.com/90417625/machine-learning-isnt-effective-at-identifying-fake-news"&gt;Ref 1&lt;/a&gt;. &lt;a href="https://www.axios.com/machine-learning-cant-flag-false-news-55aeb82e-bcbb-4d5c-bfda-1af84c77003b.html"&gt;Ref 2&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While pursuing my Master's degree at &lt;a href="https://www.ie.edu/school-human-sciences-technology/masters/master-business-analytics-big-data/"&gt;IE&lt;/a&gt;, I worked on this &lt;a href="https://fakenewsservice-ih2ql4rjjq-ew.a.run.app/notebook"&gt;Text Classification model&lt;/a&gt; as part of the NLP course. The notebook is extra messy but I will try to briefly explain what's going on in the first section.&lt;/p&gt;

&lt;h1&gt;
  
  
  NLP Classifier
&lt;/h1&gt;

&lt;p&gt;Our problem here is to define whether or not a certain &lt;strong&gt;&lt;em&gt;news article&lt;/em&gt;&lt;/strong&gt; is fake news. The &lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection/blob/master/jupyter_project/fake_or_real_news_training.csv"&gt;dataset&lt;/a&gt; is comprised of 3997 news articles each includes a &lt;strong&gt;&lt;em&gt;title&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;text&lt;/em&gt;&lt;/strong&gt;, and the target &lt;strong&gt;&lt;em&gt;label&lt;/em&gt;&lt;/strong&gt; as a REAL/FAKE binary label. Part of the course was also testing the model on a test dataset but I never received target for this dataset. The &lt;a href="https://scikit-learn.org/stable/modules/generated/sklearn.metrics.accuracy_score.html"&gt;accuracy score&lt;/a&gt; of cross validation testing within the training dataset was 94%.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zfdb1yBo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/target.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zfdb1yBo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/target.png" alt="Test Dataset Target" width="399" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o-Beto4Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/confusion-matrix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o-Beto4Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/confusion-matrix.png" alt="CV Confusion Matrix" width="343" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I won't go through the coding details of the Notebook, but I will briefly describe the main steps taken before coming up with the final model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Text Preprocessing
&lt;/h2&gt;

&lt;p&gt;We can clearly see that the target is balanced. So we jump ahead into the preprocessing by doing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lowercase the text:&lt;/strong&gt;
This preprocessing step is done so words can later be cross checked with the stopwords and pos_tag dictionaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove&lt;/strong&gt;  words with just one letter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove&lt;/strong&gt; words that contain numbers&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.geeksforgeeks.org/nlp-how-tokenizing-text-sentence-words-works/"&gt;&lt;strong&gt;Tokenize&lt;/strong&gt;&lt;/a&gt; the text and remove punctuation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove &lt;em&gt;stopwords&lt;/em&gt;:&lt;/strong&gt;
Proper analysis of text usually relies on the most recurring words. &lt;strong&gt;Stopwords&lt;/strong&gt; including words as "the", "as" and "and" appear a lot in a text, but eech word doesn't really give relevant explanation, so one of NLP comon practices is to remove such words.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove empty tokens:&lt;/strong&gt;
After tokenization, we have to make sure all tokens taken into account contribute to the label prediction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lemmatize the text:&lt;/strong&gt;
In order to normalize the text, we apply &lt;a href="https://www.datacamp.com/community/tutorials/stemming-lemmatization-python"&gt;&lt;strong&gt;lemmatization&lt;/strong&gt;&lt;/a&gt;. In this way, words with the same root are processed equally e.g. when the words "took" or "taken" are found in the text, they are &lt;strong&gt;lemmatized&lt;/strong&gt; to "take", infinitive of the verb.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the &lt;code&gt;preprocess()&lt;/code&gt; function in &lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection/blob/d879c65cda5854d63c2db80eaec641e571eb37a1/jupyter_project/python_helper.py#L79"&gt;python_helper.py:79&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Baselining
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://fakenewsservice-ih2ql4rjjq-ew.a.run.app/notebook#Baseline-Modelling"&gt;this part of the notebook&lt;/a&gt;, you can see how I split and vectorize the dataset and run several classifiers on the dataset and measure baseline accuracy.&lt;/p&gt;

&lt;p&gt;There was a significant improvement in accuracy for &lt;a href="https://blog.datumbox.com/machine-learning-tutorial-the-max-entropy-text-classifier/"&gt;Max Entropy&lt;/a&gt; text classifier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Engineering &amp;amp; Pipeline
&lt;/h2&gt;

&lt;p&gt;After we have a baseline score, we do some extra work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pos-tag text:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding a prefix to each word with its type (Noun, Verb, Adjective,...). e.g: I went to school =&amp;gt; PRP-I VBD-went TO-to NN-school&lt;/p&gt;

&lt;p&gt;Also, after lemmatization it will be 'VB-go NN-school', which indicates the semantics and distinguishes the purpose of the sentence.&lt;/p&gt;

&lt;p&gt;This will help the classifier differentiate between different types of sentences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6kf-7sk4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/FE.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6kf-7sk4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/FE.svg" alt="Pos-tagging" width="880" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TF-IDF weighting:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TF-IDF or &lt;a href="https://en.wikipedia.org/wiki/Tf%E2%80%93idf"&gt;Term Frequency–Inverse Document Frequency&lt;/a&gt; tries to calculate the importance of each word based on its recurrence in text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kVP2zX27--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/tfdif.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kVP2zX27--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/tfdif.jpg" alt="TF-IDF" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use Trigram Vectorizer instead of regular vectorizer:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I opt to use a Trigram vectorizer here, which vectorizes triplets of words rather than each word separately. &lt;em&gt;&lt;u&gt;In this short example sentence&lt;/u&gt;&lt;/em&gt;, the trigrams are "In this short", "this short example" and "short example sentence".&lt;/p&gt;

&lt;p&gt;Finally I do a &lt;a href="https://medium.com/datadriveninvestor/an-introduction-to-grid-search-ff57adcc0998"&gt;Grid Search&lt;/a&gt; for different combinations of the past steps along with different models to &lt;a href="https://en.wikipedia.org/wiki/Hyperparameter_optimization"&gt;optimize for&lt;/a&gt; the best &lt;a href="https://en.wikipedia.org/wiki/Hyperparameter_(machine_learning)"&gt;hyper parameters&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you look just above the predictions &lt;a href="https://fakenewsservice-ih2ql4rjjq-ew.a.run.app/notebook#Predicting-on-test-dataset"&gt;here&lt;/a&gt;, you will find that this is the best performing model (Vectorizer + TF-IDF + Classifier):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;trigram_vectorizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CountVectorizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analyzer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"word"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ngram_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;tf_idf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TfidfTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;norm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"l2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;classifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LogisticRegression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dual&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fit_intercept&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;intercept_scaling&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_iter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multi_class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'warn'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;n_jobs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;penalty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'l2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'warn'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;tol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;warm_start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wrap everything inside a &lt;a href="https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html"&gt;&lt;strong&gt;Pipeline&lt;/strong&gt;&lt;/a&gt; that can train (&lt;code&gt;fit()&lt;/code&gt;) and classify (&lt;code&gt;predict()&lt;/code&gt;)  input easily.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sklearn.pipeline&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Pipeline&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Pipeline&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'trigram_vectorizer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trigram_vectorizer&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'tfidf'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tf_idf&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'clf'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pickling
&lt;/h2&gt;

&lt;p&gt;Next step is fitting the pipeline on train data like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clean_and_pos_tagged_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fit_transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this stage, the &lt;code&gt;pipeline&lt;/code&gt; object can &lt;code&gt;predict()&lt;/code&gt; new input. You can find the test predicting step in the notebook &lt;a href="https://fakenewsservice-ih2ql4rjjq-ew.a.run.app/notebook#2.-Predicting-on-test"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now comes the magic. If you want to encapsulate your whole model along with the training data in one single file to be used anywhere, you use &lt;strong&gt;&lt;a href="https://docs.python.org/3/library/pickle.html"&gt;Pickle library&lt;/a&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pickle&lt;/span&gt;
&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"pipeline.pkl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"wb"&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any object in python can be pickled to be saved on disk. Then it can be transferred to be imported in another python environment. What pickle does is that it &lt;strong&gt;serializes&lt;/strong&gt; the Python object before writing it to file. Pickling is just a way to convert any python object (list, dict, etc.) into a character stream. The whole idea behind it is that this serialized textual stream contains everything needed to reconstruct the object in another python script.&lt;/p&gt;

&lt;p&gt;In this case we are pickling our &lt;code&gt;pipeline&lt;/code&gt; object so we can use it later in the API to &lt;code&gt;pipeline.predict()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;pipeline.pkl&lt;/code&gt; file is now ready to predict any news article and classify it to either &lt;code&gt;REAL&lt;/code&gt; or &lt;code&gt;FAKE&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Web Application Architecture
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1g10cJRL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/architecture.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1g10cJRL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/architecture.svg" alt="Application Architecture" width="619" height="1510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we need a web interface in which the user can enter some news text and click on a button for the application to &lt;strong&gt;&lt;em&gt;preprocess&lt;/em&gt;&lt;/strong&gt; the input and feed it to the &lt;strong&gt;&lt;em&gt;trained model&lt;/em&gt;&lt;/strong&gt; and show the classification back on screen.&lt;/p&gt;

&lt;p&gt;Keep in mind that for the &lt;strong&gt;&lt;em&gt;pickled pipeline&lt;/em&gt;&lt;/strong&gt; to predict correctly we need to feed it with text preprocessed &lt;em&gt;exactly in the same way&lt;/em&gt; the train dataset was preprocessed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Frontend/UI:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is going to be a simple one page with one input and a button. No need to complicate stuff. As I mentioned in this &lt;a href="https://iammowgoud.com/blog/What-I-learned-in-40-hours-switching-from-Angular-to-React"&gt;post&lt;/a&gt;, React would be a better fit for such straightforward function.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Backend/Server:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since we need to &lt;strong&gt;"unpickle"&lt;/strong&gt; or &lt;code&gt;pickle.load()&lt;/code&gt; our model (the &lt;code&gt;pipeline&lt;/code&gt;) to use it, the best choice would be a python web server that can receive the input over HTTP and return back the prediction result. One of the easiest and most straightforward frameworks for this is &lt;a href="https://www.fullstackpython.com/flask.html"&gt;Flask&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another addition to the server would be implementing a &lt;strong&gt;"random picker"&lt;/strong&gt; that can fetch one random news article at a time from the test dataset. This will be used to populate the UI input field.&lt;/p&gt;

&lt;p&gt;The goal is to make it easier for the user to test the application, without actually writing a news article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flask API Server
&lt;/h2&gt;

&lt;p&gt;Assuming you have a ready Python environment and are familiar with Python development in general, installing pythons is as easy as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;flask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to use a &lt;code&gt;virtualenv&lt;/code&gt; you can check the steps &lt;a href="https://flask.palletsprojects.com/en/1.1.x/installation/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A simple Flask API that serves the static React app (next section) when you hit root path &lt;code&gt;/&lt;/code&gt; would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;static_folder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"./public/static"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;template_folder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"./public"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'index.html'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Only for local running
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can only make use of &lt;code&gt;template_folder&lt;/code&gt; now in which you can add a simple hello world HTML file. In the next section when we build the React app we will use the &lt;code&gt;static_folder&lt;/code&gt; store assets like CSS and JavaScript files.&lt;/p&gt;

&lt;p&gt;If you run the command &lt;code&gt;python app.py&lt;/code&gt; and hit &lt;code&gt;http://localhost:5000&lt;/code&gt; you should see the &lt;code&gt;/public/index.html&lt;/code&gt; displayed in your browser.&lt;/p&gt;

&lt;p&gt;As discussed in previous section, we mainly have 2 functions to implement here: &lt;strong&gt;predict&lt;/strong&gt; and &lt;strong&gt;random&lt;/strong&gt;. Let's start with the easier random picker endpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;random/&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since we have the test dataset in the &lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection/tree/master/data"&gt;&lt;code&gt;/data&lt;/code&gt;&lt;/a&gt; folder, we just need to load it and pick a random index and send it back to UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;randrange&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/random'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data/fake_or_real_news_test.csv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;randrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use Pandas here to read the CSV file and then send back the data in JSON format using flask &lt;code&gt;jsonify()&lt;/code&gt; helper function.&lt;/p&gt;

&lt;p&gt;Now whenever you send a GET request to &lt;code&gt;http://localhost:5000/random/&lt;/code&gt; using Postman or even open the link &lt;a href="https://fakenewsservice-ih2ql4rjjq-ew.a.run.app/random"&gt;in your browser&lt;/a&gt; you should see a random news entry from the test dataset file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;predict/&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the prediction function we need to do some work than just exposing the endpoint. We need to take the input, preprocess it, pos-tag it, then feed it to the pipeline and return back the result.&lt;/p&gt;

&lt;p&gt;So we create a PredictionModel class in a &lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection/blob/master/predictionModel.py"&gt;separate file&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;nltk.corpus&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;wordnet&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;nltk&lt;/span&gt;
&lt;span class="n"&gt;nltk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'./nltk_data'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# local NLTK data
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;nltk.corpus&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;stopwords&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;nltk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pos_tag&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;nltk.stem&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;WordNetLemmatizer&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PredictionModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="c1"&gt;# constructor
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'original'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;preprocess&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos_tag_words&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Merge text
&lt;/span&gt;        &lt;span class="n"&gt;clean_and_pos_tagged_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'preprocessed'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; \
            &lt;span class="s"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'pos_tagged'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'prediction'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'FAKE'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clean_and_pos_tagged_text&lt;/span&gt;&lt;span class="p"&gt;])[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s"&gt;'REAL'&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;

    &lt;span class="c1"&gt;# Helper methods
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;preprocess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# check file on github
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pos_tag_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# check file on github
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then we use the class in &lt;code&gt;app.py&lt;/code&gt; endpoint like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/predict'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PredictionModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So basically when you send a POST request to &lt;code&gt;http://localhost:5000/predict&lt;/code&gt;, the script will initialize a new &lt;code&gt;PredictionModel&lt;/code&gt; instance with the input text and return the prediction.&lt;/p&gt;

&lt;p&gt;For example &lt;code&gt;PredictionModel("Some news article text")&lt;/code&gt;, will return a JSON object like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"original"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Some news article text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"preprocessed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"news article text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pos_tagged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"NN-news NN-article IN-text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prediction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"FAKE"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; I exported the NLTK data and you can see I'm loading it from a local path here. The reason for this is both for better version management as I had issues with installing the right NLTK corpse on Docker.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But we used the &lt;code&gt;pipeline&lt;/code&gt; object without actually declaring it...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Loading the pickle:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The key idea we need to understand here is that we need to load the &lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection/tree/master/pickle"&gt;.pickle file&lt;/a&gt; before using it predict. &lt;em&gt;Note that the pickle file is *&lt;/em&gt;~350 MB*&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the top of the file we can add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pickle/pipeline.pkl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind this loads when you first run the &lt;code&gt;app.py&lt;/code&gt; script and it loads the 350MB pipeline object into your machine RAM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt; initial run and when the script is in standby mde waiting for requests, Whenever you call &lt;code&gt;pipeline.predict()&lt;/code&gt; in your script it will run instantly because the object is already in your RAM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; This will work fine when you run it locally, but when you deploy it into production you need to consider your server RAM and what happens if the script crashes. I will discuss this in the &lt;strong&gt;Deployment&lt;/strong&gt; section.&lt;/p&gt;

&lt;h2&gt;
  
  
  React User Interface
&lt;/h2&gt;

&lt;p&gt;To initialize the React app we will use &lt;code&gt;create-react-app&lt;/code&gt;. You can install that globally by running &lt;code&gt;npm i -g create-react-app&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then to initialize the actual code template we run &lt;code&gt;create-react-app fake-news-client&lt;/code&gt;. This will create a folder with the name "fake-news-client" and npm install the needed packages inside it.&lt;/p&gt;

&lt;p&gt;If you cd into the folder and run a simple &lt;code&gt;react-scripts start&lt;/code&gt; you should have a simple react app built and served in your browser on &lt;code&gt;http://localhost:3000/&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that the backend files will be the root folder of the project and the frontend will live in a subdirectory inside it with the name &lt;code&gt;webapp&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we need to install an extra package we will use in the project. cd into the folder and run &lt;code&gt;npm i -s node-sass&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'm using &lt;code&gt;node-sass&lt;/code&gt; to write the app styles which means you need to rename all the &lt;code&gt;.css&lt;/code&gt; files into &lt;code&gt;.scss&lt;/code&gt; and change the reference in the &lt;code&gt;index.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's build the UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection/blob/master/webapp/src/index.js"&gt;&lt;code&gt;/src/index.js&lt;/code&gt;&lt;/a&gt; file we can start adding the state object along with the HTML template that consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input:&lt;/strong&gt; textarea for the news text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actions:&lt;/strong&gt; button to get &lt;code&gt;/random&lt;/code&gt; data and another to &lt;code&gt;/predict&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Labels:&lt;/strong&gt; App can be in one of theses states: idle, loading, or error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result label:&lt;/strong&gt; Prediction, REAL/FAKE.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;NLPInterface&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;// Textarea value&lt;/span&gt;
    &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// Loading state flag&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// Error state flag&lt;/span&gt;
    &lt;span class="na"&gt;prediction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Prediction result&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;NLP Fake News Classifier&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;textarea&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateInput&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;textarea&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"random"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Load random News from test dataset ? &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click here&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"cta"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;predict&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Predict &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Classifying ...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;ERROR&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prediction&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NLPInterface&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find the styles in the &lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection/blob/master/webapp/src/index.scss"&gt;SCSS file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next step would be writing down the UI logic needed to to wire the template with the backend.&lt;/p&gt;

&lt;p&gt;Let's start by the &lt;strong&gt;textarea&lt;/strong&gt;, we can see it reads it's value from &lt;code&gt;this.state.text&lt;/code&gt;, and &lt;code&gt;onChange&lt;/code&gt; we are binding the &lt;code&gt;this.updateInput&lt;/code&gt; event handler which will update &lt;code&gt;state.text&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;  &lt;span class="nx"&gt;updateInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;prediction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="c1"&gt;// To reset previous prediction whenever the text in the textarea changes&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we have the &lt;strong&gt;Random&lt;/strong&gt; news picker button, which fires the following function &lt;code&gt;onClick&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;  &lt;span class="nx"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/random&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;prediction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we have the actual prediction function binded to another button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;  &lt;span class="nx"&gt;predict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;prediction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Start loading&lt;/span&gt;

    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/predict&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;prediction&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prediction&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will get the prediction result, store it to &lt;code&gt;state.prediction&lt;/code&gt; which is displayed in the &lt;code&gt;H1&lt;/code&gt; tag at the bottom of the &lt;code&gt;render()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Voila!&lt;/em&gt;&lt;/strong&gt; we have a working webpage that can communicate with our Flask backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bundling
&lt;/h2&gt;

&lt;p&gt;To bundle the frontend app and move it to the &lt;code&gt;/public&lt;/code&gt; folder which the Flask app will serve, we will edit the &lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection/blob/master/webapp/package.json"&gt;&lt;strong&gt;package.json&lt;/strong&gt;&lt;/a&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prebuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rm -r ../public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postbuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mv build/ ../public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now if you run &lt;code&gt;npm run build&lt;/code&gt; inside webapp folder then go up one directory &lt;br&gt; and run &lt;code&gt;python app.py&lt;/code&gt; then visit &lt;code&gt;http://localhost:5000&lt;/code&gt; you will find the app up and running 🎉🎉&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Dockerizing &amp;amp; Deployment
&lt;/h1&gt;

&lt;p&gt;To run this app successfully on a remote server we need to consider that this will be a service with a relatively slow boot time, as we load the 350 MB pickle once the script runs.&lt;/p&gt;

&lt;p&gt;For this we will use &lt;a href="https://gunicorn.org/"&gt;gunicorn&lt;/a&gt; HTTP server to run the python app. gunicorn will basically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the server script several times in parallel using multiple &lt;a href="https://docs.gunicorn.org/en/stable/design.html#async-workers"&gt;async workers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Make sure the server is always running and accepting requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After running &lt;code&gt;pip install gunicorn&lt;/code&gt; you can run the following to run the script using gunicorn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gunicorn &lt;span class="nt"&gt;-t&lt;/span&gt; 120 &lt;span class="nt"&gt;-b&lt;/span&gt; :8080 app:app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will run the server on port 8080 and I added the &lt;code&gt;-t 120&lt;/code&gt; flag to tell it to wait 120 seconds before timing out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now we move to deployment.&lt;/strong&gt; I chose to use &lt;a href="https://cloud.google.com/run/"&gt;&lt;strong&gt;Google Cloud Run&lt;/strong&gt;&lt;/a&gt; for this application &lt;em&gt;also&lt;/em&gt; because our application has a heavy stateless workload as it needs to load the large pickle file.&lt;/p&gt;

&lt;p&gt;To use Cloud Run we need to &lt;a href="https://www.docker.com/resources/what-container"&gt;&lt;strong&gt;containerize&lt;/strong&gt;&lt;/a&gt; our application by writing down the &lt;strong&gt;Dockerfile&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.7-stretch&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; python-pip python-dev build-essential

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /app&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip

&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; gunicorn -t 120 -b :$PORT app:app&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see also that I exported all of the needed python packages into a &lt;a href="https://github.com/iammowgoud/NLP-fake-news-detection/blob/master/requirements.txt"&gt;&lt;code&gt;requirments.txt&lt;/code&gt;&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;Finally, to get this to work on Google Cloud you need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start a Google Cloud Project&lt;/li&gt;
&lt;li&gt;Activate billing&lt;/li&gt;
&lt;li&gt;Open Google online console&lt;/li&gt;
&lt;li&gt;Pull the code into your account server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd&lt;/code&gt; into the project folder and run &lt;code&gt;gcloud builds submit --tag gcr.io/[your project ID]/fake-news-service&lt;/code&gt;
This will deploy the docker container image into that URL.&lt;/li&gt;
&lt;li&gt;Go to the Cloud Run dashboard and click on "Create Service"&lt;/li&gt;
&lt;li&gt;Type the image URL you created in step 5&lt;/li&gt;
&lt;li&gt;Set the memory allocated to 1GB&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;"Create"&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1nN09D5E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/config.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1nN09D5E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/fake-news/config.png" alt="Google Cloud Run configuration" width="880" height="673"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;💃🏼 💃🏼 &lt;strong&gt;&lt;em&gt;The app will be up and running in less than 5 minutes.&lt;/em&gt;&lt;/strong&gt; 💃🏼 💃🏼&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fakenewsservice-ih2ql4rjjq-ew.a.run.app/"&gt;&lt;strong&gt;&lt;em&gt;Demo&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Related Links:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/nlp-how-tokenizing-text-sentence-words-works/"&gt;Text tokenization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.datacamp.com/community/tutorials/stemming-lemmatization-python"&gt;Text lemmatization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.datumbox.com/machine-learning-tutorial-the-max-entropy-text-classifier/"&gt;Max Entropy Text Classifier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Tf%E2%80%93idf"&gt;TF-IDF: Term Frequency–Inverse Document Frequency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/datadriveninvestor/an-introduction-to-grid-search-ff57adcc0998"&gt;Grid Search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Hyperparameter_optimization"&gt;Hyperparameter Optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/pickle.html"&gt;Pickle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.fullstackpython.com/flask.html"&gt;Flask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gunicorn.org/"&gt;gunicorn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/run/"&gt;Google Cloud Run&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nlp</category>
      <category>javascript</category>
      <category>react</category>
      <category>python</category>
    </item>
    <item>
      <title>Realtime Data Visualization with Peak Detection using Socket.IO, D3 and React 📈📈</title>
      <dc:creator>Hatem Hassan 👨‍💻☕️💻🌺😎</dc:creator>
      <pubDate>Wed, 30 Oct 2019 11:06:02 +0000</pubDate>
      <link>https://forem.com/iammowgoud/realtime-data-visualization-with-peak-detection-using-socket-io-d3-and-react-412f</link>
      <guid>https://forem.com/iammowgoud/realtime-data-visualization-with-peak-detection-using-socket-io-d3-and-react-412f</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://iammowgoud.com/blog/Realtime-Data-Visualization-with-Peak-Detection-using-SocketIO-D3-and-React/" rel="noopener noreferrer"&gt;personal blog&lt;/a&gt; (better formatting)&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; This post is &lt;strong&gt;UX research&lt;/strong&gt; + &lt;strong&gt;fullstack programming tutorial&lt;/strong&gt; for building a web application that streams time series data to be visualized in realtime using multiple Javascript frameworks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://peak-detection-visualization.herokuapp.com/" rel="noopener noreferrer"&gt;Demo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  The Why?
&lt;/h1&gt;

&lt;p&gt;IoT is growing rapidly these days and one aspect that's key to the success of this kind of projects is data visualization. Design and UX is actually one of the most critical parts in any IoT project.&lt;/p&gt;

&lt;p&gt;Any SME may have a very good infrastructure and complex integrations, but what would that do if their systems lack the tools to transform this gathered into actionable insights that can deliver real business value.&lt;/p&gt;

&lt;p&gt;One thing is to collect some data from those new cool devices, another is to visualize it and make it accessible for your business or even your customer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use case: what is happening here?
&lt;/h2&gt;

&lt;p&gt;In this project I'm trying to build a React app that can consume data using Socket.io from a live source of data (we'll call it a &lt;strong&gt;Sensor&lt;/strong&gt;) and visualize the time series data (we'll call it &lt;strong&gt;Readings&lt;/strong&gt;) in realtime using D3.js&lt;/p&gt;

&lt;p&gt;To simulate the &lt;strong&gt;Sensor&lt;/strong&gt;, I created a very simple server using Express.js that rotate over a JSON file and keeps on continuously sending the &lt;strong&gt;Readings&lt;/strong&gt; one by one &lt;em&gt;every 1.5 seconds&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;TBH I didn't spend much time on the server development and didn't implement proper error handling/reporting because that's not the scope of the project.&lt;/p&gt;

&lt;p&gt;It's worth noting that while this project is built to work with a &lt;strong&gt;&lt;em&gt;stateful&lt;/em&gt;&lt;/strong&gt; WebSockets API assuming a realtime streaming use case. We could also make it support batch streaming REST API with a periodic server pinging on a longer interval. This really depends on the nature of the data and what level of granularity you want to have. I'm assuming the customer wants to do deep analysis and monitoring down to the interval of 1.5 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Peak detection
&lt;/h2&gt;

&lt;p&gt;In the world of Real-Time Signal Analysis, &lt;strong&gt;peak detection&lt;/strong&gt; is a hot topic for many engineering fields including chemistry, biology, biomedical, optics, astrophysics and energy systems.&lt;/p&gt;

&lt;p&gt;To add some spice to this sample project, I included in the sample data the &lt;strong&gt;&lt;em&gt;Moving Z-score&lt;/em&gt;&lt;/strong&gt; of each data-point beside the actual sensor value.&lt;/p&gt;

&lt;p&gt;The Moving Z-score is a mathematical model for measuring the anomalousness of each point in sequential time series. One of its main parameters is the window size &lt;em&gt;(w)&lt;/em&gt;. Given that the moving Z-score is the number of standard deviations each data-point is away from the mean, &lt;em&gt;(w)&lt;/em&gt; limits the window in which we calculate the such statistical parameters. In this specific use case, the mean and standard deviation are computed only over the previous &lt;em&gt;(w)&lt;/em&gt; observations.&lt;/p&gt;

&lt;p&gt;In this scenario the Z-score would be a binary (0/1) value that tells whether there's a &lt;strong&gt;"peak"&lt;/strong&gt; at this point or not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fz-score.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fz-score.svg" alt="Z-Score"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this project I got hold of a dataset with manually pre-calculated z-score to detect if the sensor readings increase  suddenly (aka &lt;strong&gt;&lt;em&gt;peaks&lt;/em&gt;&lt;/strong&gt;) over a certain period of time. I included the scores in the mock data on &lt;strong&gt;server side&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Later, I'm planning to revisit this project to do this calculation on &lt;strong&gt;client-side&lt;/strong&gt;, but given we need a (w) of data-points to get the first value so there would be a little bit of lag in initializing the visualization.&lt;/p&gt;

&lt;h1&gt;
  
  
  UX Research
&lt;/h1&gt;

&lt;p&gt;So now we know that we have two pieces of information at any certain point of time:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Actual sensor reading&lt;/li&gt;
&lt;li&gt;A binary value for whether there's a peak or not&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's start by asking ourselves a few questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to show those 2 values &lt;strong&gt;effectively&lt;/strong&gt; and &lt;strong&gt;clearly&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;How to create &lt;strong&gt;readable&lt;/strong&gt; and meaningful time series chart?&lt;/li&gt;
&lt;li&gt;How to design unique and usable experience for the user interacting with the visualization?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data Visualization should be "beautiful"
&lt;/h3&gt;

&lt;p&gt;This is a must. Whichever use case you have or application you are building, if it's an IoT monitoring tool or a fancy marketing dashboard, an ugly looking visualization will discourage your end users from looking at it and may actually &lt;strong&gt;prevent&lt;/strong&gt; them from understanding the meaning behind it and what insights the data entails.&lt;/p&gt;

&lt;p&gt;But what is an "ugly" visualization? What makes it "beautiful" and visually appealing instead?&lt;/p&gt;

&lt;p&gt;Well, this is subjective. There is no silver bullet. But with some conventional wisdom and lots of experience you realize that you should consider following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use the right type of diagram:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each type of a diagram was designed to represent data in a different way and focus on one aspect of the data. Obviously, graphing population of distant cities on world map wouldn't be the best option and using a pie chart to display more than 2-3 variables is a big no, and so on.&lt;/p&gt;

&lt;p&gt;Although there's some interesting visualizations for time series like Stream and Gantt charts and there's always room of creativity and artistic improvisation in data visualization, customers tend to like what they are familiar with. And we only have two variables in this project.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Well...this is a time series. It's gonna be a line graph.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fline.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fline.svg" alt="Line Chart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Avoid overcrowded areas:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Too much elements in a tiny space can only be justified in very limited cases. Points in a scatter plot for example can be tolerated but also, it's called a &lt;strong&gt;scatter&lt;/strong&gt; plot for a reason. Only when the crowded (or &lt;em&gt;unscattered&lt;/em&gt;) data points have the same meaning you can allow crowding them together to show &lt;strong&gt;density&lt;/strong&gt;, but if they have different meaning and you can't them apart because of the crowd jam ,you are doing something wrong.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is why I started my visualization by drawing it in its simplest form then adding on top of it. I removed all of the &lt;a href="https://en.wikipedia.org/wiki/Chartjunk" rel="noopener noreferrer"&gt;chart junk&lt;/a&gt; for now and will add whatever I need along the way.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Avoid mismatching or vague colors:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Colors are very subjective too, and they are associated with different feelings. Some feelings are obvious like hot red and warm blue, but if your data doesn't represent temperature? Also, some feelings or ideas associated with certain colors are cultural and differ from one target group to another.&lt;/p&gt;

&lt;p&gt;There's lots of science behind &lt;a href="https://www.smashingmagazine.com/2010/01/color-theory-for-designers-part-1-the-meaning-of-color/" rel="noopener noreferrer"&gt;color theory&lt;/a&gt; and why we perceive colors the way we do.&lt;br&gt;
  So, for this challenge what I do is that I stick with some of the famous palettes that have proved to work over time. You can use this &lt;a href="https://color.adobe.com/explore" rel="noopener noreferrer"&gt;cool color wheel by Adobe&lt;/a&gt; to find some preset palettes or &lt;a href="https://color.adobe.com/create" rel="noopener noreferrer"&gt;create&lt;/a&gt; your own based on color harmonies like Analogous, Triad, or Complementary colors, then they have an &lt;strong&gt;&lt;em&gt;Amazing&lt;/em&gt;&lt;/strong&gt; feature where you can Copy CSS or Less.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For this project, I went with this simple palette that has 2 shades of green and 2 shades of red.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fcolors.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fcolors.svg" alt="Colors"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Compare &amp;amp; contrast
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Comparisons and contrasts lead to conclusions&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A visualization has to reflect the meaning of data and be built as simple as possible to make comparisons easier so the user can draw conclusions.&lt;/p&gt;

&lt;p&gt;First thing we need to contrast here is the Readings series to the Z-scores series, &lt;em&gt;so instead of showing the two series in different graphs we can overlay the peaks over the original signal (Readings) and decreased **opacity&lt;/em&gt;* to 10%*.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fz-score-overlay.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fz-score-overlay.svg" alt="Z-score Alignment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We face a problem here with &lt;strong&gt;scales&lt;/strong&gt; or the unit of each value. You can't place a binary value in a line chart along a numerical value like the sensor readings.&lt;/p&gt;

&lt;p&gt;In this case we need to improvise. To show the Z-score as a pink region over the line series in D3, I converted it to an &lt;strong&gt;area series&lt;/strong&gt; to span the whole height of the graph. I normalized the 0-1 values to be 0-X where X is the highest value of readings displayed currently in view.&lt;/p&gt;

&lt;p&gt;We also need to provide the user with a way to &lt;strong&gt;&lt;em&gt;compare&lt;/em&gt;&lt;/strong&gt; the sensors data to each other. Why? So, the customer can see if the peak pattern is happening in one sensor or in all of them, and most importantly if the pattern is happening across all sensors at the &lt;strong&gt;&lt;em&gt;exact time&lt;/em&gt;&lt;/strong&gt; or if there's a &lt;strong&gt;&lt;em&gt;shift&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Since I'm assuming there's only 3 sensors we are visualizing, we can't really use  a &lt;a href="https://en.wikipedia.org/wiki/Small_multiple" rel="noopener noreferrer"&gt;small multiple&lt;/a&gt;. What we can do is stack the 3 graphs we have on top of each other, making sure that all graphs are &lt;strong&gt;horizontally aligned&lt;/strong&gt; to each other.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fvertical-alignment.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fvertical-alignment.svg" alt="Vertical Alignment"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Usability &amp;amp; Interaction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Usability&lt;/em&gt;&lt;/strong&gt; is the ease of access of an interface. It’s a sub-discipline of UX. Although UX design and usability are sometimes used interchangeably, usability has grown to have to be more than the ease of access. Usability now is &lt;a href="https://www.testingtime.com/en/blog/measuring-your-ux-and-usability/" rel="noopener noreferrer"&gt;measurable&lt;/a&gt;. Measuring usability is out of the scope of this blog post, so will will take a holistic approach towards increasing usability in general.&lt;/p&gt;

&lt;p&gt;Since we are here, we need to introduce a new terms: &lt;strong&gt;Dashboards&lt;/strong&gt; and  &lt;strong&gt;Widgets&lt;/strong&gt;. A dashboard shows various semi-related visualizations that deliver a shared business value but not necessary from the same data source. Widgets are the building blocks of a dashboard.&lt;/p&gt;

&lt;p&gt;The cards you've been seeing throughout the previous sections are all widgets. What do we need to consider now to make each single card/widget user friendly and most importantly relate them to each other ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Labels &amp;amp; Controls&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We need to show several labels to guide users where to look and help them understand what are they looking at, for this project we need to include the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Titles:&lt;/strong&gt;
dashboard title and sensor title.&lt;/li&gt;
&lt;li&gt;Connectivity indicator:
Here I'm assuming that the dashboard may get disconnect from a sensor for any reason. This happens a lot in IoT applications. We need to inform the user if one chart is &lt;strong&gt;&lt;em&gt;outdated&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time series legend:&lt;/strong&gt;
This will have &lt;strong&gt;&lt;em&gt;2 functions&lt;/em&gt;&lt;/strong&gt;, it will tell the user which is the actual reading and which is the peak area, and it will act as a &lt;strong&gt;toggle&lt;/strong&gt; so the user can &lt;em&gt;show/hide one of the two variables&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Axes:&lt;/strong&gt;
Beside the fact that we need to show the units and values of each dimension, we need to make it clear in which direction time is moving.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;(Extra element) Last reading Timestamp:&lt;/strong&gt;
Since for the x-axis, I'm truncating the time stamp to show only the seconds (:20, :30,...). I added the Full timestamp of the last reading in the bottom right corner of the widget.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;States&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Any frontend component goes through a cycle of several &lt;a href="https://en.wikipedia.org/wiki/Finite-state_machine" rel="noopener noreferrer"&gt;states&lt;/a&gt;. These states are driven by the business logic, in our case we have the following states for &lt;em&gt;each&lt;/em&gt; Widget:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connecting:&lt;/strong&gt;&lt;br&gt;
This is the initial state when the page is loading and we don't have enough information to show to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Disconnected:&lt;/strong&gt;&lt;br&gt;
This is when a widget is disconnected for a server or client error. We also show the HTTP error message for debugging and &lt;a href="https://ux.stackexchange.com/questions/84838/is-it-important-to-display-http-error-codes-to-users" rel="noopener noreferrer"&gt;helping users report their issues&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this scenario we can't only rely on the Connectivity indicator, we need to &lt;strong&gt;explain to the user that the current data in view is not active&lt;/strong&gt;. &lt;em&gt;So we set the whole line graph opacity to 50%.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connected:&lt;/strong&gt; Everything is perfect 👌🏽&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;(Extra UI state) Mouseout:&lt;/strong&gt;&lt;br&gt;
This is mainly to make the visualization &lt;strong&gt;less cluttered&lt;/strong&gt; and more visually appealing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although this is debatable and some designers don't favor it, I removed the x-axis and last Reading timestamp if the user is not hovering on a Widget.&lt;/p&gt;

&lt;p&gt;My rationale behind this is that the customer is not really concerned with the exact time of each point but rather the main focus points of this visualization are the pink shaded Peak areas.&lt;br&gt;
  If users really want to know when that happened, they can hover on the graph.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;**Final design&lt;/em&gt;&lt;em&gt;:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fcontrols.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fsteps%2Fcontrols.svg" alt="UI States"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://peak-detection-visualization.herokuapp.com/" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  The How
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Engineering the solution
&lt;/h2&gt;

&lt;p&gt;The frontend app contains two main classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chart: &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/blob/master/src/components/Chart.js" rel="noopener noreferrer"&gt;src/components/Chart.js&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;This is the main React component that connects to the relevant &lt;strong&gt;sensor&lt;/strong&gt; to stream  &lt;strong&gt;readings&lt;/strong&gt;, store it then does some data manipulation logic and finally initialize and update the D3 chart.&lt;/li&gt;
&lt;li&gt;The React component has 1 &lt;strong&gt;required prop&lt;/strong&gt; &lt;code&gt;sensorID&lt;/code&gt; and optional &lt;code&gt;x-ticks&lt;/code&gt; which has a default value of 20 and a max value of 50.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;D3TsChart: &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/blob/master/src/d3-helpers/d3-ts-chart.js" rel="noopener noreferrer"&gt;src/d3-helpers/d3-ts-chart.js&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;This is the custom class that handles the Time Series Chart graphics, and everything related to the chart SVG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readings&lt;/strong&gt; are passed to this class to be rendered in DOM using D3 but never stored in the class itself. Data lives in the &lt;code&gt;Chart&lt;/code&gt; component state.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fcomponent.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fiammowgoud.com%2Fblog%2Fassets%2Fimgs%2Fpeak-detection%2Fcomponent.svg" alt="Component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File organization:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;:root             // React component
&lt;span class="gt"&gt;  &amp;gt; api           // Express JS App&lt;/span&gt;
&lt;span class="gt"&gt;  &amp;gt; src&lt;/span&gt;
&lt;span class="gt"&gt;    &amp;gt; components&lt;/span&gt;
&lt;span class="gt"&gt;    &amp;gt; d3-helpers&lt;/span&gt;
&lt;span class="gt"&gt;    &amp;gt; styles&lt;/span&gt;
&lt;span class="gt"&gt;  &amp;gt; public&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;The backend server is very simple, it's just a single Express.js file along with the the &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/blob/master/api/data.json" rel="noopener noreferrer"&gt;data.json&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;The data file contains mock data for 3 sensors. You can connect to the socket by pinging &lt;code&gt;https://localhost:4001?socket={sensorId}&lt;/code&gt;. &lt;strong&gt;sensorId&lt;/strong&gt; can only be 1 or 2 or 3 &lt;em&gt;for now&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You can begin by creating the &lt;code&gt;api&lt;/code&gt; folder and installing the 2 needed packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; socket.io express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First thing we need to import the server requirements and initialize the Express.js server (&lt;code&gt;app&lt;/code&gt;) and wrap it by the socket.IO server (&lt;code&gt;io&lt;/code&gt;). We will also import the JSON data and set a const &lt;code&gt;INTERVAL&lt;/code&gt; of 1.5 seconds. This is how frequent we will emit data to each client connected to the server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;socketIO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;socket.io&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;io&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;socketIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;4001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;INTERVAL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sensorData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep track of each client connected to the server we will create a custom object that will keep track of 1. which sensor data was requested by the client, 2. index of the next data point to serve, and 3. the &lt;code&gt;setInterval&lt;/code&gt; reference that will emit data each 1.5 seconds (&lt;code&gt;INTERVAL&lt;/code&gt;). Then we will store one object like this in a custom dictionary attached to the Socket.IO &lt;code&gt;io&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Connection object interface&lt;/span&gt;
&lt;span class="c1"&gt;// {&lt;/span&gt;
&lt;span class="c1"&gt;//     sensorId,&lt;/span&gt;
&lt;span class="c1"&gt;//     index,&lt;/span&gt;
&lt;span class="c1"&gt;//     interval&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;

&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea behind storing the &lt;code&gt;setInterval&lt;/code&gt; is that we need to emit the data periodically and we will also need to stop (&lt;code&gt;clearInterval&lt;/code&gt;) this interval when a client disconnects from the server.&lt;/p&gt;

&lt;p&gt;Now we need to listen to and handle the clients &lt;code&gt;connect&lt;/code&gt; and &lt;code&gt;disconnect&lt;/code&gt; in the Socket.IO server, and then emit data accordingly using the &lt;code&gt;emitData&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connectionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sensorId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handshake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sensor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;//parse the sensorID&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`New client connected with id:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Add a client connection to the custom dictionary&lt;/span&gt;
  &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sensorId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;emitData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;INTERVAL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Remove connection&lt;/span&gt;
  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;disconnect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Client &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; disconnected`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that we need to implement the &lt;code&gt;emitData()&lt;/code&gt; function which basically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Selects the relevant sensor data from the data file&lt;/li&gt;
&lt;li&gt;calls getReading() which gets &lt;strong&gt;One&lt;/strong&gt; Reading from the data file&lt;/li&gt;
&lt;li&gt;Store the next Reading index in the connection object we created in &lt;code&gt;io.connections&lt;/code&gt; dictionary last snippet.&lt;/li&gt;
&lt;li&gt;Emit the reading with the event name 'reading'. We will listen to this in the client app next section.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emitData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNextReading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sensorData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sensorId&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Emitted to client: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, sensor id:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sensorId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, index:  &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Get the next reading for the selected socket&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNextReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;zscore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zScores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Now if you add &lt;code&gt;"start": "node index.js"&lt;/code&gt; to the scripts property in &lt;code&gt;package.json&lt;/code&gt; file and then run &lt;code&gt;npm start&lt;/code&gt; in the &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/tree/master/api" rel="noopener noreferrer"&gt;api&lt;/a&gt; folder, the server will be up and running and read to serve clients.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can test the server using this &lt;a href="https://electronjs.org/apps/socket-io-tester" rel="noopener noreferrer"&gt;awesome Electron app&lt;/a&gt; ...or go to the next section and start implementing the React app 👏🏽👏🏽👏🏽&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;p&gt;As mentioned before the client app will basically contain the main React component &lt;code&gt;Chart&lt;/code&gt; that renders one chart and is responsible of &lt;strong&gt;controlling&lt;/strong&gt; and &lt;strong&gt;passing data&lt;/strong&gt; to the D3.js chart that lives inside the a separate custom &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/blob/master/src/d3-helpers/d3-ts-chart.js" rel="noopener noreferrer"&gt;&lt;code&gt;d3-ts-chart&lt;/code&gt;&lt;/a&gt; class.&lt;/p&gt;

&lt;h3&gt;
  
  
  React App and &lt;code&gt;Chart&lt;/code&gt; component
&lt;/h3&gt;

&lt;p&gt;To initialize the React app we will use &lt;code&gt;create-react-app&lt;/code&gt;. You can install that globally by running &lt;code&gt;npm i -g create-react-app&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then to initialize the actual code template we run &lt;code&gt;create-react-app realtime-client&lt;/code&gt;. This will create a folder with the name "realtime-client" and npm install the needed packages inside it.&lt;/p&gt;

&lt;p&gt;If you cd into the folder and run a simple &lt;code&gt;react-scripts start&lt;/code&gt; you should have a simple react app built and served in your browser on &lt;code&gt;http://localhost:3000/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that this will be the root folder of the project and the backend server will live in a subdirectory inside it with the name &lt;code&gt;api&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we need to install the extra packages we will use in the project. cd into the folder and run &lt;code&gt;npm i -s socket.io node-sass d3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'm using &lt;code&gt;node-sass&lt;/code&gt; to write the app styles which means you need to rename all the &lt;code&gt;.css&lt;/code&gt; files into &lt;code&gt;.scss&lt;/code&gt; and change the reference in the &lt;code&gt;index.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Let's build a component&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The final Chart component is a big one. I will focus on the important parts here.&lt;/p&gt;

&lt;p&gt;We will need to define some basics stuff:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The series list: which is a list of information about the series/lines that will be graphed. This is we will pass to the &lt;code&gt;D3TsChart&lt;/code&gt; later to initialize the chart.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tsChart&lt;/code&gt; is the &lt;code&gt;D3TsChart&lt;/code&gt; object that we will code later and it's the one responsible of all D3 related operations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;socket&lt;/code&gt; is the socketId object that we will use to connect to the server and listen to the data.&lt;/li&gt;
&lt;li&gt;State: The React component state in which we will store the data and some info and flags about the chart.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;So the initial Component should start as the following:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;socketIOClient&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;socket.io-client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;D3TsChart&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../d3-helpers/d3-ts-chart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Chart&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;seriesList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sensor-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LINE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#038C7E&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Readings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;labelClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;readings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;z-score&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AREA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgba(216, 13, 49, 0.2)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transparent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Peaks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;labelClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;z-score&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;tsChart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;D3TsChart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;lastTimestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;connected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'chart-container'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to connect to the socket.IO server and fetch data for &lt;strong&gt;one sensor&lt;/strong&gt; by its id. We will pass &lt;code&gt;sensorId&lt;/code&gt; to the component as a &lt;strong&gt;prop&lt;/strong&gt;. This should be done in the &lt;code&gt;componentDidMount()&lt;/code&gt; function. After passing the component HTML element reference to &lt;code&gt;tsChart&lt;/code&gt; and initializing the 2 lines to be drawn by D3, it will call the &lt;code&gt;connect()&lt;/code&gt; function and will &lt;code&gt;disconnect()&lt;/code&gt; in &lt;code&gt;componentWillUnmount()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also notice that we listen to the "reading" event coming from the server and attach the &lt;code&gt;storeReading&lt;/code&gt; handler to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;componentDidMount():&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sensorId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You have to pass "sensorId" prop to Chart component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Component enclosing DIV HTML reference.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parentRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findDOMNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsChart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="c1"&gt;// Let D3 draw the chart SVG inside .chart-container div&lt;/span&gt;
      &lt;span class="na"&gt;elRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;parentRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementsByClassName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chart-container&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;z-chart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsChart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addSeries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seriesList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// readings&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsChart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addSeries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seriesList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;//z-score&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;connect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;socketIOClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/?sensor=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sensorId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeReading&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Various Errors handling&lt;/span&gt;
    &lt;span class="nx"&gt;SOCKETIO_ERRORS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errType&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;componentWillUnmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Socket.IO several errors strings and other constants are to be found in the top of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SOCKETIO_ERRORS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reconnect_error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connect_error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connect_timeout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connect_failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAX_POINTS_TO_STORE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to implement the &lt;code&gt;storeReading&lt;/code&gt; function that will store the readings into the component &lt;code&gt;state&lt;/code&gt; and pass the new data to the &lt;code&gt;tsChart&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;We first push the new reading to the current data then we update the &lt;code&gt;state.data&lt;/code&gt; with the last &lt;code&gt;MAX_POINTS_TO_STORE&lt;/code&gt; items. We also store some &lt;strong&gt;meta data&lt;/strong&gt; like the &lt;code&gt;connected&lt;/code&gt; indicator and the &lt;code&gt;lastTimestamp&lt;/code&gt; to be displayed in UI. LAstly, we call the &lt;code&gt;updateChart()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;storeReading():&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;storeReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prevState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pointsToStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;MAX_POINTS_TO_STORE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reading&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pointsToStore&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;connected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;lastTimestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLocaleTimeString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateChart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;updateChart()&lt;/code&gt; is implemented as a separate function because this is where we calculate &lt;code&gt;highestValueInView&lt;/code&gt; from the Readings series. This is done so we can &lt;strong&gt;&lt;em&gt;normalize&lt;/em&gt;&lt;/strong&gt; the zscores 0/1 and replaces the 1s with the highest value. This will essentially make the Peaks Area series take the whole height of the current data in view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;updateChart():&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;updateChart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;highestValueInView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zscore&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;highestValueInView&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsChart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;adjustAxes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsChart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSeriesData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sensor-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsChart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSeriesData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;z-score&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;zLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This all the basic logic needed to pass the data to the &lt;code&gt;D2TsChart&lt;/code&gt; class object.&lt;/p&gt;

&lt;p&gt;Now we need to update the &lt;code&gt;render()&lt;/code&gt; function to display the meta data we store in &lt;code&gt;state&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;final render():&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastTimestamp&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Connecting...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Sensor &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sensorId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connected&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;danger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"pulse"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connected&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Connected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Disconnected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chart-container &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timestamp &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connected&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;danger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connected&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Last reading was at &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastTimestamp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally we need to update the React &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/blob/master/src/index.js" rel="noopener noreferrer"&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/a&gt; to include the charts for the &lt;strong&gt;3 Sensors&lt;/strong&gt; we can fetch from API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;index.js:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/main.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Chart&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/Chart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Peak Detection Dashboard&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Chart&lt;/span&gt; &lt;span class="na"&gt;sensorId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Chart&lt;/span&gt; &lt;span class="na"&gt;sensorId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Chart&lt;/span&gt; &lt;span class="na"&gt;sensorId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find all the needed &lt;code&gt;scss&lt;/code&gt; styles in the &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/tree/master/src/styles" rel="noopener noreferrer"&gt;&lt;code&gt;styles&lt;/code&gt;&lt;/a&gt; directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  D3 Time Series line graph
&lt;/h3&gt;

&lt;p&gt;Here's where all the actual &lt;strong&gt;"graphing"&lt;/strong&gt; happens. This is the class where we import &lt;a href="https://square.github.io/intro-to-d3/" rel="noopener noreferrer"&gt;D3.js library&lt;/a&gt; and use it to append the different SVG elements to the HTML element stored in&lt;code&gt;elRef&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We need to set some constants like &lt;code&gt;TRANSITION_DURATION&lt;/code&gt; and &lt;code&gt;MAX_Y_TICKS&lt;/code&gt;, and &lt;em&gt;for now&lt;/em&gt; we only support two &lt;code&gt;SERIES_TYPES&lt;/code&gt; in graphing: &lt;code&gt;LINE&lt;/code&gt; and &lt;code&gt;AREA&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So this is how we start with the basic class:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;d3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SERIES_TYPES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LINE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AREA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TRANSITION_DURATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAX_Y_TICKS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;D3TsChart&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;margin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;outerWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;outerHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;elRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;classList&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;elRef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// If no width/height specified, SVG will inherit container element dimensions&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responsiveWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responsiveHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;classList&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will notice that we pass some initial config to the chart in the &lt;code&gt;init&lt;/code&gt; function including a width and height which are used to set up the graph layout according to the &lt;strong&gt;&lt;a href="https://bl.ocks.org/mbostock/3019563" rel="noopener noreferrer"&gt;Margin Convention&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;draw():&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Main SVG&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerWidth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerHeight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;classed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;//Inner box group  (deducting margins)&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerWidth&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; , &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;classed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// X Axis init&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xScale&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerWidth&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xAxisRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`translate(0,&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;classed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-axis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Y Axis init&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yScale&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outerHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yAxisRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;translate(0, 0)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;classed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;y-axis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we set the main SVG (with margins) and the inner group then we set the &lt;a href="https://www.d3indepth.com/scales/" rel="noopener noreferrer"&gt;scales&lt;/a&gt; for X-axis and Y-axis.&lt;/p&gt;

&lt;p&gt;Now we need to add the functions that will draw the series (line and area) inside the SVG.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add Series:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;addSeries&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seriesDict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Series name must be unique!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;SERIES_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Series type not supported!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seriesDict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stroke&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stroke-width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;strokeWidth&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;classed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;series&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;classed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setSeriesData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;adjustAxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;series&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seriesDict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;series&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AREA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateAreaSeries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;series&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LINE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateLineSeries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;series&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Updating data of a single series:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
  &lt;span class="nf"&gt;updateLineSeries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;series&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;series&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TRANSITION_DURATION&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;easeQuadIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;line&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;y&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;updateAreaSeries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;series&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;series&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TRANSITION_DURATION&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;easeQuadIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;area&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;y0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then finally we will have a function to adjust the axes to the current data in view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;adjustAxes():&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nf"&gt;adjustAxes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xScale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xAxisRef&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TRANSITION_DURATION&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;easeLinear&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;axisBottom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xScale&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxValue&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yAxisRef&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TRANSITION_DURATION&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;easeLinear&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;axisLeft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ticks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;maxValue&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;MAX_Y_TICKS&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;maxValue&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MAX_Y_TICKS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tickFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can have a look a deeper a look at this class in the  D3TsChart definition file &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/blob/master/src/d3-helpers/d3-ts-chart.js" rel="noopener noreferrer"&gt;src/d3-helpers/d3-ts-chart.js&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying to Heroku
&lt;/h2&gt;

&lt;p&gt;To deploy to Heroku this app to &lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt;heroku&lt;/a&gt; we need to setup the app so it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Builds the react app and move the static webapp to &lt;code&gt;api/public&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run the Express.js server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can do so by adding the proper commands in the root &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/blob/master/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Package.json:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node api/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prebuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rm -r api/public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postbuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mv build api/public"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Heroku will &lt;a href="https://devcenter.heroku.com/articles/deploying-nodejs" rel="noopener noreferrer"&gt;automatically detect&lt;/a&gt; that this is a Node.js app and will run the npm commands correctly.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;final step&lt;/strong&gt; here is to set up the ExpressJS app so it serves the static app in &lt;code&gt;api/public&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ExpressJS &lt;a href="https://github.com/iammowgoud/Peak-Detection-Visualization/blob/master/api/index.js" rel="noopener noreferrer"&gt;index.js&lt;/a&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;strong&gt;&lt;em&gt;That's all folks.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Related Links:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://turi.com/learn/userguide/anomaly_detection/moving_zscore.html" rel="noopener noreferrer"&gt;Moving Z-score Algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Chartjunk" rel="noopener noreferrer"&gt;Chart junk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://color.adobe.com/explore" rel="noopener noreferrer"&gt;Adobe Color&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Beautiful-Evidence-Edward-R-Tufte/dp/1930824165" rel="noopener noreferrer"&gt;Beautiful Evidence Book by Edward R. Tufte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@chathuranga94/introduction-to-socket-io-600025322cd2" rel="noopener noreferrer"&gt;Intro to Socket.IO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/tutorial/tutorial.html" rel="noopener noreferrer"&gt;Intro to React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://square.github.io/intro-to-d3/" rel="noopener noreferrer"&gt;Intro to D3.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bl.ocks.org/mbostock/3019563" rel="noopener noreferrer"&gt;D3 Margin Convention&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.d3indepth.com/scales/" rel="noopener noreferrer"&gt;D3 Scale functions in depth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devcenter.heroku.com/articles/deploying-nodejs" rel="noopener noreferrer"&gt;Deploying Node.js Apps on Heroku&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dataviz</category>
      <category>javascript</category>
      <category>react</category>
      <category>d3js</category>
    </item>
    <item>
      <title>Designing Data Intensive Applications - Book Review</title>
      <dc:creator>Hatem Hassan 👨‍💻☕️💻🌺😎</dc:creator>
      <pubDate>Sun, 13 Oct 2019 11:29:57 +0000</pubDate>
      <link>https://forem.com/iammowgoud/designing-data-intensive-applications-book-review-23mf</link>
      <guid>https://forem.com/iammowgoud/designing-data-intensive-applications-book-review-23mf</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://iammowgoud.com/blog/Designing-Data-Intensive-Applications-Review/"&gt;personal blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This book is definitely a classic. The book basically touches upon the surface of a wide array of topics related to handling data in a distributed environment; ranging from basic database theory, ACID, replication and partitioning to more complex (and "modern") topics like stream and batch processing on the cloud.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  "Data outlives code.”
&lt;/h2&gt;

&lt;p&gt;- Martin Kleppman&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Martin Kleppman lays down all the needed information on what every engineer needs to know about designing systems that deal with any kind of data.&lt;/p&gt;

&lt;p&gt;The first part is about basic database concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relational vs. NoSQL&lt;/li&gt;
&lt;li&gt;Different query languages&lt;/li&gt;
&lt;li&gt;How data is actually persisted on storage devices. (B-Trees / LSM Trees)&lt;/li&gt;
&lt;li&gt;Encoding and serialization/deserialization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second part goes deeper and discusses the following concepts &lt;em&gt;(and their issues)&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CAP Theorem&lt;/li&gt;
&lt;li&gt;Replication&lt;/li&gt;
&lt;li&gt;Partitioning&lt;/li&gt;
&lt;li&gt;Transactions&lt;/li&gt;
&lt;li&gt;Consistency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final chapter discusses &lt;strong&gt;&lt;em&gt;derived data&lt;/em&gt;&lt;/strong&gt; and  aims to tackle the issues discussed in the previous part, as well as introducing more "modern" concepts like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Batch and Stream processing (MapReduce/Spark)&lt;/li&gt;
&lt;li&gt;Eventual consistency and "Change Data Capture"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although the book doesn't dive into any  deep technical or implementation details, it has a very good bibliography and footnotes that leads you to all of the academic papers you need. Overall, the book is an essential read for any software/data engineer in 2019.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Instagram Art:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L5IHG11v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://iammowgoud.com/blog/assets/imgs/ddia-review/cover.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L5IHG11v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://iammowgoud.com/blog/assets/imgs/ddia-review/cover.gif" alt="Some Instagram art" width="300" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.goodreads.com/review/show/2833852928"&gt;Review on Goodreads&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dataintensive.net/"&gt;Book website&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321"&gt;Book on Amazon&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>data</category>
      <category>database</category>
      <category>book</category>
      <category>review</category>
    </item>
    <item>
      <title>What I learned in 40 hours switching from Angular to React!</title>
      <dc:creator>Hatem Hassan 👨‍💻☕️💻🌺😎</dc:creator>
      <pubDate>Sat, 12 Oct 2019 23:01:22 +0000</pubDate>
      <link>https://forem.com/iammowgoud/what-i-learned-in-40-hours-switching-from-angular-to-react-56bh</link>
      <guid>https://forem.com/iammowgoud/what-i-learned-in-40-hours-switching-from-angular-to-react-56bh</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://iammowgoud.com/blog/What-I-learned-in-40-hours-switching-from-Angular-to-React"&gt;personal blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’ve been building webapps with Angular 2+ and Ember.js since 2016 but I never got the chance to start a React project before.&lt;/p&gt;

&lt;p&gt;I once did some changes in an existing react app when I was working at &lt;a href="https://www.crazyegg.com/"&gt;CrazyEgg&lt;/a&gt; but they were mostly CSS. I really never had the full experience. I never dug deep into React.&lt;/p&gt;

&lt;p&gt;So I decided to do so and I allocated 40 hours to build a simple React CRUD app and dig my way into the source code and to learn how it really works throughout the journey.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9PsROK-B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/angular-react/40-hours.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9PsROK-B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/angular-react/40-hours.jpg" alt="I use Toggl to log my time. Awesome tool" width="880" height="144"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;I use &lt;a href="https://toggl.com/"&gt;Toggl&lt;/a&gt; to log my time. Awesome tool.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  React is a library
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Angular is not.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Angular is an opinionated MVC/MVVM (or &lt;a href="https://stackoverflow.com/questions/13329485/what-does-mvw-stand-for"&gt;MVW&lt;/a&gt;) &lt;strong&gt;framework&lt;/strong&gt; that comes with several smaller packages (or &lt;a href="https://angular.io/guide/libraries"&gt;libraries&lt;/a&gt;) that handle a wide array of functionalities like routing, http requests, animations, forms,…etc.&lt;/p&gt;

&lt;p&gt;On the other hand, react is just a V. It's really only concerned with the View layer. &lt;strong&gt;&lt;em&gt;Woah woah hold on!&lt;/em&gt;&lt;/strong&gt; Don't get me wrong, I'm not trying to put down React. Actually that kind of specialization gave React a couple of advantages and it definitely beat Angular in some areas that are discussed in the rest of this post.&lt;/p&gt;

&lt;p&gt;One could say that React gives you much more &lt;strong&gt;&lt;em&gt;freedom. Less boilerplate and faster initial setup&lt;/em&gt;&lt;/strong&gt;. But however if you are going to build a complex webapp using react you need to rely on other libraries like react-router, react-promise, or Redux. Maybe Enzyme for testing.&lt;br&gt;
It's common in React that you may rely on &lt;strong&gt;&lt;em&gt;state management libraries&lt;/em&gt;&lt;/strong&gt; like &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; or &lt;a href="https://mobx.js.org/"&gt;MobX&lt;/a&gt;.&lt;br&gt;
Of course we still rely on external libraries in Angularverse like &lt;a href="https://rxjs-dev.firebaseapp.com/"&gt;RxJS&lt;/a&gt; or &lt;a href="https://ngrx.io/"&gt;NgRx&lt;/a&gt; for state management.&lt;/p&gt;

&lt;p&gt;One Angular disadvantage that it has a much steep &lt;strong&gt;&lt;em&gt;learning curve&lt;/em&gt;&lt;/strong&gt;. Angular architecture is kinda influenced by backend Java frameworks. It is built using TypeScript &lt;em&gt;(a must actually)&lt;/em&gt; and it has a &lt;strong&gt;&lt;em&gt;clear-ish standard file structure&lt;/em&gt;&lt;/strong&gt;. If you come from backend background, that would be great. Otherwise, you have to understand what is &lt;strong&gt;&lt;em&gt;dependency injection&lt;/em&gt;&lt;/strong&gt; and what are &lt;strong&gt;&lt;em&gt;static types&lt;/em&gt;&lt;/strong&gt;, add to that some basic OOP concepts like &lt;strong&gt;&lt;em&gt;inheritance&lt;/em&gt;&lt;/strong&gt; and polymorphism.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;React's architecture ? It doesn't have any.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;There are some &lt;a href="https://www.sitepoint.com/react-architecture-best-practices/"&gt;best practices&lt;/a&gt; though.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Which can be great if you want to do a simple SPA or crazy animation magic without worrying about the project structure hassle. But it also means a whole lot more &lt;strong&gt;&lt;em&gt;decision making&lt;/em&gt;&lt;/strong&gt; if you wanna build a full-fledged app, an analytics dashboard for example. These decisions mostly include picking third-party libraries, choosing how to go about code organization and file structure, sticking with JS or using TypeScript (&lt;a href="https://fettblog.eu/typescript-react/getting-started/"&gt;yes you can TS in react&lt;/a&gt;).&lt;/p&gt;
&lt;h1&gt;
  
  
  Markup
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Let's have everything in one place" - A wild Facebook Engineer, 2013&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;React introduced &lt;a href="https://reactjs.org/docs/introducing-jsx.html"&gt;JSX&lt;/a&gt; and everyone went crazy. It was controversial for brief 2 years then the frontend community realized &lt;a href="https://medium.com/@bluepnume/jsx-is-a-stellar-invention-even-with-react-out-of-the-picture-c597187134b7"&gt;it's actually not that bad&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In JSX you have JS logic inside your HTML …or maybe you actually write HTML inside JS .. &lt;strong&gt;&lt;em&gt;wut?!&lt;/em&gt;&lt;/strong&gt; 🤔🤔🤔&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Something like this&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, world!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// or even this&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formatName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;!
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="c1"&gt;// Look at this&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greetings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hola&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hey&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;greetings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                   &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;greeting&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="c1"&gt;// 🤯🤯🤯&lt;/span&gt;
              &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other hand the conservative Angular has a clear &lt;strong&gt;&lt;em&gt;separation of UI and logic&lt;/em&gt;&lt;/strong&gt;. You write your template in the HTML file in TypeScript in the &lt;code&gt;.ts&lt;/code&gt; file like how our parents raised us.&lt;/p&gt;

&lt;p&gt;This distinction is highly debatable. While the Angular way is more readable and easy to understand if you come from any formal framework-y experience. JSX has better code completion and compile-time checks as everything is one file. Keep in mind, you also have to learn how to use custom directives like &lt;code&gt;ng-for&lt;/code&gt; and &lt;code&gt;ng-if&lt;/code&gt; to make use of Angular special "HTML on steroids" version.&lt;/p&gt;

&lt;h1&gt;
  
  
  Data binding
&lt;/h1&gt;

&lt;p&gt;Whether you have a separated template file and TS file or you have them mixed up in a JSX file, at the end of the day you have a UI and some logic that runs it. Say you have an input field in the template and it pulls its value from a JS variable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_bmQ1TqF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/angular-react/mvvm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_bmQ1TqF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/angular-react/mvvm.jpg" alt="Angular MVVM data binding" width="406" height="279"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Angular MVVM data binding.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Angular this value can flow in both directions, if you change it programmatically in your TS code or if you changed in your browser writing in the input field. This is called &lt;strong&gt;&lt;em&gt;two-way data binding&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;React works a little bit differently. You can only change this state (value of the JS variable) programmatically, and then the UI gets updated automatically. But if user changed the HTML input field value from the browser, that doesn't reflect on the JS variable. &lt;strong&gt;&lt;em&gt;This is one-way binding&lt;/em&gt;&lt;/strong&gt;. To achieve two-way binding in React we rely on &lt;strong&gt;&lt;em&gt;callbacks&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;DOM events&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Updating state in React&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;someData&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{({&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;someData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  DOM Manipulation
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;If you know what you are doing, React is fast. Really fast.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The reason behind this is that React uses a &lt;a href="https://reactjs.org/docs/faq-internals.html"&gt;&lt;strong&gt;Virtual DOM&lt;/strong&gt;&lt;/a&gt; which basically diffs the DOM tree looking for changes and then only updates the changes &lt;em&gt;(like how git works)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Angular uses Regular DOM that traverses the whole tree till it finds the target element it wants to change and then edit it.&lt;/p&gt;

&lt;p&gt;In the grand scheme of things this difference in performance is &lt;strong&gt;&lt;em&gt;negligible&lt;/em&gt;&lt;/strong&gt; unless you are doing crazy stuff with lots of elements in the page (&lt;a href="https://developers.google.com/web/tools/lighthouse/audits/dom-size"&gt;Say more than 1500&lt;/a&gt;). This can actually block the main thread of the JS engine and freeze the UI if you are not careful.&lt;/p&gt;

&lt;h1&gt;
  
  
  Unit Testing
&lt;/h1&gt;

&lt;p&gt;Using Angular CLI you can set up your project to include the boilerplate file provided by &lt;a href="https://jasmine.github.io/"&gt;Jasmine&lt;/a&gt; testing framework which runs by &lt;a href="https://karma-runner.github.io/latest/index.html"&gt;Karma&lt;/a&gt; test runner. You can also use Karma to replace Jasmine with other frameworks like &lt;a href="https://mochajs.org/"&gt;Mocha&lt;/a&gt; or QUnit. Karma plays very well too if you want to integrate with continuous integration services like &lt;a href="https://jenkins.io/"&gt;Jenkins&lt;/a&gt;, &lt;a href="https://travis-ci.org/"&gt;TravisCI&lt;/a&gt;, or &lt;a href="https://circleci.com/"&gt;CircleCI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;React uses Jest out of the box with no need to do any configuration. You can also use AirBnb's Enzyme library next to Jest. &lt;a href="https://airbnb.io/enzyme/"&gt;Enzyme&lt;/a&gt; mimics JQuery API to facilitate DOM interactions in tests.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;That's all folks!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>You Don't Know JS - Book Review</title>
      <dc:creator>Hatem Hassan 👨‍💻☕️💻🌺😎</dc:creator>
      <pubDate>Sat, 12 Oct 2019 22:40:14 +0000</pubDate>
      <link>https://forem.com/iammowgoud/you-don-t-know-js-book-review-2039</link>
      <guid>https://forem.com/iammowgoud/you-don-t-know-js-book-review-2039</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://iammowgoud.com/blog/Data-driven-Frontend-development-using-RNN/"&gt;personal blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Just finished You don't Know JS series by &lt;a href="https://github.com/getify"&gt;Kyle Simpson&lt;/a&gt;. It took me almost 4 months to get through the 6 books, and I will definitely go back to reread certain parts of it.&lt;/p&gt;

&lt;p&gt;I think this series is essential for anyone who want to dive deep into Javascript. From syntax gotchas and quirks to how coercion works to asynchronicity (or the illusion of asynchronicity).&lt;/p&gt;

&lt;p&gt;Kyle Simpson has a unique way in explaining complex CS concepts and ideas in simple words.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types &amp;amp; Grammar
&lt;/h2&gt;

&lt;p&gt;This book is not as interesting or intriguing as other books in the series because it goes through the basic stuff then it's basically a list of Gotchas and quirks in the language logic. I gave it 5 stars because Kyle's explanations and examples are amazing even if the material itself is dull.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;this&lt;/code&gt; &amp;amp; Object Prototypes
&lt;/h2&gt;

&lt;p&gt;The book explains the deep quirks and gotchas of the dynamic nature of JavaScript embodied in the [[Prototype]] concept. It gives you a general understanding of how objects are created and how behavior is executed or rather "delegated" in JS.&lt;/p&gt;

&lt;p&gt;Kyle in the last chapter proposes his own design pattern OLOO (Objects Linked to Other Objects) which aims to solve many of the issues of trying to code JS in an traditional OO pattern. I have my reservations on the pattern and how readable it's syntax is.&lt;/p&gt;

&lt;p&gt;The fact that he wants each object to have it's unique method names and prohibits overriding at all is beyond me, it makes code more complex, less intuitive and also doesn't make it any easier for new engineers to work with an already existing codebase. However, he lays down some strong arguments against writing JS code in traditional OOP style, which ignore or "hide" the dynamic nature of the language and try to tame it into a static one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Async &amp;amp; Performance
&lt;/h2&gt;

&lt;p&gt;Amazing book if you want to understand how asynchronicity in JavaScript works. Kyle has a unique way of explaining deep technical CS concepts in a simple and straightforward manner. He lays down the differences between concurrency, serialism and parallelism and then use those differences to explain the JS Event loop and then goes into the technicalities of implementation using callbacks, promises, and generators. Finally, he gives some overview of assessing performance and benchmarking.&lt;/p&gt;

&lt;h1&gt;
  
  
  ES6 &amp;amp; Beyond
&lt;/h1&gt;

&lt;p&gt;I consider this book to be the most important one in the You don't know JS series, especially for those who have some experience and have been working with Javascript for years. It goes through all of the tricks and gotchas of ES6 and as usual Kyle's way of explanation is very clear and straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Overall, the books are amazing and mind opening, and I highly recommend them.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.goodreads.com/review/list/8891666-hatem?utf8=%E2%9C%93&amp;amp;search%5Bquery%5D=You+Don%27t+Know+JS"&gt;Reviews on Goodreads&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/getify/You-Dont-Know-JS"&gt;Online version of the book on GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>book</category>
      <category>review</category>
    </item>
    <item>
      <title>Data driven Frontend development using RNN and Markov Chains</title>
      <dc:creator>Hatem Hassan 👨‍💻☕️💻🌺😎</dc:creator>
      <pubDate>Sat, 12 Oct 2019 22:13:31 +0000</pubDate>
      <link>https://forem.com/iammowgoud/data-driven-frontend-development-using-rnn-and-markov-chains-1p2j</link>
      <guid>https://forem.com/iammowgoud/data-driven-frontend-development-using-rnn-and-markov-chains-1p2j</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://iammowgoud.com/blog/Data-driven-Frontend-development-using-RNN/"&gt;personal blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The dark ages of the Web
&lt;/h2&gt;

&lt;p&gt;Throughout my career as a frontend engineer, I've worked with many libraries, &lt;a href="https://www.npmjs.com"&gt;packages&lt;/a&gt;, and &lt;a href="https://lexi-lambda.github.io/blog/2016/08/24/understanding-the-npm-dependency-model/"&gt;dependencies&lt;/a&gt;. I admit that when I used JQuery for the first time almost 10 years ago I never really thought about what was happening behind this innocent &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag. I was amazed with how easy it to &lt;code&gt;$('.cool-logo').slideUp()&lt;/code&gt;, I didn't even consider how it works behind the scenes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://code.jquery.com/jquery.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/assets/slideshow.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/assets/form-validations.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/assets/moment.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- We need those `a year ago` strings, don't we? --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/assets/thatAnimationThingWeUseInOnePage.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;-- Part of a very cool website &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;Not only is this way hard to manage, because if one library depends on another we will probably mess it up, it also can make your website size grow rapidly without even noticing. You don't know how many of these libraries imports &lt;code&gt;loadash&lt;/code&gt; or which version does it import. Are these libraries updated and secure? Are there duplicates? 🤷🏽‍♂️&lt;/p&gt;

&lt;h2&gt;
  
  
  We need a change
&lt;/h2&gt;

&lt;p&gt;Now the web has evolved a lot and we don't only have libraries, we have &lt;strong&gt;&lt;em&gt;frameworks&lt;/em&gt;&lt;/strong&gt;, like Angular. We've seen lots of changes and innovation in the way we build &lt;em&gt;web applications&lt;/em&gt;. JavaScript &lt;strong&gt;&lt;em&gt;bundling&lt;/em&gt;&lt;/strong&gt; is a major component of any Frontend framework in 2019. Basically what a &lt;strong&gt;&lt;em&gt;Static File Bundler&lt;/em&gt;&lt;/strong&gt; does is put your JavaScript files (and assets) and all its dependencies together in one &lt;em&gt;(or more)&lt;/em&gt; file(s). Two of the most popular bundlers are &lt;a href="http://browserify.org/"&gt;browserify&lt;/a&gt; and &lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e9FZ9q_k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/guessjs/webpack.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e9FZ9q_k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/guessjs/webpack.jpg" alt="Webpack homepage" width="650" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Webpack
&lt;/h3&gt;

&lt;p&gt;Webpack is wildly adopted because it is the bundler used by Angular CLI to build production assets. In case of static websites, what it does is finding and eliminating all those random &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags in HTML all over your project and only includes one single JavaScript file (or a few).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://webpack.js.org/guides/getting-started/"&gt;Getting started with Webpack configuration&lt;/a&gt; can have a steep learning curve but it is nothing compared to manually managing dependencies. The basic concept a beginner engineer needs to understand about Webpack is that you give it an &lt;strong&gt;&lt;em&gt;entry file&lt;/em&gt;&lt;/strong&gt;; which Webpack will access to recursively look for all those &lt;code&gt;import&lt;/code&gt;s and &lt;code&gt;require&lt;/code&gt;s to figure out all of the dependencies in the project. Then it builds a &lt;strong&gt;&lt;em&gt;dependency tree&lt;/em&gt;&lt;/strong&gt;, which is very useful for various reasons, one of which is removing duplicate libraries. Finally it compiles (and possibly compress) everything  into bundle(s).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It doesn't stop here!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Bundle optimization&lt;/em&gt;&lt;/strong&gt; is another hot topic right now. Frameworks like Angular are trying optimize how these bundles are built and &lt;strong&gt;&lt;em&gt;splitted&lt;/em&gt;&lt;/strong&gt;. For example, if you use one big graphing library in some pages of a dashboard Webapp, it doesn't really make sense to load this library in all pages and right away. What would you do with it in the &lt;code&gt;/login&lt;/code&gt; page? Always remember that our goal is to eventually decrease page load time.&lt;/p&gt;

&lt;p&gt;That's one reason we divide our Angular app into &lt;strong&gt;modules&lt;/strong&gt;. Angular and Webpack will create  a specific bundle for all of the pages contained in that module and load it on demand. Assuming the modules structure is mapped to the path structure, this can be called &lt;strong&gt;&lt;em&gt;&lt;a href="https://web.dev/route-level-code-splitting-in-angular"&gt;Route-level code splitting&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are lots in play when it comes to bundle optimization. &lt;a href="https://angular.io/guide/lazy-loading-ngmodules"&gt;Lazy loading&lt;/a&gt;, Eager loading and Preloading are all strategies used to optimize bundling and decrease page load time. You can read more about it in this &lt;a href="https://medium.com/@lifei.8886196/eager-loading-lazy-loading-and-pre-loading-in-angular-2-what-when-and-how-798bd107090c"&gt;sweet article&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Machine Learning comes to the rescue
&lt;/h2&gt;

&lt;p&gt;Googlers from the Angular team started a very cool project called Guess.js to tackle the bundling issues in Angular as well as static sites.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SKkFk46k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/guessjs/cover.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SKkFk46k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/guessjs/cover.jpg" alt="Guess.js" width="880" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google's Guess.js is optimizing code &lt;strong&gt;bundling&lt;/strong&gt; and &lt;strong&gt;prefetching&lt;/strong&gt; using &lt;a href="https://www.tensorflow.org/js"&gt;TensorFlow.js&lt;/a&gt; RNN Machine Learning model (or Markov Chain) to learn &lt;strong&gt;&lt;em&gt;navigation patterns&lt;/em&gt;&lt;/strong&gt;.  These patterns are used to predict users' next transition, as in next possibly visited page (or pages). Why? to prefetch these pages and provide &lt;strong&gt;&lt;em&gt;instant&lt;/em&gt;&lt;/strong&gt; transitions with your application. Cool, right?&lt;/p&gt;

&lt;h3&gt;
  
  
  WTH is RNN?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dZBRoHXG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/guessjs/rnn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dZBRoHXG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/guessjs/rnn.jpg" alt="Recurrent Neural Network" width="650" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RNN is a &lt;strong&gt;&lt;em&gt;Recurrent Neural Network&lt;/em&gt;&lt;/strong&gt; that uses its internal memory to process a sequence of inputs. In this case, think about a web navigation sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User 1: /login =&amp;gt; /dasboard =&amp;gt; /dasboard/report/1 =&amp;gt; /dashboard/report/2 =&amp;gt; /logout
User 2: /login =&amp;gt; /account  =&amp;gt; /dashboard/add/user =&amp;gt; /dashboard/add/user/success/ =&amp;gt; /logout
User 3: ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What RNN does is that it &lt;strong&gt;&lt;em&gt;learns&lt;/em&gt;&lt;/strong&gt; the common patterns in such sequences then given a sequence of inputs it can predict the next item in the sequence.&lt;/p&gt;

&lt;h4&gt;
  
  
  But why RNN ?
&lt;/h4&gt;

&lt;p&gt;The output of an RNN unit does not only depend on the current input but it also considers the previous hidden state which carries past information. This means the network learns from its past to come up with &lt;strong&gt;better&lt;/strong&gt; target (prediction).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;**Note:&lt;/em&gt;* I'm not sure how RNNs are implemented exactly inside Guess.js, this is just a description of how RNNs are relevant to navigation patterns prediction*.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are limitations of RNN though:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://machinelearningmastery.com/exploding-gradients-in-neural-networks/"&gt;It has vanishing and exploding gradients.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infolks.info/blog/recurrent-neural-network/"&gt;It doesn't remember long term dependencies.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the two variants of RNN that tackle these limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://colah.github.io/posts/2015-08-Understanding-LSTMs/"&gt;LSTM (Long Short Term Memory)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://towardsdatascience.com/understanding-gru-networks-2ef37df6c9be"&gt;GRU (Gated Recurrent units)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most obvious difference between those two is GRU has output and hidden state, while LSTM has output, hidden state and &lt;strong&gt;cell state&lt;/strong&gt;. &lt;em&gt;Check the list in the end of this post for more details about RNNs.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So in summary RNN contains internal state that gets updated every time we feed it with new input. During output sequence prediction, the knowledge of the past is used through hidden states.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about Markov Chains?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Once again, this is general description of Markov Chains, not Guess.js implementation&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Markov chain is named after mathematician Andrey Markov and it is a probabilistic model that simulates the flow from one &lt;strong&gt;&lt;em&gt;"state"&lt;/em&gt;&lt;/strong&gt; to another. In other words, in a space of multiple events/states, the model can tell us how likely it is that we &lt;strong&gt;&lt;em&gt;"hop"&lt;/em&gt;&lt;/strong&gt; from event A to event B, or from B =&amp;gt; C, what about B =&amp;gt; C =&amp;gt; A, and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---9Ah5Q06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/guessjs/markov.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---9Ah5Q06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://iammowgoud.com/blog/assets/imgs/guessjs/markov.jpg" alt="Markov Chains Example" width="550" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our case, a Markov Model would give us for instance the probability of a certain user jumping from the &lt;code&gt;/product&lt;/code&gt; page to the &lt;code&gt;/checkout&lt;/code&gt; page. So if there is a high probability of the user "transitioning" from this product page to the checkout page, Guess.js can start loading that Stripe payment JS bundle in the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data-driven predictions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;So how do we get those sequences? Where is the data?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;brilliant&lt;/strong&gt; thing about Guess.js is that it grabs its data from &lt;a href="https://marketingplatform.google.com/about/analytics/"&gt;&lt;strong&gt;&lt;em&gt;Google Analytics&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; to better train the RNN model and perform data-driven &lt;strong&gt;&lt;em&gt;route-level&lt;/em&gt;&lt;/strong&gt; JavaScript parsing and code splitting optimizations. That's how it predicts which JavaScript bundle it should load next and when.&lt;/p&gt;

&lt;p&gt;Here comes the cool part. Google Analytics has been widely used by many websites for years and it provides &lt;em&gt;exactly&lt;/em&gt; the kind of data we need to feed Guess.js.&lt;/p&gt;

&lt;p&gt;This combination of Google Analytics + Guess.js automagically figures out the best way to bundle your application and optimize its resources for better performance.&lt;/p&gt;

&lt;p&gt;It even goes so much deeper that it can predict the next piece of content (article, product, video) a user is likely to want to view and adjust or filter the user experience to account for this. It also can predict the types of widgets an individual user is likely to interact with more and use this data to tailor a more custom experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;I honestly think this is a breakthrough in Machine Learning empowering Customer Experience and Web Performance. It is basically instant page transitions.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/guess-js/guess/"&gt;Guess.js Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;You can read more about RNNs &lt;a href="https://medium.com/explore-artificial-intelligence/an-introduction-to-recurrent-neural-networks-72c97bf0912"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Check this &lt;a href="http://setosa.io/ev/markov-chains/"&gt;awesome visual playground&lt;/a&gt; of Markov Chains.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://towardsdatascience.com/brief-introduction-to-markov-chains-2c8cab9c98ab"&gt;Much Math&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>machinelearning</category>
      <category>angular</category>
      <category>javascript</category>
      <category>tensorflow</category>
    </item>
  </channel>
</rss>
