From 5400934de99f18d734120b5df04253037c51fc14 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 5 Sep 2011 17:16:14 -0500 Subject: [PATCH 01/62] Checking if googlecode's Git is more friendly to the appstore --- icon128.png | Bin 0 -> 3041 bytes jmat.html | 6 ++++++ jmat.js | 1 + manifest.json | 13 +++++++++++++ 4 files changed, 20 insertions(+) create mode 100644 icon128.png create mode 100644 jmat.html create mode 100644 jmat.js create mode 100644 manifest.json diff --git a/icon128.png b/icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..005c5991719aabaccb68eb30af1de3140afc466d GIT binary patch literal 3041 zcma);c{CL48o)=k5GqtOg$&su+b|#5vdmy8#$K{Bc4KUfU7BoTtXXo)I@v$lm5799 zNOswo7-1x9lii)}Ki|Fge1F_Op7%M=dY&nn;(# zvn=#;>}B#0T`>fh>T93Td>`ITH`x53)&T&(Mf7iBm~#~jp*#7}x>jg2UsrUn1Ih&e zM>?T=1L&5JiK{Ep$t7}K$sYjVaDeG(Aws6s^D$nw!FKB+c=O%7a)%={xh`bkLO zZ9dRzFiWhk;!`pEKT(_e-Qxx}hX0`QCg5(9wpm-~Or-&xoh<}2rzG$sC>j-n?(02F!y6g>tJ zVvPdg88x{`3_`3FdbhvAf9Io@crSX^4`Y%1v&M$#ZhnuFED2?LGY;$>_rjJs?kOfE zYJ!AEskz`!Z7x#npT*dR=!{(Vx-LdY4o2KWTIlFhZ~#@=^%FR7(z+-t_`B3(`X;q2 zR^q1Kyr-Op+V{e&q&yp3Xz##%^$dNEz?FCB zFZfa%V>VanzGvt+uF2VOW>ABNR}PU|Ej3wzN0CVSqN5#|@*`i{3Du$J-PG}FOE7L# z^Y(u>av$mnsT<;?lIaV-*7u9Oqv4$+E}swCTn2?^Wz#eI^^b1IL<8|fj-X$vbw${) z+cS|87O9?V2L{JU6fGO)Y5H~D%d8q;s_*ct_ma#ML^Re^ly*o*G=Z>V91tOW=9N&n z8+jdXZ(U`q44)tz1Xdlskd=iVvs|U`Om(W38;))VIWz7W(cGfBD$2+CtlWx5MsGw! z+UN73G;zJ>sdYmnOj#iZO1i(JDV<_ae)&~ELhyKsKv#or=VeCv2>cf$bvdmo#)ocFr?IruN2r+eAtOTo;wo1FGxsxc9O3Y@U7EbN5`R6X428#G91^qK;3r-~Kgf<*P#r>+X#iTK;*8coT5_p0^ye#}WeP}DR`K5Bv(Xsgr>EKYcUVH5 z+-z^lJN#W=l-EgamDWfsw!nWtbAD7^#4ut7%dn2Ufp8+IZM6j(^hbbsbJS zQZ)El1!YjkPhocT){*3m{Jw9^i(2uIoB0kNemii0+^bqmbv7*k9rZF44?F)%SXnx88a`%x$cN%o0%Ey?2TY6zNYf>}3J)y^9QywldW#FTU zYc^O=8m402DbnWA>Wvj3zsnM2WuD2 ztKb|+U&trX#VF+GwW|~f}-XHsk8jjRMra))GKrw;iU~29YJu&@cmIW?S z!I>@F{Ly1=tIA7K$X@BjSqcr@>QAs?hHO=<7^N`rj2NF zr!~c3DfD0{1UesRGyUl7fTZY<2aJ<4cm>$7u^-yt{`pekh+6ghEcV*V>Q5V6WI)(z zhJO7xJ48|2u_isJZ5Yqpwq%jQgV}|kHhWA=gD=i44h6N-dPjw^ALYToBv)SN>g{)K zX0EgG7p5Mhzckodo}pEOsRSV`%Mz4RwQM;|r&TL6BYQJeiKdln5pFaMXJcm}!vfj_ zo@=b(b{uMnjP!qK($sHutUJ3v~ctwb^+ zc3vlbtS;U$>m2*_W%Y-GCQiQIc}5o_tG7JbkIj?vJ@k3D&{9!k#^yGH`zGnNufA*N z{(7bn)HiI97Y>nb)T4%w^cMw-mq$kuET8%A+dV71qhu};7Xq{59Q|cuR2f#k z*J?6%p<*WYoM7X}Le$%^eXNHt)&{l7pd8@6E5_B;e5GiGMorUpTz4yNsW8kb``DTJ zuxDA_YB<~%LVXJ4kiaS+ORuV%N)6WZ)5+C4)jC-b1wy@NUze9_sfg4~0tzf1#Ep1wLTtt%ntWA4@vcQ~HMKIh4u_&mP< zOyi~8i!2d#NUtbsjmLm!DOuM3v?N>dW{C$|{~OpeW?!^0u83?gW35^d${d+e)r1k! zZ>CIaSK0Uc5XyOwQZ~nN!GK$~jf)!Q47e#)TxM7@;NA4NbcAY|vU{^`e8sm(8&}t} zWwfQhP%=t>zob&aE#2?Lya$(_6^u}*X(OOqcJ&gqfE#|BH9awjHAfF8W5h`J!4UQr zVp5+gLQ|z0kX!!%U2SgGL!5z5mUSp!r1;j~Zy;*b&c(&mJ0`O}Y(V$I*MA+lFLR5a z^}+qB!V1jahSnczNKwQA!Dmt_BnnOF`(a>`slaNNrG%F{&$TempcGq)IhC@D!*XaM zUrnA|JOI)wp+75`xFR#5 zwqUnw3iVrXFmSN3mD)@QpC*Li?;0LL$~k4G@`i_=$<-$hrG+-g#Q-(45Y;>f#r<9Q zn5{jvsViDs_joab#UYrQFZMYpt$8oT9W?QbyeaQ2Y*)`UCalKKk?#PHpF0*dGt=Q? zY2aRH(rB8$*`o0CAMOJFX3o<`Ju(SXG literal 0 HcmV?d00001 diff --git a/jmat.html b/jmat.html new file mode 100644 index 0000000..c119b5f --- /dev/null +++ b/jmat.html @@ -0,0 +1,6 @@ + + + + + JMAT + diff --git a/jmat.js b/jmat.js new file mode 100644 index 0000000..6540fa2 --- /dev/null +++ b/jmat.js @@ -0,0 +1 @@ +console.log('jmat :-)') \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..3b17a59 --- /dev/null +++ b/manifest.json @@ -0,0 +1,13 @@ +{ + "name": "jMat", + "description": "m-code for the js console", + "version": "0.0.0.3", + "icons": { + "128": "icon128.png" + }, + "app": { + "launch": { + "web_url": "http://jmat.googlecode.com/hg/jmat.html" + } + } +} \ No newline at end of file From 75c67d68c964ef2a3f397cdb15bb0f105d54326b Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 5 Sep 2011 17:20:17 -0500 Subject: [PATCH 02/62] correction of URL in manifest --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 3b17a59..e09943e 100644 --- a/manifest.json +++ b/manifest.json @@ -7,7 +7,7 @@ }, "app": { "launch": { - "web_url": "http://jmat.googlecode.com/hg/jmat.html" + "web_url": "http://jmat.googlecode.com/git/jmat.html" } } } \ No newline at end of file From e06b07edc855312458dbc40dc0403f7367b99d4c Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 5 Sep 2011 17:36:30 -0500 Subject: [PATCH 03/62] appstore verification file --- google24741bc4ba4d02c3.html | 1 + 1 file changed, 1 insertion(+) create mode 100644 google24741bc4ba4d02c3.html diff --git a/google24741bc4ba4d02c3.html b/google24741bc4ba4d02c3.html new file mode 100644 index 0000000..ac934bf --- /dev/null +++ b/google24741bc4ba4d02c3.html @@ -0,0 +1 @@ +google-site-verification: google24741bc4ba4d02c3.html \ No newline at end of file From a5403f99e1f9150dbd83da91730f4cfcfcda61eb Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 5 Sep 2011 17:40:42 -0500 Subject: [PATCH 04/62] appstore metatag added to jmat.html --- jmat.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jmat.html b/jmat.html index c119b5f..e297622 100644 --- a/jmat.html +++ b/jmat.html @@ -1,4 +1,7 @@ + + + From 0dd298bf799e07fe07eced73b235657fd63def9d Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 7 Nov 2011 06:49:05 -0600 Subject: [PATCH 05/62] JSON style functions adopted --- jmat.js | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index 6540fa2..aa35018 100644 --- a/jmat.js +++ b/jmat.js @@ -1 +1,79 @@ -console.log('jmat :-)') \ No newline at end of file +console.log('jmat :-)') + +jmat = { + + transpose:function (x){ // transposes 2D array + var y=[],n=x.length,m=x[0].length + for(var j=0;j=0;i=i-1){ + m=Math.pow(2,i); + if(x>=m){b=b+'1';x=x-m} + else{b=b+'0'} + }; + return b + }, + + cat:function(x,y){ // cat will work for matrices and objects + x=this.stringify(x); + y=this.stringify(y); + return this.parse(x.slice(0,x.length-1)+','+y.slice(1,y.length)); + }, + + length:function(x){ // js Array.length returns highest index, not always the numerical length + var n=0 + for(var i in x){n++}; + return n + }, + + array2mat:function(x){ // to handle indexed arrays by converting them into two separate numerically indexed arrays + var j = 0, y1=[], y2=[]; + for(var i in x){ + y1[j]=i; + y2[j]=x[i]; + j=j+1; + } + return [y1,y2] } - + } \ No newline at end of file From be605a23e654983a029caf8df868d8ac1432d5f8 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Fri, 2 Dec 2011 10:06:24 -0600 Subject: [PATCH 08/62] get url added --- jmat.js | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/jmat.js b/jmat.js index 9e640eb..92adc4b 100644 --- a/jmat.js +++ b/jmat.js @@ -101,8 +101,12 @@ jmat = { else{return Math.log(x)/Math.log(n)} }, - toBin:function(x,n){ - if(!n){n=this.log(x,2)+1}; + str2num:function(x){ + return JSON.parse(x); + }, + + dec2bin:function(x,n){ + if(!n){n=Math.ceil(this.log(x,2))+1}; var b=''; for(i=n-1;i>=0;i=i-1){ m=Math.pow(2,i); @@ -112,6 +116,13 @@ jmat = { return b }, + bin2dec:function(x){ + var n=x.length; + return x.split('').map(function(xi,i){return xi*Math.pow(2,n-i-1)}).reduce(function(a,b){return a+b}); + }, + + + cat:function(x,y){ // cat will work for matrices and objects x=this.stringify(x); y=this.stringify(y); @@ -124,6 +135,14 @@ jmat = { return n }, + load:function(fname){ + var s = document.createElement('script'); + s.src=fname; + s.id = this.uid(); + document.body.appendChild(s); + setTimeout('document.body.removeChild(document.getElementById("'+s.id+'"));',30000); // is the waiting still needed ? + }, + array2mat:function(x){ // to handle indexed arrays by converting them into two separate numerically indexed arrays var j = 0, y1=[], y2=[]; for(var i in x){ @@ -132,6 +151,26 @@ jmat = { j=j+1; } return [y1,y2] - } + }, + array2str:function(x,sp){ // convert array into a sp separated + if (!sp){sp='\n'} + y=x[0]; + for (var i=1;i Date: Wed, 7 Dec 2011 09:51:15 -0600 Subject: [PATCH 09/62] fixed delete jobs --- jmat.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/jmat.js b/jmat.js index 92adc4b..39a5b49 100644 --- a/jmat.js +++ b/jmat.js @@ -31,11 +31,9 @@ jmat = { }, sort:function (x){ // [y,I]=sort(x), where y is the sorted array and I contains the indexes - var y = new Array; - for(var i =0;i Date: Mon, 26 Dec 2011 11:19:06 -0600 Subject: [PATCH 10/62] working on reveal --- jmat.js | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/jmat.js b/jmat.js index 39a5b49..033f600 100644 --- a/jmat.js +++ b/jmat.js @@ -133,9 +133,9 @@ jmat = { return n }, - load:function(fname){ + load:function(url){ var s = document.createElement('script'); - s.src=fname; + s.src=url; s.id = this.uid(); document.body.appendChild(s); setTimeout('document.body.removeChild(document.getElementById("'+s.id+'"));',30000); // is the waiting still needed ? @@ -160,16 +160,60 @@ jmat = { return y }, - get:function(url,callback){ // get content at url + webrwUrl:'http://sandbox1.mathbiol.org', + + get:function(key,callback,url){ // get content at url or key if (!callback){callback=function(x){console.log(x)}} + if (!url){url=this.webrwUrl}; var uid = this.uid(); if(!this.get.jobs){this.get.jobs=[]} - this.get.jobs[uid]={fun:callback}; - url='http://sandbox1.mathbiol.org/webrw.php?get='+url+'&callback=jmat.get.jobs.'+uid+'.fun'; + this.get.jobs[uid]={'fun':callback}; + var url=url+'/webrw.php?get='+key+'&callback=jmat.get.jobs.'+uid+'.fun'; var s=document.createElement('script'); s.id = uid;s.src=url; document.body.appendChild(s); setTimeout('document.body.removeChild(document.getElementById("'+uid+'"));delete jmat.get.jobs.'+uid+';',10000); // is the waiting still need ? script onload would be another possibility to delete it return uid; + }, + + + set:function(val,callback,key,url){ // set key-val pairs in the webrw endpoint, calback will have the key as its argument + if (!callback){callback=function(x){console.log(x)}}; + if (typeof(val)!='string'){this.stringify(val)}; + if (!url){url=this.webrwUrl} + if(!this.set.jobs){this.set.jobs=[]} + var uid = this.uid(); + this.set.jobs[uid]={'fun':callback}; + var s=document.createElement('script');s.id=uid; + if (!key){s.src=url+'/webrw.php?set='+val+'&callback=jmat.set.jobs.'+uid+'.fun'} + else{s.src=url+'/webrw.php?set='+val+'&key='+key+'&callback=jmat.set.jobs.'+uid+'.fun'} + document.body.appendChild(s); + setTimeout('document.body.removeChild(document.getElementById("'+uid+'"));delete jmat.set.jobs.'+uid+';',10000); + return uid; + }, + + reval:function(x,fun,callback,url){ + if (!Array.isArray(x)){x=[x]} // make sure x is an array + if (!Array.isArray(fun)){fun=[fun]} // make sure it is an array of functions + if (!url){url=this.webrwUrl}; + //if (!Array.isArray(fun)){fun=[fun]} // make sure it is an array of functions + // create webrw jobList + if (!this.reval.jobs){this.reval.jobs=[]} + var uid = this.uid(); + this.reval.jobs[uid]={fun:fun,x:x,callback:callback,url:url} + //match x and fun dimensions + var n = Math.max(jmat.reval.jobs[uid].x.length,jmat.reval.jobs[uid].fun.length); + for (var i=jmat.reval.jobs[uid].x.length;i Date: Mon, 26 Dec 2011 12:24:56 -0600 Subject: [PATCH 11/62] gId will look for classes if ids are not found --- jmat.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index 033f600..f73f147 100644 --- a/jmat.js +++ b/jmat.js @@ -74,7 +74,14 @@ jmat = { }, gId:function(x){ // x is the id of an existing DOM element - return document.getElementById(x) + // return null if neither id nor class are found + // so constructs like !jmat.gId(someID) can be used + var y=document.getElementById(x); + if(!y){ + var z=document.getElementById(x); + if(z.length>0){return z} + else{return y} + } }, unique:function(x){ // x is an Array From 08a3821968ad91727d07ee0347af499c509e0816 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 26 Dec 2011 13:26:21 -0600 Subject: [PATCH 12/62] fieldnames --- jmat.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/jmat.js b/jmat.js index f73f147..8999521 100644 --- a/jmat.js +++ b/jmat.js @@ -84,6 +84,15 @@ jmat = { } }, + fieldnames:function(x){ + y=[];i=0; + for(var f in x){ + y[i]=f; + i++; + } + return y; + }, + unique:function(x){ // x is an Array var u = []; // store unique here u[0]=x[0]; From 1d29e9008ab6fd054224e600ef462aa43fc23239 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 26 Dec 2011 21:39:19 -0600 Subject: [PATCH 13/62] cEl = document.createElement --- jmat.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index 8999521..c6b45c1 100644 --- a/jmat.js +++ b/jmat.js @@ -78,10 +78,11 @@ jmat = { // so constructs like !jmat.gId(someID) can be used var y=document.getElementById(x); if(!y){ - var z=document.getElementById(x); + var z=document.getElementsByClassName(x); if(z.length>0){return z} else{return y} } + else{return y} }, fieldnames:function(x){ @@ -93,6 +94,12 @@ jmat = { return y; }, + cEl:function(x,id){ + x = document.createElement(x); + if(id){x.id=id} + return x + }, + unique:function(x){ // x is an Array var u = []; // store unique here u[0]=x[0]; From 73ca578dbebf4f294ed4017636ff0bd679012941 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 26 Dec 2011 21:48:25 -0600 Subject: [PATCH 14/62] returning gId to being about ID's only --- jmat.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/jmat.js b/jmat.js index c6b45c1..c2d1cc3 100644 --- a/jmat.js +++ b/jmat.js @@ -76,13 +76,14 @@ jmat = { gId:function(x){ // x is the id of an existing DOM element // return null if neither id nor class are found // so constructs like !jmat.gId(someID) can be used - var y=document.getElementById(x); - if(!y){ - var z=document.getElementsByClassName(x); - if(z.length>0){return z} - else{return y} - } - else{return y} + //var y=document.getElementById(x); + //if(!y){ + // var z=document.getElementsByClassName(x); + // if(z.length>0){return z} + // else{return y} + //} + //else{return y} + return document.getElementById(x) }, fieldnames:function(x){ From 5ce3cbe611b74e9b9a6cd37308f17a87f8ddd39f Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Wed, 28 Dec 2011 22:18:04 -0600 Subject: [PATCH 15/62] imread and imwrite --- jmat.js | 508 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 277 insertions(+), 231 deletions(-) diff --git a/jmat.js b/jmat.js index c2d1cc3..317d1ef 100644 --- a/jmat.js +++ b/jmat.js @@ -2,242 +2,288 @@ console.log('jmat :-)') jmat = { - transpose:function (x){ // transposes 2D array - var y=[],n=x.length,m=x[0].length - for(var j=0;j=0;i=i-1){ + m=Math.pow(2,i); + if(x>=m){b=b+'1';x=x-m} + else{b=b+'0'} + }; + return b +}, + +get:function(key,callback,url){ // get content at url or key + if (!callback){callback=function(x){console.log(x)}} + if (!url){url=this.webrwUrl}; + var uid = this.uid(); + if(!this.get.jobs){this.get.jobs=[]} + this.get.jobs[uid]={'fun':callback}; + var url=url+'/webrw.php?get='+key+'&callback=jmat.get.jobs.'+uid+'.fun'; + var s=document.createElement('script'); + s.id = uid;s.src=url; + document.body.appendChild(s); + setTimeout('document.body.removeChild(document.getElementById("'+uid+'"));delete jmat.get.jobs.'+uid+';',10000); // is the waiting still need ? script onload would be another possibility to delete it + return uid; +}, + +fieldnames:function(x){ + y=[];i=0; + for(var f in x){ + y[i]=f; + i++; + } + return y; +}, + +gId:function(x){ // x is the id of an existing DOM element + // return null if neither id nor class are found + // so constructs like !jmat.gId(someID) can be used + //var y=document.getElementById(x); + //if(!y){ + // var z=document.getElementsByClassName(x); + // if(z.length>0){return z} + // else{return y} + //} + //else{return y} + return document.getElementById(x) +}, + +imread:function(cv){ // reads image from context into matrix + // find out what type of input + if(typeof(cv)=='string'){ // cv is the id of a canvas element + cv=jmat.gId(cv) + } + var ct=cv.getContext('2d'), n=cv.width, m=cv.height; + var imData=ct.getImageData(0,0,n,m); // pixel values will be stored in imData.data + return this.imData2data(imData) +}, + +imwrite:function(cv,im,dx,dy){ + if(!dy){dx=0;dy=0} // default location + if(typeof(cv)=='string'){cv=jmat.gId(cv)} //cv can also be the id of a canvas element + if(!im.data){im=jmat.data2imData(im)} // such that im can also be the matrix created by imread + var ct = cv.getContext('2d'); + ct.putImageData(im,dx,dy); + return ct; +}, + +imData2data:function(imData){ // imData is the data structure returned by canvas.getContext('2d').getImageData(0,0,n,m) + var m=imData.width, n=imData.height, data=[]; + for (var i=0;ixi,yixi,yi=0;i=i-1){ - m=Math.pow(2,i); - if(x>=m){b=b+'1';x=x-m} - else{b=b+'0'} - }; - return b - }, - - bin2dec:function(x){ - var n=x.length; - return x.split('').map(function(xi,i){return xi*Math.pow(2,n-i-1)}).reduce(function(a,b){return a+b}); - }, - - - - cat:function(x,y){ // cat will work for matrices and objects - x=this.stringify(x); - y=this.stringify(y); - return this.parse(x.slice(0,x.length-1)+','+y.slice(1,y.length)); - }, - - length:function(x){ // js Array.length returns highest index, not always the numerical length - var n=0 - for(var i in x){n++}; - return n - }, - - load:function(url){ - var s = document.createElement('script'); - s.src=url; - s.id = this.uid(); - document.body.appendChild(s); - setTimeout('document.body.removeChild(document.getElementById("'+s.id+'"));',30000); // is the waiting still needed ? - }, - - array2mat:function(x){ // to handle indexed arrays by converting them into two separate numerically indexed arrays - var j = 0, y1=[], y2=[]; - for(var i in x){ - y1[j]=i; - y2[j]=x[i]; - j=j+1; - } - return [y1,y2] - }, - - array2str:function(x,sp){ // convert array into a sp separated - if (!sp){sp='\n'} - y=x[0]; - for (var i=1;i Date: Fri, 30 Dec 2011 09:20:10 -0600 Subject: [PATCH 16/62] clone --- jmat.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/jmat.js b/jmat.js index 317d1ef..d0d7cc7 100644 --- a/jmat.js +++ b/jmat.js @@ -38,6 +38,19 @@ cEl:function(x,id){ return x }, +clone:function(x){ // clone object without functional elements + return JSON.parse(JSON.stringify(x)) +}, + +clone2:function(x){ // clone object that may have functional elements + return jmat.parse(jmat.stringify(x)) +}, + +cloneArray:function(A){ + if(Array.isArray(A)){return A.map(function(x){return jmat.cloneArray(x)})} + else{return A} +}, + data2imData:function(data){ // the reverse of im2data, data is a matlabish set of 4 2d matrices, with the r, g, b and alpha values var n=data.length, m=data[0].length; //var imData = {width:m, height:n, data:[]}; @@ -66,6 +79,10 @@ dec2bin:function(x,n){ return b }, +dotFun:function(A,B,fun){ // dot matrix function + 4; +}, + get:function(key,callback,url){ // get content at url or key if (!callback){callback=function(x){console.log(x)}} if (!url){url=this.webrwUrl}; @@ -152,6 +169,14 @@ log:function(x,n){ else{return Math.log(x)/Math.log(n)} }, +max:function(x){ //return maximum value of array + return x.reduce(function(a,b){if(a>b){return a}else{return b}}) +}, + +max2:function(x){ // returns maximum value of array and its index, i.e. [max,i] + return x.map(function(xi,i){return [xi,i]}).reduce(function(a,b){if(a[0]>b[0]){return a}else{return b}}) +}, + parse:function(x){ // x is a stringified Object eval('var res='+x); return res; From ca70e58d439c4aa29905b90f23cffa2daa4cb0e4 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Fri, 30 Dec 2011 16:59:15 -0600 Subject: [PATCH 17/62] load and read local files (.loadFiles, .readFiles) --- jmat.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index d0d7cc7..c8283e0 100644 --- a/jmat.js +++ b/jmat.js @@ -156,7 +156,7 @@ length:function(x){ // js Array.length returns highest index, not always the num return n }, -load:function(url){ +load:function(url){ // load script / JSON var s = document.createElement('script'); s.src=url; s.id = this.uid(); @@ -164,6 +164,32 @@ load:function(url){ setTimeout('document.body.removeChild(document.getElementById("'+s.id+'"));',30000); // is the waiting still needed ? }, +loadFiles:function(files,readAs,callback){ + // //<-- example of button for reading text files + if(!readAs){readAs='readAsDataURL'} // default is to read as dataURL + for(var i=0;i Date: Wed, 4 Jan 2012 16:46:24 -0600 Subject: [PATCH 18/62] catArray and generalization of webrw endpoint URL --- jmat.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/jmat.js b/jmat.js index c8283e0..d7ddf14 100644 --- a/jmat.js +++ b/jmat.js @@ -32,6 +32,16 @@ cat:function(x,y){ // cat will work for matrices and objects return this.parse(x.slice(0,x.length-1)+','+y.slice(1,y.length)); }, +catArray:function(A){ // optimized for conCATenation of an array of numerically indexed arrays + // this function was developed to adress memory issues of dealing with large arrays, not performance + var Astr='[',Ai=''; + for(var i=0;i Date: Wed, 4 Jan 2012 22:21:17 -0600 Subject: [PATCH 19/62] disp --- jmat.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jmat.js b/jmat.js index d7ddf14..b6bdc3b 100644 --- a/jmat.js +++ b/jmat.js @@ -89,6 +89,11 @@ dec2bin:function(x,n){ return b }, +disp:function(x){ // by default displays both in the console and in document.body + console.log(x); + document.body.innerHTML+='
'+x+''; +}, + dotFun:function(A,B,fun){ // dot matrix function 4; }, From 3cd7dfabf88d680c54078f3c6772d5f1191422eb Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Wed, 4 Jan 2012 22:32:11 -0600 Subject: [PATCH 20/62] disp color blue --- jmat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index b6bdc3b..eb5f3a7 100644 --- a/jmat.js +++ b/jmat.js @@ -91,7 +91,7 @@ dec2bin:function(x,n){ disp:function(x){ // by default displays both in the console and in document.body console.log(x); - document.body.innerHTML+='
'+x+''; + document.body.innerHTML+='
'+x+''; }, dotFun:function(A,B,fun){ // dot matrix function From 8c94369834ba7d02f81f5cf214bfa3d939c233c3 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 9 Jan 2012 10:50:45 -0600 Subject: [PATCH 21/62] image segmentation started such as imthreshold --- jmat.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/jmat.js b/jmat.js index eb5f3a7..b3e4a50 100644 --- a/jmat.js +++ b/jmat.js @@ -61,6 +61,18 @@ cloneArray:function(A){ else{return A} }, +colormap:function(c){ + if(!c){c='default'} + switch(c){ + case 'default': + c=[[0,0,0.5625],[0,0,0.625],[0,0,0.6875],[0,0,0.75],[0,0,0.8125],[0,0,0.875],[0,0,0.9375],[0,0,1],[0,0.0625,1],[0,0.125,1],[0,0.1875,1],[0,0.25,1],[0,0.3125,1],[0,0.375,1],[0,0.4375,1],[0,0.5,1],[0,0.5625,1],[0,0.625,1],[0,0.6875,1],[0,0.75,1],[0,0.8125,1],[0,0.875,1],[0,0.9375,1],[0,1,1],[0.0625,1,0.9375],[0.125,1,0.875],[0.1875,1,0.8125],[0.25,1,0.75],[0.3125,1,0.6875],[0.375,1,0.625],[0.4375,1,0.5625],[0.5,1,0.5],[0.5625,1,0.4375],[0.625,1,0.375],[0.6875,1,0.3125],[0.75,1,0.25],[0.8125,1,0.1875],[0.875,1,0.125],[0.9375,1,0.0625],[1,1,0],[1,0.9375,0],[1,0.875,0],[1,0.8125,0],[1,0.75,0],[1,0.6875,0],[1,0.625,0],[1,0.5625,0],[1,0.5,0],[1,0.4375,0],[1,0.375,0],[1,0.3125,0],[1,0.25,0],[1,0.1875,0],[1,0.125,0],[1,0.0625,0],[1,0,0],[0.9375,0,0],[0.875,0,0],[0.8125,0,0],[0.75,0,0],[0.6875,0,0],[0.625,0,0],[0.5625,0,0],[0.5,0,0]]; + break; + default: + c = 'not found'; + } + return c +}, + data2imData:function(data){ // the reverse of im2data, data is a matlabish set of 4 2d matrices, with the r, g, b and alpha values var n=data.length, m=data[0].length; //var imData = {width:m, height:n, data:[]}; @@ -165,6 +177,15 @@ imData2data:function(imData){ // imData is the data structure returned by canvas return data; }, +imMap:function(im,fun){ // applies function to all pixels of an image and returns the 2D map of fun values + if(!fun){fun=function(xy){return 0}} // in no fun return a 2D zero matrix + return im.map(function(x){ + return x.map(function(xy){ + return fun(xy) + }) + }) +}, + length:function(x){ // js Array.length returns highest index, not always the numerical length var n=0 for(var i in x){n++}; @@ -218,6 +239,11 @@ max2:function(x){ // returns maximum value of array and its index, i.e. [max,i] return x.map(function(xi,i){return [xi,i]}).reduce(function(a,b){if(a[0]>b[0]){return a}else{return b}}) }, +not:function(x){ // negates Boolean value, or an array thereof + if(Array.isArray(x)){return x.map(function(xi){return jmat.not(xi)})} + else{return !x} +}, + parse:function(x){ // x is a stringified Object eval('var res='+x); return res; @@ -332,6 +358,13 @@ transpose:function (x){ // transposes 2D array return y }, +threshold:function(im,thr){ // image segmentation by thresholding, returns binary image matrix + if(!im.width){var dt=im} + else{dt=this.imData2data(im)} // in case im is an imageData object + if(!thr){thr = jmat.max(jmat.catArray(dt))/2} // default threshold is 1/10 of maximum, write something better later + return jmat.imMap(dt,function(xy){return (xy>thr)}); // threshold value, thr, is passed to the function through a closure +}, + uid:function(prefix){ if(!prefix){prefix='UID'} var uid=prefix+Math.random().toString().slice(2); From fbff36a11b66f7024cc348f34787657cdaa64e5a Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Tue, 10 Jan 2012 16:03:08 -0600 Subject: [PATCH 22/62] plot started --- jmat.js | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/jmat.js b/jmat.js index b3e4a50..92ae731 100644 --- a/jmat.js +++ b/jmat.js @@ -48,6 +48,11 @@ cEl:function(x,id){ return x }, +class:function(x){ + if(!x.constructor){return null} + else{return x.constructor.name} +}, + clone:function(x){ // clone object without functional elements return JSON.parse(JSON.stringify(x)) }, @@ -258,6 +263,84 @@ parseUrl:function(url){ // parsing url and its arguments out return u }, +plot:function(ctx,x,y,s,opt){ // plot +if(this.class(ctx)!="CanvasRenderingContext2D"){ // get context then + switch (this.class(ctx)){ + case "String": + ctx=jmat.gId(ctx).getContext('2d'); + break; + case "HTMLCanvasElement": + // assume it is a canvas element + ctx=ctx.getContext('2d'); + break; + } + + } + //default opt + var opt0={ + MarkerSize:12, + Color:[0,0,1], + MarkerEdgeColor:'auto', + MarkerFaceColor:'none', + x:x, + y:y + } + if(!opt){opt=opt0}; + opt = jmat.cat(opt0,opt); + // inherit colors + if (typeof(opt.MarkerEdgeColor)=='string'){ + if(opt.MarkerEdgeColor=='auto'){opt.MarkerEdgeColor=opt.Color} + else{opt.MarkerEdgeColor=[0,0,0,0]} + } + if (typeof(opt.MarkerFaceColor)=='string'){ + if(opt.MarkerFaceColor=='auto'){opt.MarkerFaceColor=opt.Color} + else{opt.MarkerFaceColor=[0,0,0,0]} // string is 'none' + } + if(opt.Color.length==3){opt.Color} + var L=opt.MarkerSize; + switch(s){ + case 'o': // draw a circle + ctx.beginPath(); + ctx.strokeStyle=jmat.rgba(opt.MarkerEdgeColor); + ctx.arc(x,y,L/2,0,2*Math.PI,true); + ctx.closePath(); + ctx.stroke(); + break; + case 's': // draw a square + ctx.beginPath(); + ctx.strokeStyle=jmat.rgba(opt.MarkerEdgeColor); + ctx.strokeRect(x-L/2,y-L/2,L,L); + ctx.closePath(); + ctx.stroke(); + break; + case '+': // draw a + + ctx.beginPath(); + ctx.strokeStyle=jmat.rgba(opt.MarkerEdgeColor); + ctx.moveTo(x-L/2,y);ctx.lineTo(x+L/2,y); + ctx.moveTo(x,y-L/2);ctx.lineTo(x,y+L/2); + ctx.closePath(); + ctx.stroke(); + break; + case 'x': // draw a x + ctx.beginPath(); + ctx.strokeStyle=jmat.rgba(opt.MarkerEdgeColor); + ctx.moveTo(x-L/2,y-L/2);ctx.lineTo(x+L/2,y+L/2); + ctx.moveTo(x-L/2,y+L/2);ctx.lineTo(x+L/2,y-L/2); + ctx.closePath(); + ctx.stroke(); + break; + case '*': // draw a * + this.plot(ctx,x,y,'+',opt); + this.plot(ctx,x,y,'x',opt); + break; + } + // return handle structure + opt.x=x; + opt.y=y; + opt.radius=opt.MarkerSize; + return opt +}, + ranksum:function(x,y){ // this is just a first approximation while something saner emerges for stats var s=x.map(function(xi){return y.map(function(yi){return [yi>xi,yi Date: Thu, 12 Jan 2012 22:47:34 -0600 Subject: [PATCH 23/62] arrayfun, imbw --- jmat.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/jmat.js b/jmat.js index 92ae731..33c96e5 100644 --- a/jmat.js +++ b/jmat.js @@ -1,6 +1,11 @@ console.log('jmat :-)') jmat = { + +abs:function(x){ // absolute value + if (Array.isArray(x)){return x.map(function(xi){return jmat.abs(xi)})} + else{return Math.abs(x)} +}, array2mat:function(x){ // to handle indexed arrays by converting them into two separate numerically indexed arrays var j = 0, y1=[], y2=[]; @@ -21,6 +26,11 @@ array2str:function(x,sp){ // convert array into a sp separated return y }, +arrayfun:function(x,fun){ // apply function to each element of an array + if (Array.isArray(x)){return x.map(function(xi){return jmat.arrayfun(xi,fun)})} + else{return fun(x)} +}, + bin2dec:function(x){ var n=x.length; return x.split('').map(function(xi,i){return xi*Math.pow(2,n-i-1)}).reduce(function(a,b){return a+b}); @@ -191,6 +201,14 @@ imMap:function(im,fun){ // applies function to all pixels of an image and return }) }, +im2bw:function(im,thr){ // segments 2d matrix into 0's and 1's for values below or above a threshold + return jmat.imMap(im,function(xy){ + if(xy>=thr){return 1} + else{return 0} + } + ) +}, + length:function(x){ // js Array.length returns highest index, not always the numerical length var n=0 for(var i in x){n++}; @@ -331,6 +349,7 @@ if(this.class(ctx)!="CanvasRenderingContext2D"){ // get context then break; case '*': // draw a * this.plot(ctx,x,y,'+',opt); + opt.MarkerSize=L*Math.cos(Math.PI/4); this.plot(ctx,x,y,'x',opt); break; } From 067c04f4be9069bf89d69101b993d371421e9c93 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Sun, 22 Jan 2012 15:58:59 -0600 Subject: [PATCH 24/62] jmat.load unload and on error function calls added --- jmat.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index 33c96e5..3103be4 100644 --- a/jmat.js +++ b/jmat.js @@ -161,6 +161,10 @@ gId:function(x){ // x is the id of an existing DOM element return document.getElementById(x) }, +im1to255:function(x){// converts {0-1} matrix into an im data matrix + 4 +}, + imread:function(cv){ // reads image from context into matrix // find out what type of input if(typeof(cv)=='string'){ // cv is the id of a canvas element @@ -215,12 +219,15 @@ length:function(x){ // js Array.length returns highest index, not always the num return n }, -load:function(url){ // load script / JSON +load:function(url,cb,er){ // load script / JSON var s = document.createElement('script'); s.src=url; s.id = this.uid(); + if(cb){s.onload=cb} + if(er){s.onerror=er} document.body.appendChild(s); setTimeout('document.body.removeChild(document.getElementById("'+s.id+'"));',30000); // is the waiting still needed ? + return s.id }, loadFiles:function(files,readAs,callback){ From 94eece67f53ee703a0d561ae86445d6befa13ed9 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Tue, 24 Jan 2012 13:21:57 -0600 Subject: [PATCH 25/62] funTable added --- funTable.html | 19 +++++++++++++++++++ funTable.js | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ jmat.js | 6 ++++++ 3 files changed, 75 insertions(+) create mode 100644 funTable.html create mode 100644 funTable.js diff --git a/funTable.html b/funTable.html new file mode 100644 index 0000000..c9c413e --- /dev/null +++ b/funTable.html @@ -0,0 +1,19 @@ + + +

