Ethan Hughes

Ethan Hughes

1607374440

A Beginner’s Guide To JavaScript Primitive vs. Reference Values

In JavaScript, a variable may store two types of values: primitive and reference.

#javascript #programming #javascript-tips

What is GEEK

Buddha Community

A Beginner’s Guide To JavaScript Primitive vs. Reference Values
Archie  Powell

Archie Powell

1658181600

Tensorflex: Tensorflow Bindings for The Elixir Programming Language

Tensorflex

The paper detailing Tensorflex was presented at NeurIPS/NIPS 2018 as part of the MLOSS workshop. The paper can be found here

Contents

How to run

  • You need to have the Tensorflow C API installed. Look here for details.
  • You also need the C library libjpeg. If you are using Linux or OSX, it should already be present on your machine, otherwise be sure to install (brew install libjpeg for OSX, and sudo apt-get install libjpeg-dev for Ubuntu).
  • Simply add Tensorflex to your list of dependencies in mix.exs and you are good to go!:
{:tensorflex, "~> 0.1.2"}

In case you want the latest development version use this:

{:tensorflex, github: "anshuman23/tensorflex"}

Documentation

Tensorflex contains three main structs which handle different datatypes. These are %Graph, %Matrix and %Tensor. %Graph type structs handle pre-trained graph models, %Matrix handles Tensorflex 2-D matrices, and %Tensor handles Tensorflow Tensor types. The official Tensorflow documentation is present here and do note that this README only briefly discusses Tensorflex functionalities.

read_graph/1:

Used for loading a Tensorflow .pb graph model in Tensorflex.

Reads in a pre-trained Tensorflow protobuf (.pb) Graph model binary file.

Returns a tuple {:ok, %Graph}.

%Graph is an internal Tensorflex struct which holds the name of the graph file and the binary definition data that is read in via the .pb file.

get_graph_ops/1:

Used for listing all the operations in a Tensorflow .pb graph.

Reads in a Tensorflex %Graph struct obtained from read_graph/1.

Returns a list of all the operation names (as strings) that populate the graph model.

create_matrix/3:

Creates a 2-D Tensorflex matrix from custom input specifications.

Takes three input arguments: number of rows in matrix (nrows), number of columns in matrix (ncols), and a list of lists of the data that will form the matrix (datalist).

Returns a %Matrix Tensorflex struct type.

matrix_pos/3:

Used for accessing an element of a Tensorflex matrix.

Takes in three input arguments: a Tensorflex %Matrix struct matrix, and the row (row) and column (col) values of the required element in the matrix. Both row and col here are NOT zero indexed.

Returns the value as float.

size_of_matrix/1:

Used for obtaining the size of a Tensorflex matrix.

Takes a Tensorflex %Matrix struct matrix as input.

Returns a tuple {nrows, ncols} where nrows represents the number of rows of the matrix and ncols represents the number of columns of the matrix.

append_to_matrix/2:

Appends a single row to the back of a Tensorflex matrix.

Takes a Tensorflex %Matrix matrix as input and a single row of data (with the same number of columns as the original matrix) as a list of lists (datalist) to append to the original matrix.

Returns the extended and modified %Matrix struct matrix.

matrix_to_lists/1:

Converts a Tensorflex matrix (back) to a list of lists format.

Takes a Tensorflex %Matrix struct matrix as input.

Returns a list of lists representing the data stored in the matrix.

NOTE: If the matrix contains very high dimensional data, typically obtained from a function like load_csv_as_matrix/2, then it is not recommended to convert the matrix back to a list of lists format due to a possibility of memory errors.

float64_tensor/2, float32_tensor/2, int32_tensor/2:

Creates a TF_DOUBLE, TF_FLOAT, or TF_INT32 tensor from Tensorflex matrices containing the values and dimensions specified.

Takes two arguments: a %Matrix matrix (matrix1) containing the values the tensor should have and another %Matrix matrix (matrix2) containing the dimensions of the required tensor.

Returns a tuple {:ok, %Tensor} where %Tensor represents an internal Tensorflex struct type that is used for holding tensor data and type.

float64_tensor/1, float32_tensor/1, int32_tensor/1, string_tensor/1:

Creates a TF_DOUBLE, TF_FLOAT, TF_INT32, or TF_STRING constant value one-dimensional tensor from the input value specified.

Takes in a float, int or string value (depending on function) as input.

Returns a tuple {:ok, %Tensor} where %Tensor represents an internal Tensorflex struct type that is used for holding tensor data and type.

float64_tensor_alloc/1, float32_tensor_alloc/1, int32_tensor_alloc/1:

Allocates a TF_DOUBLE, TF_FLOAT, or TF_INT32 tensor of specified dimensions.

This function is generally used to allocate output tensors that do not hold any value data yet, but will after the session is run for Inference. Output tensors of the required dimensions are allocated and then passed to the run_session/5 function to hold the output values generated as predictions.

Takes a Tensorflex %Matrix struct matrix as input.

Returns a tuple {:ok, %Tensor} where %Tensor represents an internal Tensorflex struct type that is used for holding the potential tensor data and type.

tensor_datatype/1:

Used to get the datatype of a created tensor.

Takes in a %Tensor struct tensor as input.

