Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Monday, March 13, 2017

2nd Xap I built, AWS S3

Last mile vs first mile

The previous post showed how I built my 1st Xap. I deliberately avoided directly file import. My logical thinking is reconstructed as follows:
  1. One line of d3 code d3.csv(file, function) has already integrated 3 steps: open the local or remote file by the string name or URL, parse the file object into JSON format, callback a function to process the data.
  2. Although the first 2 steps have the corresponding Exaptive components, building a pure step-3 component could be more difficult than building a one-stop-shopping component.
  3. At that time, I hadn’t figure out what exactly is the data format during the flow between components and being sent to the dimple function.
  4. To get d3.csv work, I came out a nerdy approach: host the dataset in my own GitHub.
So my 1st Xap is focused on the data visualization, the last mile for a data scientist. “Begin with the End in Mind” is a hard lesson I learned during my past years. After that, I turned my attention to the first mile. I want to be very clear about the data format in each step and I would like to peek into every black box.

Gear up: WebStorm, AWS S3

Then I looked for a Javascript IDE, something like Jupyter notebook in Python. WebStorm caught my attention. It offers 30-day free trial and is free for 2 years for students and teachers, training and open source projects. Even for a standard individual customer, the annual fee of $59 is affordable.
After playing for a while, I realized WebStorm is good for developing the complex function of a simple input, something more pure for javascript coding. But for a web-based application, you always have to deal with file input and script input. If you don’t have a html file, the powerful libraries like jQuery and D3 are sitting on the bench because they are born to manipulate the DOM.
So I return to my previous tool set: start up a local host by python, use atom to write html/javascript codes and check the visual effect on Chrome.
Once I handcraft my html pages, I would like to have a remote host to display them. Years ago Google Drive provided such service for free. Now the hosting business is taken by AWS. I am surprised to see AWS provides up to 17 categories of services such as: compute, storage, database, developer tools, management tools, analytics, AI, Internet of things. S3 (simple static storage) is only a tiny business. By the way, the AWS page looks ugly. I guess because it is like a warehouse shopping center, the target customers care more about the price and stability, rather than a sexy face.
Here are my examples:
Note: For security reasons. the browsers block the Javascript codes. To unblock, in Chrome, there is a shield logo, click on it and “load unsafe scripts”. In firebox, there is “i” sign to fix. In Safari, sorry I don’t know how to solve it.

Papa.parse

Papa parse seems one of the most popular JavaScript libraries that do the parsing job. 4000 stars in Github. Major development around 2014. By the way, this implies it was at the time when the author, Matt Holt, was working at SmartyStreets(a company providing address info) and an undergraduate student at Brigham Young University.
I love the style of its official website: http://papaparse.com/ It uses friendly dialogues to provide case-by-case solution. So the users can quickly pin down what they want, whether it is parsing csv-format string, local file, remote file or even convert JSON back to csv. Actually, it is smart enough that it can find the right delimiter by scanning the first few rows.
var results = Papa.parse(csvString);
console.log(results.meta.delimiter);
However, there is a pitfall when parsing a local file:
Papa.parse(file, {
    complete: function(results) {
        console.log(results);}
});
According to the documentation, file is a File object obtained from the DOM. You can’t just use “data.csv” and hope it can do the magic. Papa will think “data.csv” is only a string and tell you it can’t find a delimiter. In this sense, d3 is much smarter in that d3.csv("data.csv", callback) works for local file.
Anyway, the lower-level of Papa.parse means it has more flexibility to manipulate the data stream. In a github issue discussion , Holt provides some codes that use jQuery AJAX call to pass a file:
$.get("/basic_charts/train.csv", function(text){
    var data = Papa.parse(text);
    console.log(data);
});
However, the problem by this AJAX request is that the whole file is loaded into memory. If the file is too large, the browser gets crash. Alternatively, Papa uses HTML5’s FileReader API to “stream” in the file, if a <input type="file"> element is used in the HTML file. Thanks to Raffael Vogler for providing a pain-free tutorial
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.2/papaparse.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
function handleFileSelect(evt) {
    var file = evt.target.files[0];
    Papa.parse(file, {
        header: true,
        dynamicTyping: true,
        complete: function(results) {
            console.log(JSON.stringify(results, null, 2));}
    });
}
$(document).ready(function(){
    $("#csv-file").change(handleFileSelect);
});
</script>
<!--To get started we need a button to open a file: -->
<input type="file" id="csv-file" name="files"/>
console.log()is only able to print simple data formats such as string, number or array. JSON.stringify is a very powerful debugger tool that you can print the original format of an object. The only thing you can’t print is the function.
debug finding:
  1. jQeury change() is triggered by any change made to <input>, \<textara> and \<select> elements.
  2. evt is a jQuery object, has 9 top-level keys, one of them is target. Below target is an encoded JQuery file object.
  3. results has 3 top-level keys: data, errors, meta. The JSON array is under data key.
  4. add indention in stringify parameter for pretty print.
