Converting CSV to JSON in a strange format - javascript

I have a lot of geo's which I want to use in webgl globe.
The format for Webgl is
Sample for Googles .json file in their working webgl globe source [["1993",[long, lat,weight,long, lat,weight],["1994",[long, lat,weight,long, lat,weight,long, lat,weight,long, lat,weight]]]
I've been looking for a way to convert this but i can't find a converter online.
Does anyone know where I can find a converter for this format or suggest a way to do this.
Sample of my data:
- Year Latitude Longitude Magnitude
- 1995 -82.8627519 -135 0.11
- 1995 -54.423199 3.413194 0.01
- 1994 -53.08181 73.504158 0.01
- 1994 -51.796253 -59.523613 0.04
- 1993 -49.280366 69.348557 0.02
- 1993 -41.4370868 147.1393767 0.18
Looking at this more, I think the json file Google are using is a nested json array of arrays. This

There are multiple ways to parse the data.
The first step is to save the data to a file.
For example:
Year Latitude Longitude Magnitude
1995 -82.8627519 -135 0.11
1995 -54.423199 3.413194 0.01
1994 -53.08181 73.504158 0.01
1994 -51.796253 -59.523613 0.04
1993 -49.280366 69.348557 0.02
1993 -41.4370868 147.1393767 0.18
in raw.txt
The second step is to load and parse data.
With parsing there are a couple of things to keep in mind:
The raw data has an inconsistent number of white spaces separating values, so those need to be collapsed first so we can split a row/line by the space character. Luckily the data doesn't contains names containing spaces so we can use a RegEx like so /\s{2,}/g
We want to gather all the data pertaining to one year into a single list. One way is to use an array and continuously check if it has the year value already. Another is to simply use an Object/associative array/dictionary and not worry about any checks.
Once the data is correctly gathered in a object we pop it into a an array so it matches the format of the data being used.
Here's what I mean:
xhr = new XMLHttpRequest();
xhr.open('GET', '/globe/raw.txt', true);
xhr.onreadystatechange = function(e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var lines = xhr.responseText.split("\n");//split .txt file into lines
var data = [];//prepare an array to hold the end result
var dict = {};//use an Object/Dictionary to collapse data from same key/year
for(var i = 1 ; i < lines.length; i++){//for each line
var line = lines[i].replace(/\s{2,}/g, ' ').split(' ');//collapse white spaces and split into an array of values
if( !dict[line[0]]) dict[line[0]] = [];//if there isn't an array to store that data yes, make one
dict[line[0]].push(parseFloat(line[1]));//append data into the coresponding key/year
dict[line[0]].push(parseFloat(line[2]));
dict[line[0]].push(parseFloat(line[3]));
}
for(var key in dict) data.push([key,dict[key]]);//at the end, loop through the object and populate an array
console.log(data);
}
}
};
xhr.send(null);
so if you use something like this:
xhr = new XMLHttpRequest();
xhr.open('GET', '/globe/raw.txt', true);
xhr.onreadystatechange = function(e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var lines = xhr.responseText.split("\n");//split .txt file into lines
var data = [];//prepare an array to hold the end result
var dict = {};//use an Object/Dictionary to collapse data from same key/year
for(var i = 1 ; i < lines.length; i++){//for each line
var line = lines[i].replace(/\s{2,}/g, ' ').split(' ');//collapse white spaces and split into an array of values
if( !dict[line[0]]) dict[line[0]] = [];//if there isn't an array to store that data yes, make one
dict[line[0]].push(parseFloat(line[1]));//append data into the coresponding key/year
dict[line[0]].push(parseFloat(line[2]));
dict[line[0]].push(parseFloat(line[3]));
}
for(var key in dict) data.push([key,dict[key]]);//at the end, loop through the object and populate an array
window.data = data;
for (i=0;i<data.length;i++) {
globe.addData(data[i][1], {format: 'magnitude', name: data[i][0], animated: true});
}
globe.createPoints();
settime(globe,0)();
globe.animate();
}
}
};
xhr.send(null);
in the WebGL Globe experiment running on a server you will see your data.