Returns a tuple {:ok, datatype} where datatype is an atom representing the list of Tensorflow TF_DataType tensor datatypes. Click here to view a list of all possible datatypes.

load_image_as_tensor/1:

Loads JPEG images into Tensorflex directly as a TF_UINT8 tensor of dimensions image height x image width x number of color channels.

This function is very useful if you wish to do image classification using Convolutional Neural Networks, or other Deep Learning Models. One of the most widely adopted and robust image classification models is the Inception model by Google. It makes classifications on images from over a 1000 classes with highly accurate results. The load_image_as_tensor/1 function is an essential component for the prediction pipeline of the Inception model (and for other similar image classification models) to work in Tensorflex.

Reads in the path to a JPEG image file (.jpg or .jpeg).

Returns a tuple {:ok, %Tensor} where %Tensor represents an internal Tensorflex struct type that is used for holding the tensor data and type. Here the created Tensor is a uint8 tensor (TF_UINT8).

NOTE: For now, only 3 channel RGB JPEG color images can be passed as arguments. Support for grayscale images and other image formats such as PNG will be added in the future.

loads_csv_as_matrix/2:

Loads high-dimensional data from a CSV file as a Tensorflex 2-D matrix in a super-fast manner.

The load_csv_as_matrix/2 function is very fast-- when compared with the Python based pandas library for data science and analysis' function read_csv on the test.csv file from MNIST Kaggle data (source), the following execution times were obtained:

  • read_csv: 2.549233 seconds
  • load_csv_as_matrix/2: 1.711494 seconds

This function takes in 2 arguments: a path to a valid CSV file (filepath) and other optional arguments opts. These include whether or not a header needs to be discarded in the CSV, and what the delimiter type is. These are specified by passing in an atom :true or :false to the header: key, and setting a string value for the delimiter: key. By default, the header is considered to be present (:true) and the delimiter is set to ,.

Returns a %Matrix Tensorflex struct type.

run_session/5:

Runs a Tensorflow session to generate predictions for a given graph, input data, and required input/output operations.

This function is the final step of the Inference (prediction) pipeline and generates output for a given set of input data, a pre-trained graph model, and the specified input and output operations of the graph.

Takes in five arguments: a pre-trained Tensorflow graph .pb model read in from the read_graph/1 function (graph), an input tensor with the dimensions and data required for the input operation of the graph to run (tensor1), an output tensor allocated with the right dimensions (tensor2), the name of the input operation of the graph that needs where the input data is fed (input_opname), and the output operation name in the graph where the outputs are obtained (output_opname). The input tensor is generally created from the matrices manually or using the load_csv_as_matrix/2 function, and then passed through to one of the tensor creation functions. For image classification the load_image_as_tensor/1 can also be used to create the input tensor from an image. The output tensor is created using the tensor allocation functions (generally containing alloc at the end of the function name).

Returns a List of Lists (similar to the matrix_to_lists/1 function) containing the generated predictions as per the output tensor dimensions.

add_scalar_to_matrix/2:

Adds scalar value to matrix.

Takes two arguments: %Matrix matrix and scalar value (int or float)

Returns a %Matrix modified matrix.

subtract_scalar_from_matrix/2:

Subtracts scalar value from matrix.

Takes two arguments: %Matrix matrix and scalar value (int or float)

Returns a %Matrix modified matrix.

multiply_matrix_with_scalar/2:

Multiplies scalar value with matrix.

Takes two arguments: %Matrix matrix and scalar value (int or float)

Returns a %Matrix modified matrix.

divide_matrix_by_scalar/2:

Divides matrix values by scalar.

Takes two arguments: %Matrix matrix and scalar value (int or float)

Returns a %Matrix modified matrix.

add_matrices/2:

Adds two matrices of same dimensions together.

Takes in two %Matrix matrices as arguments.

Returns the resultant %Matrix matrix.

subtract_matrices/2:

Subtracts matrix2 from matrix1.

Takes in two %Matrix matrices as arguments.

Returns the resultant %Matrix matrix.

tensor_to_matrix/1:

Converts the data stored in a 2-D tensor back to a 2-D matrix.

Takes in a single argument as a %Tensor tensor (any TF_Datatype).

Returns a %Matrix 2-D matrix.

NOTE: Tensorflex doesn't currently support 3-D matrices, and therefore tensors that are 3-D (such as created using the load_image_as_tensor/1 function) cannot be converted back to a matrix, yet. Support for 3-D matrices will be added soon.

Examples

Examples are generally added in full description on my blog here. A blog post covering how to do classification on the Iris Dataset is present here.


INCEPTION CNN MODEL EXAMPLE:

Here we will briefly touch upon how to use the Google V3 Inception pre-trained graph model to do image classficiation from over a 1000 classes. First, the Inception V3 model can be downloaded here: http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz

After unzipping, see that it contains the graphdef .pb file (classify_image_graphdef.pb) which contains our graph definition, a test jpeg image that should identify/classify as a panda (cropped_panda.pb) and a few other files I will detail later.

Now for running this in Tensorflex first the graph is loaded:

