tag:blogger.com,1999:blog-41089621413796841632024-03-14T01:19:26.054-05:00Think, Forrest! Think!Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.comBlogger360125tag:blogger.com,1999:blog-4108962141379684163.post-59337513644995305952023-06-20T11:27:00.005-05:002023-06-20T11:27:49.349-05:00AWS network inbound rules: All traffic is no traffic I found a very weird problem in AWS' network inbound rules, that although the default rule is to allow all traffic, it actually allows no traffic. At least is the case for PostgreSQL's port 5432 and SSH's port 22. <div><br /></div><div>To fix, I had to manually add rules to allow inbound traffic to certain ports, like below:
</div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgURsqOGUK8K5gIELeNy3oHAaPj0I7uZTz12K2GLixZ7k3oce3ytBlBiOwgQFJqtvlCLiboUKoH54pSJnmccYGD_P0ckdlqCoFIxmupXwknkHOb-EezbOoz9hrKaCKs1fiah8Tum2anfAx9fo9sZIbTconTAD-s6FY3QGh1wDigUNR8htdyYim9F7zwsvGS" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="277" data-original-width="1789" height="99" src="https://blogger.googleusercontent.com/img/a/AVvXsEgURsqOGUK8K5gIELeNy3oHAaPj0I7uZTz12K2GLixZ7k3oce3ytBlBiOwgQFJqtvlCLiboUKoH54pSJnmccYGD_P0ckdlqCoFIxmupXwknkHOb-EezbOoz9hrKaCKs1fiah8Tum2anfAx9fo9sZIbTconTAD-s6FY3QGh1wDigUNR8htdyYim9F7zwsvGS=w640-h99" width="640" /></a></div><br />This sounds redundant but I had to do this to make it work. </div><div><br /></div><div>I could set the source in the first rule to 0.0.0.0/0. This was the error I got: </div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgEK8NRIIvcKgzgmtWZaTcCo1PbO2a4D55M4Wz_lzSINlWv1xPQW0GK_9yvpZB9zdZDUJUnN9mWGbKVTldp9HxTB-CBojE8obrgNBjewSWbB4u2o8DBR5XB-djKI2JYu1CC1xVDsUMAaeBPryMRXsFxKehsfMkuyJFrkcVsWz28XcsS7Re_CQeNMvFeVqta" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="206" data-original-width="1368" height="96" src="https://blogger.googleusercontent.com/img/a/AVvXsEgEK8NRIIvcKgzgmtWZaTcCo1PbO2a4D55M4Wz_lzSINlWv1xPQW0GK_9yvpZB9zdZDUJUnN9mWGbKVTldp9HxTB-CBojE8obrgNBjewSWbB4u2o8DBR5XB-djKI2JYu1CC1xVDsUMAaeBPryMRXsFxKehsfMkuyJFrkcVsWz28XcsS7Re_CQeNMvFeVqta=w640-h96" width="640" /></a></div><br />If you have an explanation, please feel free to let me know. </div><div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-59610973979426822622021-12-27T20:49:00.002-06:002021-12-27T20:49:13.379-06:00Loading or including images or asset files in Webpack or ReactJS<p>In Webpack, or pretty much any frontend framework that relies on it, like ReactJS, if you want to include an image or any asset file, like a PDF, you will need a loader to handle it. You cannot simply write a line of HTML like <code> <img src="pipeline_demo.gif"/></code>, which will not move the asset file to the compiled output, making asset files inaccessible (404 error). </p>
<p>Instead, you need to use the <a href="https://www.npmjs.com/package/file-loader"><code>file-loader</code></a> module and import an asset file into a variable before using it. Just follow the official instructions and you will a really good result. There are lots of good examples at the end of the official doc. Many answers on Stackoverflow are noises -- like you need to have both <code>file-loader</code> and <code>url-loader</code>. </p>
<p>One thing that you want to pay attention to is that:</p>
<blockquote>
<p>ℹ️ By default the filename of the resulting file is the hash of the file's contents with the original extension of the required resource.</p>
</blockquote>
<p>So if you do not use any option for <code>file-loader</code>, it will result in a pretty big HTML file with the asset files being super long hash strings, like this:
<code>
< img src="data:image/gif;base64,R0lG0......" >
</code>
Hence, you want to use the <code>name</code> option unless you really want the hash strings, e.g., when you only have storage access to HTML files.
</p>
<p>Lastly, as someone who is new to MODERN front-end development, I feel front-end development has become so complicated. There are so much stuff to learn at once to start. So many points work together. It's very newbie-unfriendly. </p><div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-59171948591459207952021-09-01T00:53:00.005-05:002021-09-01T00:54:27.582-05:00When Tensorflow cannot match the checkpoint file ERROR:tensorflow:Couldn't match files for checkpoint <p>It seems that Tensorflow hardcodes the path to a checkpoint file using an absolute path. So if you move the checkpoints from one computer to another, you may run into errors like below: </p><pre>ERROR:tensorflow:Couldn't match files for checkpoint /root/result_base/cnn_dailymail/sent_delete/model.ckpt-273863</pre><p>To fix it, it's very simple. Just open the <code>checkpoint</code> file in the folder that stores Tensorflow result from an experiment, and replace the paths to checkpoints with the ones fit for the new computer. </p><p>For example, from</p><pre>model_checkpoint_path: "/root/result_base/cnn_dailymail/sent_delete/model.ckpt-273863"
all_model_checkpoint_paths: "/root/result_base/cnn_dailymail/sent_delete/model.ckpt-273863"</pre>
<p>to</p>
<pre>model_checkpoint_path: "/mnt/12T/data/NLP/result_base/cnn_dailymail/sent_delete/model.ckpt-273863"
all_model_checkpoint_paths: "/mnt/12T/data/NLP/result_base/cnn_dailymail/sent_delete/model.ckpt-273863"</pre><div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-1557542329341112642020-09-29T18:06:00.005-05:002020-09-29T18:06:57.466-05:00Linux WiFi disabled after a long period of no activities: bad wifi powersave<p>I have Lubuntu 18.04 on my Dell Inspiron 5000 laptop. A recurring problem
is that the WiFi becomes unavailable after I leave my laptop on for a long
period. The problem won't appear if I always put it back to sleep before leaving
it idle for a long time. Once the problem happens, I have to turn off and turn
on the computer exactly twice to fix it. Rebooting (e.g., sudo reboot) won't
even fix it. </p><p>Today I was so annoyed by this problem so I googled around. I am not
alone. Nearly everyone who had the issue points to WiFi power management. Some say that it
just took a really long time, e.g., 30 seconds, for the WiFi adapter to wake up
from sleep. Some has the problem after system wake up from
suspension -- but I don't have this problem. </p><p> It turns out that the most effective fix is to simply disable WiFi power management to prevent the WiFi adapter from going
into powersave mode. Just edit
</p><pre>/etc/NetworkManager/conf.d/default-wifi-powersave-on.conf
</pre>
and change the line
<pre>wifi.powersave = 3
</pre>
into
<pre>wifi.powersave = 2
</pre><p>
However, this also means that you will waste energy on WiFi when the computer is
idle. </p><p>Below are some links for those who want more information. </p><ul style="text-align: left;"><li>https://www.reddit.com/r/Lubuntu/comments/54endb/help_new_install_but_wifi_disconnects_randomly/ </li><li>https://core.docs.ubuntu.com/en/stacks/network/network-manager/docs/reference/snap-configuration/wifi-powersave</li><li><br /></li><li>https://askubuntu.com/questions/1022203/how-to-prevent-wifi-sleep-after-suspend </li><li>https://askubuntu.com/questions/695867/disable-wifi-power-management/961460</li><li>https://askubuntu.com/questions/1030653/wifi-randomly-disconnected-on-ubuntu-18-04-lts</li><li><br /></li></ul><div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-87558484431135084882020-05-17T06:51:00.000-05:002020-05-17T06:51:18.320-05:00Installing CircuitPython on Arduino MKR WIFIPart I: Installing CircuitPython<br />
<br />
In this part, we will be flashing two bootloaders sequentially onto MKR. <br />
<br />
1. Download and install the latest Arduino IDE https://www.arduino.cc/en/Main/Software <br />
2. Open the IDE. Go to Tools -> Boards -> Boards Manager. In Boards Manager, search "Arduino SAMD Boards (32-bits AMR Cortex-M0+)" and then click Install. After installation, select Tools -> Boards -> MKR WIFI 1010 <br />
3. Plug-in MKR WIFI into the computer via a USB cable, and select Tools -> Port -> MKR WIFI or the only USB device when MKR is plugged in. <br />
4. Download latest INO for MKR Zero's bootloader from https://github.com/adafruit/uf2-samdx1/releases to your computer, e.g., https://github.com/adafruit/uf2-samdx1/releases/download/v3.9.0/update-bootloader-mkrzero-v3.9.0.ino<br />
5. Open the INO file just downloaded and upload it to MKR. You should see something like this on your Arduino IDE:<br />
<code><br />
Sketch uses 21112 bytes (8%) of program storage space. Maximum is 262144 bytes.<br />
Global variables use 3464 bytes of dynamic memory.<br />
Atmel SMART device 0x10010005 found<br />
Device : ATSAMD21G18A<br />
Chip ID : 10010005<br />
Version : v2.0 [Arduino:XYZ] Mar 19 2018 09:45:14<br />
Address : 8192<br />
Pages : 3968<br />
Page Size : 64 bytes<br />
Total Size : 248KB<br />
Planes : 1<br />
Lock Regions : 16<br />
Locked : none<br />
Security : false<br />
Boot Flash : true<br />
BOD : true<br />
BOR : true<br />
Arduino : FAST_CHIP_ERASE<br />
Arduino : FAST_MULTI_PAGE_WRITE<br />
Arduino : CAN_CHECKSUM_MEMORY_BUFFER<br />
Erase flash<br />
done in 0.823 seconds<br />
<br />
Write 21112 bytes to flash (330 pages)<br />
<br />
[===== ] 19% (64/330 pages)<br />
[=========== ] 38% (128/330 pages)<br />
[================= ] 58% (192/330 pages)<br />
[======================= ] 77% (256/330 pages)<br />
[============================= ] 96% (320/330 pages)<br />
[==============================] 100% (330/330 pages)<br />
done in 0.128 seconds<br />
<br />
Verify 21112 bytes of flash with checksum.<br />
Verify successful<br />
done in 0.018 seconds<br />
CPU reset.<br />
</code><br />
<br />
6. MKR will restart. If not, press the reset button. A USB storage device called MKRZEROBOOT shall pop-up on your computer now. If a file called <pre>CURRENT.UF2</pre>is there, then you are good. <br />
<br />
7. Download the CircuitPython image for MKR from https://circuitpython.org/board/arduino_mkrzero/, the UF2 file. Then copy it to the MKRZEROBOOT device. Then the MKR will restart and the new USB storage device's name will become CIRCUITPY. If it doesn't restart automatically, press the reset button. <br />
<br />
<br />
Part II: Play around with CircuitPython<br />
<br />
1. Download and install Mu editor. For Windows and Mac, go to https://codewith.mu/en/download . For Linux, or Python on other platforms, you can simply use pip: <code>pip3 install mu-editor --user</code> Then start the Mu editor. <br />
<br />
2. Upon initial start, select "Adafruit CircuitPython". Then you see an blank editor. Now, click the "Serial" button at the top of the window. And you shall see the "Adafruit CircuitPython REPL" box. Click in it, and press any key to activate the Python console. Then, you can enjoy the Python shell. <br />
<br />
3. To run a script, in the Mu editor, paste the code below and save it as a file on your CIRCUITPY storage device and make sure it is the only file there. After saving, the MKR will restart on its own -- if not, press the reset button. And you shall see the orange LED blinking. <br />
<code><br />
import board<br />
import digitalio<br />
import time<br />
<br />
led = digitalio.DigitalInOut(board.D6)<br />
led.direction = digitalio.Direction.OUTPUT<br />
<br />
while True:<br />
print("Hello, CircuitPython!")<br />
led.value = True<br />
time.sleep(1)<br />
led.value = False<br />
time.sleep(1)<br />
</code><br />
<br />
Note that the interactive mode Python shell and the scripting mode (i.e., running code from a script file) cannot coexist. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-74227762286056902932020-04-24T04:59:00.001-05:002020-04-24T04:59:58.844-05:00Different Doesn’t Mean Wrong! I just realize that the East Asian culture has an anti-diversity or pro-orthodoxy part, kinda like monotheism. For thousands of years, kings heavily prompted only one philosophy, the Confucianism. Other ideas were considered unorthodox and eventually marginalized. So, East Asian cultures lack the mechanism of tolerating different options. In this sense, East Asia today, or even East Asian communities in the Western World, share something with Medieval Europe where anyone who said differently to the Pope's teaching were burned, exiled, banned from owning properties, etc. It happened to me several times that some Chinese American, or Chinese Chinese, friends broke up with me on professional things, e.g., terminating research collaboration, because I said something about the Chinese Communist Party that they disagreed -- there was no debate, i just posted on FB/TW. Because no one is holy and no one monopolies the truth, it's better to live with, and to enjoy different opinions. I am very proud of my culture heritage. But the pro-orthodoxy or "solo-truth" mentality, is something I do not agree -- hey, I do not say it is wrong nor do I hate my background. Happy Asian Pacific American Heritage Month of 2020! <br />
<br />
我突然意識到東亞文化是一種容不得異見的文化。你看韓國,所謂民主,前總統會被後總統搞死,不止一次了。在美國,敗選的政治人物無所謂,前總統不會被搞死。在東亞,幾千年的「罷黜百家,獨尊儒術」,使東亞人民相信,很多事情只有一個正解,其他都是錯的. 所以,若兩人觀點不同,只有兩種可能: a) 你是SB,腦殘,無腦,etc. b) 你是大逆不道,我不和你寫paper,不和你開公司,不和你在一個team,甚至把政治觀點帶到performance review中. 絕對不可能兩人都是對的或者錯的。東亞人民還活在中世紀的歐洲,和教皇意見相左的人士被燒死,被流放,被不能擁有房產,不能上大學,etc.<div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-69539928513660465962020-02-02T07:22:00.001-06:002020-02-02T07:22:48.159-06:00Jupyter server OSError: [Errno 99] Cannot assign requested addressIf you run into this error: <br />
<pre>OSError: [Errno 99] Cannot assign requested address
</pre>a likely fix is going to <code>/etc/hosts</code> and pointing <code>localhost</code> only to ipv4 loopback (127.0.0.1), not to ipv6's (::1). <br />
<br />
For example, on my computer, <code>/etc/hosts</code> looks like this: <br />
<br />
<pre>127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
xxx.xxx.xxx.xxx tinyai tinyai
</pre><br />
Just change it to <br />
<br />
<br />
<pre>127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
xxx.xxx.xxx.xxx tinyai tinyai
</pre><br />
Note the change at the <code>::1</code> line. <br />
<br />
For more details, read <a href="https://github.com/ipython/ipython/issues/6193#issuecomment-466082026">https://github.com/ipython/ipython/issues/6193#issuecomment-466082026</a><div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-62091135720283697552019-10-01T16:48:00.001-05:002019-10-01T16:48:29.493-05:00Python lists as local variables in recursionToday I ran into a really interesting problem. Let's use Leetcode's <a href="https://leetcode.com/problems/combinations/" target="_blank">Problem 77 combination</a> as an example. I wanted write a function that prints all possible combinations (no order, unlike permutation).<br />
<br />
So here is my function definition and call: <br />
<pre>def helper(n, k, start, L):
# L = list (L) # make a copy
if len(L) == k:# all k elements have been drawn
print L
else:
for i in range(start, n+1):
L.append(i)
print "L before recursion", l
helper(n,k,i+1, L) # down to next level
print "L after recursion", l
L = L[:-1]
helper(3,2,1, []) # picking 2 from 3
</pre><br />
But this was what I got: <pre>L before recursion [1]
L before recursion [1, 2]
[1, 2]
L after recursion [1, 2]
L before recursion [1, 3]
[1, 3]
L after recursion [1, 3]
L after recursion [1, 2] --- l is supposed to be [1] here as quitting the inner recursion
L before recursion [1, 2]
[1, 2]
L after recursion [1, 2]
L before recursion [1, 3]
[1, 3]
L after recursion [1, 3]
</pre><br />
As you can see, <code>L</code> never came back to <code>[1]</code>. It became (at the 8th line of the print-out) <code>[1,2]</code> after executing <code>helper(3,2,2, [1])</code>. Further, there are unmatching numbers of "before" and "after" which made no sense to me. <br />
<br />
It took me a couple of hours to think until I realized that maybe the reference of a list was the culprit. So I uncommented the "make a copy" line, and then things worked as expected:<pre>L before recursion [1]
L before recursion [1, 2]
[1, 2]
L after recursion [1, 2]
L before recursion [1, 3]
[1, 3]
L after recursion [1, 3]
L after recursion [1]
L before recursion [2]
L before recursion [2, 3]
[2, 3]
L after recursion [2, 3]
L after recursion [2]
L before recursion [3]
L after recursion [3]
</pre><br />
But I still had no clue why a copy fixed it, and even the in-and-out of recursions. <br />
If you know why, let me know. <br />
<br />
PS: An alternative fix is to let the function to return <code>L[:-1]</code>. In this way, the old <code>l</code> can be restored after a recursive call. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-38687498162128894842019-08-02T06:04:00.002-05:002019-08-02T06:04:52.988-05:00The evil and immoral cruise line business I had my first cruise trip not long ago. It wasn't a pleasant experience. The food was good. The room was good. The view was good. So why wasn't it pleasant? The way that the service staff were treated by the company.<br />
<br />
The food and stateroom service staff were talking to me as if I was the king and they were my peasants. I couldn't stand it. They acted like people who were not as equal as me, but inferior to me. I speculated that the company put lots of pressure on them to behave like that. I'd feel more comfortable should they interacted with me like how American hospitality works interact with me.<br />
<br />
Now I feel morally wrong to take cruise trips. I wish the cruise companies could behave as hiring someone on American soil, e.g., a McDonald's garnisher. Technically, the cruise was on US water. So I don't know why they were treated so badly.<div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-6719976427432571712019-05-24T00:16:00.004-05:002019-10-03T17:46:53.386-05:00Crowdfunding first time: BreadShield for Arduino<br />
<b>Update 10/2/2019</b>: BreadShield has hit the store of <a href="https://www.mouser.com/Tools-Supplies/Accessories/Crowd-Supply-Accessories/_/N-fb8waZ1yzvvqx?P=1y8chm1&FS=True">Mouser</a>, and <a href="https://www.tindie.com/products/16258/">Tindie</a>. Feel free to order from there. If you are outside of the US, I think our <a href="https://www.tindie.com/products/16258/">Tindie store</a> offers the most inexpensive shipping methods, with tracking info. <br />
<br />
<br />
tl;dr: Jump to here: <a href="https://www.crowdsupply.com/loser/breadshield?src=loser">https://www.crowdsupply.com/loser/breadshield</a><br />
<br />
I prototype a lot in Arduino and breadboard. But quite often, I end up with a jumper wire mess or spaghetti, like the one below:<br />
<br />
<img height="425" src="https://www.crowdsupply.com/img/e604/before-lcd-image-0483-clean_png_project-body.jpg" width="640" /><br />
<br />
And more important, I cannot use any shield boards jointly with my circuit on the breadboard -- jumper wires take all the spots. <br />
<br />
One day I thought, what if I could replace the mess with a shield board? So BreadShield was born. <br />
<br />
Take a look: <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-ZlLIpjXpUDU/XOd870TMxKI/AAAAAAAAPiA/4ko4v-7H3ZsRcpbKaPfylvzQtJwuSV18wCLcBGAs/s1600/IMG_0500.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://1.bp.blogspot.com/-ZlLIpjXpUDU/XOd870TMxKI/AAAAAAAAPiA/4ko4v-7H3ZsRcpbKaPfylvzQtJwuSV18wCLcBGAs/s640/IMG_0500.JPG" width="640" /></a></div><br />
And here is a comparison: <br />
<br />
<img src="https://www.crowdsupply.com/img/e823/breadshield-lcd-before-after-arrow_png_project-body.jpg" /><br />
<br />
Once the campaign concludes, I will open up the Github repository with all KiCAD files. It is open hardware. <br />
<br />
If you also think it can save you a lot of time, go grab one now <a href="https://www.crowdsupply.com/loser/breadshield?src=loser">https://www.crowdsupply.com/loser/breadshield</a>. It's just 7 dollars each (or 15 dollars for 3) and free US shipping is included. Thank you! <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-10456056942043514412018-11-09T18:54:00.001-06:002018-11-09T18:54:15.023-06:00A filesystem being mounted as either ext4 and ext3? I came across a very interesting problem on my computer today when moving my Dropbox folder as Dropbox is dropping support for non-ext4 filesystems on Linux now. I wasted a lot of time on this as I always believed that this partition was in ext4. So I couldn't figure out why I couldn't get expected by following instructions. <br />
<br />
I could mount a partition on my hard drive as either ext4 or ext3 format. Dropbox's daemon is not stupid. If the partition is mounted as ext3, it will complain. <br />
<br />
So here is the details. If I do not specify the format, it will be mounted as an ext3 partition. <br />
<br />
<pre>forrest@test:~$ sudo mount /dev/sdd1 /mnt/test/
forrest@test:~$ mount | grep sdd1
/dev/sdd1 on /mnt/test type ext3 (rw,relatime,data=ordered)
</pre><br />
If I specify the ext4 format, it will be mounted as an ext4 partition. <br />
<br />
<pre>forrest@test:~$ sudo umount /dev/sdc1
forrest@test:~$ sudo mount -t ext4 /dev/sdd1 /mnt/test/
forrest@test:~$ mount | grep sdc1
/dev/sdd1 on /mnt/test type ext4 (rw,relatime,data=ordered)
</pre><br />
<br />
I don't know why. But it confused me quite a bit. <br />
<br />
<div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-49294345301559571612017-10-08T16:50:00.002-05:002017-10-08T16:50:17.416-05:00My template to reject fundamentally flawed papersFrom time to time, I am invited to review papers that are fundamentally flawed. Those papers are written so poorly that I can decide their fates in 1 minute. To save myself from typing again, below is a template. I will just copy and paste. <br />
<br />
This paper is very poorly written. <br />
1. Lack of background from the biology problem to the computing counterpart to help broader audiences understand the problem. <br />
2. Equations without explanation of the variables used. <br />
3. No clear distinction between previous work and the authors' contribution(s). <br />
4. Typesetting making reading extremely difficult, e.g., lengthy English phrases in math/italic fonts. <br />
5. Too many English problems. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-54601202431806821812017-10-07T21:45:00.001-05:002017-10-07T21:47:08.604-05:00Quick reference examples for Amazon AWS Glacier command line interface (CLI)I do not use Amazon AWS Glacier very often. I backing up my files to Glacier every a few months. So I hate to check the manual all the time. Hence, this blog post. <br />
<br />
<h2>Preparation</h2><br />
Make sure that you have the <code>~/.aws/config</code> and <code>~/.aws/credentials</code> configured. In terms of how to set up, look at here: <a href="http://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html">http://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html</a><br />
<br />
I would also assume that you are familiar with the terminology of AWS Glacier. <br />
<br />
<h2>Listing vaults</h2><br />
In case that you forget what vaults you have in an AWS data center, do this: <br />
<br />
<pre>aws glacier list-vaults --account-id - --region us-east-2 --output table</pre><br />
<h2>Initiating a job for inventory retrieval</h2><br />
Basically if you wanna know what is in a vault, you do this. <br />
<br />
<pre>aws glacier initiate-job --account-id - --vault-name myvault --region us-east-2 --job-parameters "{\"Type\": \"inventory-retrieval\", \"Format\":\"CSV\", \"Description\":\"what's in my Neuro vault?\"}"</pre><br />
For more details, refer to <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-initiate-job-post.html">http://docs.aws.amazon.com/amazonglacier/latest/dev/api-initiate-job-post.html</a> and <a href="http://docs.aws.amazon.com/cli/latest/reference/glacier/initiate-job.html">http://docs.aws.amazon.com/cli/latest/reference/glacier/initiate-job.html</a><br />
<br />
To my surprise, I don't need to specify which profile to use. The AWS CLI seems to automatically find the profile/credential that match the data center and vault name. <br />
<br />
<h2>Listing jobs</h2><br />
Fetching the inventory is a job. In case the job ID is lost, here is the way to get it back. <br />
<br />
<pre>aws glacier list-jobs --account-id - --region us-east-1 --vault-name myvault --output table</pre><br />
I always prefer table-format output. <br />
<br />
<h2>Fetching job result</h2><br />
Either archive retrieval (download the file uploaded to the vault) or inventory retrieval is a job. You need to fetch the result after the job is done. Depending on the type of job, you will either get an inventory in the format specified (JSON by default) or the file uploaded to the vault. Be sure to specify the correct job ID. <br />
<br />
<pre>aws glacier get-job-output --account-id - --region us-east-1 --job-id xxxyyyzzz --vault-name myvault data.txt</pre><br />
<h2>Deleting an archive</h2><br />
<pre>aws glacier delete-archive --account-id - --vault-name myvault --archive-id xxxyyyzzz
</pre><div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-1527396107587546772017-10-02T17:18:00.001-05:002017-10-02T17:18:29.801-05:00Friendship before mentorship<br />
"You should run your startup like a cult" -- Peter Thiel, "Zero to One"<br />
<br />
Short version: If you are a graduate student who do not want to become friends ever with your PhD advisor, then my lab is not a good place for your PhD study. <br />
<br />
When it comes down to what graduate students to work with, I am very picky. <br />
<br />
I believe that a graduate student and his/her advisor (note not a supervisor) should at least be friends. Otherwise, they shouldn't work together. Of course, there are many positions and professional relationships that are not like that. But I cannot work with people who just treat me as another piece of equipment. <br />
<br />
By friend, I mean a person that you feel comfortable sharing the following information with:<br />
1. I had a dog when I was 5. And the dog passed away tragically. (because you seek sympathy from a friend)<br />
2. I broke up with my girlfriend last week. (because you seek support from a friend)<br />
3. I got Nobel Prize in 2017! (because you share happiness with a friend, or you just wanna show off)<br />
<br />
You don't have to be a friend with me right now. But if you anticipate that you cannot become a friend with me after a semester, maybe you shouldn't walk into my office and ask "Are you taking any graduate students?"<div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-53467473420666308322017-09-23T14:14:00.000-05:002017-09-23T14:14:39.685-05:00Tuning Grub 2, the bootloaderBelow of some useful tips for Grub2, the open source bootloader. You are to edit the file <code>/etc/default/grub</code>. After you are done with any of the changes below, run <pre>sudo grub-update</pre>to apply the change. <br />
<br />
1. Get rid of the submenu:<br />
<br />
Add a line: <pre>GRUB_DISABLE_SUBMENU=y</pre><br />
2. Set the default entry: https://help.ubuntu.com/community/Grub2/Submenus<br />
<br />
3. If you want your Linux system to book into text mode/console/command line, just follow this http://ubuntuhandbook.org/index.php/2014/01/boot-into-text-console-ubuntu-linux-14-04/ Basically, you need to make the following changes. <br />
<br />
3.1 Uncomment or enable the line <code>GRUB_TERMINAL=console</code><br />
3.2 Commend or disable the line <code>GRUB_CMD_LINE_LINUX_DEFAULT="quiet splash"</code> or whatever value on the right hand side of the equal sign. <br />
3.3 Change <code> GRUB_CMDLINE_LINUX=””</code> to <code>GRUB_CMDLINE_LINUX=”text”</code><br />
<br />
4. Leave you a timeout for changing Grub at system boot<br />
<br />
Remember to always set a non-zero value for <code>GRUB_TIMEOUT</code>, e.g., <br />
<pre>GRUB_TIMEOUT=10</pre>in case something goes wrong. <br />
<br />
But it is not terribly bad if you mess up. Just mount the drive in which you Ubuntu is installed, go to <code>/boot/grub/grub.cfg</code> to edit the settings. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-6569884316342924282017-09-20T17:42:00.001-05:002017-09-20T17:42:53.838-05:00Connecting to a WiFi network on Linux at startup without GUIMany embedded Linux platforms are expected to connect to a WiFi network at startup automatically. And the Linux system is booted into multi-user model, i.e., no GUI, X window, or desktop environment. A lot of the solutions, e.g., making a connection available for all users, floating on the Internet are for Linux systems that boot into a desktop environment. In those cases, the <code>nm-applet</code>, which has an icon sitting in the tray area of the desktop environment, handles the connection to WiFi. <br />
<br />
The discussion below applies to Ubuntu 15.04+, which uses <code>systemd</code> to manage initialization process. <br />
<br />
<h2>Background</h2>NetworkManager is a daemon that manages networking devices on Linux systems. It has become the de facto network managing program for Linux since its introduction in 2004. See more at Wikipedia: <a href="https://en.wikipedia.org/wiki/NetworkManager">https://en.wikipedia.org/wiki/NetworkManager</a> <br />
<br />
Since it is a daemon, users interact with it via other applications. On most modern Linux distributions, you see an icon on the tray area, that once clicked, will give you a list of WiFi network IDs (SSIDs). This application is called <code>nm-applet</code>. NetworkManager also has a command line interface called <code>nmcli</code>.<br />
<br />
<h2>Easy solution: Connect once and remember. </h2><br />
NetworkManager will automatically connect to a WiFi network that was connected to previously. So, you can connect to a WiFi network under a desktop environment using <code>nm-applet</code>, or use command line (see below), then boot into no-GUI (e.g., system level 3) forever, and enjoy the same WiFi network forever. <br />
<br />
If you've connected to multiple WiFi networks before, it's very hard to say which one will be connected to in the future, supposing they will all be available. Most likely, the very last one connected to will be the top candidate. If unsure, see the next two sections. <br />
<br />
<h2>In case you need to connect to a WiFi network via command line</h2>There are many cases that you want to specify which WiFi network to connect to, e.g., the first time or you want to switch the network. The command to connect to a WiFi SSID uses the following syntax: <br />
<pre>nmcli device wifi connect $SSID</pre>For example, <br />
<pre>nmcli device wifi connect Haha</pre>where <code>H360</code> is the SSID. <br />
<br />
<h2>Specifying the WiFi network to connect to at startup</h2><br />
As mentioned earlier, if you have connected to multiple WiFi networks before, NetworkManager will use an algorithm, which is unfortunately unclear and thus underterministic to me, to pick one (assuming that they are all still available) the next time. To ensure to connect to a particular network, you can create a startup service for <code>systemd</code>, the initialization manager of modern Linux, to be executed at system startup. <br />
<br />
Let's call the service <code>mywifi</code>. Create a file called <code>mywifi.service</code> under <br />
<pre>/etc/systemd/system</pre>with content like this:<br />
<pre>[Unit]
Description=Connect to Haha
[Service]
ExecStart=/usr/bin/nmcli device wifi connect
[Install]
WantedBy=multi-user.target
</pre><br />
As you can see, the command to connect to a network called H360 is to be executed at startup, only when the system is booting into multi-user level (see <a href="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/sect-Managing_Services_with_systemd-Targets.html">the Red Hat doc for levels</a>.)<br />
<br />
Then enable this service and finally reboot<br />
<pre>systemctl enable mywifi</pre><br />
By "enable", we mean automatically running this service at startup without logging in. <br />
<br />
<h2>Troubleshooting: device unavailable</h2>I had some rare cases that a WiFi interface device is unavailable. Simply stop and restart the NetworkManager service may solve the problem: <br />
<pre>systemctl stop NetworkManager
systemctl start NetworkManager
</pre><br />
<h2>Some examples for using <code>nmcli</code></h2><pre>forrest@A785GM-M:~$ nmcli device status
DEVICE TYPE STATE CONNECTION
wlx001478962ea6 wifi connected Haha 4
en2s0 ethernet unavailable --
lo loopback unmanaged --
forrest@A785GM-M:~$ nmcli general status
STATE CONNECTIVITY WIFI-HW WIFI WWAN-HW WWAN
connected full enabled enabled enabled enabled
forrest@A785GM-M:~$ nmcli radio wifi
enabled
forrest@A785GM-M:~$ nmcli dev wifi
* SSID MODE CHAN RATE SIGNAL BARS SECURITY
* Haha Infra 1 54 Mbit/s 100 ▂▄▆█ WEP
TP-LINK_6DFF Infra 5 54 Mbit/s 100 ▂▄▆█ WPA1 WPA2
-- Infra 10 54 Mbit/s 100 ▂▄▆█ WPA2
* Haha Infra 1 54 Mbit/s 99 ▂▄▆█ WEP
</pre><br />
<h2>References</h2><ul><li>How to write startup script for systemd, <a href="https://unix.stackexchange.com/questions/47695/how-to-write-startup-script-for-systemd">https://unix.stackexchange.com/questions/47695/how-to-write-startup-script-for-systemd</a><br />
</li>
<li>What is the structure of network managers system-connections files? <a href="https://askubuntu.com/questions/368560/what-is-the-structure-of-network-managers-system-connections-files">https://askubuntu.com/questions/368560/what-is-the-structure-of-network-managers-system-connections-files</a></li>
<li>How to connect and disconnect to a network manually in terminal?<a href="https://askubuntu.com/questions/16584/how-to-connect-and-disconnect-to-a-network-manually-in-terminal/">https://askubuntu.com/questions/16584/how-to-connect-and-disconnect-to-a-network-manually-in-terminal/</a></li>
<li>nmcli-examples -- usage examples of nmcli, <a href="https://developer.gnome.org/NetworkManager/stable/nmcli-examples.html">https://developer.gnome.org/NetworkManager/stable/nmcli-examples.html</a></li>
</ul><div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-72235089032690068692017-08-03T00:17:00.003-05:002017-08-03T00:19:18.875-05:00Solution to most not-found or undefined problems in C/C++ compilationMany people have compilation errors. If you search "undefined reference to" in Google, or maybe StackOverflow alone, you will notice that those problems have been asked dozens if not hundreds of times. There are generally 4 problems:<br />
<ul><li>was not declared in this scope</li>
<li>no such a file or directory</li>
<li>undefined reference to</li>
<li>error while loading shared library, or cannot open shared object file</li>
</ul><br />
The thing is actually very simple: the compiler is not told to find the right file at the right place. The discussion below is based on Linux using GCC for C and C++.<br />
<br />
<h1>Problem 1: <code>was not declared in this scope</code></h1>Usually, this problem has nothing to do with your system settings or compiler configuration. It's a problem within your source code. On the top level, the function is not defined. The reason can vary. <br />
<br />
One reason is that the file declaring (or defining, if the declaration is done together with definition) the functions is not specified, e.g., the header file is not included. This can be easily fixed by including such a file in your source code.<br />
<br />
Another reason is that you used the function beyond its class or namespace. <br />
<br />
<h1>Problem 2: <code>No such a file or directory</code> for a header file</h1><br />
If a header file is not found, the preprocessor or the preprocessor part of the compiler, will raise the error <code>No such a file or directory</code>. Depends on where the header files are supposed to be at, there are different solutions. <br />
<br />
Most C/C++ compiles treat the quote form of <code>#include</code> and angle-bracket form of <code>#include</code> differently. Simply running <br />
<pre>$ echo | gcc -E -Wp,-v -</pre>will tell you the difference: <br />
<pre>#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/5/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
</pre><br />
Those directories listed under the section <code>#include <...> search starts here:</code> are referred to as standard system directories [1]. They are from the convention of Linux systems' file hierarchy. <br />
<br />
If you want to expand the search for angle-bracket form <code>#include<...></code>, use the <code>-I</code> option. The preprocessor will search header files in directories followed by <code>-I</code> option before searching system directories. Hence, a header file in a <code>-I</code>-option directory will override its counterpart in system directories and be used to compile your code. <br />
<br />
For quote form <code>#include"..."</code>, the preprocessor will first search in the current directory that the source file is at and then all the directories specified after the <code>-iquote</code> option.<br />
<br />
The example below will show you how <code>-I</code> and <code>-iquote</code> append search paths:<br />
<pre>l$ echo | gcc -iquote/home/forrest/Downloads -I/home/forrest/Dropbox -E -Wp,-v -
#include "..." search starts here:
/home/forrest/Downloads
#include <...> search starts here:
/home/forrest/Dropbox
/usr/lib/gcc/x86_64-linux-gnu/5/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
</pre><br />
So, if you have the following macro in your code called <code>mycode.c</code>:<br />
<pre>#include < xyz.h>
#include "abc/xyz.h"</pre>and your GCC command is like this<br />
<pre>gcc mycode.c -I/opq/ -iquote/uvw
</pre>then the GCC's preprocessor (again, it's part of the GCC) will look for header files in the following full paths (on Ubuntu Linux 16.04) in addition to the search in system directories:<br />
<pre>/opq/xyz.h
/uvw/abc/xyz.h
</pre>According to GCC document[1], it searches for header files in quote form <code>#include"..."</code> before searching for angle-bracket form <code>#include"..."</code>. <br />
<br />
Further specifications can be achieved using two other options <code>-isystem</code> and <code>-idirafter</code>. They are all well documented in GCC document[2]. <br />
<br />
<h1>Problem 3: <code>Undefined reference to</code></h1>You probably see an error like this <br />
<pre>face.cpp:(.text._ZN2cv3Mat7releaseEv[_ZN2cv3Mat7releaseEv]+0x4b): undefined reference to `cv::Mat::deallocate()'
collect2: error: ld returned 1 exit status</pre>This is a link-time error when the linker <code>ld</code>, which is called automatically when you use GCC, cannot find the binary library that contains at least one function called by your code. <br />
<br />
To fix, first tell the compiler (actually it's linker part) the path containing library files using the <code>-L</code> option [2] and then library file names using the <code>-l</code> option [4]. If we denote the values after <code>-l</code> and <code>-L</code> options as X and Y respectively, the compiler will search for every file called <code>libY.so</code> under every directory X. That's why on (almost) all Linux systems, a shared library file begins with <code>lib</code> and ends with the appendix <code>.so</code>, such as <code>libopencv_core.so</code>.<br />
<br />
For example, the command<br />
<pre>$ g++ face.cpp -L/opencv/lib -lopencv_core -lopencv_videoio</pre>will ask the linker to find the following binary library files:<br />
<pre>/opencv/lib/libopencv_core.so
/opencv/lib/libopencv_videoio.so
</pre><br />
Note that you may not be able to use some shell directives, such as <code>~</code> after the <code>-L</code> option. <br />
<br />
In most cases, you do not need to use the <code>-L</code> and <code>-l</code> options because the compiler (again, its linker part) automatically searches in a set of system directories. When you have to, some tools can help you, such as <a href="https://www.freedesktop.org/wiki/Software/pkg-config/">pkg-config</a>. I will write another blog post. <br />
<br />
<h1>Problem 4: <code>error while loading shared libraries</code> or <code>cannot open shared object file</code><br />
</h1><br />
Now, your program has been successfully compiled. When running it, you probably see an error like this: <br />
<pre>./a.out: error while loading shared libraries: libopencv_core.so.3.3: cannot open shared object file: No such file or directory </pre>This problem is from the loader. Unlike the link-time error above, this problem is a run-time error. The shared library filenames are usually hardcoded into your binary program. To fix it, simply tell the loader where to find the specified shared library files. There are multiple ways. <br />
<br />
<b>Solution 1</b>: Most Linux systems maintain an environment variable <code>LD_LIBRARY_PATH</code> and the loader will search for binary library files requested by a program in all directories listed in <code>LD_LIBRARY_PATH</code>, on top of a set of standard system directories, such as <code>/lib</code> or <code>/usr/lib</code>. To set <code>LD_LIBRARY_PATH</code> is like how you set any other environment variables, e.g., export on the Shell or edit and source <code>~/.bashrc</code>. <br />
<br />
<b>Solution 2</b>: Most Linux systems also maintains a shared library cache by a program called <code>ld-config</code>. It remembers where to find the default location of each shared library file. Simply run <br />
<pre>$ ldconfig -p</pre>it will tell you the mapping from shared library files to absolute paths in the system, e.g., <br />
<pre>2591 libs found in cache `/etc/ld.so.cache'
libzzipwrap-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzipwrap-0.so.13
libzzipmmapped-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzipmmapped-0.so.13
libzzipfseeko-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzipfseeko-0.so.13</pre><br />
To change the mapping, simply edit <code> /etc/ld.so.conf </code> and then run <br />
<pre>$ sudo ldconfig</pre>to rebuild the cache. <br />
<br />
<b>Solution 3</b>: The two changes above are applied system-wide. A more flexible way is to specify the location of the shared libraries when linking your code using the <br />
<pre>-Wl,-rpath</pre>option, e.g., <br />
<pre>g++ face.cpp -idirafter ~/Downloads/opencv_TBB_install/include -L/home/forrest/Downloads/opencv_TBB_install/lib -lopencv_core -lopencv_objdetect -lopencv_highgui -lopencv_imgproc -lopencv_videoio -Wl,-rpath=/home/forrest/Downloads/opencv_TBB_install/lib</pre><br />
The disadvantage of Solution 3 is that if you change the location of the shared library, then you will run into error again. <br />
<br />
<br />
References:<br />
[1] Filesystem Hierarchy, https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard<br />
[2] GCC options for directories https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html<br />
[3] Shared Library How-To, http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html<br />
[4] GCC options for linking, https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html<div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-87678184194525924322017-07-07T22:06:00.001-05:002017-07-07T22:06:21.177-05:00The correct dimensions of Hitec C1 spline The C1 spline of 24 teeth is the standard shaft size for Hitec's servo motors, which are quite popular in maker community. Recently, I needed to design some parts that fits with it. However, finding it's accurate inner (basic) and outer (tip or addendum) diameters is very difficult. I don't know why this company does not simply release a drawing of it. <br />
<br />
Some info floating on the Internet is not really accurate, such as this one: <a href="https://www.blogger.com/www.robotshop.com/blog/en/hobby-robot-industry-standards-hubs-patterns-18681">www.robotshop.com/blog/en/hobby-robot-industry-standards-hubs-patterns-18681</a> <br />
<br />
In the end, I reverse engineered from a design shared on GrabCAD and get the dimensions that work: <a href="https://grabcad.com/library/servo-horn-with-c1-spline-1">https://grabcad.com/library/servo-horn-with-c1-spline-1</a><br />
<br />
Here we go:<br />
<ul>
<li>Inner radius: 2.520 mm</li>
<li>Outer radius: 2.845 mm. </li>
</ul>
If you wanna 3D print an inner gear (a.k.a., annular gear) that fits with C1 spline, be sure to take the error or expansion that 3D printing can produce into consideration. In my case, I increased both inner and outer radii by 0.15 mm to 2.670 and 2.995mm respectively. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-62900925774705200502017-06-21T21:37:00.004-05:002017-06-21T21:37:58.197-05:00Creating an arbitrary surface or any geometric element in FreeCADCreating an arbitrary geometric element, such as a surface or a polygon, is a task common in CAD. <br />
<br />
FreeCAD provides two ways to do so in its Part module. <br />
<br />
The first approach is called Create Primitives, where you specify the parameters to define a geometric element. The menu is Part -> CreatePrimitives. See <a href="https://www.freecadweb.org/wiki/Part_CreatePrimitives">https://www.freecadweb.org/wiki/Part_CreatePrimitives</a><br />
<br />
An example is below. <br />
<br />
<a href="https://2.bp.blogspot.com/-BGCPaW-WPio/WUstVUo4I8I/AAAAAAAANqM/xEA0X1fZGyQ89zbg6ZO8Rr6F3O6pQxp7ACLcBGAs/s1600/FreeCAD_Parametric_Primitive.png" imageanchor="1" ><img border="0" src="https://2.bp.blogspot.com/-BGCPaW-WPio/WUstVUo4I8I/AAAAAAAANqM/xEA0X1fZGyQ89zbg6ZO8Rr6F3O6pQxp7ACLcBGAs/s320/FreeCAD_Parametric_Primitive.png" width="258" height="320" data-original-width="625" data-original-height="775" /></a><br />
<br />
The second approach is called Shape Builder, where you build a new shape from elements defined earlier, such as creating a face from edges or vertexes. The menu is Part -> Shapebuilder. See <a href="https://www.freecadweb.org/wiki/Part_Shapebuilder">https://www.freecadweb.org/wiki/Part_Shapebuilder</a><br />
<br />
A good reference of all functions that Part module provides can be found here <a href="https://www.freecadweb.org/wiki/Part_Module">https://www.freecadweb.org/wiki/Part_Module</a><div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-64028318635522836182015-12-22T00:20:00.001-06:002015-12-22T00:21:59.295-06:00Population of Northeast OhioLet's just look at some data of the population of northeast Ohio (NEO).<br />
<br />
This is what the population distribution in NEO looks like:<br />
<br />
<iframe id="cr-embed-33000US184-demographics-age-distribution_by_decade-total" class="census-reporter-embed" src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/iframe.html?geoID=33000US184&chartDataID=demographics-age-distribution_by_decade-total&releaseID=ACS_2013_1-year&chartType=histogram&chartHeight=200&chartQualifier=&chartTitle=Population+by+age+range&initialSort=&statType=scaled-percentage" frameborder="0" width="100%" height="300" style="margin: 1em; max-width: 720px;"></iframe><br />
<script src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/js/embed.chart.make.js"></script><br />
<br />
In contrast, this is what the overall US population distribution looks like:<br />
<br />
<iframe id="cr-embed-01000US-demographics-age-distribution_by_decade-total" class="census-reporter-embed" src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/iframe.html?geoID=01000US&chartDataID=demographics-age-distribution_by_decade-total&releaseID=ACS_2013_1-year&chartType=histogram&chartHeight=200&chartQualifier=&chartTitle=Population+by+age+range&initialSort=&statType=scaled-percentage" frameborder="0" width="100%" height="300" style="margin: 1em; max-width: 720px;"></iframe><br />
<script src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/js/embed.chart.make.js"></script><br />
<br />
NEO is older than the other two big metros in Ohio, Cincinnati and Columbus:<br />
<br />
<iframe id="cr-embed-31000US17140-demographics-age-distribution_by_decade-total" class="census-reporter-embed" src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/iframe.html?geoID=31000US17140&chartDataID=demographics-age-distribution_by_decade-total&releaseID=ACS_2013_1-year&chartType=histogram&chartHeight=200&chartQualifier=&chartTitle=Population+by+age+range&initialSort=&statType=scaled-percentage" frameborder="0" width="100%" height="300" style="margin: 1em; max-width: 720px;"></iframe><br />
<script src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/js/embed.chart.make.js"></script><br />
<br />
<iframe id="cr-embed-31000US18140-demographics-age-distribution_by_decade-total" class="census-reporter-embed" src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/iframe.html?geoID=31000US18140&chartDataID=demographics-age-distribution_by_decade-total&releaseID=ACS_2013_1-year&chartType=histogram&chartHeight=200&chartQualifier=&chartTitle=Population+by+age+range&initialSort=&statType=scaled-percentage" frameborder="0" width="100%" height="300" style="margin: 1em; max-width: 720px;"></iframe><br />
<script src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/js/embed.chart.make.js"></script><br />
<br />
This is what Dallas looks like: <br />
<br />
<iframe id="cr-embed-31000US19100-demographics-age-distribution_by_decade-total" class="census-reporter-embed" src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/iframe.html?geoID=31000US19100&chartDataID=demographics-age-distribution_by_decade-total&releaseID=ACS_2013_1-year&chartType=histogram&chartHeight=200&chartQualifier=&chartTitle=Population+by+age+range&initialSort=&statType=scaled-percentage" frameborder="0" width="100%" height="300" style="margin: 1em; max-width: 720px;"></iframe><br />
<script src="https://s3.amazonaws.com/embed.censusreporter.org/1.0/js/embed.chart.make.js"></script><br />
<br />
The average ages in Cleveland, Cincinnati, and Columbus are: 41.1, 37.9, and 35.7. As a comparison, the average age of Dallas is 34.2. Cleveland population is 7 years older than that of Dallas. <br />
<br />
The fertility rate of Cleveland, Cincinnati, and Columbus are: 4.8%, 5.2%, and 5.4%. As a comparison, the fertility rate of Dallas is 5.4%. <br />
<br />
Hence, NEO has fewer women at birth age (15 to 50) than the national average and its fertility rate is under national average. The result? Fewer babies. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-55136927815405971832015-11-22T15:43:00.000-06:002015-11-24T14:42:06.091-06:00Bowtie index building problem for U's in sequencesI am having a weird problem with <a href="http://bowtie-bio.sourceforge.net">Bowtie</a> index builder. <br />
<br />
I have two entries in my FASTA file: <pre>forrest@narnia:/bioinfo/out-house/miRBase$ cat 157.fa
>ath-miR157a-5p-U
UUGACAGAAGAUAGAGAGCAC
>ath-miR157a-5p_T
TTGACAGAAGATAGAGAGCAC</pre><br />
After building the index, I use <code>bowtie-inspector</code> to check the index. <pre>forrest@narnia:/bioinfo/out-house/miRBase$ bowtie-build 157.fa 157 -q
forrest@narnia:/bioinfo/out-house/miRBase$ bowtie-inspect -s 157
Colorspace 0
SA-Sample 1 in 32
FTab-Chars 10
Sequence-1 ath-miR157a-5p-U 18
Sequence-2 ath-miR157a-5p_T 21
</pre><br />
Strangely, the length of ath-miR157a-5p-U becomes 18 instead of 21. The 3 U's of it are missed. <br />
<br />
Even more strangely, not all U's in all sequences are ignored. This problem happens for some but not all. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-54781512914772935092015-11-03T08:35:00.000-06:002015-11-03T08:38:52.923-06:00Named Entity Recognition using SpaCy in 5 minutesRecently, I am looking it <a href="http://spacy.io/">SpaCy</a>, a startup and an NLP toolkit. It is fabulous on its speed. Today, I just gave it a try on NER. Just a few lines (as in iPython):<br />
<br />
<pre>In [1]: import spacy.en
In [2]: parser = spacy.en.English()
In [12]: ParsedSentence = parser(u"alphabet is a new startup specializing in eating their own words on leaving china to fight for information freedom")
In [13]: print ParsedSentence.ents
()
In [14]: ParsedSentence = parser(u"Alphabet is a new startup specializing in eating their own words on leaving China to fight for information freedom")
In [15]: print ParsedSentence.ents
(Alphabet, China)
In [16]: for Entity in ParsedSentence.ents:
....: print Entity.label, Entity.label_, ' '.join(t.orth_ for t in Entity)
....:
349 ORG Alphabet
350 GPE China
</pre><br />
I used only default settings. Apparently, the NER of SpaCy is very sensitive to case of words. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com1tag:blogger.com,1999:blog-4108962141379684163.post-67893435286767064232015-10-01T22:52:00.000-05:002015-10-01T22:52:38.590-05:00Why is it hard to learn Amazon AWSAmazon AWS is awesome. And it is not really difficult to learn - except the part of reading documents and learning terminology. <br />
<br />
If you want answer for one thing, AWS could give you more than one places. For example, if you wanna know how to SSH into your instance, here are the two places in the same user guide:<br />
<br />
<a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html">http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html</a><br />
<br />
and <br />
<br />
<a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-connect-to-instance-linux.html">http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-connect-to-instance-linux.html</a><br />
<br />
I wish the learning experience can be easier. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-53753289559604480942015-08-05T23:07:00.000-05:002015-08-09T13:48:27.172-05:00Epilepsy 101 for Computational PeopleDisclaimer: This document cannot be used as any ground for medical and legal purposes. I write this up just because I am tired of explaining basic epilepsy terms to my colleagues (informatists, not neurologists) again and again.<br />
<br />
<ol><li><a href="https://en.wikipedia.org/wiki/Epilepsy">Epilepsy</a> is a neurological disorder while seizure is a characteristic symptom of epilepsy. Jerks are one kind of seizures.</li>
<li>In 1981, ILAE made a <b><a href="https://en.wikipedia.org/wiki/Seizure_types">seizure classification</a></b> that is widely used until today<br />
<ol type="I"><li><a href="https://en.wikipedia.org/wiki/Partial_seizure">Focal Seizures</a>: seizure limited in or originated from one hemisphere of the brain<br />
<ol type="A"><li>simple partial seizures, (simple: no interruption on consciousness)</li>
<li>complex partial seizures, (complex: with interruption on consciousness) and </li>
<li>partial seizure evolving into secondary generalized seizures, about 1/3 of partial seizures</li>
</ol></li>
<!--End of partial seizure type-->
<li>(Primary) Generalized Seizures: seizure all over the brain<br />
<ol type="A"><li>absence seizures (kinda like blackout), formerly called petit mal</li>
<li><a href="https://en.wikipedia.org/wiki/Tonic%E2%80%93clonic_seizure">tonic-clonic seizures</a> (kinda like whole-body jerk), formerly called grand mal</li>
<li>many other generalized seizures</li>
</ol></li>
<!--End of generalized seizures-->
<li>Unclassified epileptic seizures</li>
</ol></li>
<!--End of seizure classification-->
<li>In 1989, ILAE made an <b><a href="https://en.wikipedia.org/wiki/Epilepsy#Classification">epilepsy classification</a></b> that is widely used until today<br />
<ol type ="I"><li>Focal Epilepsies<br />
<ol type="A"><li>sympotomatic or cryptogenic (cause unknown): e.g., <a href="https://en.wikipedia.org/wiki/Temporal_lobe_epilepsy">temporal lobe epilepsy (TLE)</a></li>
<li>idopathic (genetic causes): e.g., benign childhood epilepsy</li>
</ol></li>
<!--End of focal epilepsies-->
<li>Generalized Epilepsies<br />
<ol type="A"><li>sympotomatic or cryptogenic (cause unknown): e.g., West syndrome, Lennox-Gastaut syndrom</li>
<li>idiopathic: e.g., childhood absence epilepsy, juvenile absence epilepsy, </li>
</ol></li>
<!--End of generalized epilepsies-->
<li>Epilepsies undertermined whether focal or generalized</li>
</ol></li>
<!--End of epilepsy classification-->
<li>When seizure is onset, we say the subject is in <b>ictal</b> state. Otherwise, <b>interictal</b> state. Because seizure duration (few seconds/minutes) is much shorter compared with interictal period, interictal EEG is more accessible.</li>
<li>EEG is a gold standard for epilepsy diagnosis. However, neurologists heavily rely on either ictal EEG or <a href="http://emedicine.medscape.com/article/1138880-overview">interictal epileptiform discharges (IEDs</a>, such as sharp wave and spikes) in diagnosis. The IEDs are the distinctive EEG patterns for epilepsy when subjects are not in seizure. Because seizure and IEDs happen unpredictably and sporadically, the way to catch them is to use long-term EEG recordings which can last from hours to days. Such tedious procedure is costly and inconvenient. </li>
<li>Typical signal processing and machine learning problems related to epileptic EEG<br />
<ol type="a"><li>coarse epilepsy diagnosis: distinguishing epileptic interictal EEG (with or without IEDs) and non-epileptic EEG</li>
<li>fine epilepsy/seizure diagnosis: identifying the type of seizure and/or epilepsy based on ictal or interictal EEG</li>
<li>seizure detection: detecting seizure activities from epileptic subjects' EEG</li>
<li>seizure prediction: predicting the onsets of seizure activities from epileptic subjects' EEG </li>
<li>focus localization: locating the epileptogenic zone (for focal seizures only) </li>
</ol></li>
<!--End of epilepsy research problem--> </ol><br />
References:<br />
1. For complete list of seizure types and epilepsy types, check Tables 9-1 and 9-2 on Pages 121-122 of this doc from British gov: h<a href="http://www.nice.org.uk/guidance/cg137/resources/cg137-epilepsy-full-guideline3">ttp://www.nice.org.uk/guidance/cg137/resources/cg137-epilepsy-full-guideline3</a> which are reprinted from 1981 and 1989 ILAE classifications. <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0tag:blogger.com,1999:blog-4108962141379684163.post-37174706857618438862015-07-16T15:50:00.002-05:002015-07-16T15:58:20.615-05:00MinMaxScaler() of sklearn.preprocessingThis is just a note demonstrating how to scale and de-scale data using MinMaxScaler() of sklearn.preprocessing. <br />
<br />
<pre>In [4]: import sklearn.preprocessing
In [5]: X=sklearn.preprocessing.MinMaxScaler()
In [7]: X.fit_transform([1.,2.,3.,4.])
Out[7]: array([ 0. , 0.33333333, 0.66666667, 1. ])
In [10]: X.scale_
Out[10]: 0.33333333333333331
In [14]: X.min_
Out[14]: -0.33333333333333331
In [17]: 4.*X.scale_+X.min_ # from non-scaled value to scaled value, a.k.a., transform
Out[17]: 1.0
In [19]: (1-X.min_)/X.scale_ # from scaled value back to scaled_value, a.k.a., inverse_transform
Out[19]: 4.0
</pre><br />
<br />
References:<br />
<br />
[1] <a href="http://stackoverflow.com/questions/24724717/scikit-learn-minmaxscaler-produces-slightly-different-results-than-a-numpy-imple">http://stackoverflow.com/questions/24724717/scikit-learn-minmaxscaler-produces-slightly-different-results-than-a-numpy-imple</a> <div class="blogger-post-footer">Forrest Sheng Bao</div>Forrest Baohttp://www.blogger.com/profile/09295343268146353423noreply@blogger.com0