If the file is written in JSON format or JSON array,
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        myObj = JSON.parse(this.responseText); // read raw text
        console.log(JSON.stringify(myObj));
    }
}; // define action
xmlhttp.open("GET", "data.txt", true);
xmlhttp.send();

TitanicXap2

The ready-to-use Xap is here, you can download the csv file from here). Drop the file to see the magic.
The block diagram is:
FileDropTarget:
    CSVParser:
        dimple_barplt
        Titanic_python: pie_plotly
I am going to document my source code.
For the whole Xap, the page DOM is configured in Edit-style-HTML. We can see there are three visible objects.
<div data-node="FileDropTarget_0"></div>
<div data-node="dimple_barplot_0" id="barplot"></div>
<div data-node="pie_plotly_0" id = "pie"></div>

dimple_barplot

Input: data: multiset
spect: dependencies: jQuery, d3, dimple
script: inside export default{data(){},};
let d3 = this.api.imports.d3;
let dimple = this.api.imports.dimple;
let data = this.api.inputState.export().data; // JSON Array
//this.api.log("I am Cool: ", JSON.stringify(data)); // test the raw data
function draw(data) {
  "use strict";
  var svg = dimple.newSvg("#barplot", 600, 400);  // svg inside id barplot with size (600,400)
  svg.append("text").
  attr("x", 300).attr("y", 20).attr("text-anchor", "middle").style("font-size", "20px").style("font-weight", "bold").text("Titanic Survivor");
  var myChart = new dimple.chart(svg, data);
  var x = myChart.addCategoryAxis("x", "Pclass");
  var y = myChart.addPctAxis("y", "Survived");
  var s = myChart.addSeries("Sex", dimple.plot.bar);

  s.afterDraw = function (shape, data) {
    var s = d3.select(shape),
      rect = {
        x: parseFloat(s.attr("x")),
        y: parseFloat(s.attr("y")),
        width: parseFloat(s.attr("width")),
        height: parseFloat(s.attr("height"))
      };
    if (rect.height >= 8) {
      svg.append("text")
        .attr("x", rect.x + rect.width / 2)
        .attr("y", rect.y + rect.height / 2 + 3.5)
        .style("text-anchor", "middle")
        .style("font-size", "10px")
        .style("font-family", "sans-serif")
        .style("opacity", 0.6)
        .style("pointer-events", "none")
        .text(data.yValue);
    }
  }; // end s.afterDraw
  myChart.addLegend(150, 10, 380, 20, "right");
  myChart.draw();
}// end function draw
draw(data); // call function and feed data with JSON Array format
The majority of the code is from dimple github.

Titanic_python

Input: data: dynamic
output: feature_weight: enitity
SPEC. Tricks:
  1. sklearn is based on scipy;
  2. json can’t be install by pip
  3. pandas is 0.19.2, numpy is 1.12, sklearn is 0.18