iex(1)> {:ok, graph} = Tensorflex.read_graph("classify_image_graph_def.pb")
2018-07-29 00:48:19.849870: W tensorflow/core/framework/op_def_util.cc:346] Op BatchNormWithGlobalNormalization is deprecated. It will cease to work in GraphDef version 9. Use tf.nn.batch_normalization().
{:ok,
 %Tensorflex.Graph{
   def: #Reference<0.2597534446.2498625538.211058>,
   name: "classify_image_graph_def.pb"
 }}

Then the cropped_panda image is loaded using the new load_image_as_tensor function:

iex(2)> {:ok, input_tensor} = Tensorflex.load_image_as_tensor("cropped_panda.jpg")
{:ok,
 %Tensorflex.Tensor{
   datatype: :tf_uint8,
   tensor: #Reference<0.2597534446.2498625538.211093>
 }}

Then create the output tensor which will hold out output vector values. For the inception model, the output is received as a 1008x1 tensor, as there are 1008 classes in the model:

iex(3)> out_dims = Tensorflex.create_matrix(1,2,[[1008,1]])
%Tensorflex.Matrix{
  data: #Reference<0.2597534446.2498625538.211103>,
  ncols: 2,
  nrows: 1
}

iex(4)> {:ok, output_tensor} = Tensorflex.float32_tensor_alloc(out_dims)
{:ok,
 %Tensorflex.Tensor{
   datatype: :tf_float,
   tensor: #Reference<0.2597534446.2498625538.211116>
 }}

Then the output results are read into a list called results. Also, the input operation in the Inception model is DecodeJpeg and the output operation is softmax:

iex(5)> results = Tensorflex.run_session(graph, input_tensor, output_tensor, "DecodeJpeg", "softmax")
2018-07-29 00:51:13.631154: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA
[
  [1.059142014128156e-4, 2.8240500250831246e-4, 8.30648496048525e-5,
   1.2982363114133477e-4, 7.32232874725014e-5, 8.014426566660404e-5,
   6.63459359202534e-5, 0.003170756157487631, 7.931600703159347e-5,
   3.707312498590909e-5, 3.0997329304227605e-5, 1.4232713147066534e-4,
   1.0381334868725389e-4, 1.1057958181481808e-4, 1.4321311027742922e-4,
   1.203602587338537e-4, 1.3130248407833278e-4, 5.850398520124145e-5,
   2.641105093061924e-4, 3.1629020668333396e-5, 3.906813799403608e-5,
   2.8646905775531195e-5, 2.2863158665131778e-4, 1.2222197256051004e-4,
   5.956588938715868e-5, 5.421260357252322e-5, 5.996063555357978e-5,
   4.867801326327026e-4, 1.1005574924638495e-4, 2.3433618480339646e-4,
   1.3062104699201882e-4, 1.317620772169903e-4, 9.388553007738665e-5,
   7.076268957462162e-5, 4.281177825760096e-5, 1.6863139171618968e-4,
   9.093972039408982e-5, 2.611844101920724e-4, 2.7584232157096267e-4,
   5.157176201464608e-5, 2.144951868103817e-4, 1.3628098531626165e-4,
   8.007588621694595e-5, 1.7929042223840952e-4, 2.2831936075817794e-4,
   6.216531619429588e-5, 3.736453436431475e-5, 6.782123091397807e-5,
   1.1538144462974742e-4, ...]
]

Finally, we need to find which class has the maximum probability and identify it's label. Since results is a List of Lists, it's better to read in the nested list. Then we need to find the index of the element in the new list which as the maximum value. Therefore:

iex(6)> max_prob = List.flatten(results) |> Enum.max
0.8849328756332397

iex(7)> Enum.find_index(results |> List.flatten, fn(x) -> x == max_prob end)
169

We can thus see that the class with the maximum probability predicted (0.8849328756332397) for the image is 169. We will now find what the 169 label corresponds to. For this we can look back into the unzipped Inception folder, where there is a file called imagenet_2012_challenge_label_map_proto.pbtxt. On opening this file, we can find the string class identifier for the 169 class index. This is n02510455 and is present on Line 1556 in the file. Finally, we need to match this string identifier to a set of identification labels by referring to the file imagenet_synset_to_human_label_map.txt file. Here we can see that corresponding to the string class n02510455 the human labels are giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca (Line 3691 in the file).

Thus, we have correctly identified the animal in the image as a panda using Tensorflex!


RNN LSTM SENTIMENT ANALYSIS MODEL EXAMPLE:

A brief idea of what this example entails:

  • The Recurrent Neural Network utilizes Long-Short-Term-Memory (LSTM) cells for holding the state for the data flowing in through the network
  • In this example, we utilize the LSTM network for sentiment analysis on movie reviews data in Tensorflex. The trained models are originally created as part of an online tutorial (source) and are present in a Github repository here.

To do sentiment analysis in Tensorflex however, we first need to do some preprocessing and prepare the graph model (.pb) as done multiple times before in other examples. For that, in the examples/rnn-lstm-example directory there are two scripts: freeze.py and create_input_data.py. Prior to explaining the working of these scripts you first need to download the original saved models as well as the datasets:

  • For the model, download from here and then store all the 4 model files in the examples/rnn-lstm-example/model folder
  • For the dataset, download from here. After decompressing, we do not need all the files, just the 2 numpy binaries wordsList.npy and wordVectors.npy. These will be used to encode our text data into UTF-8 encoding for feeding our RNN as input.