Related

How can I convert an image file to base 2 binary?

I'm trying to do it like this:
function handleFiles(files) {
var selectedFile = files[0];
var reader = new FileReader();
reader.readAsBinaryString(selectedFile);
reader.onloadend = function() {
var result = reader.result;
convert(result);
};
}
function convert(data) {
var img = document.createElement("img");
var result = data.toString(2);
document.body.appendChild(img);
img.src = 'data:image/jpeg;base64,' + btoa(data); // this works
console.log("Base ?: " + data); // not sure, I think 16 or more likely 64,
// the MDN documentation doesn't specify what base of binary is produced by the readAsBinaryString method
console.log("Base 2: " + result); // not base 2 binary data as expected
}
<input type="file" id="input" onchange="handleFiles(this.files)">
This code will convert a jpeg into binary data, then render it, but it is not first converting to base 2 binary. If you run that code and look at the logs, it's something more (I'm naive on the subject of bases and binary, but my guess is base 16 or 64). I think toString(2) is supposed to convert to base 2, but it doesn't seem to be doing that. Before converting it back to base 64, I want to get the binary data to base 2 for experimentation.
Can't you just step through your binary string and convert each character to a binary representation?
function convert(data) {
var result = ''
for (let i = 0; i < data.length; i++){
result += data.charCodeAt(i).toString(2)
}
console.log(result)
}
[ I would test this with a small file first. It writes a lot to the console, as you might imagine ]
EDIT -- sorry, didn't realize you wanted to go back and forth. If you want to get from a binary string back to something else, you'll probably want to pad the binary with zeros so you can pull out 8 bit (or whatever) at a time:
function convert(data) {
var result = ''
for (let i = 0; i < data.length; i++){
// pad to make all binary string parts 8 bits long
result += data.charCodeAt(i).toString(2).padStart(8, 0)
}
return result
}
function makeBuffer(string){
buffer = ''
for(let i = 0; i < string.length/8; i++){
let stIdx = i*8
// maybe a way to do this without the slice? dunno.
buffer += String.fromCharCode(parseInt(string.slice(stIdx,stIdx+8), 2))
}
return buffer
}
Binary is always base 2, that's what the "bi" in "binary" means.
When you call fileReader.readAsBinaryString() it's returning binary; Strings can store binary because they're really just an array of characters.
Displaying the string will not be a series of zeros and ones, it will be a jumble of different ASCII characters (letters, numbers, symbols, etc.) because those are the equivalent characters that match the binary values.
Additionally, you don't need the following line since your data you're passing in is already a string.
var result = data.toString(2);

Datetime array to array with dates, get corresponding time afterwards

Specific situation.. I'm having an array filled with datetimes I pull in via an api.
Users should be able to select a date from a datepicker (only showing dates available in the array) and afterwards see the corresponding time.
So what I've done..
The original array is obtained via php, so before starting to populate the datepicker with possible dates I create an extra array with dates only.
Since I maintain the key's it's possible to put these 2 arrays next to eachother.
Array looks as following:
["8-8-2017,07:00", "26-8-2017,07:00"];
So far so good...
After a user picks a date I trigger this to be able to start digging for the time corresponding that date.
Now it's getting messy...
$('#datepick').datepicker().on("input change", function(e) {
$("#uur").text('');
var selecteddate = e.target.value;
var searchArr = datesArray;
var ind = searchArr.indexOf(selecteddate.toString());
var result = datesArray.filter(function(item) {
return typeof item == 'string' && item.indexOf(selecteddate.toString()) > -1;
});
var afterComma = result.toString().substr(result.toString().indexOf(",") + 1);
var final = afterComma.replace(":", "u");
$("#uur").text("De warming up party gaat van start rond " + final);
});
The result is that this only works on the last element of the array.
Because I'm splitting based on the comma's. Now I know the easiest way to work arround this would be to change the , that's seperating date and time in another symbol but still I'm wondering why this couldn't be easier.
You convert whole array to string every time. You should change following code:
var afterComma = result.toString().substr(result.toString().indexOf(",") + 1);
To this;
var afterComma = item.toString().substr(item.toString().indexOf(",") + 1);
Edit:
I also missed the loop above
//for every item in result, afterComma will refer to related minute string
for (var item in result) {
var afterComma = item.toString().substr(item.toString().indexOf(",") + 1);
// Do rest here
}