"dependencies":{
      "apt": [],
    "pip": [
      {"path": "numpy"},
      {"path": "pandas"},
      {"path": "scikit-learn"},
      {"path": "scipy"}
    ],
    "file":[]
},
script
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score,fbeta_score
import numpy as np
import sklearn
import pandas as pd

def data(self):
    data = self.api.inputstate.export()['data'] 
    # self.api.log("I am Cool: ", data) # test data
    df = pd.DataFrame(data)  # convert JSON array to dataframe
    df['Age'] = df['Age'].apply(pd.to_numeric, args=('coerce',)) # convert to number
    train_data = df

    # Data preprocessing
    # use median age to fill missing value
    def get_median_ages(df):
        median_ages = np.zeros((2,3))
        for j in range(0, 3):
            median_ages[0,j] = df[(df['Sex'] == 'female') & \
                                  (df['Pclass'] == j+1)]['Age'].dropna().median()
            median_ages[1,j] = df[(df['Sex'] == 'male') & \
                                  (df['Pclass'] == j+1)]['Age'].dropna().median()
        return median_ages
    def data_clean(df, median_ages):
        df['Gender'] = df['Sex'].map( {'female': 0, 'male': 1} ).astype(int)
        # use median age to fill the missing data
        for i in range(0, 2):
            for j in range(0, 3):
                  df.loc[ (df.Age.isnull()) & (df.Gender == i) & (df.Pclass == j+1),\
                        'Age'] = median_ages[i,j]

        droplist = ['Name','Ticket','Cabin','Embarked','Sex'] # reserve ID for check
        features = df.drop(droplist, axis = 1)
        return features

    median_ages = get_median_ages(train_data)
    train_cleaned = data_clean(train_data,median_ages)
    features = train_cleaned.drop(['PassengerId','Survived'],axis=1)
    labels = train_data ['Survived']

    # machine learning to predict a target feature: Survived
    # use train-test split to generate 2 sets of data
    X_train, X_test,y_train,y_test = train_test_split(features, labels, test_size=0.3, random_state=0)
    clf=DecisionTreeClassifier()
    clf.fit(X_train,y_train)
    pred=clf.predict(X_test)
    self.api.log("test score:",accuracy_score(y_test, pred))  # 0.81, seems good

    feature_weight={}
    for i,key in enumerate(X_train.columns.values):
        feature_weight[key] = clf.feature_importances_[i]
    self.api.output("feature_weight", feature_weight)
Note that in line 11, df = pd.DataFrame(data) convert JSON array to dataframe. This is the most important glue code that connects JavaScript to Python.

pie_plotly

Initially I tried dimple for an hour or so, but got a lot of bug. Then I switch to plotly and it was awesome!
input: data: entity
spec:
"dependencies": {
    "file": [
        {
            "type": "js",
            "path": "https://cdn.plot.ly/plotly-latest.min.js",
            "name": "Plotly"
        },
        {
            "type": "js",
            "path": "https://d3js.org/d3.v4.min.js",
            "name": "d3"
        },
        {
            "type": "js",
            "path": "https://cdnjs.cloudflare.com/ajax/libs/numeric/1.2.6/numeric.min.js",
            "name": "numeric"
        }
    ]
},
script:
export default {
    data() {
    let data = this.api.inputState.export().data;
    let d3 = this.api.imports.d3;
    let Plotly = this.api.imports.Plotly; 

    var labels = [];
    var values = [];
    var row;
    for (row in data) {        
        labels.push(String(row));
        values.push(data[row]);
    }

    var d = {}; // dictionary to store labels, values, type
    d.labels = labels;
    d.values = values;
    d.type  = "pie";

    var layout = {
      width: 500,
      height: 400,
      title : "Feature importance",
      titlefont : 20
    };

    var li = [d];
    Plotly.newPlot('pie', li, layout);
    this.api.log(labels[0]);
    }
};

Sunday, March 12, 2017

w3chools