Now, for the Python two scripts: freeze.py and create_input_data.py:

  • freeze.py: This is used to create our pb model from the Python saved checkpoints. Here we will use the downloaded Python checkpoints' model to create the .pb graph. Just running python freeze.py after putting the model files in the correct directory will do the trick. In the same ./model/ folder, you will now see a file called frozen_model_lstm.pb. This is the file which we will load into Tensorflex. In case for some reason you want to skip this step and just get the loaded graph here is a Dropbox link
  • create_input_data.py: Even if we can load our model into Tensorflex, we also need some data to do inference on. For that, we will write our own example sentences and convert them (read encode) to a numeral (int32) format that can be used by the network as input. For that, you can inspect the code in the script to get an understanding of what is happening. Basically, the neural network takes in an input of a 24x250 int32 (matrix) tensor created from text which has been encoded as UTF-8. Again, running python create_input_data.py will give you two csv files (one indicating positive sentiment and the other a negative sentiment) which we will later load into Tensorflex. The two sentences converted are:
    • Negative sentiment sentence: That movie was terrible.
    • Positive sentiment sentence: That movie was the best one I have ever seen.

Both of these get converted to two files inputMatrixPositive.csv and inputMatrixNegative.csv (by create_input_data.py) which we load into Tensorflex next.

Inference in Tensorflex: Now we do sentiment analysis in Tensorflex. A few things to note:

  • The input graph operation is named Placeholder_1
  • The output graph operation is named add and is the eventual result of a matrix multiplication. Of this obtained result we only need the first row
  • Here the input is going to be a integer valued matrix tensor of dimensions 24x250 representing our sentence/review
  • The output will have 2 columns, as there are 2 classes-- for positive and negative sentiment respectively. Since we will only be needing only the first row we will get our result in a 1x2 vector. If the value of the first column is higher than the second column, then the network indicates a positive sentiment otherwise a negative sentiment. All this can be observed in the original repository in a Jupyter notebook here: ```elixir iex(1)> {:ok, graph} = Tensorflex.read_graph "examples/rnn-lstm-example/model/frozen_model_lstm.pb" {:ok, %Tensorflex.Graph{ def: #Reference<0.713975820.1050542081.11558>, name: "examples/rnn-lstm-example/model/frozen_model_lstm.pb" }}

iex(2)> Tensorflex.get_graph_ops graph ["Placeholder_1", "embedding_lookup/params_0", "embedding_lookup", "transpose/perm", "transpose", "rnn/Shape", "rnn/strided_slice/stack", "rnn/strided_slice/stack_1", "rnn/strided_slice/stack_2", "rnn/strided_slice", "rnn/stack/1", "rnn/stack", "rnn/zeros/Const", "rnn/zeros", "rnn/stack_1/1", "rnn/stack_1", "rnn/zeros_1/Const", "rnn/zeros_1", "rnn/Shape_1", "rnn/strided_slice_2/stack", "rnn/strided_slice_2/stack_1", "rnn/strided_slice_2/stack_2", "rnn/strided_slice_2", "rnn/time", "rnn/TensorArray", "rnn/TensorArray_1", "rnn/TensorArrayUnstack/Shape", "rnn/TensorArrayUnstack/strided_slice/stack", "rnn/TensorArrayUnstack/strided_slice/stack_1", "rnn/TensorArrayUnstack/strided_slice/stack_2", "rnn/TensorArrayUnstack/strided_slice", "rnn/TensorArrayUnstack/range/start", "rnn/TensorArrayUnstack/range/delta", "rnn/TensorArrayUnstack/range", "rnn/TensorArrayUnstack/TensorArrayScatter/TensorArrayScatterV3", "rnn/while/Enter", "rnn/while/Enter_1", "rnn/while/Enter_2", "rnn/while/Enter_3", "rnn/while/Merge", "rnn/while/Merge_1", "rnn/while/Merge_2", "rnn/while/Merge_3", "rnn/while/Less/Enter", "rnn/while/Less", "rnn/while/LoopCond", "rnn/while/Switch", "rnn/while/Switch_1", "rnn/while/Switch_2", "rnn/while/Switch_3", ...]

First we will try for positive sentiment:
```elixir
iex(3)> input_vals = Tensorflex.load_csv_as_matrix("examples/rnn-lstm-example/inputMatrixPositive.csv", header: :false)
%Tensorflex.Matrix{
  data: #Reference<0.713975820.1050542081.13138>,
  ncols: 250,
  nrows: 24
}

iex(4)> input_dims = Tensorflex.create_matrix(1,2,[[24,250]])
%Tensorflex.Matrix{
  data: #Reference<0.713975820.1050542081.13575>,
  ncols: 2,
  nrows: 1
}

iex(5)> {:ok, input_tensor} = Tensorflex.int32_tensor(input_vals, input_dims)
{:ok,
 %Tensorflex.Tensor{
   datatype: :tf_int32,
   tensor: #Reference<0.713975820.1050542081.14434>
 }}

iex(6)> output_dims = Tensorflex.create_matrix(1,2,[[24,2]])
%Tensorflex.Matrix{
  data: #Reference<0.713975820.1050542081.14870>,
  ncols: 2,
  nrows: 1
}

