Thursday, 10 May 2018

Converting svg to base64

So i was trying to to convert some svg string to base64. Was using this nice module and them get an error. When looked into it I found out the core function to do that is URL.createObjectURL. And my bug was eventually solved by adding xmlns="http://www.w3.org/2000/svg" to my svg element. I have no idea why that happened...

Wednesday, 7 February 2018

Python dynamic function call example

dynamic function call python

class dataWriter(object):

def __init__(self, data):
self.data = data

#main function
def write(self):

#if contains this data, execute the corresponding writing function
for category,value in self.data.items():
self.__getattribute__(
'write'+category)(value)

def writeA(self, A):
print(
'A: ' + str(A))

def writeB(self, B):
print(
'B: ' + str(B))

def writeC(self, C):
print(
'C: '+ str(C))


a = dataWriter(data={
'A':100, 'B': 10})
a.write()
##result
#A: 100
#B: 10

Tuesday, 23 January 2018

On d3's Data Join and Why Sometimes Method Chaining is Troublesome

Don't get me wrong. D3 is a very powerful library, and data join is a very powerful feature. However, I have problem with its tendency to advertise method chaining in the official examples.

If you are using d3, the general updating pattern is probably the first thing you’ve learned.

Let's take the force-directed graph for example. The code below is directly copied from here.

var link = svg.append("g")
.attr(
"class", "links")
.selectAll(
"line")
.data(graph.links)
.enter().append(
"line")
.attr(
"stroke-width", function(d) { return Math.sqrt(d.value); });


And you probably have noticed the method chaining. Everything up to this point seems quite natural. let’s read it together line by line.

So, we append a group element to the svg, add a class attribute, select all the line elements(which gives us an empty collection at this point), binding it to our data graph.links. Then calling enter() gives us the the unbound data (If you don’t know how that happens, go to this official introduction), to which we append a line for each.

How neat, you would think! Yep, it is neat, for now.

But wait! One of the the merit of data binding is to modify the data and have our elements changing accordingly. So what say if we want to have an update function, which we call each time the data changes? Luckily there’s another example we can referring to. The parts relating to modifying link elements are copied below.

var link = g.append("g").selectAll("line");
function restart() {
// Apply the general update pattern to the links.
link = link.data(links,
function(d) { return d.source.id + "-" + d.target.id; });
link.exit().remove();
link = link.enter().append(
"line").merge(link);
...
}

Chances are you’ve never gone beyond the vanilla version of updating in the first part, and these three lines would throw you off the balance. So we know link.data do the data binding, but what does it really return? Digging a little bit into the reference and we know the answer:

It returns the overlapping part of the data and the existing elements - the update collection, as it is called. It also has two collections appending to it, calling enter() gives you the unbound data collection, and calling exit() gives you the unbound elements.

So we removes the unbound elements, adding new elements to new data. But what is merge doing here? The parameter ‘link’ is our update collection, and the caller on left side is still the newly bound elements, so we are adding the newly bound to the existing bound, which gives us all the elements at this point. Re-assigning it to link, next time when restart is called, we can again bind our new data to this collection.

Then you realize there’s no reason at all, to name the data binding return as ‘link’! We could name it as something else like linkUpdate, which is far clearer.

linkUpdate = link.data(links, function(d) { return d.source.id + "-" + d.target.id; });
linkUpdate.exit().remove();
link = linkUpdate.enter().append(
"line").merge(linkUpdate);

Right, so now let’s say our existing code is exactly like the first code, and we try to extend it to accommodate updating. Which parts should you put into the update function? So we read through the code, and saying oh, so up till the selectAll line will give me the initial data collection, so I should first cut this out. Then next line is data binding, then call enter gives me the new collection, wait, i need to delete the unbound elements, so I should first stop at data binding and make an assignment, with which later I can call exit()... Cover up the second code and try it yourself. Realize how cumbersome this process is?

var link = svg.append("g")
.attr(
"class", "links")
.selectAll(
"line")//cut here
.data(graph.links)//cut here so we call call exit
.enter().append(
"line")
.attr(
"stroke-width", function(d) { return Math.sqrt(d.value); });

var link = svg.append("g")
.attr(
"class", "links")
.selectAll(
"line")

var linkUpdate = link.data(graph.links);
linkUpdate.enter().append(
"line")
.attr(
"stroke-width", function(d) { return Math.sqrt(d.value); });

But what if we start with something like above? For one we just need to move sentences around and adding new ones, instead of reading through the whole chain trying to break it up.

But why is it better, you might ask? And why the previous one gives us problem?

You see, when we are using method chain, we usually hold the idea that we will always get the same object back each time we call a new function on it.

So for example in Jquery, you will be very comfortable with the following.

myEl.text('helloworld').css("color", "red").addClass("myclass")

Navigation is also not that hard to understand.

myEl.next().css("color", "red")

But be careful, in the second example we have context switching. After we call next, we are no long referring to the same object as before. But it is a very simple one so you mind bends without effort.