Recap:
  1. Basic Javascript, jQuery in Intro Nanodegree, stage 5, front-end
  2. d3 in Data Analyst Nanodegree, data visualization
  3. dimple also in Data Analyst Nanodegree

I was aware of this website on the first day when I enrolled Intro to Programming nanodegree. But until today I didn’t realize how useful it is for beginners like me who wants to have a systematic study.
It reminds me how to teach/learn knowledge more effectively. Does big idea or small details come first? It seems I don’t remember/understand the big picture unless I have some basic concepts. So it is a better strategy to make some connections with learners’ personal experience, and make adjustment specific to learners’ knowledge level. If a student already knows, he gets bored; if a student knows nothing, he becomes overwhelmed. That’s why teaching is an art and requires teachers’ emotional commitment. And that’s why online education and QA sites are so powerful because you can learn at your own pace and at your chosen tastes.
For the Intro nanodegree, stage 1 teaches some basic html tags and CSS styles to make an about-me page; stage 5 (front-end path) bluff into the online resume project with only a passing mention of JavaScript, jQuery and DOM. Big black boxes there.
W3schools should be the first place for beginners learn web technologies. It covers HTML,CSS, JavaScript, SQL, PHP and BootStrap with very clear explanation and in-place practice/example. In terms of knowledge levels, there are 3 parts: tutorial, references, and examples.

html5 tutorial

<body style="background-color:powderblue;">
<a href="https://www.w3schools.com">This is a link</a>
<img src="w3schools.jpg" alt="W3Schools.com" width="104" height="142">
</body>
- <b> - Bold text
- <strong> - Important text
- <i> - Italic text
- <em> - Emphasized text
- <mark> - Marked text
- <small> - Small text
- <del> - Deleted text
- <ins> - Inserted text
- <sub> - Subscript text
- <sup> - Superscript text
  Note:** Browsers display <strong> as <b>, and <em> as <i>. However, there is a difference in the meaning of these tags: <b> and <i> defines bold and italic text, but <strong> and <em> means that the text is "important".

form and input

<form action="/action_page.php" method = "get">
 name:<input type="text" name="name"><br>
 password:<input type="password" name="psw">
  <input type="submit" value="Submit"> 
  <input type="button" onclick="alert('Hello World!')" value="Click Me!">
  <button type="button" onclick="alert('Hello World!')">Click Me!</button>
  color:<input type="color" name="favcolor">
  Birthday:<input type="date" name="bday">
  Enter a date after 2000-01-01:
  <input type="date" name="bday" min="2000-01-02"><br>
  E-mail:<input type="email" name="email">
  Quantity (between 1 and 5):
  <input type="number" name="quantity" min="1" max="5">
  <input type="range" name="points" min="0" max="10">
  Search:<input type="search" name="search">
</form>
Note that the \ defines a buttion for submitting the form data and trigger the <form action>
Other form elements or input type are radio, textarea, label, legend, option, output, etc.
Note that the button type can be used in both tags. While input tag is an empty tag with value attribute, button tag is paired tag that can have enclosed content.
alart() is a pre-define JavaScript function

svg

<svg width="100" height="100">
  <circle cx="50" cy="50" r="40"
  stroke="green" stroke-width="4" fill="yellow" />
   <rect x="50" y="20" rx="20" ry="20" width="150" height="150"
  style="fill:red;stroke:black;stroke-width:5;opacity:0.5" />
   <polygon points="100,10 40,198 190,78 10,78 160,198"
  style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;" />
</svg>

google maps

<div id="map" style="width:400px;height:400px;background:yellow"></div>
<script src="http://maps.googleapis.com/maps/api/js?libraries=places&key=AIzaSyAUTM81QOy9PMhOgCs1JJuWZjk5x36ugP4">
</script>
<script>
var coord = {lat: 35.193966, lng: -97.443609};
var mapOptions = {
center : coord,
zoom : 10,   // 1 for world, 10 for city, 20 for building
mapTypeId: 'hybrid'   // 'roadmap'   'satellite'  'hybrid'   'terrain'
}
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
var marker = new google.maps.Marker({
position: coord,
map: map
});
</script>
Note:
  1. For each new project, you need to apply a new API key here
  2. If served within China, change script source to
    \
  3. loading a cluster of markers will require this.