iex(7)> {:ok, output_tensor} = Tensorflex.float32_tensor_alloc(output_dims)
{:ok,
 %Tensorflex.Tensor{
   datatype: :tf_float,
   tensor: #Reference<0.713975820.1050542081.15363>
 }}

We only need the first row, the rest do not indicate anything:

iex(8)> [result_pos | _ ] = Tensorflex.run_session(graph, input_tensor,output_tensor, "Placeholder_1", "add")
[
  [4.483788013458252, -1.273943305015564],
  [-0.17151066660881042, -2.165886402130127],
  [0.9569928646087646, -1.131581425666809],
  [0.5669126510620117, -1.3842089176177979],
  [-1.4346938133239746, -4.0750861167907715],
  [0.4680981934070587, -1.3494354486465454],
  [1.068990707397461, -2.0195648670196533],
  [3.427264451980591, 0.48857203125953674],
  [0.6307879686355591, -2.069119691848755],
  [0.35061028599739075, -1.700657844543457],
  [3.7612719535827637, 2.421398878097534],
  [2.7635951042175293, -0.7214710116386414],
  [1.146680235862732, -0.8688814640045166],
  [0.8996094465255737, -1.0183486938476563],
  [0.23605018854141235, -1.893072247505188],
  [2.8790698051452637, -0.37355837225914],
  [-1.7325369119644165, -3.6470277309417725],
  [-1.687785029411316, -4.903762340545654],
  [3.6726789474487305, 0.14170047640800476],
  [0.982108473777771, -1.554244875907898],
  [2.248904228210449, 1.0617655515670776],
  [0.3663095533847809, -3.5266385078430176],
  [-1.009346604347229, -2.901120901107788],
  [3.0659966468811035, -1.7605335712432861]
]

iex(9)> result_pos
[4.483788013458252, -1.273943305015564]

Thus we can clearly see that the RNN predicts a positive sentiment. For a negative sentiment, next:

iex(10)> input_vals = Tensorflex.load_csv_as_matrix("examples/rnn-lstm-example/inputMatrixNegative.csv", header: :false)
%Tensorflex.Matrix{
  data: #Reference<0.713975820.1050542081.16780>,
  ncols: 250,
  nrows: 24
}

iex(11)> {:ok, input_tensor} = Tensorflex.int32_tensor(input_vals,input_dims)
{:ok,              
 %Tensorflex.Tensor{
   datatype: :tf_int32,
   tensor: #Reference<0.713975820.1050542081.16788>
 }}

iex(12)> [result_neg|_] = Tensorflex.run_session(graph, input_tensor,output_tensor, "Placeholder_1", "add")
[
  [0.7635725736618042, 10.895986557006836],
  [2.205151319503784, -0.6267685294151306],
  [3.5995595455169678, -0.1240251287817955],
  [-1.6063352823257446, -3.586883068084717],
  [1.9608432054519653, -3.084211826324463],
  [3.772461414337158, -0.19421455264091492],
  [3.9185996055603027, 0.4442034661769867],
  [3.010765552520752, -1.4757057428359985],
  [3.23650860786438, -0.008513949811458588],
  [2.263028144836426, -0.7358709573745728],
  [0.206748828291893, -2.1945853233337402],
  [2.913491725921631, 0.8632720708847046],
  [0.15935257077217102, -2.9757845401763916],
  [-0.7757357358932495, -2.360766649246216],
  [3.7359719276428223, -0.7668198347091675],
  [2.2896337509155273, -0.45704856514930725],
  [-1.5497230291366577, -4.42919921875],
  [-2.8478822708129883, -5.541027545928955],
  [1.894787073135376, -0.8441318273544312],
  [0.15720489621162415, -2.699129819869995],
  [-0.18114641308784485, -2.988100051879883],
  [3.342879056930542, 2.1714375019073486],
  [2.906526565551758, 0.18969044089317322],
  [0.8568912744522095, -1.7559258937835693]
]
iex(13)> result_neg
[0.7635725736618042, 10.895986557006836]

Thus we can clearly see that in this case the RNN indicates negative sentiment! Our model works!

Pull Requests Made


Author: anshuman23
Source code: https://github.com/anshuman23/tensorflex
License: Apache-2.0 license

#elixir #tensorflow #machine-learning 

Mike  Kozey

Mike Kozey

1656151740

Test_cov_console: Flutter Console Coverage Test

Flutter Console Coverage Test

This small dart tools is used to generate Flutter Coverage Test report to console

How to install

Add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dev_dependencies:
  test_cov_console: ^0.2.2

How to run

run the following command to make sure all flutter library is up-to-date

flutter pub get
Running "flutter pub get" in coverage...                            0.5s

run the following command to generate lcov.info on coverage directory

flutter test --coverage
00:02 +1: All tests passed!

run the tool to generate report from lcov.info

flutter pub run test_cov_console
---------------------------------------------|---------|---------|---------|-------------------|
File                                         |% Branch | % Funcs | % Lines | Uncovered Line #s |
---------------------------------------------|---------|---------|---------|-------------------|
lib/src/                                     |         |         |         |                   |
 print_cov.dart                              |  100.00 |  100.00 |   88.37 |...,149,205,206,207|
 print_cov_constants.dart                    |    0.00 |    0.00 |    0.00 |    no unit testing|