javascript removing characters from multiple strings using a for loop

I'm reading a log file using file reader and then want to do some text manipulation using javascript, to use the read data further in my program. So far I managed to split my input by lines, but now that I want to format the specific strings in the array nothing happens. Is this due to not declaring the array globally? Basically I wanted to do a for loop that checks all the strings inside my array and remove " " (four blank spaces) that appear at the start for some of my strings. This is my code
$("#draftlog").change(function() {
var logFile = $('#draftlog').get(0).files[0];
//gets first file from draftlog
var reader = new FileReader;
reader.readAsText(logFile);
reader.onload = function(e) {
var rawLog = reader.result;
//reads first file from draftlog as text
var re=/\r\n|\n\r|\n|\r/g;
arrayOfLines = rawLog.replace(re,"\n").split("\n");
//splits the text into an array of strings for every new line
for(x=0;x<arrayOfLines.length;x++) {
arrayOfLines[x].replace(/ /g,'');
}
console.log(arrayOfLines);
};
});
my input will typicaly look like this:
Event #: 7952945
Time: 5.2.2015 17:14:54
Players:
TheDoktorJot
Arlekin
Jokulgoblin
Felo
Petrolit
Greyjoy
--> Susti
themuse1975
n0sfea
------ FRF ------
Pack 1 pick 1:
Abzan Runemark
Rakshasa's Disdain
Reach of Shadows
Grim Contest
Aven Skirmisher
Lotus Path Djinn
Formless Nurturing
Tasigur's Cruelty
Temur Battle Rage
Return to the Earth
--> Temur Sabertooth
Fascination
Jeskai Barricade
Arcbond
Rugged Highlands
Pack 1 pick 2:
Sandblast
Sultai Runemark
Jeskai Sage
Hooded Assassin
Pressure Point
Gore Swine
Whisperer of the Wilds
Mardu Runemark
Ambush Krotiq
Write into Being
Qarsi High Priest
Hewed Stone Retainers
Wardscale Dragon
--> Mastery of the Unseen
Strings are immutable, you have to write it back
for(x=0;x<arrayOfLines.length;x++) {
arrayOfLines[x] = arrayOfLines[x].replace(/ /g,'');
}
You could also just trim it to remove leading and following whitespace
arrayOfLines[x] = arrayOfLines[x].trim();

Read formatted data with d3.dsv.parseRows