Fun With Tables

+ + +
+
+ +
+
+ +
+ + + + + + + \ No newline at end of file diff --git a/funTable.js b/funTable.js new file mode 100644 index 0000000..5e3c39b --- /dev/null +++ b/funTable.js @@ -0,0 +1,50 @@ +console.log('fun with tables (funTable) loaded'); + +funTable={ + loadFiles:function(files,readAs,callback){ + // + if(!readAs){readAs='readAsDataURL'} // default is to read as dataURL + for(var i=0;i Date: Tue, 24 Jan 2012 13:29:44 -0600 Subject: [PATCH 26/62] mergingTables --- mergingTables.html | 13 +++++++++++++ mergingTables.js | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 mergingTables.html create mode 100644 mergingTables.js diff --git a/mergingTables.html b/mergingTables.html new file mode 100644 index 0000000..f5bf35f --- /dev/null +++ b/mergingTables.html @@ -0,0 +1,13 @@ + + +Merging tables: + + + + +
ABf(A,B)
+ + + + + \ No newline at end of file diff --git a/mergingTables.js b/mergingTables.js new file mode 100644 index 0000000..6b80967 --- /dev/null +++ b/mergingTables.js @@ -0,0 +1,13 @@ +console.log('mergingTables loaded'); + +mTable={ + dir:function(){ // list all txt documents + //fr=jmat.gId('loadingFrame'); + + }, + read:function(src){ // read source + fr=jmat.gId('loadingFrame'); + fr.src='.'; + + } +} \ No newline at end of file From e1e7b9dac21598508f7ff3e24959cfd582036cb0 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Fri, 3 Feb 2012 16:38:33 -0600 Subject: [PATCH 27/62] rand and textread --- jmat.js | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/jmat.js b/jmat.js index 2c84bac..074e64c 100644 --- a/jmat.js +++ b/jmat.js @@ -125,6 +125,30 @@ dotFun:function(A,B,fun){ // dot matrix function 4; }, +dimFun:function(){ // first argument is the function, subsequent arguments specify dimensions + if(arguments.length==0){arguments=[function(){return 0}]} + var fun=arguments[0]; + if(arguments.length>1){ + if(Array.isArray(arguments[1])){var x = arguments[1]} + else{var x=[];for(var i=1;ib[0]){return a}else{return b}}) }, +memb:function(x,dst){ // builds membership function + if(!dst){ + + } + +}, + not:function(x){ // negates Boolean value, or an array thereof if(Array.isArray(x)){return x.map(function(xi){return jmat.not(xi)})} else{return !x} @@ -367,6 +403,28 @@ if(this.class(ctx)!="CanvasRenderingContext2D"){ // get context then return opt }, +rand:function(){ + if(arguments.length>0){ + if(Array.isArray(arguments[0])){var x = arguments[0]} + else{var x=[];for(var i=0;ixi,yi Date: Fri, 3 Feb 2012 17:10:07 -0600 Subject: [PATCH 28/62] dimFun + zeros, ones and rand rewritten o use it --- jmat.js | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/jmat.js b/jmat.js index 074e64c..107a48f 100644 --- a/jmat.js +++ b/jmat.js @@ -129,7 +129,7 @@ dimFun:function(){ // first argument is the function, subsequent arguments speci if(arguments.length==0){arguments=[function(){return 0}]} var fun=arguments[0]; if(arguments.length>1){ - if(Array.isArray(arguments[1])){var x = arguments[1]} + if(typeof(arguments[1])!='number'){var x = [];for(var i=0;i Date: Wed, 8 Feb 2012 14:16:59 -0600 Subject: [PATCH 29/62] webrw redirected to webrw.no.de --- jmat.js | 56 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/jmat.js b/jmat.js index 107a48f..d3d0c8f 100644 --- a/jmat.js +++ b/jmat.js @@ -26,9 +26,9 @@ array2str:function(x,sp){ // convert array into a sp separated return y }, -arrayfun:function(x,fun){ // apply function to each element of an array - if (Array.isArray(x)){return x.map(function(xi){return jmat.arrayfun(xi,fun)})} - else{return fun(x)} +arrayfun:function(x,fun,i){ // apply function to each element of an array + if (Array.isArray(x)){return x.map(function(xi,i){return jmat.arrayfun(xi,fun,i)})} + else{return fun(x,i)} }, bin2dec:function(x){ @@ -125,7 +125,7 @@ dotFun:function(A,B,fun){ // dot matrix function 4; }, -dimFun:function(){ // first argument is the function, subsequent arguments specify dimensions +dimfun:function(){ // first argument is the function, subsequent arguments specify dimensions if(arguments.length==0){arguments=[function(){return 0}]} var fun=arguments[0]; if(arguments.length>1){ @@ -141,7 +141,7 @@ dimFun:function(){ // first argument is the function, subsequent arguments speci var x0=x[0]; x=x.slice(1); for(var i=0;i Date: Mon, 13 Feb 2012 22:33:22 -0600 Subject: [PATCH 30/62] edge --- jmat.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/jmat.js b/jmat.js index d3d0c8f..9d1ada2 100644 --- a/jmat.js +++ b/jmat.js @@ -76,6 +76,12 @@ cloneArray:function(A){ else{return A} }, +colon:function(x){// equivalent to x(:) + var y=[]; // to have it in the scope + jmat.arrayfun(x,function(x){y[y.length]=x}); + return y; +}, + colormap:function(c){ if(!c){c='default'} switch(c){ @@ -149,6 +155,19 @@ dimfun:function(){ // first argument is the function, subsequent arguments speci return z }, +edge:function(M){//find edge in bidimensional binary matrix such as what is produced by im2bw + var n = M.length, m = M[0].length; + var E=M.map(function(x,i){return x.map(function(y,j){ + if((i>0)&&(i0)&&(jb[0]){return a}else{return b}}) }, +min:function(x){ //return maximum value of array + return x.reduce(function(a,b){if(a Date: Tue, 21 Feb 2012 08:38:36 -0600 Subject: [PATCH 31/62] imhalve and prod --- jmat.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/jmat.js b/jmat.js index 9d1ada2..a22bd22 100644 --- a/jmat.js +++ b/jmat.js @@ -218,6 +218,29 @@ imread:function(cv){ // reads image from context into matrix return this.imData2data(imData) }, +imhalve:function(dt0,PSmax){ // poor man's version of imresize, it halves an image size by averaging two rows/columns + var s = jmat.size(dt0); + if(!PSmax){PSmax = jmat.prod(s.slice(0,2))-1} // if maximum size not defined then just have it once + if(jmat.prod(s.slice(0,2))>PSmax){ + if(jmat.length(s)!==3){throw('this should be an image value matrix, size n x m x 4')} + if(s[2]!==4){throw('this should be an image value matrix, size n x m x 4')} + s = jmat.arrayfun(s,function(x){return Math.floor(x/2)}); // half size, with floored integers + s[2]=4; // rgba + var dt = jmat.zeros(s[0],s[1],s[2]); + dt=dt.map(function(x,i){ + return x.map(function(y,j){ + return y.map(function(z,k){ + return (dt0[i*2][j*2][k]+dt0[i*2+1][j*2+1][k]+dt0[i*2][j*2+1][k])/3; + }) + }) + }); + } + else{var dt = dt0}; + // if maximum pixel size was set and was exceeded keep halving + if(jmat.prod(jmat.size(dt).slice(0,2))>PSmax){dt = jmat.imhalve(dt,PSmax)} + return dt +}, + imwrite:function(cv,im,dx,dy){ if(!dy){dx=0;dy=0} // default location if(typeof(cv)=='string'){cv=jmat.gId(cv)} //cv can also be the id of a canvas element @@ -487,6 +510,8 @@ if(this.class(ctx)!="CanvasRenderingContext2D"){ // get context then return opt }, +prod:function(x){return x.reduce(function(a,b){return a*b})}, + rand:function(){ return jmat.dimfun(function(){return Math.random()},arguments) }, @@ -499,6 +524,7 @@ ranksum:function(x,y){ // this is just a first approximation while something san reval:function(x,fun,callback,url){ if (!Array.isArray(x)){x=[x]} // make sure x is an array if (!Array.isArray(fun)){fun=[fun]} // make sure it is an array of functions + if (!callback){callback=function(x){console.log(x)}} if (!url){url=this.webrwUrl}; //if (!Array.isArray(fun)){fun=[fun]} // make sure it is an array of functions // create webrw jobList @@ -510,6 +536,7 @@ reval:function(x,fun,callback,url){ for (var i=jmat.reval.jobs[uid].x.length;i Date: Wed, 22 Feb 2012 13:57:37 -0600 Subject: [PATCH 32/62] testing server side script loading from node --- lala.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 lala.js diff --git a/lala.js b/lala.js new file mode 100644 index 0000000..0ae9f76 --- /dev/null +++ b/lala.js @@ -0,0 +1 @@ +exports.lala=function(x){return 2*x} \ No newline at end of file From fc14cdd03dd9a5bbaabaa7e9b87348825136c5f6 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Fri, 2 Mar 2012 01:45:01 -0600 Subject: [PATCH 33/62] loadScripts and improved sum --- jmat.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index a22bd22..d68d648 100644 --- a/jmat.js +++ b/jmat.js @@ -345,6 +345,12 @@ load:function(url,cb,er){ // load script / JSON return s.id }, +loadScripts:function(urls,cb,er){ // loading multiple scripts sequentially, runn callback after the last one is loaded + console.log('loading script '+urls[0]+' ...'); + if (urls.length>1){jmat.load(urls[0],function(){jmat.loadScripts(urls.slice(1))})} // recursion + else {jmat.load(urls[0],cb,er)} +}, + loadFiles:function(files,readAs,callback){ // //<-- example of button for reading text files if(!readAs){readAs='readAsDataURL'} // default is to read as dataURL @@ -595,7 +601,10 @@ sort:function(x){ // [y,I]=sort(x), where y is the sorted array and I contains t return this.transpose(x) }, -sum:function(x){return x.reduce(function(a,b){return a+b})}, +sum:function(x){ + if(Array.isArray(x[0])){return x.map(function(xi){return jmat.sum(xi)})} + else{return x.reduce(function(a,b){return a+b})}; +}, str2num:function(x){ return JSON.parse(x); From 4c2980f17b08879ea4827b78f78efc016f6cbb13 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Sat, 3 Mar 2012 00:16:50 -0600 Subject: [PATCH 34/62] extraction of segmented features: extractSegs --- jmat.js | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/jmat.js b/jmat.js index d68d648..342c6dc 100644 --- a/jmat.js +++ b/jmat.js @@ -168,6 +168,30 @@ edge:function(M){//find edge in bidimensional binary matrix such as what is prod return E }, +extractSegs:function(bw){ // extracts segmented features from a [0,1] matrix and retruns them as an Array + if(typeof(segFeatures)=='undefined'){var segFeatures=[]} // collect extracted features here + var m = jmat.max2(bw); + var n = jmat.size(bw); + while(m[0]>0){ // extract this feature + var C=[1,0,0]; // always use yellow + //jmat.plot(cvTop,m[1][1],m[1][0],'s',{Color:[1,1,0],MarkerSize:30}); + var extractSeg = function(x,y,S){ // bw is passed in the scope of extractSegs + if(typeof(S)=='undefined'){var S=[]} // collect feature's positions + S[S.length]=[x,y];bw[x][y]=0; + // check which neighbors are >0 and take them out too + var xi,yi; + if(x>0){xi=x-1;yi=y;if(bw[xi][yi]>0){S=extractSeg(xi,yi,S)}} + if(x0){S=extractSeg(xi,yi,S)}} + if(y>0){xi=x;yi=y-1;if(bw[xi][yi]>0){S=extractSeg(xi,yi,S)}} + if(y0){S=extractSeg(xi,yi,S)}} + return S; + } + segFeatures[segFeatures.length]=extractSeg(m[1][0],m[1][1]);//extraction starts with coordiantes ofmaximum value + m = jmat.max2(bw); + } + return segFeatures.map(function(si){return jmat.transpose(si)}) +}, + get:function(key,callback,url){ // get content at url or key if (!callback){callback=function(x){console.log(x)}} if (!url){url=this.webrwUrl}; @@ -383,11 +407,19 @@ log:function(x,n){ }, max:function(x){ //return maximum value of array - return x.reduce(function(a,b){if(a>b){return a}else{return b}}) + if(Array.isArray(x[0])){return x.map(function(xi){return jmat.max(xi)})} + else{return x.reduce(function(a,b){if(a>b){return a}else{return b}})}; + //return x.reduce(function(a,b){if(a>b){return a}else{return b}}) }, max2:function(x){ // returns maximum value of array and its index, i.e. [max,i] - return x.map(function(xi,i){return [xi,i]}).reduce(function(a,b){if(a[0]>b[0]){return a}else{return b}}) + if(Array.isArray(x[0])){ // coded only up to 2 dimensions + var xx = jmat.transpose(x.map(function(xi){return jmat.max2(xi)})) + var y = jmat.max2(xx[0]); + return [y[0],[y[1],xx[1][y[1]]]]; + } + else{return x.map(function(xi,i){return [xi,i]}).reduce(function(a,b){if(a[0]>b[0]){return a}else{return b}})}; + //return x.map(function(xi,i){return [xi,i]}).reduce(function(a,b){if(a[0]>b[0]){return a}else{return b}}) }, min:function(x){ //return maximum value of array From 4ec7931d17ccc17d27e724d51ae0342b871bc98a Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 12 Mar 2012 15:49:41 -0500 Subject: [PATCH 35/62] shorten numbers and strings, also of arrays thereof --- jmat.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/jmat.js b/jmat.js index 342c6dc..3ae6594 100644 --- a/jmat.js +++ b/jmat.js @@ -618,6 +618,14 @@ set:function(val,callback,key,url){ // set key-val pairs in the webrw endpoint, return uid; }, +shorten:function(x,n){ // shortens numbers or strings + if (Array.isArray(x)){return x.map(function(xi){return jmat.shorten(xi,n)})} + else { + if(typeof(x)=='number'){x +=''} + return x.slice(0,n); + } +}, + size:function(x){ var L=function(y){ s[s.length]=y.length; From a6ad08a207e4f9d42efa94e1a3b5ceb99bc90bb1 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 19 Mar 2012 16:44:04 -0500 Subject: [PATCH 36/62] compress and decompress --- jmat.js | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/jmat.js b/jmat.js index 3ae6594..61d37ec 100644 --- a/jmat.js +++ b/jmat.js @@ -82,6 +82,78 @@ colon:function(x){// equivalent to x(:) return y; }, +compress: function (uncompressed) { // Source: http://rosettacode.org/wiki/LZW_compression#JavaScript + uncompressed = this.stringify(uncompressed); // this is new - such that we are sompressing JS objects, not strings + // Build the dictionary. + var i, + dictionary = {}, + c, + wc, + w = "", + result = [], + dictSize = 256; + for (i = 0; i < 256; i += 1) { + dictionary[String.fromCharCode(i)] = i; + } + + for (i = 0; i < uncompressed.length; i += 1) { + c = uncompressed.charAt(i); + wc = w + c; + if (dictionary[wc]) { + w = wc; + } else { + result.push(dictionary[w]); + // Add wc to the dictionary. + dictionary[wc] = dictSize++; + w = String(c); + } + } + + // Output the code for w. + if (w !== "") { + result.push(dictionary[w]); + } + return result; + }, + +decompress: function (compressed) { + "use strict"; + // Build the dictionary. + var i, + dictionary = [], + w, + result, + k, + entry = "", + dictSize = 256; + for (i = 0; i < 256; i += 1) { + dictionary[i] = String.fromCharCode(i); + } + + w = String.fromCharCode(compressed[0]); + result = w; + for (i = 1; i < compressed.length; i += 1) { + k = compressed[i]; + if (dictionary[k]) { + entry = dictionary[k]; + } else { + if (k === dictSize) { + entry = w + w.charAt(0); + } else { + return null; + } + } + + result += entry; + + // Add w+entry[0] to the dictionary. + dictionary[dictSize++] = w + entry.charAt(0); + + w = entry; + } + return this.parse(result); + }, + colormap:function(c){ if(!c){c='default'} switch(c){ @@ -582,6 +654,14 @@ revalSet:function(uid){ // set job for remote evaluation, task is the key of the console.log(uid); }, +require:function(url){ // checking if I got the require mechanism correctly + jmat.load(url,function(){ + 4 + } + ) + 4 +}, + revalGet:function(task){ // 4; }, From d1ecfda86aace535db31441306f38dedeb85ac6d Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Tue, 24 Apr 2012 18:52:02 -0500 Subject: [PATCH 37/62] find and lookUp --- jmat.js | 99 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 85 insertions(+), 14 deletions(-) diff --git a/jmat.js b/jmat.js index 61d37ec..7ac1867 100644 --- a/jmat.js +++ b/jmat.js @@ -166,6 +166,26 @@ colormap:function(c){ return c }, +d3:{ + figure:function(id,type){ // create figure by appending d3's svg element to DOM element with specified id + if (typeof(id)==='undefined'){ + var fig = d3.select("body").append("div"); + fig.id = jmat.uid('fig'); + } + else{ + if(jmat.gId(id)!=null){var fig = d3.select('#'+id);} // if it exists + else {var fig = this.figure();fig[0][0].id = id} // otherwise create it + } + + if (typeof(type)==='string'){ + fig.attr('class',type); // possibilities: "chart", + } + this.gcf=fig; + return fig; + }, + +}, + data2imData:function(data){ // the reverse of im2data, data is a matlabish set of 4 2d matrices, with the r, g, b and alpha values var n=data.length, m=data[0].length; //var imData = {width:m, height:n, data:[]}; @@ -264,6 +284,28 @@ extractSegs:function(bw){ // extracts segmented features from a [0,1] matrix and return segFeatures.map(function(si){return jmat.transpose(si)}) }, +fieldnames:function(x){ + y=[];i=0; + for(var f in x){ + y[i]=f; + i++; + } + return y; +}, + +find:function(x,patt,modifier){ // find wich elements of an array match a pattern + if(!modifier){modifier='gi'}// default is global and case insensitive + var y = []; + if(Array.isArray(patt)){patt='('+patt.join(')|(')+')'} // allows multiple patterns + patt = new RegExp(patt,modifier); + var M + for(var i in x){ + M=x[i].match(patt); + if(!!M){y.push(i)} + } + return y +}, + get:function(key,callback,url){ // get content at url or key if (!callback){callback=function(x){console.log(x)}} if (!url){url=this.webrwUrl}; @@ -278,15 +320,6 @@ get:function(key,callback,url){ // get content at url or key return uid; }, -fieldnames:function(x){ - y=[];i=0; - for(var f in x){ - y[i]=f; - i++; - } - return y; -}, - gId:function(x){ // x is the id of an existing DOM element // return null if neither id nor class are found // so constructs like !jmat.gId(someID) can be used @@ -350,13 +383,14 @@ image:function(cv,im,dx,dy){ // for consistency return this.imwrite(cv,im,dx,dy); }, -imagesc:function(cv,dt,cm,fun){ // scales values to use full range of values. cv is the canvas, dt the data, and cm the colormap +imagesc:function(cv,dt,cm,fun,M){ // scales values to use full range of values. cv is the canvas, dt the data, and cm the colormap if(!cm){cm=jmat.colormap()} if(!fun){fun=function(){return 1}}; // opaque function cm = jmat.transpose(cm); // to get one vector per channel var n = cm[0].length-1; // should be 64-1=63 var I = jmat.dimfun(function(i){return i/(n)},n+1); // 64 numbers evenly spaced between 0 and 1 - var M = jmat.max(jmat.max(dt)); + if(!M){M = jmat.max(jmat.max(dt))}; + if(typeof(fun)=='string'){eval('fun='+fun)} // allow eval fun with transparencies dt = jmat.arrayfun(dt,function(x){return [jmat.interp1(I,cm[0],[x/M])[0],jmat.interp1(I,cm[1],[x/M])[0],jmat.interp1(I,cm[2],[x/M])[0],fun(x)]}); dt = jmat.arrayfun(dt,function(x){return Math.round(255*x)}); if(!!cv){jmat.imwrite(cv,dt)}; @@ -434,10 +468,10 @@ load:function(url,cb,er){ // load script / JSON var s = document.createElement('script'); s.src=url; s.id = this.uid(); - if(cb){s.onload=cb} - if(er){s.onerror=er} + if(!!cb){s.onload=cb} + if(!!er){s.onerror=er} document.body.appendChild(s); - setTimeout('document.body.removeChild(document.getElementById("'+s.id+'"));',30000); // is the waiting still needed ? + setTimeout('document.body.removeChild(document.getElementById("'+s.id+'"));',3000); // is the waiting still needed ? return s.id }, @@ -473,11 +507,48 @@ readFile:function(f,readAs,callback){ reader[readAs](f); }, +loadD3:function(callback){ // loads d3.js library + //jmat.load('http://mbostock.github.com/d3/d3.v2.js',callback); + jmat.load('d3.v2.min.js',callback); +}, + log:function(x,n){ if (!n){return Math.log(x)} else{return Math.log(x)/Math.log(n)} }, +lookUp:function(tbl,col_in,val_in,col_out){// lookup in table tbl, + // for value in column col_out where the column col_in has the value val_in + var val_out={};// return results as a table + // Find Columns + var col_in_i=this.find(tbl.cols,col_in); + if(col_in_i.length==0){throw('input column not found')} + // if output columns not specified use the same as the input cols + if(!col_out){col_out=col_in;var col_out_i=col_in_i} + else{var col_out_i=this.find(tbl.cols,col_out)} + // Find which rows have those values + var rows = jmat.transpose(tbl.rows) , r=[] , Ind=[]; + for(var c in col_in_i){ + r=jmat.find(rows[col_in_i[c]],val_in); + if(r.length>0){for (var i in r){Ind.push(r[i])}} + } + Ind = jmat.unique(Ind); + val_out.cols=col_out_i.map(function(i){return tbl.cols[i]}); + val_out.rows=jmat.zeros(col_out_i.length,Ind.length); + for(var i=0;ib){return a}else{return b}})}; From b33636531dc1cbbc749fe857011ffb30ecab813f Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Thu, 26 Apr 2012 15:27:00 -0500 Subject: [PATCH 38/62] lookup finished --- jmat.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jmat.js b/jmat.js index 7ac1867..fe8745d 100644 --- a/jmat.js +++ b/jmat.js @@ -517,7 +517,7 @@ log:function(x,n){ else{return Math.log(x)/Math.log(n)} }, -lookUp:function(tbl,col_in,val_in,col_out){// lookup in table tbl, +lookup:function(tbl,col_in,val_in,col_out){// lookup in table tbl, // for value in column col_out where the column col_in has the value val_in var val_out={};// return results as a table // Find Columns @@ -527,14 +527,14 @@ lookUp:function(tbl,col_in,val_in,col_out){// lookup in table tbl, if(!col_out){col_out=col_in;var col_out_i=col_in_i} else{var col_out_i=this.find(tbl.cols,col_out)} // Find which rows have those values - var rows = jmat.transpose(tbl.rows) , r=[] , Ind=[]; + var rows = this.transpose(tbl.rows) , r=[] , Ind=[]; for(var c in col_in_i){ - r=jmat.find(rows[col_in_i[c]],val_in); + r=this.find(rows[col_in_i[c]],val_in); if(r.length>0){for (var i in r){Ind.push(r[i])}} } - Ind = jmat.unique(Ind); + Ind = this.unique(Ind); val_out.cols=col_out_i.map(function(i){return tbl.cols[i]}); - val_out.rows=jmat.zeros(col_out_i.length,Ind.length); + val_out.rows=this.zeros(col_out_i.length,Ind.length); for(var i=0;i Date: Tue, 1 May 2012 16:34:25 -0500 Subject: [PATCH 39/62] Added an "extractSegs2" function for comparison --- jmat.js | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index fe8745d..f411c00 100644 --- a/jmat.js +++ b/jmat.js @@ -284,6 +284,89 @@ extractSegs:function(bw){ // extracts segmented features from a [0,1] matrix and return segFeatures.map(function(si){return jmat.transpose(si)}) }, + extractSegs2: function (bw) { + // This function was written by Sean Wilkinson as a variation on a theme + // of segmentation extraction from binary matrices. It returns a matrix + // whose elements' entries represent membership in a numbered partition. + // I have actually enclosed my entire "count_nuclei.js" here as a single + // function to be optimized and rewritten at some point in the future to + // take advantage of functionality that 'jmat' already provides :-) + var col, cols, isSpecial, neighborhood, partition, row, rows, + traced_image; + cols = bw[0].length; + isSpecial = function (pixel) { + // This function needs documentation. + return (pixel === 1); + }; + neighborhood = function (row, col) { + // This function needs documentation. + var ball, flag, i, temp; + ball = []; + temp = [ + [row + 1, col + 0], //- North + [row + 1, col + 1], //- North-East + [row + 0, col + 1], //- East + [row - 1, col + 1], //- South-East + [row - 1, col + 0], //- South + [row - 1, col - 1], //- South-West + [row + 0, col - 1], //- West + [row + 1, col - 1] //- North-West + ]; + for (i = 0; i < 8; i += 1) { + flag = ((0 <= temp[i][0]) && + (temp[i][0] < rows) && + (0 <= temp[i][1]) && + (temp[i][1] < cols)); + if (flag === true) { + ball.push(temp[i]); + } + } + ball.push(ball[0]); + return ball; + }; + partition = 0; + rows = bw.length; + // First, preallocate a two-dimensional array with null values ... + traced_image = new Array(rows); + for (row = 0; row < rows; row += 1) { + traced_image[row] = new Array(cols); + for (col = 0; col < cols; col += 1) { + traced_image[row][col] = null; + } + } + // Then, start hunting for "black" pixels ... + for (row = 0; row < rows; row += 1) { + for (col = 0; col < cols; col += 1) { + if (traced_image[row][col] === null) { + if (isSpecial(bw[row][col])) { + partition += 1; + traced_image[row][col] = partition; + (function cover(ball) { + // This function needs documentation. + var col, i, row; + for (i = 0; i < ball.length; i += 1) { + row = ball[i][0]; + col = ball[i][1]; + if (traced_image[row][col] === null) { + if (isSpecial(bw[row][col])) { + traced_image[row][col] = partition; + cover(neighborhood(row, col)); + } else { + traced_image[row][col] = 0; + } + } + } + return; + }(neighborhood(row, col))); + } else { + traced_image[row][col] = 0; + } + } + } + } + return traced_image; + }, + fieldnames:function(x){ y=[];i=0; for(var f in x){ @@ -892,4 +975,4 @@ zeros:function(){ webrwUrl:'http://webrw.no.de', -} \ No newline at end of file +} From 567f9cff3318422b25fecd3a214ed2ab1f63e584 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 21 May 2012 16:43:33 -0500 Subject: [PATCH 40/62] transposing rows of lookup table --- jmat.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index fe8745d..930f74f 100644 --- a/jmat.js +++ b/jmat.js @@ -260,6 +260,11 @@ edge:function(M){//find edge in bidimensional binary matrix such as what is prod return E }, +exist:function(x){ // does it exist? note x is the variable name, not the variable itself + if(eval('typeof('+x+')')=='undefined'){return false} + else{return true} +}, + extractSegs:function(bw){ // extracts segmented features from a [0,1] matrix and retruns them as an Array if(typeof(segFeatures)=='undefined'){var segFeatures=[]} // collect extracted features here var m = jmat.max2(bw); @@ -537,7 +542,7 @@ lookup:function(tbl,col_in,val_in,col_out){// lookup in table tbl, val_out.rows=this.zeros(col_out_i.length,Ind.length); for(var i=0;i Date: Mon, 21 May 2012 16:50:34 -0500 Subject: [PATCH 41/62] oops, transposition was unecessary --- jmat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jmat.js b/jmat.js index 930f74f..ab2a617 100644 --- a/jmat.js +++ b/jmat.js @@ -542,7 +542,7 @@ lookup:function(tbl,col_in,val_in,col_out){// lookup in table tbl, val_out.rows=this.zeros(col_out_i.length,Ind.length); for(var i=0;i Date: Mon, 21 May 2012 16:54:35 -0500 Subject: [PATCH 42/62] lets try transposition again for lookup --- jmat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jmat.js b/jmat.js index ab2a617..a005c81 100644 --- a/jmat.js +++ b/jmat.js @@ -539,10 +539,10 @@ lookup:function(tbl,col_in,val_in,col_out){// lookup in table tbl, } Ind = this.unique(Ind); val_out.cols=col_out_i.map(function(i){return tbl.cols[i]}); - val_out.rows=this.zeros(col_out_i.length,Ind.length); + val_out.rows=this.zeros(Ind.length,col_out_i.length); for(var i=0;i Date: Tue, 19 Jun 2012 00:40:42 -0500 Subject: [PATCH 43/62] 1st version of fminSearch --- jmat.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/jmat.js b/jmat.js index a005c81..20f3f00 100644 --- a/jmat.js +++ b/jmat.js @@ -311,6 +311,40 @@ find:function(x,patt,modifier){ // find wich elements of an array match a patter return y }, +fminsearch:function(fun,Parm0,x,y,objFun,Opt){// fun = function(x,Parm) + // default Objective function is the sum of squared deviations + if(!objFun){objFun=function(y,yp){return jmat.sum(y.map(function(yi,i){return Math.pow((yi-yp[i]),2)}))}} + if(!Opt){Opt={ // Default Options + maxIter:100, // maximum number of iterations + step:Parm0.map(function(p){return p/100}) // initial step is 1/100 of initial value (remember not to use zero in Parm0) + } + } + var ya,y0,yb,fP0,fP1; + var P0=jmat.clone(Parm0),P1=jmat.clone(Parm0); + var n = P0.length; + var step=Opt.step; + var funParm=function(P){return objFun(y,fun(x,P))}//function (of Parameters) to minimize + // silly multi-univariate screening + for(var i=0;i Date: Tue, 19 Jun 2012 13:37:37 -0500 Subject: [PATCH 44/62] fminsearch updated with a more flexible use of Options --- jmat.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/jmat.js b/jmat.js index 20f3f00..8da0e95 100644 --- a/jmat.js +++ b/jmat.js @@ -313,12 +313,20 @@ find:function(x,patt,modifier){ // find wich elements of an array match a patter fminsearch:function(fun,Parm0,x,y,objFun,Opt){// fun = function(x,Parm) // default Objective function is the sum of squared deviations + // example + // x = [32,37,42,47,52,57,62,67,72,77,82,87,92] + // y=[749,1525,1947,2201,2380,2537,2671,2758,2803,2943,3007,2979,2992] + // fun = function(x,P){return x.map(function(xi){return (P[0]+P[1]*(1-Math.exp(-P[2]*(xi-P[3]))))})} + // jmat.fminsearch(fun,[100,3000,1,30],x,y) if(!objFun){objFun=function(y,yp){return jmat.sum(y.map(function(yi,i){return Math.pow((yi-yp[i]),2)}))}} - if(!Opt){Opt={ // Default Options - maxIter:100, // maximum number of iterations - step:Parm0.map(function(p){return p/100}) // initial step is 1/100 of initial value (remember not to use zero in Parm0) - } - } + if(!Opt){Opt={}}; + if(!Opt.maxIter){Opt.maxIter=1000}; + if(!Opt.step){// initial step is 1/100 of initial value (remember not to use zero in Parm0) + Opt.step=Parm0.map(function(p){return p/100}); + Opt.step=Opt.step.map(function(si){if(si==0){return 1}else{ return si}}); // convert null steps into 1's + }; + if(!Opt.display){Opt.display=true}; + var ya,y0,yb,fP0,fP1; var P0=jmat.clone(Parm0),P1=jmat.clone(Parm0); var n = P0.length; @@ -335,11 +343,9 @@ fminsearch:function(fun,Parm0,x,y,objFun,Opt){// fun = function(x,Parm) } else{ step[j]=-(0.5*step[j]); // reverse and go slower - } - console.log(i,funParm(P0),P0); - //console.log(j,P0); - //console.log(step); + } } + if(Opt.display){if(i>(Opt.maxIter-10)){console.log(i+1,funParm(P0),P0)}} } return P0 }, From 2bab47bfeb21d96dd8b9988578089db1579920fa Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Tue, 19 Jun 2012 20:39:25 -0500 Subject: [PATCH 45/62] fminsearch mostly done, syntax stable --- jmat.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/jmat.js b/jmat.js index 8da0e95..7292068 100644 --- a/jmat.js +++ b/jmat.js @@ -311,27 +311,32 @@ find:function(x,patt,modifier){ // find wich elements of an array match a patter return y }, -fminsearch:function(fun,Parm0,x,y,objFun,Opt){// fun = function(x,Parm) - // default Objective function is the sum of squared deviations +fminsearch:function(fun,Parm0,x,y,Opt){// fun = function(x,Parm) // example + // // x = [32,37,42,47,52,57,62,67,72,77,82,87,92] // y=[749,1525,1947,2201,2380,2537,2671,2758,2803,2943,3007,2979,2992] // fun = function(x,P){return x.map(function(xi){return (P[0]+P[1]*(1-Math.exp(-P[2]*(xi-P[3]))))})} - // jmat.fminsearch(fun,[100,3000,1,30],x,y) - if(!objFun){objFun=function(y,yp){return jmat.sum(y.map(function(yi,i){return Math.pow((yi-yp[i]),2)}))}} + // Parms=jmat.fminsearch(fun,[100,3000,1,30],x,y) + // + // Opt is an object will all other parameters, from the objective function (cost function), to the + // number of iterations, initial step vector and the display switch, for example + // Parms=jmat.fminsearch(fun,[100,3000,1,30],x,y,{maxIter:5000,display:false}) + if(!Opt){Opt={}}; if(!Opt.maxIter){Opt.maxIter=1000}; if(!Opt.step){// initial step is 1/100 of initial value (remember not to use zero in Parm0) Opt.step=Parm0.map(function(p){return p/100}); Opt.step=Opt.step.map(function(si){if(si==0){return 1}else{ return si}}); // convert null steps into 1's }; - if(!Opt.display){Opt.display=true}; + if(typeof(Opt.display)=='undefined'){Opt.display=true}; + if(!Opt.objFun){Opt.objFun=function(y,yp){return jmat.sum(y.map(function(yi,i){return Math.pow((yi-yp[i]),2)}))}} var ya,y0,yb,fP0,fP1; var P0=jmat.clone(Parm0),P1=jmat.clone(Parm0); var n = P0.length; var step=Opt.step; - var funParm=function(P){return objFun(y,fun(x,P))}//function (of Parameters) to minimize + var funParm=function(P){return Opt.objFun(y,fun(x,P))}//function (of Parameters) to minimize // silly multi-univariate screening for(var i=0;i Date: Thu, 21 Jun 2012 10:24:15 -0500 Subject: [PATCH 46/62] cloneVector, fminsearch sped up a bit --- jmat.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/jmat.js b/jmat.js index 7292068..2fc4c76 100644 --- a/jmat.js +++ b/jmat.js @@ -76,6 +76,10 @@ cloneArray:function(A){ else{return A} }, +cloneVector:function(V){// fastar than cloneArray if your array only has one dimension + return V.map(function(v){return v}) +}, + colon:function(x){// equivalent to x(:) var y=[]; // to have it in the scope jmat.arrayfun(x,function(x){y[y.length]=x}); @@ -333,18 +337,18 @@ fminsearch:function(fun,Parm0,x,y,Opt){// fun = function(x,Parm) if(!Opt.objFun){Opt.objFun=function(y,yp){return jmat.sum(y.map(function(yi,i){return Math.pow((yi-yp[i]),2)}))}} var ya,y0,yb,fP0,fP1; - var P0=jmat.clone(Parm0),P1=jmat.clone(Parm0); + var P0=jmat.cloneVector(Parm0),P1=jmat.cloneVector(Parm0); var n = P0.length; var step=Opt.step; var funParm=function(P){return Opt.objFun(y,fun(x,P))}//function (of Parameters) to minimize // silly multi-univariate screening for(var i=0;i Date: Tue, 28 Aug 2012 15:05:06 -0500 Subject: [PATCH 47/62] updating tabular "cols" to "columns" to match Google's fusion tables new API --- jmat.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jmat.js b/jmat.js index 2fc4c76..abf3776 100644 --- a/jmat.js +++ b/jmat.js @@ -575,11 +575,11 @@ lookup:function(tbl,col_in,val_in,col_out){// lookup in table tbl, // for value in column col_out where the column col_in has the value val_in var val_out={};// return results as a table // Find Columns - var col_in_i=this.find(tbl.cols,col_in); + var col_in_i=this.find(tbl.columns,col_in); if(col_in_i.length==0){throw('input column not found')} - // if output columns not specified use the same as the input cols + // if output columns not specified use the same as the input columns if(!col_out){col_out=col_in;var col_out_i=col_in_i} - else{var col_out_i=this.find(tbl.cols,col_out)} + else{var col_out_i=this.find(tbl.columns,col_out)} // Find which rows have those values var rows = this.transpose(tbl.rows) , r=[] , Ind=[]; for(var c in col_in_i){ @@ -587,9 +587,9 @@ lookup:function(tbl,col_in,val_in,col_out){// lookup in table tbl, if(r.length>0){for (var i in r){Ind.push(r[i])}} } Ind = this.unique(Ind); - val_out.cols=col_out_i.map(function(i){return tbl.cols[i]}); + val_out.columns=col_out_i.map(function(i){return tbl.columns[i]}); val_out.rows=this.zeros(Ind.length,col_out_i.length); - for(var i=0;i Date: Tue, 4 Sep 2012 12:16:51 -0500 Subject: [PATCH 48/62] fminsearch playground --- fminsearch.html | 13 ++++++++ fminsearch.js | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 fminsearch.html create mode 100644 fminsearch.js diff --git a/fminsearch.html b/fminsearch.html new file mode 100644 index 0000000..16d8656 --- /dev/null +++ b/fminsearch.html @@ -0,0 +1,13 @@ + + + + + + +fminsearch :-) +
+ + + \ No newline at end of file diff --git a/fminsearch.js b/fminsearch.js new file mode 100644 index 0000000..904816f --- /dev/null +++ b/fminsearch.js @@ -0,0 +1,82 @@ +fminsearch=function(fun,Parm0,x,y,Opt){// fun = function(x,Parm) + // example + // + // x = [32,37,42,47,52,57,62,67,72,77,82,87,92];y=[749,1525,1947,2201,2380,2537,2671,2758,2803,2943,3007,2979,2992] + // fun = function(x,P){return x.map(function(xi){return (P[0]+1/(1/(P[1]*(xi-P[2]))+1/P[3]))})} + // Parms=jmat.fminsearch(fun,[100,30,10,5000],x,y) + // + // Another test: + // x=[32,37,42,47,52,57,62,67,72,77,82,87,92];y=[0,34,59,77,99,114,121,133,146,159,165,173,170]; + // + // Opt is an object will all other parameters, from the objective function (cost function), to the + // number of iterations, initial step vector and the display switch, for example + // Parms=fminsearch(fun,[100,30,10,5000],x,y,{maxIter:10000,display:false}) + + if(!Opt){Opt={}}; + if(!Opt.maxIter){Opt.maxIter=1000}; + if(!Opt.step){// initial step is 1/100 of initial value (remember not to use zero in Parm0) + Opt.step=Parm0.map(function(p){return p/100}); + Opt.step=Opt.step.map(function(si){if(si==0){return 1}else{ return si}}); // convert null steps into 1's + }; + if(typeof(Opt.display)=='undefined'){Opt.display=true}; + if(!Opt.objFun){Opt.objFun=function(y,yp){return y.map(function(yi,i){return Math.pow((yi-yp[i]),2)}).reduce(function(a,b){return a+b})}} //SSD + + var cloneVector=function(V){return V.map(function(v){return v})}; + var ya,y0,yb,fP0,fP1; + var P0=cloneVector(Parm0),P1=cloneVector(Parm0); + var n = P0.length; + var step=Opt.step; + var funParm=function(P){return Opt.objFun(y,fun(x,P))}//function (of Parameters) to minimize + // silly multi-univariate screening + for(var i=0;i(Opt.maxIter-10)){console.log(i+1,funParm(P0),P0)}} + } + if (!!document.getElementById('plot')){ // if there is then use it + fminsearch.plot(x,y,fun(x,P0),P0); + } + return P0 +}; + +fminsearch.load=function(src){ // script loading + // example: fminsearch.load('http://localhost:8888/jmat/jmat.js') + var s = document.createElement('script'); + s.src = src; + document.head.appendChild(s); + s.parentElement.removeChild(s); +}; + +fminsearch.plot=function(x,y,yp,Parms){ // ploting results using + // create Array in Google's format + var data = new google.visualization.DataTable(); + data.addColumn('number', 'X'); + data.addColumn('number', 'Observed'); + data.addColumn('number', 'Model fit'); + var n = x.length; + for (var i=0;i Date: Tue, 4 Sep 2012 12:58:37 -0500 Subject: [PATCH 49/62] demo included --- f.png | Bin 0 -> 6224 bytes fminsearch.html | 12 +++++++++++- fminsearch.js | 12 +++++++++--- 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 f.png diff --git a/f.png b/f.png new file mode 100644 index 0000000000000000000000000000000000000000..d730d995ee086a92c88e49b0c92ebd416167a0aa GIT binary patch literal 6224 zcmb_gg;N_&unxto5G;k_+M>l%ym)X6?(PJqxI>G(OL2k~C>ER|r37iQ;_g~p3Os)A zUwH3k_HJh9_HOT+oo{#VlbVVgJ`M#A006*;$V+QHuer}siiPn!SB|E>0RT`>?WCmC zAW~AaYHlvpc8*p6z?-Bv=#tBV7K!*L7sC=V@xuD}m!vUuP)&oj*Az8_7?70GJxPkT z(Lbyu!=BC*nzI7UlTOfrs~0YKH>kl4nAC|rk`#FTR}Duf-yoVFNT(S~L_OvuY*Vg6 z;jr2|&32=~)}*?i_dDKVC%^b5hIFzwG9l!q%V$RX1xX17nd!pXblBq`SS}>W%luRj zhMX@r2P5QWzMIhXE(>DLA3V8xYFCz{GUiJ<>WBtV|FsKFtrV^$pk0=|J$<|KVezlX zIu$2#w62*?`Ud-VUP>AQu;%_7^YoaK*(TO?rv3+B?psH^bIQ;r233xI3Ix(u-RmgZ z?6)pLRqbh<-$g+GukYWzvu);t_4b5mWAC9U!k}7*Hb_4gL)Z2VIdc%{-_AiprZ^ui ziLR_C+W_@L5btp^1)V)_p2LpZU#I?yzwNGkI5DojnQpM=gv|!;kmD~b4J|7 zH^rJ*zl=}S!qcrfsigg1#WV30ntsPS7SjES!c&nLh1W#|Q`baARZ3Nx(nx*vsod

d@PgcE-Duya->BRe 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 Cr}`}b literal 0 HcmV?d00001 diff --git a/fminsearch.html b/fminsearch.html index 16d8656..1f8a9b7 100644 --- a/fminsearch.html +++ b/fminsearch.html @@ -4,7 +4,17 @@ -fminsearch :-) +

+

fminsearch

+

(http://jmat.googlecode.com/git/fminsearch.html)
+ In the browser's console you could, for example, :
+

    +
  1. x=[32,37,42,47,52,57,62,67,72,77,82,87,92];y=[0,34,59,77,99,114,121,133,146,159,165,173,170]; // some data
  2. +
  3. fun = function(x,P){return x.map(function(xi){return (1/(1/(P[0]*(xi-P[1]))+1/P[2]))})}; // some model
  4. +
  5. P=fminsearch(fun,[34.6,32,173],x,y); // the regression with some starting values
  6. +
+

+
+fminsearch.plot=function(x,y,yp,Parms,id){ // ploting results using + // defaults + var titulo='Model fitting'; + if(!!Parms){titulo='Model parameters: '+Parms}; + if(!id){var id='plot'} // create Array in Google's format var data = new google.visualization.DataTable(); data.addColumn('number', 'X'); @@ -66,11 +70,8 @@ fminsearch.plot=function(x,y,yp,Parms){ // ploting results using + - here ! +Experimenting with 23andme \ No newline at end of file diff --git a/23andme.js b/23andme.js new file mode 100644 index 0000000..48c4573 --- /dev/null +++ b/23andme.js @@ -0,0 +1,20 @@ +//https://api.23andme.com/user/login/?redirect=/authorize/?redirect_uri=http://jmat.googlecode.com/git/23andme.html&response_type&code%26client_id=D09568fd79aa7911dad7727a024936f8d&scope=basic + +MB23={ // 23and me application document object model + code:null, + parms:{}, + search4parms:function(){ // gets parameters from call and pushes them to .parms + var parms = window.document.location.search.slice(1).split('&'); + parms.map(function(x){ + xx = x.split('='); + MB23.parms[xx[0]]=xx[1] + }) + + // + } +} + + + +// find out what is being provided and push it to parms +MB23.search4parms(); \ No newline at end of file From 5edb9cab17315b8f07e06796975fdec838bc801d Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 8 Oct 2012 13:25:47 -0500 Subject: [PATCH 58/62] jQuery added to 23andme app --- 23andme.html | 1 + 23andme.js | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/23andme.html b/23andme.html index 3143b9d..3db75dc 100644 --- a/23andme.html +++ b/23andme.html @@ -1,5 +1,6 @@ + diff --git a/23andme.js b/23andme.js index 48c4573..60bbb6b 100644 --- a/23andme.js +++ b/23andme.js @@ -17,4 +17,15 @@ MB23={ // 23and me application document object model // find out what is being provided and push it to parms -MB23.search4parms(); \ No newline at end of file +MB23.search4parms(); +if(!!MB23.parms.code){ + MB23.code=MB23.parms.code; + console.log('code = '+MB23.code); +} +else if (!!localStorage.getItem('code')){ // find out if there is one in the localstorage + MB23.code = localStorage.getItem('code'); + console.log('code = '+MB23.code); +} +else{ + throw('23andme access code not found :-(') +} \ No newline at end of file From a684cb79f52a0673655f344b90618cd080ddf044 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 8 Oct 2012 13:51:34 -0500 Subject: [PATCH 59/62] fixing jQuery call --- 23andme.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/23andme.html b/23andme.html index 3db75dc..ba39cc4 100644 --- a/23andme.html +++ b/23andme.html @@ -1,9 +1,9 @@ - - + Experimenting with 23andme + \ No newline at end of file From e50d19a96d158f2849281d3358bc751a6f81a085 Mon Sep 17 00:00:00 2001 From: Jonas Almeida Date: Mon, 8 Oct 2012 14:14:26 -0500 Subject: [PATCH 60/62] loading 23andme own JS library --- 23andme.html | 1 + 23andme.js | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/23andme.html b/23andme.html index ba39cc4..6cd4766 100644 --- a/23andme.html +++ b/23andme.html @@ -1,6 +1,7 @@ + Experimenting with 23andme diff --git a/23andme.js b/23andme.js index 60bbb6b..5cdd0d5 100644 --- a/23andme.js +++ b/23andme.js @@ -1,13 +1,15 @@ -//https://api.23andme.com/user/login/?redirect=/authorize/?redirect_uri=http://jmat.googlecode.com/git/23andme.html&response_type&code%26client_id=D09568fd79aa7911dad7727a024936f8d&scope=basic - -MB23={ // 23and me application document object model +//https://api.23andme.com/authorize/?redirect_uri=http://jmat.googlecode.com/git/23andme.html&response_type=code&client_id=09568fd79aa7911dad7727a024936f8d&scope=basic +// response directed to http://jmat.googlecode.com/git/23andme.html, alternative URL: +//https://dl-web.dropbox.com/get/http/jmat/23andme.html?w=bba1484b&code={borrow from above} +// +UAB={ // 23and me application document object model code:null, parms:{}, search4parms:function(){ // gets parameters from call and pushes them to .parms var parms = window.document.location.search.slice(1).split('&'); parms.map(function(x){ xx = x.split('='); - MB23.parms[xx[0]]=xx[1] + UAB.parms[xx[0]]=xx[1] }) // @@ -17,14 +19,14 @@ MB23={ // 23and me application document object model // find out what is being provided and push it to parms -MB23.search4parms(); -if(!!MB23.parms.code){ - MB23.code=MB23.parms.code; - console.log('code = '+MB23.code); +UAB.search4parms(); +if(!!UAB.parms.code){ + UAB.code=UAB.parms.code; + console.log('code = '+UAB.code); } else if (!!localStorage.getItem('code')){ // find out if there is one in the localstorage - MB23.code = localStorage.getItem('code'); - console.log('code = '+MB23.code); + UAB.code = localStorage.getItem('code'); + console.log('code = '+UAB.code); } else{ throw('23andme access code not found :-(') From d19596a287016eced00878640b9a56a05e69a7cb Mon Sep 17 00:00:00 2001 From: Sean Wilkinson Date: Tue, 9 Oct 2012 10:28:00 -0500 Subject: [PATCH 61/62] Added an ignore file --- .gitignore | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d43030c --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +#- Git configuration file + +#- .gitignore ~~ +# ~~ last updated 08 Oct 2012 + +#- Mercurial repository itself (if present) +.hg/ + +#- Vim swap files +*.swp + +#- OS generated files +.DS_Store* +ehthumbs.db +Icon\? +.localized +Thumbs.db + +#- vim:set syntax=gitconfig: From 6ae7d9b1c93c6ec3478b22ac43d0e7c1c19cfac5 Mon Sep 17 00:00:00 2001 From: Sean Wilkinson Date: Tue, 9 Oct 2012 11:49:10 -0500 Subject: [PATCH 62/62] Wow. I got the first 24% of jMat to pass JSLint, at least ... --- jmat.js | 2079 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 1111 insertions(+), 968 deletions(-) diff --git a/jmat.js b/jmat.js index 893ce9a..84551c8 100644 --- a/jmat.js +++ b/jmat.js @@ -1,296 +1,461 @@ -console.log('jmat :-)'); +//- JavaScript source code -jmat = { - -abs:function(x){ // absolute value - if (Array.isArray(x)){return x.map(function(xi){return jmat.abs(xi)})} - else{return Math.abs(x)} -}, - -array2mat:function(x){ // to handle indexed arrays by converting them into two separate numerically indexed arrays - var j = 0, y1=[], y2=[]; - for(var i in x){ - y1[j]=i; - y2[j]=x[i]; - j=j+1; - } - return [y1,y2] -}, - -array2str:function(x,sp){ // convert array into a sp separated - if (!sp){sp='\n'} - y=x[0]; - for (var i=1;i 1) { + x = []; + if ((typeof args[1]) !== 'number') { + for (i = 0; i < args[1].length; i += 1) { + x[i] = args[1][i]; + } } else { - result.push(dictionary[w]); - // Add wc to the dictionary. - dictionary[wc] = dictSize++; - w = String(c); + // note first argument is always fun + for (i = 1; i < args.length; i += 1) { + x[i - 1] = args[i]; + } + } + z = []; + if (x.length < 2) { + for (i = 0; i < x[0]; i += 1) { + z[i] = fun(i); // fun has access to array index + } + } else { + x0 = x[0]; + x = x.slice(1); + for (i = 0; i < x0; i += 1) { + z[i] = dimfun(fun, x); + } } + } else { + z = fun(); } - - // Output the code for w. - if (w !== "") { - result.push(dictionary[w]); + return z; + }; + + ones = function () { + return dimfun(function () { + return 1; + }, arguments); + }; + + parse = function (x) { + // x is a stringified Object + // + // @Jonas: This function probably won't work in ES5 Strict Mode, but it + // _might_ work if you use `JSON.parse` in the same way that you used + // `JSON.stringify` inside your own `stringify` function. + // + /*jslint evil: true */ + eval('var res = ' + x); + return res; + }; + + stringify = function (x) { + // extends JSON.stringify to work with both values and functions + var i, v, y; + y = (typeof x); + switch (y) { + case 'function': + y = x.toString(); + break; + case 'object': + if (Array.isArray(x)) { + y = '['; + for (i = 0; i < x.length; i += 1) { + y += stringify(x[i]) + ','; + } + y = y.slice(0, y.length - 1) + ']'; + } else { + y = '{'; + for (v in x) { + y += v + ':' + stringify(x[v]) + ','; + } + y = y.slice(0, y.length - 1) + '}'; + } + break; + case 'string': + y = JSON.stringify(x); + break; + case 'number': + y = JSON.stringify(x); + break; + default: + // (placeholder) } - return result; - }, + return y; + }; + + zeros = function () { + return dimfun(function () { + return 0; + }, arguments); + }; + + // Out-of-scope definitions + + window.jmat = { + abs: abs, + array2mat: array2mat, + array2str: array2str, + arrayfun: arrayfun, + bin2dec: bin2dec, + cat: cat, + catArray: catArray, + cEl: cEl, + + // ------------------------------------------------------------------------ + + class: function (x) { + if (!x.constructor) { + return null; + } + return x.constructor.name; + }, + + clone: clone, + clone2: clone2, + cloneArray: cloneArray, + cloneVector: cloneVector, + colon: colon, + + compress: function (uncompressed) { + // Source: http://rosettacode.org/wiki/LZW_compression#JavaScript + // this is new -- such that we are compressing JS objects, not strings + uncompressed = this.stringify(uncompressed); + // Build the dictionary. + var c, dictionary, dictSize, i, result, w, wc; + dictionary = {}; + dictSize = 256; + result = []; + w = ''; + // @Jonas: Should `256` in the following line be `dictSize`? + for (i = 0; i < 256; i += 1) { + dictionary[String.fromCharCode(i)] = i; + } + for (i = 0; i < uncompressed.length; i += 1) { + c = uncompressed.charAt(i); + wc = w + c; + if (dictionary[wc]) { + w = wc; + } else { + result.push(dictionary[w]); + // Add wc to the dictionary. + dictionary[wc] = dictSize++; + w = String(c); + } + } + // Output the code for w. + if (w !== "") { + result.push(dictionary[w]); + } + return result; + }, decompress: function (compressed) { - "use strict"; - // Build the dictionary. - var i, - dictionary = [], - w, - result, - k, - entry = "", - dictSize = 256; - for (i = 0; i < 256; i += 1) { - dictionary[i] = String.fromCharCode(i); - } - - w = String.fromCharCode(compressed[0]); - result = w; - for (i = 1; i < compressed.length; i += 1) { - k = compressed[i]; - if (dictionary[k]) { - entry = dictionary[k]; - } else { - if (k === dictSize) { - entry = w + w.charAt(0); - } else { - return null; - } - } - - result += entry; - - // Add w+entry[0] to the dictionary. - dictionary[dictSize++] = w + entry.charAt(0); - - w = entry; - } - return this.parse(result); - }, + "use strict"; + // Build the dictionary. + var i, + dictionary = [], + w, + result, + k, + entry = "", + dictSize = 256; + for (i = 0; i < 256; i += 1) { + dictionary[i] = String.fromCharCode(i); + } + + w = String.fromCharCode(compressed[0]); + result = w; + for (i = 1; i < compressed.length; i += 1) { + k = compressed[i]; + if (dictionary[k]) { + entry = dictionary[k]; + } else { + if (k === dictSize) { + entry = w + w.charAt(0); + } else { + return null; + } + } + + result += entry; + + // Add w+entry[0] to the dictionary. + dictionary[dictSize++] = w + entry.charAt(0); + + w = entry; + } + return this.parse(result); + }, colormap:function(c){ - if(!c){c='default'} - switch(c){ - case 'default': - c=[[0,0,0.5625],[0,0,0.625],[0,0,0.6875],[0,0,0.75],[0,0,0.8125],[0,0,0.875],[0,0,0.9375],[0,0,1],[0,0.0625,1],[0,0.125,1],[0,0.1875,1],[0,0.25,1],[0,0.3125,1],[0,0.375,1],[0,0.4375,1],[0,0.5,1],[0,0.5625,1],[0,0.625,1],[0,0.6875,1],[0,0.75,1],[0,0.8125,1],[0,0.875,1],[0,0.9375,1],[0,1,1],[0.0625,1,0.9375],[0.125,1,0.875],[0.1875,1,0.8125],[0.25,1,0.75],[0.3125,1,0.6875],[0.375,1,0.625],[0.4375,1,0.5625],[0.5,1,0.5],[0.5625,1,0.4375],[0.625,1,0.375],[0.6875,1,0.3125],[0.75,1,0.25],[0.8125,1,0.1875],[0.875,1,0.125],[0.9375,1,0.0625],[1,1,0],[1,0.9375,0],[1,0.875,0],[1,0.8125,0],[1,0.75,0],[1,0.6875,0],[1,0.625,0],[1,0.5625,0],[1,0.5,0],[1,0.4375,0],[1,0.375,0],[1,0.3125,0],[1,0.25,0],[1,0.1875,0],[1,0.125,0],[1,0.0625,0],[1,0,0],[0.9375,0,0],[0.875,0,0],[0.8125,0,0],[0.75,0,0],[0.6875,0,0],[0.625,0,0],[0.5625,0,0],[0.5,0,0]]; - break; - default: - c = 'not found'; - } - return c + if(!c){c='default'} + switch(c){ + case 'default': + c=[[0,0,0.5625],[0,0,0.625],[0,0,0.6875],[0,0,0.75],[0,0,0.8125],[0,0,0.875],[0,0,0.9375],[0,0,1],[0,0.0625,1],[0,0.125,1],[0,0.1875,1],[0,0.25,1],[0,0.3125,1],[0,0.375,1],[0,0.4375,1],[0,0.5,1],[0,0.5625,1],[0,0.625,1],[0,0.6875,1],[0,0.75,1],[0,0.8125,1],[0,0.875,1],[0,0.9375,1],[0,1,1],[0.0625,1,0.9375],[0.125,1,0.875],[0.1875,1,0.8125],[0.25,1,0.75],[0.3125,1,0.6875],[0.375,1,0.625],[0.4375,1,0.5625],[0.5,1,0.5],[0.5625,1,0.4375],[0.625,1,0.375],[0.6875,1,0.3125],[0.75,1,0.25],[0.8125,1,0.1875],[0.875,1,0.125],[0.9375,1,0.0625],[1,1,0],[1,0.9375,0],[1,0.875,0],[1,0.8125,0],[1,0.75,0],[1,0.6875,0],[1,0.625,0],[1,0.5625,0],[1,0.5,0],[1,0.4375,0],[1,0.375,0],[1,0.3125,0],[1,0.25,0],[1,0.1875,0],[1,0.125,0],[1,0.0625,0],[1,0,0],[0.9375,0,0],[0.875,0,0],[0.8125,0,0],[0.75,0,0],[0.6875,0,0],[0.625,0,0],[0.5625,0,0],[0.5,0,0]]; + break; + default: + c = 'not found'; + } + return c }, d3:{ - figure:function(id,type){ // create figure by appending d3's svg element to DOM element with specified id - if (typeof(id)==='undefined'){ - var fig = d3.select("body").append("div"); - fig.id = jmat.uid('fig'); - } - else{ - if(jmat.gId(id)!=null){var fig = d3.select('#'+id);} // if it exists - else {var fig = this.figure();fig[0][0].id = id} // otherwise create it - } - - if (typeof(type)==='string'){ - fig.attr('class',type); // possibilities: "chart", - } - this.gcf=fig; - return fig; - }, - + figure:function(id,type){ // create figure by appending d3's svg element to DOM element with specified id + if (typeof(id)==='undefined'){ + var fig = d3.select("body").append("div"); + fig.id = jmat.uid('fig'); + } + else{ + if(jmat.gId(id)!=null){var fig = d3.select('#'+id);} // if it exists + else {var fig = this.figure();fig[0][0].id = id} // otherwise create it + } + + if (typeof(type)==='string'){ + fig.attr('class',type); // possibilities: "chart", + } + this.gcf=fig; + return fig; + }, + }, data2imData:function(data){ // the reverse of im2data, data is a matlabish set of 4 2d matrices, with the r, g, b and alpha values - var n=data.length, m=data[0].length; - //var imData = {width:m, height:n, data:[]}; - var imData = document.createElement('canvas').getContext('2d').createImageData(m,n); - for (var i=0;i=0;i=i-1){ - m=Math.pow(2,i); - if(x>=m){b=b+'1';x=x-m} - else{b=b+'0'} - }; - return b + if(!n){n=Math.ceil(this.log(x,2))+1}; + var b=''; + for(i=n-1;i>=0;i=i-1){ + m=Math.pow(2,i); + if(x>=m){b=b+'1';x=x-m} + else{b=b+'0'} + }; + return b }, disp:function(x){ // by default displays both in the console and in document.body - console.log(x); - document.body.innerHTML+='
'+x+''; + console.log(x); + document.body.innerHTML+='
'+x+''; }, dotFun:function(A,B,fun){ // dot matrix function - 4; -}, - -dimfun:function(){ // first argument is the function, subsequent arguments specify dimensions - if(arguments.length==0){arguments=[function(){return 0}]} - var fun=arguments[0]; - if(arguments.length>1){ - if(typeof(arguments[1])!='number'){var x = [];for(var i=0;i0)&&(i0)&&(j0)&&(i0)&&(j0){ // extract this feature - var C=[1,0,0]; // always use yellow - //jmat.plot(cvTop,m[1][1],m[1][0],'s',{Color:[1,1,0],MarkerSize:30}); - var extractSeg = function(x,y,S){ // bw is passed in the scope of extractSegs - if(typeof(S)=='undefined'){var S=[]} // collect feature's positions - S[S.length]=[x,y];bw[x][y]=0; - // check which neighbors are >0 and take them out too - var xi,yi; - if(x>0){xi=x-1;yi=y;if(bw[xi][yi]>0){S=extractSeg(xi,yi,S)}} - if(x0){S=extractSeg(xi,yi,S)}} - if(y>0){xi=x;yi=y-1;if(bw[xi][yi]>0){S=extractSeg(xi,yi,S)}} - if(y0){S=extractSeg(xi,yi,S)}} - return S; - } - segFeatures[segFeatures.length]=extractSeg(m[1][0],m[1][1]);//extraction starts with coordiantes ofmaximum value - m = jmat.max2(bw); - } - return segFeatures.map(function(si){return jmat.transpose(si)}) + if(typeof(segFeatures)=='undefined'){var segFeatures=[]} // collect extracted features here + var m = jmat.max2(bw); + var n = jmat.size(bw); + while(m[0]>0){ // extract this feature + var C=[1,0,0]; // always use yellow + //jmat.plot(cvTop,m[1][1],m[1][0],'s',{Color:[1,1,0],MarkerSize:30}); + var extractSeg = function(x,y,S){ // bw is passed in the scope of extractSegs + if(typeof(S)=='undefined'){var S=[]} // collect feature's positions + S[S.length]=[x,y];bw[x][y]=0; + // check which neighbors are >0 and take them out too + var xi,yi; + if(x>0){xi=x-1;yi=y;if(bw[xi][yi]>0){S=extractSeg(xi,yi,S)}} + if(x0){S=extractSeg(xi,yi,S)}} + if(y>0){xi=x;yi=y-1;if(bw[xi][yi]>0){S=extractSeg(xi,yi,S)}} + if(y0){S=extractSeg(xi,yi,S)}} + return S; + } + segFeatures[segFeatures.length]=extractSeg(m[1][0],m[1][1]);//extraction starts with coordiantes ofmaximum value + m = jmat.max2(bw); + } + return segFeatures.map(function(si){return jmat.transpose(si)}) }, extractSegs2: function (bw) { @@ -376,909 +541,887 @@ extractSegs:function(bw){ // extracts segmented features from a [0,1] matrix and return traced_image; }, -fieldnames:function(x){ - y=[];i=0; - for(var f in x){ - y[i]=f; - i++; - } - return y; -}, + fieldnames: function (x) { + var f, i, y; + i = 0; + y = []; + for (f in x) { + y[i] = f; + i += 1; + } + return y; + }, find:function(x,patt,modifier){ // find wich elements of an array match a pattern - if(!modifier){modifier='gi'}// default is global and case insensitive - var y = []; - if(Array.isArray(patt)){patt='('+patt.join(')|(')+')'} // allows multiple patterns - patt = new RegExp(patt,modifier); - var M - for(var i in x){ - M=x[i].match(patt); - if(!!M){y.push(i)} - } - return y + if(!modifier){modifier='gi'}// default is global and case insensitive + var y = []; + if(Array.isArray(patt)){patt='('+patt.join(')|(')+')'} // allows multiple patterns + patt = new RegExp(patt,modifier); + var M + for(var i in x){ + M=x[i].match(patt); + if(!!M){y.push(i)} + } + return y }, fminsearch:function(fun,Parm0,x,y,Opt){// fun = function(x,Parm) - // example - // - // x = [32,37,42,47,52,57,62,67,72,77,82,87,92] - // y=[749,1525,1947,2201,2380,2537,2671,2758,2803,2943,3007,2979,2992] - // fun = function(x,P){return x.map(function(xi){return (P[0]+P[1]*(1-Math.exp(-P[2]*(xi-P[3]))))})} - // Parms=jmat.fminsearch(fun,[100,3000,1,30],x,y) - // - // Opt is an object will all other parameters, from the objective function (cost function), to the - // number of iterations, initial step vector and the display switch, for example - // Parms=jmat.fminsearch(fun,[100,3000,1,30],x,y,{maxIter:5000,display:false}) - - if(!Opt){Opt={}}; - if(!Opt.maxIter){Opt.maxIter=1000}; - if(!Opt.step){// initial step is 1/100 of initial value (remember not to use zero in Parm0) - Opt.step=Parm0.map(function(p){return p/100}); - Opt.step=Opt.step.map(function(si){if(si==0){return 1}else{ return si}}); // convert null steps into 1's - }; - if(typeof(Opt.display)=='undefined'){Opt.display=true}; - if(!Opt.objFun){Opt.objFun=function(y,yp){return jmat.sum(y.map(function(yi,i){return Math.pow((yi-yp[i]),2)}))}} - - var ya,y0,yb,fP0,fP1; - var P0=jmat.cloneVector(Parm0),P1=jmat.cloneVector(Parm0); - var n = P0.length; - var step=Opt.step; - var funParm=function(P){return Opt.objFun(y,fun(x,P))}//function (of Parameters) to minimize - // silly multi-univariate screening - for(var i=0;i(Opt.maxIter-10)){console.log(i+1,funParm(P0),P0)}} - } - return P0 + // example + // + // x = [32,37,42,47,52,57,62,67,72,77,82,87,92] + // y=[749,1525,1947,2201,2380,2537,2671,2758,2803,2943,3007,2979,2992] + // fun = function(x,P){return x.map(function(xi){return (P[0]+P[1]*(1-Math.exp(-P[2]*(xi-P[3]))))})} + // Parms=jmat.fminsearch(fun,[100,3000,1,30],x,y) + // + // Opt is an object will all other parameters, from the objective function (cost function), to the + // number of iterations, initial step vector and the display switch, for example + // Parms=jmat.fminsearch(fun,[100,3000,1,30],x,y,{maxIter:5000,display:false}) + + if(!Opt){Opt={}}; + if(!Opt.maxIter){Opt.maxIter=1000}; + if(!Opt.step){// initial step is 1/100 of initial value (remember not to use zero in Parm0) + Opt.step=Parm0.map(function(p){return p/100}); + Opt.step=Opt.step.map(function(si){if(si==0){return 1}else{ return si}}); // convert null steps into 1's + }; + if(typeof(Opt.display)=='undefined'){Opt.display=true}; + if(!Opt.objFun){Opt.objFun=function(y,yp){return jmat.sum(y.map(function(yi,i){return Math.pow((yi-yp[i]),2)}))}} + + var ya,y0,yb,fP0,fP1; + var P0=jmat.cloneVector(Parm0),P1=jmat.cloneVector(Parm0); + var n = P0.length; + var step=Opt.step; + var funParm=function(P){return Opt.objFun(y,fun(x,P))}//function (of Parameters) to minimize + // silly multi-univariate screening + for(var i=0;i(Opt.maxIter-10)){console.log(i+1,funParm(P0),P0)}} + } + return P0 }, get:function(key,callback,url){ // get content at url or key - if (!callback){callback=function(x){console.log(x)}} - if (!url){url=this.webrwUrl}; - var uid = this.uid(); - if(!this.get.jobs){this.get.jobs=[]} - this.get.jobs[uid]={'fun':callback}; - var url=url+'?get='+key+'&callback=jmat.get.jobs.'+uid+'.fun'; - var s=document.createElement('script'); - s.id = uid;s.src=url; - document.body.appendChild(s); - setTimeout('document.body.removeChild(document.getElementById("'+uid+'"));delete jmat.get.jobs.'+uid+';',10000); // is the waiting still need ? script onload would be another possibility to delete it - return uid; -}, - -gId:function(x){ // x is the id of an existing DOM element - // return null if neither id nor class are found - // so constructs like !jmat.gId(someID) can be used - //var y=document.getElementById(x); - //if(!y){ - // var z=document.getElementsByClassName(x); - // if(z.length>0){return z} - // else{return y} - //} - //else{return y} - return document.getElementById(x) -}, + if (!callback){callback=function(x){console.log(x)}} + if (!url){url=this.webrwUrl}; + var uid = this.uid(); + if(!this.get.jobs){this.get.jobs=[]} + this.get.jobs[uid]={'fun':callback}; + var url=url+'?get='+key+'&callback=jmat.get.jobs.'+uid+'.fun'; + var s=document.createElement('script'); + s.id = uid;s.src=url; + document.body.appendChild(s); + setTimeout('document.body.removeChild(document.getElementById("'+uid+'"));delete jmat.get.jobs.'+uid+';',10000); // is the waiting still need ? script onload would be another possibility to delete it + return uid; +}, + + gId:function(x){ // x is the id of an existing DOM element + // return null if neither id nor class are found + // so constructs like !jmat.gId(someID) can be used + //var y=document.getElementById(x); + //if(!y){ + // var z=document.getElementsByClassName(x); + // if(z.length>0){return z} + // else{return y} + //} + //else{return y} + return document.getElementById(x) + }, im1to255:function(x){// converts {0-1} matrix into an im data matrix - 4 + 4 }, imread:function(cv){ // reads image from context into matrix - // find out what type of input - if(typeof(cv)=='string'){ // cv is the id of a canvas element - cv=jmat.gId(cv) - } - var ct=cv.getContext('2d'), n=cv.width, m=cv.height; - var imData=ct.getImageData(0,0,n,m); // pixel values will be stored in imData.data - return this.imData2data(imData) + // find out what type of input + if(typeof(cv)=='string'){ // cv is the id of a canvas element + cv=jmat.gId(cv) + } + var ct=cv.getContext('2d'), n=cv.width, m=cv.height; + var imData=ct.getImageData(0,0,n,m); // pixel values will be stored in imData.data + return this.imData2data(imData) }, imhalve:function(dt0,PSmax){ // poor man's version of imresize, it halves an image size by averaging two rows/columns - var s = jmat.size(dt0); - if(!PSmax){PSmax = jmat.prod(s.slice(0,2))-1} // if maximum size not defined then just have it once - if(jmat.prod(s.slice(0,2))>PSmax){ - if(jmat.length(s)!==3){throw('this should be an image value matrix, size n x m x 4')} - if(s[2]!==4){throw('this should be an image value matrix, size n x m x 4')} - s = jmat.arrayfun(s,function(x){return Math.floor(x/2)}); // half size, with floored integers - s[2]=4; // rgba - var dt = jmat.zeros(s[0],s[1],s[2]); - dt=dt.map(function(x,i){ - return x.map(function(y,j){ - return y.map(function(z,k){ - return (dt0[i*2][j*2][k]+dt0[i*2+1][j*2+1][k]+dt0[i*2][j*2+1][k])/3; - }) - }) - }); - } - else{var dt = dt0}; - // if maximum pixel size was set and was exceeded keep halving - if(jmat.prod(jmat.size(dt).slice(0,2))>PSmax){dt = jmat.imhalve(dt,PSmax)} - return dt + var s = jmat.size(dt0); + if(!PSmax){PSmax = jmat.prod(s.slice(0,2))-1} // if maximum size not defined then just have it once + if(jmat.prod(s.slice(0,2))>PSmax){ + if(jmat.length(s)!==3){throw('this should be an image value matrix, size n x m x 4')} + if(s[2]!==4){throw('this should be an image value matrix, size n x m x 4')} + s = jmat.arrayfun(s,function(x){return Math.floor(x/2)}); // half size, with floored integers + s[2]=4; // rgba + var dt = jmat.zeros(s[0],s[1],s[2]); + dt=dt.map(function(x,i){ + return x.map(function(y,j){ + return y.map(function(z,k){ + return (dt0[i*2][j*2][k]+dt0[i*2+1][j*2+1][k]+dt0[i*2][j*2+1][k])/3; + }) + }) + }); + } + else{var dt = dt0}; + // if maximum pixel size was set and was exceeded keep halving + if(jmat.prod(jmat.size(dt).slice(0,2))>PSmax){dt = jmat.imhalve(dt,PSmax)} + return dt }, imwrite:function(cv,im,dx,dy){ - if(!dy){dx=0;dy=0} // default location - if(typeof(cv)=='string'){cv=jmat.gId(cv)} //cv can also be the id of a canvas element - if(!im.data){im=jmat.data2imData(im)} // such that im can also be the matrix created by imread - var ct = cv.getContext('2d'); - ct.putImageData(im,dx,dy); - return ct; + if(!dy){dx=0;dy=0} // default location + if(typeof(cv)=='string'){cv=jmat.gId(cv)} //cv can also be the id of a canvas element + if(!im.data){im=jmat.data2imData(im)} // such that im can also be the matrix created by imread + var ct = cv.getContext('2d'); + ct.putImageData(im,dx,dy); + return ct; }, image:function(cv,im,dx,dy){ // for consistency - return this.imwrite(cv,im,dx,dy); + return this.imwrite(cv,im,dx,dy); }, imagesc:function(cv,dt,cm,fun,M){ // scales values to use full range of values. cv is the canvas, dt the data, and cm the colormap - if(!cm){cm=jmat.colormap()} - if(!fun){fun=function(){return 1}}; // opaque function - cm = jmat.transpose(cm); // to get one vector per channel - var n = cm[0].length-1; // should be 64-1=63 - var I = jmat.dimfun(function(i){return i/(n)},n+1); // 64 numbers evenly spaced between 0 and 1 - if(!M){M = jmat.max(jmat.max(dt))}; - if(typeof(fun)=='string'){eval('fun='+fun)} // allow eval fun with transparencies - dt = jmat.arrayfun(dt,function(x){return [jmat.interp1(I,cm[0],[x/M])[0],jmat.interp1(I,cm[1],[x/M])[0],jmat.interp1(I,cm[2],[x/M])[0],fun(x)]}); - dt = jmat.arrayfun(dt,function(x){return Math.round(255*x)}); - if(!!cv){jmat.imwrite(cv,dt)}; - return dt + if(!cm){cm=jmat.colormap()} + if(!fun){fun=function(){return 1}}; // opaque function + cm = jmat.transpose(cm); // to get one vector per channel + var n = cm[0].length-1; // should be 64-1=63 + var I = jmat.dimfun(function(i){return i/(n)},n+1); // 64 numbers evenly spaced between 0 and 1 + if(!M){M = jmat.max(jmat.max(dt))}; + if(typeof(fun)=='string'){eval('fun='+fun)} // allow eval fun with transparencies + dt = jmat.arrayfun(dt,function(x){return [jmat.interp1(I,cm[0],[x/M])[0],jmat.interp1(I,cm[1],[x/M])[0],jmat.interp1(I,cm[2],[x/M])[0],fun(x)]}); + dt = jmat.arrayfun(dt,function(x){return Math.round(255*x)}); + if(!!cv){jmat.imwrite(cv,dt)}; + return dt }, imagebw:function(cv,dt,C0,C1){ // imagesc for binary matrices - if(!C0){C0=[0,0,0,0]} - if(!C1){C1=[255,255,255,255]} - var dt01 = jmat.arrayfun(dt,function(x){if(x==1){return C1}else{return C0}}) - if(!!cv){jmat.imwrite(cv,dt01)}; - return dt01; + if(!C0){C0=[0,0,0,0]} + if(!C1){C1=[255,255,255,255]} + var dt01 = jmat.arrayfun(dt,function(x){if(x==1){return C1}else{return C0}}) + if(!!cv){jmat.imwrite(cv,dt01)}; + return dt01; }, imData2data:function(imData){ // imData is the data structure returned by canvas.getContext('2d').getImageData(0,0,n,m) - var m=imData.width, n=imData.height, data=[]; - for (var i=0;i=thr){return 1} - else{return 0} - } - ) + return jmat.imMap(im,function(xy){ + if(xy>=thr){return 1} + else{return 0} + } + ) }, interp1:function(X,Y,XI){ // linear interpolation, remember X is supposed to be sorted - var n = X.length; - var YI = XI.map(function(XIi){ - var i=jmat.sum(X.map(function(Xi){if (Xi1){jmat.load(urls[0],function(){jmat.loadScripts(urls.slice(1))})} // recursion - else {jmat.load(urls[0],cb,er)} + console.log('loading script '+urls[0]+' ...'); + if (urls.length>1){jmat.load(urls[0],function(){jmat.loadScripts(urls.slice(1))})} // recursion + else {jmat.load(urls[0],cb,er)} }, loadFiles:function(files,readAs,callback){ - // //<-- example of button for reading text files - if(!readAs){readAs='readAsDataURL'} // default is to read as dataURL - for(var i=0;i //<-- example of button for reading text files + if(!readAs){readAs='readAsDataURL'} // default is to read as dataURL + for(var i=0;i1){jmat.load} - if(V.length>0){ - if(V.length>1){jmat.loadVar(V[0],function(){jmat.loadVar(V.slice(1),cb,er,cbId)},er,cbId)} - else{ // V.length=1 - jmat.loadVar(V[0],jmat.loadVarCallBack[cbId],er); - } - } - } - else{ - switch(V){ - case 'Q': - url = 'https://qmachine.org/q.js';break; - case 'CoffeeScript': - url = 'https://raw.github.com/jashkenas/coffee-script/master/extras/coffee-script.js';break; - case 'jQuery': - url='jquery-1.8.2.min.js';break; - default : - throw('No library was found to assemble "'+V+'"'); - } - jmat.load(url,cb,er); - console.log('variable "'+V+'"'+' loaded from '+url); - } - //return true; + if(Array.isArray(V)){ // are there more than one? + if(!cbId){cbId=jmat.uid();jmat.loadVarCallBack[cbId]=cb} + //if(V.length==1){jmat.load(V[0],cb,er)} + //else if(V.length>1){jmat.load} + if(V.length>0){ + if(V.length>1){jmat.loadVar(V[0],function(){jmat.loadVar(V.slice(1),cb,er,cbId)},er,cbId)} + else{ // V.length=1 + jmat.loadVar(V[0],jmat.loadVarCallBack[cbId],er); + } + } + } + else{ + switch(V){ + case 'Q': + url = 'https://qmachine.org/q.js';break; + case 'CoffeeScript': + url = 'https://raw.github.com/jashkenas/coffee-script/master/extras/coffee-script.js';break; + case 'jQuery': + url='jquery-1.8.2.min.js';break; + default : + throw('No library was found to assemble "'+V+'"'); + } + jmat.load(url,cb,er); + console.log('variable "'+V+'"'+' loaded from '+url); + } + //return true; }, lookup:function(tbl,col_in,val_in,col_out){// lookup in table tbl, - // for value in column col_out where the column col_in has the value val_in - var val_out={};// return results as a table - // Find Columns - var col_in_i=this.find(tbl.columns,col_in); - if(col_in_i.length==0){throw('input column not found')} - // if output columns not specified use the same as the input columns - if(!col_out){col_out=col_in;var col_out_i=col_in_i} - else{var col_out_i=this.find(tbl.columns,col_out)} - // Find which rows have those values - var rows = this.transpose(tbl.rows) , r=[] , Ind=[]; - for(var c in col_in_i){ - r=this.find(rows[col_in_i[c]],val_in); - if(r.length>0){for (var i in r){Ind.push(r[i])}} - } - Ind = this.unique(Ind); - val_out.columns=col_out_i.map(function(i){return tbl.columns[i]}); - val_out.rows=this.zeros(Ind.length,col_out_i.length); - for(var i=0;i0){for (var i in r){Ind.push(r[i])}} + } + Ind = this.unique(Ind); + val_out.columns=col_out_i.map(function(i){return tbl.columns[i]}); + val_out.rows=this.zeros(Ind.length,col_out_i.length); + for(var i=0;ib){return a}else{return b}})}; - //return x.reduce(function(a,b){if(a>b){return a}else{return b}}) + if(Array.isArray(x[0])){return x.map(function(xi){return jmat.max(xi)})} + else{return x.reduce(function(a,b){if(a>b){return a}else{return b}})}; + //return x.reduce(function(a,b){if(a>b){return a}else{return b}}) }, max2:function(x){ // returns maximum value of array and its index, i.e. [max,i] - if(Array.isArray(x[0])){ // coded only up to 2 dimensions - var xx = jmat.transpose(x.map(function(xi){return jmat.max2(xi)})) - var y = jmat.max2(xx[0]); - return [y[0],[y[1],xx[1][y[1]]]]; - } - else{return x.map(function(xi,i){return [xi,i]}).reduce(function(a,b){if(a[0]>b[0]){return a}else{return b}})}; - //return x.map(function(xi,i){return [xi,i]}).reduce(function(a,b){if(a[0]>b[0]){return a}else{return b}}) + if(Array.isArray(x[0])){ // coded only up to 2 dimensions + var xx = jmat.transpose(x.map(function(xi){return jmat.max2(xi)})) + var y = jmat.max2(xx[0]); + return [y[0],[y[1],xx[1][y[1]]]]; + } + else{return x.map(function(xi,i){return [xi,i]}).reduce(function(a,b){if(a[0]>b[0]){return a}else{return b}})}; + //return x.map(function(xi,i){return [xi,i]}).reduce(function(a,b){if(a[0]>b[0]){return a}else{return b}}) }, min:function(x){ //return maximum value of array - return x.reduce(function(a,b){if(a'} - else{if(y[j].error){ // if error - y[j].error=false; - //y[j]=jmat.qmachine.submit(y[j].more,fun,box,step); - console.log('Mapping error at #'+i+':',y[i]); - doneStr+='*'; // "*" indicates error - } - else{doneStr+='-'} // not done yet - } - } - //console.log('countMap:',jmat.sum(done)); - console.log('M'+i+'('+doneStr+')'); - if(jmat.sum(done)==n){clearInterval(t)}; - },step); - return y; - - }, - reduce:function(x,fun,box,step){ - if(!step){step=jmat.qmachine.step}; // control default step at jmat.qmachine.step - // check that the array is of Avar elements - if(x[0].constructor.name!=="AVar"){ - x=x.map(function(xi){return Q.avar({val:xi,box:box,done:true})}) - } - var n = x.length , doneStr = ''; - //x.map(function(xi){xi.reduceStarted=false;return false}); // prepare reduce parm - //var y = Q.avar({val:x , box:box , done:false}); // results wil be placed here - var r = x.map(function(xi){return {}}); // keep flags for reduction process here - var i = 0, toReduce=[], t = setInterval(function(){ // timer - i+=1; - toReduce=[]; // reset each time - for(var j=0;j'}; // being reduced as we speak - if(j==n-1){doneStr+=':'}; - - } - for(var j=r.length;j<(2*n-1);j++){doneStr+=' '}; - - var countReduce=jmat.sum(x.map(function(xi,j){return (xi.done)}))+jmat.sum(x.map(function(xi,j){return (!!r[j].started)})); - //console.log('countReduce:',countReduce); - if(countReduce==(4*n-3)){ - clearInterval(t); - //console.log('R'+i+'['+doneStr.slice(0,doneStr.length-1)+'+]'); - console.log('R'+i+'['+doneStr.slice(0,doneStr.length-1)+'<'+x[x.length-1].val+'>]'); - console.log(x[x.length-1].val); - } - else{console.log('R'+i+'['+doneStr+']');} - - },step); - - return x; - }, - mapReduce:function(x,funMap,funReduce,box,step){ // mapReduce(x,funMap(xi){},funReduce(x1,x2){},box) - return jmat.qmachine.reduce(jmat.qmachine.map(x,funMap,box,step),funReduce,box,step); - } + step:1000, // miliseconds between calls + load:function(cb,er){ // load qmachine js library + jmat.loadVar(['Q','CoffeeScript'],function(){ + Q.submit=function(val,fun,box,more,jobId){return jmat.qmachine.submit(val,fun,box,more,jobId)}; + //Q.map=function(val,fun,box,rvStep){return jmat.qmachine.map(val,fun,box,rvStep)}; + //Q.reduce=function(val,fun,box,rvStep){return jmat.qmachine.reduce(val,fun,box,rvStep)}; + Q.mapReduce=function(val,funMap,funReduce,box,step){return jmat.qmachine.mapReduce(val,funMap,funReduce,box,step)}; + }); + }, + jobs:{}, + reval:function(val,fun,box,more,jobId){ + if(typeof(Q)=='undefined'){ + throw('Q not loaded') + } + return jmat.qmachine.jobs[jmat.qmachine.revalJob(val,fun,box,more,jobId)]; + }, + + submit:function(val,fun,box,more,jobId){ + if(!jobId){jobId=jmat.uid('job')}; + jmat.qmachine.jobs[jobId] = {done:false,jobId:jobId}; + if((typeof(Q)=='undefined')||(typeof(CoffeeScript)=='undefined')){ + jmat.loadVar(['CoffeeScript','Q'],function(){ + fun=jmat.qmachine.fun(fun); + jmat.qmachine.revalJob(val,fun,box,more,jobId); + }) + } + else { + fun=jmat.qmachine.fun(fun); + jmat.qmachine.revalJob(val,fun,box,more,jobId); + } + return jmat.qmachine.jobs[jobId]; + }, + + revalJob:function(val,fun,box,more,jobId){ // version of reval that directs output to a jobs object + if(!more){more=[]}; + if(!jobId){jobId=jmat.uid('job')}; + //this.jobs[jobId].done=false; + //this.jobs[jobId]=this.reval(val,fun,box); + this.jobs[jobId]=function(){ // this is where the job is done !! + var qi = Q.avar(); + qi.val = {f: fun, x: val}; + qi.box = box; + qi.done = false; + qi.more=more; // to pass additional arguments + //qi.onready = function (evt) { this.val = fun(this.val); return evt.exit(); }; + //qi.onready=fun; + qi.onready = function (evt) { + this.val = this.val.f(this.val.x); + //this.done=true; + return evt.exit(); + }; + qi.onready = function (evt) { + qi.done = true; + qi.error = false; + //qi.error = false; + return evt.exit(); + }; + qi.onerror = function (evt) { + qi.error = true; + } + return qi; + }(val,fun,box); + this.jobs[jobId].jobId=jobId; + return jobId; + }, + fun:function(f){ // converts CoffeeScript to JavaScript if f is a string + other fun house cleaning + if(typeof(f)=='string'){ + if(typeof(CoffeeScript)=='undefined'){jmat.loadVar('CoffeeScript');throw('CoffeeScript was missing, try again')}; + return CoffeeScript.eval(f); + } + else{ // assuming it is a function, kiss ass of JSLint zealots and add a ; before closing } + return jmat.parse(f.toString().replace(/([^;]{2})}/,'$1;}')); + } + }, + map:function(x,fun,box,step){ // jmat.qmachine.map(valArray,funMap) + //if (typeof(fun)==='string'){fun = jmat.parse(jmat.coffee.compile2js(fun))}; + if(!step){step=jmat.qmachine.step}; // control default step at jmat.qmachine.step + fun = jmat.qmachine.fun(fun); + var n = x.length; + y = x.map(function(xi){return jmat.qmachine.submit(xi,fun,box,xi)}); // note original value being kept as more, the 4th input argument + // revive + var trv=setInterval + + // monitor mapping + var done, doneStr='', i = 0;t = setInterval(function(){ + i+=1; + done = y.slice(0,n).map(function(yi,j){return y[j].done}); + doneStr=''; + for(var j=0;j'} + else{if(y[j].error){ // if error + y[j].error=false; + //y[j]=jmat.qmachine.submit(y[j].more,fun,box,step); + console.log('Mapping error at #'+i+':',y[i]); + doneStr+='*'; // "*" indicates error + } + else{doneStr+='-'} // not done yet + } + } + //console.log('countMap:',jmat.sum(done)); + console.log('M'+i+'('+doneStr+')'); + if(jmat.sum(done)==n){clearInterval(t)}; + },step); + return y; + + }, + reduce:function(x,fun,box,step){ + if(!step){step=jmat.qmachine.step}; // control default step at jmat.qmachine.step + // check that the array is of Avar elements + if(x[0].constructor.name!=="AVar"){ + x=x.map(function(xi){return Q.avar({val:xi,box:box,done:true})}) + } + var n = x.length , doneStr = ''; + //x.map(function(xi){xi.reduceStarted=false;return false}); // prepare reduce parm + //var y = Q.avar({val:x , box:box , done:false}); // results wil be placed here + var r = x.map(function(xi){return {}}); // keep flags for reduction process here + var i = 0, toReduce=[], t = setInterval(function(){ // timer + i+=1; + toReduce=[]; // reset each time + for(var j=0;j'}; // being reduced as we speak + if(j==n-1){doneStr+=':'}; + + } + for(var j=r.length;j<(2*n-1);j++){doneStr+=' '}; + + var countReduce=jmat.sum(x.map(function(xi,j){return (xi.done)}))+jmat.sum(x.map(function(xi,j){return (!!r[j].started)})); + //console.log('countReduce:',countReduce); + if(countReduce==(4*n-3)){ + clearInterval(t); + //console.log('R'+i+'['+doneStr.slice(0,doneStr.length-1)+'+]'); + console.log('R'+i+'['+doneStr.slice(0,doneStr.length-1)+'<'+x[x.length-1].val+'>]'); + console.log(x[x.length-1].val); + } + else{console.log('R'+i+'['+doneStr+']');} + + },step); + + return x; + }, + mapReduce:function(x,funMap,funReduce,box,step){ // mapReduce(x,funMap(xi){},funReduce(x1,x2){},box) + return jmat.qmachine.reduce(jmat.qmachine.map(x,funMap,box,step),funReduce,box,step); + } }, rand:function(){ - return jmat.dimfun(function(){return Math.random()},arguments) + return jmat.dimfun(function(){return Math.random()},arguments) }, ranksum:function(x,y){ // this is just a first approximation while something saner emerges for stats - var s=x.map(function(xi){return y.map(function(yi){return [yi>xi,yixi,yithr)}); // threshold value, thr, is passed to the function through a closure + if(!im.width){var dt=im} + else{dt=this.imData2data(im)} // in case im is an imageData object + if(!thr){thr = jmat.max(jmat.catArray(dt))/2} // default threshold is 1/10 of maximum, write something better later + return jmat.imMap(dt,function(xy){return (xy>thr)}); // threshold value, thr, is passed to the function through a closure }, twitter:{ - calls:{}, - loadUser:function(uname,cb){ // load @uname, default callback is console.log - var callId=jmat.uid(); - if(!cb){cb=function(x){console.log(x)}}; - this.calls[callId]=cb; - //https://api.twitter.com/1/statuses/user_timeline.json?screen_name=divInformatics&include_entities=true&include_rts=true&callback=lala - jmat.load('https://api.twitter.com/1/statuses/user_timeline.json?screen_name='+uname+'&include_entities=true&include_rts=true&callback=jmat.twitter.calls.'+callId); - return 'jmat.twitter.loadUser("'+uname+'",jmat.twitter.calls.'+callId+')'; - }, + calls:{}, + loadUser:function(uname,cb){ // load @uname, default callback is console.log + var callId=jmat.uid(); + if(!cb){cb=function(x){console.log(x)}}; + this.calls[callId]=cb; + //https://api.twitter.com/1/statuses/user_timeline.json?screen_name=divInformatics&include_entities=true&include_rts=true&callback=lala + jmat.load('https://api.twitter.com/1/statuses/user_timeline.json?screen_name='+uname+'&include_entities=true&include_rts=true&callback=jmat.twitter.calls.'+callId); + return 'jmat.twitter.loadUser("'+uname+'",jmat.twitter.calls.'+callId+')'; + }, }, uid:function(prefix){ - if(!prefix){prefix='UID'} - var uid=prefix+Math.random().toString().slice(2); - return uid + if(!prefix){prefix='UID'} + var uid=prefix+Math.random().toString().slice(2); + return uid }, unique:function(x){ // x is an Array - var u = []; // store unique here - u[0]=x[0]; - for (var i=1; i