lib/                                         |         |         |         |                   |
 test_cov_console.dart                       |    0.00 |    0.00 |    0.00 |    no unit testing|
---------------------------------------------|---------|---------|---------|-------------------|
 All files with unit testing                 |  100.00 |  100.00 |   88.37 |                   |
---------------------------------------------|---------|---------|---------|-------------------|

Optional parameter

If not given a FILE, "coverage/lcov.info" will be used.
-f, --file=<FILE>                      The target lcov.info file to be reported
-e, --exclude=<STRING1,STRING2,...>    A list of contains string for files without unit testing
                                       to be excluded from report
-l, --line                             It will print Lines & Uncovered Lines only
                                       Branch & Functions coverage percentage will not be printed
-i, --ignore                           It will not print any file without unit testing
-m, --multi                            Report from multiple lcov.info files
-c, --csv                              Output to CSV file
-o, --output=<CSV-FILE>                Full path of output CSV file
                                       If not given, "coverage/test_cov_console.csv" will be used
-t, --total                            Print only the total coverage
                                       Note: it will ignore all other option (if any), except -m
-p, --pass=<MINIMUM>                   Print only the whether total coverage is passed MINIMUM value or not
                                       If the value >= MINIMUM, it will print PASSED, otherwise FAILED
                                       Note: it will ignore all other option (if any), except -m
-h, --help                             Show this help

example run the tool with parameters

flutter pub run test_cov_console --file=coverage/lcov.info --exclude=_constants,_mock
---------------------------------------------|---------|---------|---------|-------------------|
File                                         |% Branch | % Funcs | % Lines | Uncovered Line #s |
---------------------------------------------|---------|---------|---------|-------------------|
lib/src/                                     |         |         |         |                   |
 print_cov.dart                              |  100.00 |  100.00 |   88.37 |...,149,205,206,207|
lib/                                         |         |         |         |                   |
 test_cov_console.dart                       |    0.00 |    0.00 |    0.00 |    no unit testing|
---------------------------------------------|---------|---------|---------|-------------------|
 All files with unit testing                 |  100.00 |  100.00 |   88.37 |                   |
---------------------------------------------|---------|---------|---------|-------------------|

report for multiple lcov.info files (-m, --multi)

It support to run for multiple lcov.info files with the followings directory structures:
1. No root module
<root>/<module_a>
<root>/<module_a>/coverage/lcov.info
<root>/<module_a>/lib/src
<root>/<module_b>
<root>/<module_b>/coverage/lcov.info
<root>/<module_b>/lib/src
...
2. With root module
<root>/coverage/lcov.info
<root>/lib/src
<root>/<module_a>
<root>/<module_a>/coverage/lcov.info
<root>/<module_a>/lib/src
<root>/<module_b>
<root>/<module_b>/coverage/lcov.info
<root>/<module_b>/lib/src
...
You must run test_cov_console on <root> dir, and the report would be grouped by module, here is
the sample output for directory structure 'with root module':
flutter pub run test_cov_console --file=coverage/lcov.info --exclude=_constants,_mock --multi
---------------------------------------------|---------|---------|---------|-------------------|
File                                         |% Branch | % Funcs | % Lines | Uncovered Line #s |
---------------------------------------------|---------|---------|---------|-------------------|
lib/src/                                     |         |         |         |                   |
 print_cov.dart                              |  100.00 |  100.00 |   88.37 |...,149,205,206,207|
lib/                                         |         |         |         |                   |
 test_cov_console.dart                       |    0.00 |    0.00 |    0.00 |    no unit testing|
---------------------------------------------|---------|---------|---------|-------------------|
 All files with unit testing                 |  100.00 |  100.00 |   88.37 |                   |
---------------------------------------------|---------|---------|---------|-------------------|
---------------------------------------------|---------|---------|---------|-------------------|
File - module_a -                            |% Branch | % Funcs | % Lines | Uncovered Line #s |
---------------------------------------------|---------|---------|---------|-------------------|
lib/src/                                     |         |         |         |                   |
 print_cov.dart                              |  100.00 |  100.00 |   88.37 |...,149,205,206,207|
lib/                                         |         |         |         |                   |
 test_cov_console.dart                       |    0.00 |    0.00 |    0.00 |    no unit testing|
---------------------------------------------|---------|---------|---------|-------------------|
 All files with unit testing                 |  100.00 |  100.00 |   88.37 |                   |
---------------------------------------------|---------|---------|---------|-------------------|
---------------------------------------------|---------|---------|---------|-------------------|
File - module_b -                            |% Branch | % Funcs | % Lines | Uncovered Line #s |
---------------------------------------------|---------|---------|---------|-------------------|
lib/src/                                     |         |         |         |                   |
 print_cov.dart                              |  100.00 |  100.00 |   88.37 |...,149,205,206,207|
lib/                                         |         |         |         |                   |
 test_cov_console.dart                       |    0.00 |    0.00 |    0.00 |    no unit testing|
---------------------------------------------|---------|---------|---------|-------------------|
 All files with unit testing                 |  100.00 |  100.00 |   88.37 |                   |