I am starting to learn javascript and d3.js (version 3.3.3). I need to read data from files with a format which is neither csv nor tsv. I could probably use d3.dsv.parseRows, but I'm kind of stuck with it - I'd really appreciate some help to get started, an example would be great.
The data format is ASCII, two columns of numbers separated by an unknown number of whitespace characters (tabs or spaces). The comment character is #.
# Example
# The data is obviously poorly aligned
# The two values in each row are separated
# by one or more tabs and/or spaces
#
1.0 10.00
2.0 20
3.0 30. # this data line should be read
# 4.0 40.0 # this data line should be ignored
5.0 50.00
I need to have the data in an array of arrays of numbers, so I can go on with some nice d3 plotting:
[ [1.0,10.0], [2.0,20.0], [3.0,30.0], [5.0,50.0] ]
It sound like you'l have to write your own request, I've made a start on one with a couple of notes below, you'll need to finish it off though ...
var dsvFile = new XMLHttpRequest();
dsvFile.open("GET", "dsv.txt", true);
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (req.status === 200 ||
req.status === 0) {
var data = req.responseText;
cleanData(data)
}
}
};
req.open('GET', "dsv.txt", true);
req.send(null);
var cleanData = function(data) {
var clean = [];
var lines = data.split("\n");
for (var i = 0; i < lines.length; i++) {
var comment = /^#/
var whiteSpace = /^\s+/
var OK = comment.exec(lines[i]) // check for comment lines
var white = whiteSpace.exec(lines[i]) // check white whitespace at begining of line
if(!OK) // if no comments then
{
if(white) // if whitespace at begining of line remove
{
var str = lines[i].replace(whiteSpace, '')
}
else
{
var str = lines[i]
}
clean.push(str)
}
};
console.log(clean)
};
To process data files with multiple spaces (and maybe more complicated pattern),
d3.text can be combined with a regex and then d3.csvParseRows
var a = [];
d3.text("http://cdsarc.u-strasbg.fr/ftp/J/AJ/159/187/table3.dat")
.then(function(d){a = d3.csvParseRows(d.replace(/ +/g, ","))})
Note due to CORS, urls will work only for some webpages.

Dealing with uint8_t in javascript

G'day peoples,
I'm using MavLink to obtain GPS information. One of the message types is GPS_STATUS which is described by MavLink using a series of uint8_t[20].
If I run the following code:
console.log(' sat prn: ' + message.satellite_prn);
console.log(' sat prn: ' + JSON.stringify(message.satellite_prn));
console.log(' sat prn: ' + JSON.stringify(new Uint8Array(message.satellite_prn)));
I get the following output:
sat prn: <weird charcaters...>
sat prn: "\u0002\u0005\n\f\u000f\u0012\u0015\u0019\u001a\u001b\u001d\u001e\u001f\u0000\u0000\u0000\u0000"
sat prn: {"BYTES_PER_ELEMENT":1,"buffer":{"byteLength":0},"length":0,"byteOffset":0,"byteLength":0}
So obviously it's not working. I need a means to get the int value of each element.
I found this https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays?redirectlocale=en-US&redirectslug=JavaScript_typed_arrays
Which made me think I would be able to do the following:
satellite_prn = Array.apply([], new Uint8Array(message.satellite_prn));
satellite_prn.length === 20;
satellite_prn.constructor === Array;
But when I stringify it via JSON it reports [], I presume this is an empty array.
Anyone know how I can do this? I know that the data is an array of 20 unsigned 8 bit integers. I just need to know how to access or parse them.
Note: I'm using node.js, but that shouldn't affect what I'm doing. This is why I'm using console.log, as it's avail in node.js.
Two issues with your code:
message.satellite_prn is a string not an array
Unit8Array needs to be loaded with .set
To get an array of numbers from message.satellite_prn, do this:
var array = message.satellite_prn.map(function(c) { return c.charCodeAt(0) })
To load an ArrayBuffer, do this:
var buffer = new ArrayBuffer(array.length);
var uint8View = new Uint8Array(buffer);
uint8View.set(array);
Ideally you wouldn't need to go through the string. If you are obtaining the data from an up-to-date implementation of XMLHttpRequest, such as xhr2, you can set:
responseType = "arraybuffer"
Looks like the problem is my understanding on how to deal with binary data within javascript. I found that I can just do the following to get the data as base 10 via charCodeAt().
The following is the code that allowed me to iterate through the 20 unsigned 8 bit integers and get each value as a decimal:
for(var i = 0, l = message.satellite_prn.length; i < l; i++) {
console.log(' Satellite ' + i + ', id: ' +
parseInt(message.satellite_prn.charCodeAt(i), 10)
);
}
I suspect that there may be a function that allows me to convert the binary data into an array, but for an unknown reason Uint8Array didn't appear to be working for me. However the above does.

Categories