But in the previous no-break chain, how many times have we switched context? Five times! Big chances you might need to reuse some of the intermediate steps in the future. And everytime you are reading it, your mind is doing an extra hard round of twister. Why?

For one, the data() call for data binding and enter() call for getting to unbound collection are hardly very natural for human mind, as least not as self-explanatory as functions like next(). That, plus the example’s naming convention, aka calling these different contexts the same name, you will have headache 3 months later trying to read through your code ( which is exactly what happened to me yesterday).

So do yourself a favour, think twice when you are using method chain, and breaking them up if you notice you are switching context too many times.

Sunday, 21 January 2018

A useful pattern: disallow an action for a certain time

So I run into this problem when I have a socket event that fires quite frequently( but is supposed to work that way), and have an animation linking to this event, but do not want to fire the animation as frequently as the socket event itself. The solusion I deviced is to use a custom timer.


Thursday, 24 August 2017

Blur Brush

So I was looking for a blur brush and came across this neat solusion
The basic idea is to overlay [the brushed area to be blured] with the same area in actual image by using "source-in" composition, then draw this blured area back on top the original image. 
But one tiny problem with the original example is that it each time overlays the selected area with the original image instead of the updated one from last blurring, so the result of each brush does not add up. I modified the fiddle by adding another hidden canvas to keep account of the updates. 

Monday, 14 August 2017

Angular + d3(v4) pie chart

Been reading about  D3-ON-ANGULARJS, and in the chapter Dynamic Visualization it provides a nice example of a changeable d3 pie chart written with Angular. However the example is in v3, so I did a little bit modification to make it work in v4.


Wednesday, 19 April 2017

Async collection in a nutshell

So I am using async with Nodejs and think it might be useful to make myself a cheat sheet about Async Collection.

Why do I need Async Collections?

Me: So I want to do async operations on a batch of items...

Async: Say no more, bro.
“正是在下 表情包”的图片搜索结果


So, aync collection library have 12 distinct groups of functions, each including what I call a base form and its derivatives. The 12 base functions are:
concat, detect,each, every, filter, groupBy, map, sortBy, reduce, transform, some, reject.
Baker's dozen? False.
A dozen is twelve no matter who it came from. - Baker's dozen? False.
A dozen is twelve no matter who it came from.  Schrute


A little bit too much? Men's memory block is 4-7, right? Don't worry. Let's group them.

Let's do it in the form of a little questionare.


1. So you have a batch of items on which you want to run async functions. Is the function a truth test? 

A. Truth test. (Go to 2)        B. NO, OF COURSE NOT YOU ANIMAL. (Go to 5)


2. Do you just want a yes or no as result, or you want to have those objects as results?

A. Gimme boolean.(Go to 3)     B. Gimme Objects.(Go to 4)


3. So you want a simple yes or no. You wanna to know if every one of the items have passed the test? Or just if any of them have passed the test?

A. Every. (Use every.)               B. Any. (Use some)


4. You want group of items as results. Do you want the first one that has passed the test, or all? Or maybe all that failed the test?

A. First one passed.(Use detect). B. All passed.(Use filter). C.All failed. (Use reject.)


5. So you dont want truth test. But maybe you want a retained state between operation on each object?

A. NO, Seriously why would I want that.(Go to 6). B. YES. (Go to 9)


6.So you want normal stuff. Ok, do you need a grouped result of all operations or you are ok if they are seperately handled?

A. Separate, please. (Use each.)          B. No. I need all results to be handled together. (Go to 7)


7. So you want results of all items together. Does the sequence matter to you?

A. YES(Go to 8).       B. NO.(Use concat)


8. So you want results in right sequence. Do you have a criteria to group them, sort them, or original sequence of item is fine?

A. Group. (Use groupBy).            B.Sort. (Use sortBy)       C. Original sequence.(Use map)


9. So you want a retained state between operations. You can do it in series, or do it in parallel but with a key information. Which one?

A. Series. (Use reduce).        B.With key. (Use transform)




To sum up, let's use a chart.




I also made a small test program to tell the difference between each, concat and map.




And here's the result.





Oh, no. Almost forgot. What about the derivatives? So you may see a function like concatseries, what does the little affix 'series' mean you may wonder.

Here's a list of all the 'affixes'.

  • series : The async operation is run in series. One at a time.
  • limit : Runs a maximum number of async operations at a time. User can define this number through argument 'limit'.
  • of : This is only used with 'each'. Let you supply  key as an arguement of the async ooperations.
  • values: Used with 'map' function only. This function is used for objects and the async operation can have a key argument
  • right :Only used with reduce. Run series of items in reverse order.



Limit Series
concat
detect
every
filter
groupBy
reduce
reject
some
each
sortBy
map
transform


Special cases with each, map, reduce
each: eachOf, eachOfLimits. eachOfSeries
map: mapValues, mapValuesLimit, mapValuesSeries
reduce: reduceRight