---------------------------------------------|---------|---------|---------|-------------------|

Output to CSV file (-c, --csv, -o, --output)

flutter pub run test_cov_console -c --output=coverage/test_coverage.csv

#### sample CSV output file:
File,% Branch,% Funcs,% Lines,Uncovered Line #s
lib/,,,,
test_cov_console.dart,0.00,0.00,0.00,no unit testing
lib/src/,,,,
parser.dart,100.00,100.00,97.22,"97"
parser_constants.dart,100.00,100.00,100.00,""
print_cov.dart,100.00,100.00,82.91,"29,49,51,52,171,174,177,180,183,184,185,186,187,188,279,324,325,387,388,389,390,391,392,393,394,395,398"
print_cov_constants.dart,0.00,0.00,0.00,no unit testing
All files with unit testing,100.00,100.00,86.07,""

Installing

Use this package as an executable

Install it

You can install the package from the command line:

dart pub global activate test_cov_console

Use it

The package has the following executables:

$ test_cov_console

Use this package as a library

Depend on it

Run this command:

With Dart:

 $ dart pub add test_cov_console

With Flutter:

 $ flutter pub add test_cov_console

This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get):

dependencies:
  test_cov_console: ^0.2.2

Alternatively, your editor might support dart pub get or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:test_cov_console/test_cov_console.dart';

example/lib/main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
        // This makes the visual density adapt to the platform that you run
        // the app on. For desktop platforms, the controls will be smaller and
        // closer together (more dense) than on mobile platforms.
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Author: DigitalKatalis
Source Code: https://github.com/DigitalKatalis/test_cov_console 
License: BSD-3-Clause license

#flutter #dart #test 

Ethan Hughes

Ethan Hughes

1607374440

A Beginner’s Guide To JavaScript Primitive vs. Reference Values

In JavaScript, a variable may store two types of values: primitive and reference.

#javascript #programming #javascript-tips

Sival Alethea

Sival Alethea

1624298400

Learn JavaScript - Full Course for Beginners. DO NOT MISS!!!

This complete 134-part JavaScript tutorial for beginners will teach you everything you need to know to get started with the JavaScript programming language.
⭐️Course Contents⭐️
0:00:00 Introduction
0:01:24 Running JavaScript
0:04:23 Comment Your Code
0:05:56 Declare Variables
0:06:15 Storing Values with the Assignment Operator
0:11:31 Initializing Variables with the Assignment Operator
0:11:58 Uninitialized Variables
0:12:40 Case Sensitivity in Variables
0:14:05 Add Two Numbers
0:14:34 Subtract One Number from Another
0:14:52 Multiply Two Numbers
0:15:12 Dividing Numbers
0:15:30 Increment
0:15:58 Decrement
0:16:22 Decimal Numbers
0:16:48 Multiply Two Decimals
0:17:18 Divide Decimals
0:17:33 Finding a Remainder
0:18:22 Augmented Addition
0:19:22 Augmented Subtraction
0:20:18 Augmented Multiplication
0:20:51 Augmented Division
0:21:19 Declare String Variables
0:22:01 Escaping Literal Quotes
0:23:44 Quoting Strings with Single Quotes
0:25:18 Escape Sequences
0:26:46 Plus Operator
0:27:49 Plus Equals Operator
0:29:01 Constructing Strings with Variables
0:30:14 Appending Variables to Strings
0:31:11 Length of a String
0:32:01 Bracket Notation
0:33:27 Understand String Immutability
0:34:23 Find the Nth Character
0:34:51 Find the Last Character
0:35:48 Find the Nth-to-Last Character
0:36:28 Word Blanks
0:40:44 Arrays
0:41:43 Nest Arrays
0:42:33 Access Array Data
0:43:34 Modify Array Data
0:44:48 Access Multi-Dimensional Arrays
0:46:30 push()
0:47:29 pop()
0:48:33 shift()
0:49:23 unshift()
0:50:36 Shopping List
0:51:41 Write Reusable with Functions
0:53:41 Arguments
0:55:43 Global Scope
0:59:31 Local Scope
1:00:46 Global vs Local Scope in Functions
1:02:40 Return a Value from a Function
1:03:55 Undefined Value returned
1:04:52 Assignment with a Returned Value
1:05:52 Stand in Line
1:08:41 Boolean Values
1:09:24 If Statements
1:11:51 Equality Operator
1:13:18 Strict Equality Operator
1:14:43 Comparing different values
1:15:38 Inequality Operator
1:16:20 Strict Inequality Operator
1:17:05 Greater Than Operator
1:17:39 Greater Than Or Equal To Operator
1:18:09 Less Than Operator
1:18:44 Less Than Or Equal To Operator
1:19:17 And Operator
1:20:41 Or Operator
1:21:37 Else Statements
1:22:27 Else If Statements
1:23:30 Logical Order in If Else Statements
1:24:45 Chaining If Else Statements
1:27:45 Golf Code
1:32:15 Switch Statements
1:35:46 Default Option in Switch Statements
1:37:23 Identical Options in Switch Statements
1:39:20 Replacing If Else Chains with Switch
1:41:11 Returning Boolean Values from Functions
1:42:20 Return Early Pattern for Functions
1:43:38 Counting Cards
1:49:11 Build Objects
1:50:46 Dot Notation
1:51:33 Bracket Notation
1:52:47 Variables
1:53:34 Updating Object Properties
1:54:30 Add New Properties to Object
1:55:19 Delete Properties from Object
1:55:54 Objects for Lookups
1:57:43 Testing Objects for Properties
1:59:15 Manipulating Complex Objects
2:01:00 Nested Objects
2:01:53 Nested Arrays
2:03:06 Record Collection
2:10:15 While Loops
2:11:35 For Loops
2:13:56 Odd Numbers With a For Loop
2:15:28 Count Backwards With a For Loop
2:17:08 Iterate Through an Array with a For Loop
2:19:43 Nesting For Loops
2:22:45 Do…While Loops
2:24:12 Profile Lookup
2:28:18 Random Fractions
2:28:54 Random Whole Numbers
2:30:21 Random Whole Numbers within a Range
2:31:46 parseInt Function
2:32:36 parseInt Function with a Radix
2:33:29 Ternary Operator
2:34:57 Multiple Ternary Operators
2:36:57 var vs let
2:39:02 var vs let scopes
2:41:32 const Keyword
2:43:40 Mutate an Array Declared with const
2:44:52 Prevent Object Mutation
2:47:17 Arrow Functions
2:28:24 Arrow Functions with Parameters
2:49:27 Higher Order Arrow Functions
2:53:04 Default Parameters
2:54:00 Rest Operator
2:55:31 Spread Operator
2:57:18 Destructuring Assignment: Objects
3:00:18 Destructuring Assignment: Nested Objects
3:01:55 Destructuring Assignment: Arrays
3:03:40 Destructuring Assignment with Rest Operator to Reassign Array
3:05:05 Destructuring Assignment to Pass an Object
3:06:39 Template Literals
3:10:43 Simple Fields
3:12:24 Declarative Functions
3:12:56 class Syntax
3:15:11 getters and setters
3:20:25 import vs require
3:22:33 export
3:23:40 * to Import
3:24:50 export default
3:25:26 Import a Default Export
📺 The video in this post was made by freeCodeCamp.org
The origin of the article: https://www.youtube.com/watch?v=PkZNo7MFNFg&list=PLWKjhJtqVAblfum5WiQblKPwIbqYXkDoC&index=4