JavaScripts

JavaScripts can be placed in either \ section or \ section.
In HTML,
<p id="demo">JavaScript can change HTML content.</p>
<button type="button"
onclick="document.getElementById('demo').innerHTML = Date()">Click me to display Date and Time.</button>
<button type="button" onclick="myFunction()">Try it</button>
<script src="myScript.js"></script>
<script src="https://www.w3schools.com/js/myScript1.js"></script>
In JavaScript,
document.getElementById("demo").innerHTML = "Hello JavaScript!";
document.getElementById("demo").style.fontSize = "25px";
document.getElementById("demo").style.display = "block";
function myFunction() {
document.getElementById("demo").innerHTML = "change";}
document.write(5 + 6);  // testing purpose only, may earase all
window.alert(5 + 6);
console.log(5 + 6); // debugging purpose
object constructor
function person(first, last, age, eye) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eye;
}
var myFather = new person("John", "Doe", 50, "blue");
var myMother = new person("Sally", "Rally", 48, "green");
It’s interesting that function is just a special type of objects.
two equivalent way to create the same type of object:
var x1 = new Object();    // A new Object object
var x2 = new String();    // A new String object
var x3 = new Number();    // A new Number object
var x4 = new Boolean();   // A new Boolean object
var x5 = new Array();     // A new Array object
var x6 = new RegExp();    // A new RegExp object
var x7 = new Function();  // A new Function object
var x8 = new Date();      // A new Date object
// equivalent
var x1 = {};            // new object
var x2 = "";            // new primitive string
var x3 = 0;             // new primitive number
var x4 = false;         // new primitive boolean
var x5 = [];            // new array object
var x6 = /()/           // new regexp object
var x7 = function(){};  // new function object
Note that Javascript object is passed by reference, no new copy.

w3.js

using the button tag can interactively show the change!
<script src="https://www.w3schools.com/lib/w3.js"></script>
<button onclick="w3.hide('h2')">Hide h2</button>
<button onclick="w3.hide('#London')">Hide </button>
<button onclick="w3.show('#London')">Show</button>
<button onclick="w3.toggleShow('#London')">Toggle Hide/Show</button>
<button onclick="w3.hide('.city')">Hide</button>
<button onclick="w3.hide('*')">Hide</button>
other w3 scripts
w3.addStyle('#London','background-color','red');
w3.addClass('#London','marked');
w3.removeClass('#London','marked');
w3.toggleClass('#London','marked');
w3.sortHTML('#id01', 'li');  // sort list
w3.sortHTML('#myTable','.item', 'td:nth-child(1)'); //sort table
w3.slideshow(".nature", 2000); //change every 2s
// also can add buttion to show pervious/next
w3.includeHTML(); //inject other html code
w3.getHttpObject("customers.js", function(myObject) {
  w3.displayObject("id01", myObject);
});
Note in the display of list or talbe or check box, the attribute looks like:
<li w3-repeat="customers">{{CustomerName}}</li>
<tr w3-repeat="customers"><td>{{CustomerName}}</td> </tr>
“customers” is a top-level key of a JSON, the paired value is a list of dictionaries. And “CustomerName” is the common key for these dictionaries.