🔥 If you’re a beginner. I believe the article below will be useful to you ☞ What You Should Know Before Investing in Cryptocurrency - For Beginner
⭐ ⭐ ⭐The project is of interest to the community. Join to Get free ‘GEEK coin’ (GEEKCASH coin)!
☞ **-----CLICK HERE-----**⭐ ⭐ ⭐
Thanks for visiting and watching! Please don’t forget to leave a like, comment and share!

#javascript #learn javascript #learn javascript for beginners #learn javascript - full course for beginners #javascript programming language

Lowa Alice

Lowa Alice

1624379820

JavaScript Tutorial for Beginners: Learn JavaScript in 1 Hour

Watch this JavaScript tutorial for beginners to learn JavaScript basics in one hour.
avaScript is one of the most popular programming languages in 2019. A lot of people are learning JavaScript to become front-end and/or back-end developers.

I’ve designed this JavaScript tutorial for beginners to learn JavaScript from scratch. We’ll start off by answering the frequently asked questions by beginners about JavaScript and shortly after we’ll set up our development environment and start coding.

Whether you’re a beginner and want to learn to code, or you know any programming language and just want to learn JavaScript for web development, this tutorial helps you learn JavaScript fast.

You don’t need any prior experience with JavaScript or any other programming languages. Just watch this JavaScript tutorial to the end and you’ll be writing JavaScript code in no time.

If you want to become a front-end developer, you have to learn JavaScript. It is the programming language that every front-end developer must know.

You can also use JavaScript on the back-end using Node. Node is a run-time environment for executing JavaScript code outside of a browser. With Node and Express (a popular JavaScript framework), you can build back-end of web and mobile applications.

If you’re looking for a crash course that helps you get started with JavaScript quickly, this course is for you.

⭐️TABLE OF CONTENT ⭐️

00:00 What is JavaScript
04:41 Setting Up the Development Environment
07:52 JavaScript in Browsers
11:41 Separation of Concerns
13:47 JavaScript in Node
16:11 Variables
21:49 Constants
23:35 Primitive Types
26:47 Dynamic Typing
30:06 Objects
35:22 Arrays
39:41 Functions
44:22 Types of Functions

📺 The video in this post was made by Programming with Mosh
The origin of the article: https://www.youtube.com/watch?v=W6NZfCO5SIk&list=PLTjRvDozrdlxEIuOBZkMAK5uiqp8rHUax&index=2
🔥 If you’re a beginner. I believe the article below will be useful to you ☞ What You Should Know Before Investing in Cryptocurrency - For Beginner
⭐ ⭐ ⭐The project is of interest to the community. Join to Get free ‘GEEK coin’ (GEEKCASH coin)!
☞ **-----CLICK HERE-----**⭐ ⭐ ⭐
Thanks for visiting and watching! Please don’t forget to leave a like, comment and share!

#javascript #javascript tutorial #javascript tutorial for beginners #beginners