jQuery

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
    $("p").click(function(){
        $(this).hide();
    });
});
</script>
<p>If you click on me, I will disappear.</p>
<p>Click me away!</p>
$(document).ready(function(){... is good practice to wait for the document to be fully loaded and ready before working with it. This also allows you to have your JavaScript code before the body of your document, in the head section. To be more informative, the following scripts is inside the document ready scope.

click, mouseeneter, hover

$("button").click(function(){
    $("p").hide();
});
$("p").dblclick(function(){
    $(this).hide();
});
$("#p1").mouseenter(function(){
    alert("You entered p1!");
});
// handle mouseenter and mouseleave
$("#p1").hover(function(){ 
    alert("You entered p1!");
},
function(){
    alert("Bye! You now leave p1!");
}); 
// handle single event requires double quote & comma
$("p").on("click", function(){ 
    $(this).hide();
});  
// combine multiple event handlers together
$("p").on({ 
    mouseenter: function(){
        $(this).css("background-color", "lightgray");
    }, 
    mouseleave: function(){
        $(this).css("background-color", "lightblue");
    }, 
    click: function(){
        $(this).css("background-color", "yellow");
    } 
});

toggle

jQueary is slightly better than w3 due to more concise grammar
<button onclick="$('p').toggle()"> Toggle Hide/Show</button>
<button onclick="w3.toggleShow('p')"> Toggle Hide/Show</button>

fading/sliding effect

<script>
$(document).ready(function(){
    $("button").click(function(){
        $("#div1").fadeToggle();
        $("#div2").fadeToggle("slow");
        $("#div3").fadeToggle(3000);
    });
});
</script>
<button>Click to fade in/out boxes</button><br><br>
<div id="div1" style="width:80px;height:80px;background-color:red;"></div><br>
<div id="div2" style="width:80px;height:80px;background-color:green;"></div><br>
<div id="div3" style="width:80px;height:80px;background-color:blue;"></div>
<!-- slide toggle -->
<script> 
$(document).ready(function(){
    $("#flip").click(function(){
        $("#panel").slideToggle("slow");
    });
});
</script>
<style> 
#panel, #flip {
    padding: 5px;
    text-align: center;
    background-color: #e5eecc;
    border: solid 1px #c3c3c3;
}
#panel {
    padding: 50px;
    display: none;
}
</style>
<div id="flip">Click to slide the panel down or up</div>
<div id="panel">Hello world!</div>

get/set

$("#test").text();  // default for get, input for set
$("#test").html();
$("#test").val(); // get content of "value" attribute
$("#test").attr("href"); // get content of "href" attr
$("p").append("Some appended text."); // insert content
$("p").prepend("Some prepended text."); // insert content at the begining
$("#div1").remove(); // delete everything including the div
$("#div1").empty(); // delete everything except the div
$("p").remove(".test, .demo"); // delete certain class
$("p").css("background-color", "yellow");
$("p").css({"background-color": "yellow", "font-size": "200%"});

jQuery vs D3

D3 is based on jQuery and has some improvement. We can see how D3 is better when the two are actually doing the same job:
jQuery D3
$(“body”).append("<p></p>"); d3.select(“body”).append(“p”);
$(‘p’).css(“color”, ‘red’); d3.select(‘p’).style(“color”,”red”);
$(‘p’).width(500).height(500); d3.select(‘p’).attr(‘width’, 600).attr(‘height’,300);
$(‘p’).addClass(“cities”); d3.select(‘p’).attr(‘class’, “cities”);

AJAX

$("div").load("data.txt #p1"); // file is written in HTML format, and only element with id="p1" is loaded
$.ajax({url: "demo_test.txt", success: function(result){
    $("#div1").html(result);
}});
$.get("test.php", { name:"Donald", town:"Ducktown" });

PHP syntax

PHP can be perceived as a server-side version of html, which allows for making highly dynamic and interactive web pages. PHP files have extension .php, and can contain text, html, css, javascript and php codes. Only the PHP code are executed on the server and result is sent to the browser.
PHP is inside the <?php and ?> tag.$ indicates variable.
<!DOCTYPE html>
<html>
<body>
<h1>My first PHP page</h1>
<?php
echo "My first PHP script!";
$color = "red";
echo "My car is " . $color . "<br>";
// This is a single-line comment
# This is also a single-line comment
/*
This is a multiple-lines comment block
*/
?>
</body>
</html>