2015년 6월 30일 화요일

다른 리소스를 필요로 하는 프로그램

 어떤 프로그램은 다른 리소스를 필요로 한다. 예를 들어 face detector는 model file이 필요하다(물론 그렇지 않은 detector도 있다). 얼굴에 대한 정보를 가지고 있는 model file이 있어야 target image에서 얼굴을 잡아낼 수 있다. OpenCV가 제공하는 face detector의 경우 xml파일이 이에 해당한다.
 팀 내에서 프로젝트를 하는데 이 model파일을 찾아내서 사용하는 프로그램을 넘겨받았다. 환경변수를 다 뒤져서 그 경로마다 해당 파일이 있는지 확인하고 있으면 사용한다. 이런 짓은 이식성에 도움을 주기는 커녕 사용하는 사람들을 혼란에 빠트릴 뿐이다. 프로그램이 현재 실행되는 디렉토리에서 찾아보든지 아니면 실행시 argument로 file을 명시적으로 지정하게 해야 한다. 그 외에는 에러를 주고 멈추면 되는 것이다.
 쓸데없는 노력으로 자신의 자부심나무에만 열심히 물을 주고 주변 모든 사람들을 괴롭게 만드는 사람들이 어디에나 있다.


 Some program needs other resources to run. For example, OpenCV's face detector needs an xml file which includes model data about face. It finds faces using this model.
 If one writes a program like this, there is no need to make the program find everywhere possible to find that xml file. Just find 'current' directory or get an argument that specifies the xml path. If it can not find an xml file, just stop to run with a generous error. My co-worker writes a program that finds everywhere possible using environment variables. If it runs well that way, it is more harmful more than not running. If the program stops or runs problematic way with the xml file problem, a user would not know where is errornous.

2015년 5월 21일 목요일

grep: count total number of occurrences

원출처는 http://unix.stackexchange.com/questions/6979/grep-count-total-number-of-occurrences


파일안에 특정 스트링이 총 몇번 나오는지 세려고 -c옵션을 쓰면, 해당 스트링을 포함하는 라인수만 나온다. 예를 들어 라인은 하나인데(\n이 딱 하나 들어있는데) 스트링은 수천만자에 달하는 긴 스트링에 대해 grep -c string 하면 1만 나온다는 뜻.

-o 옵션과 wc 명령을 섞어 쓴다.
grep -o string filename | wc -l

-o
--only-matching
Print only the matched (non-empty) parts of matching lines, with each such part on a separate output line. 

2015년 4월 14일 화요일

‘도은이 아빠’네

확실하지는 않지만 아마
‘도은이 아빠’라고 불리는 분의 블로그인것 같다.
http://doeun.blogspot.kr
요즘도 조판에 열심이신가보다.
한국에서 \(\LaTeX\)을 접하는 사람이라면 누구나 한번쯤 접해보았을 그 이름.

 작정하고 파고들 기회도 없었지만, 계속 다루다보면 어느정도 감이 생길법도 한데 아직도 어떤 원리나 구조로 \(\TeX\)이 동작하는지, 한글을 가능하게 한 노고는 어디에서 비롯된 것인지 대강도 이해하지 못한다. 아마 앞으로도 그럴 것 같다. 그래서 한번 만나뵌적도 없지만 존경하게 되는 것 같다. 교수님이시라는 얘기도 있던데. 검색해봐도 KTUG의 무수한 질문과 답변글 뿐, 흔한 뉴스기사 한토막 안나온다.

2015년 3월 25일 수요일

tiff로 스캔받은것 pdf로 변환

처음부터 pdf로 받으면 되는데 사정상 이리 됨.


150메가정도 되는 multi page tiff file을 pdf로 변환하려고 하는데 적당한 툴을 못찾겠다.
웹에서 무료변환해주는 사이트나 툴이 몇개 있는데 두세개 해보니 모두 메모리 부족.
(총 104페이지로 분량이 많은건 아닌데 full color가 들어있어서 중간에 메모리가 많이 필요한것 같았다. 하나씩 분리한 뒤 보니 가장 큰 페이지가 22M정도.)
acrobat XI pro 로 한번에 import 한 뒤 변환하려 했는데 이것도 에러남.




tiff를 하나씩 split한 다음 다시 pdf로 합하는 방법을 쓰기로 했다.
tiff splitter만 성공했다. 다른것들은 모두 메모리 부족. imagemagick도 받아서 convert를 썼는데 역시 메모리 부족이었다.


이렇게 해서 다 나누고 나니 페이지가 돌아가 있어서 바로 돌리고,
 for i in {3..104}; do  convert page\ \($i\).tif -rotate 270 p$i.tif ; done

이제 acrobat XI에서 모두 import하면 pdf를 얻는다.

pdf에서 한쪽이 다음과 같은 모양이어서,


split.py를 이용해 pdf의 각 페이지를 자른다.
(이게 출처가 기억이 안남..)

(split.py 코드)
import copy
import math
import pyPdf

def split_pages(src, dst):
src_f = file(src, 'r+b')
dst_f = file(dst, 'w+b')

input = pyPdf.PdfFileReader(src_f)
output = pyPdf.PdfFileWriter()

for i in range(input.getNumPages()):
p = input.getPage(i)
q = copy.copy(p)
q.mediaBox = copy.copy(p.mediaBox)

x1, x2 = p.mediaBox.lowerLeft
x3, x4 = p.mediaBox.upperRight

x1, x2 = math.floor(x1), math.floor(x2)
x3, x4 = math.floor(x3), math.floor(x4)
x5, x6 = math.floor(x3/2), math.floor(x4/2)

if x3 > x4:
# horizontal
p.mediaBox.upperRight = (x5, x4)
p.mediaBox.lowerLeft = (x1, x2)

q.mediaBox.upperRight = (x3, x4)
q.mediaBox.lowerLeft = (x5, x2)
else:
# vertical
p.mediaBox.upperRight = (x3, x4)
p.mediaBox.lowerLeft = (x1, x6)

q.mediaBox.upperRight = (x3, x6)
q.mediaBox.lowerLeft = (x1, x2)

output.addPage(p)
output.addPage(q)

output.write(dst_f)
src_f.close()
dst_f.close()


그럼 끝.


2014년 5월 30일 금요일

install VTK at OSX 10.9.3

The goal is setup python environment of VTK.
Main idea was came from the document http://www.it.uu.se/edu/course/homepage/vetvis/ht10/vtk/instructions_vtk_OSX.pdf

ccmake must be installed already. But tk/tcl is not (at least as for me).


  1. Download source code.
    • Use Google to find the URL
    • Move the downloaded folder to target path where you want to install VTK. After compile, you cannot move the folder. If you move that, python would not find the VTK module.
  2. ccmake
    • If your VTK folder is /Users/me/VTK
      > mkdir build
      > cd build
      > ccmake ..
    • An old-fashioned screen appears. Then, hit 'c' until you can see 'g' option.
      Maybe after two hit of 'c', you would see 'g' option.
    • Hit 'g'.
  3. make
    • After ccmake screen disappears,
      > make
    • This takes about 30 minutes for me.
  4. export some environment variables and run
    • > export PYTHONPATH=$PYTHONPATH:/Users/me/VTK/build/bin:/Users/me/VTK/build/Wrapping/Python:/Users/me/VTK/build/lib
    • run python and test some examples.
    • If python complains about import vtk, export some more environment variables.
      eg. LD_LIBRARY_PATH , DYDL_FALLBACK_LIBRARY_PATH
      (for more information, refer the pdf mentioned above.)
  5. A test program

    import vtk

    # create a rendering window and renderer
    ren = vtk.vtkRenderer()
    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(ren)

    # create a renderwindowinteractor
    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)

    # create cube
    cube = vtk.vtkCubeSource()

    # mapper
    cubeMapper = vtk.vtkPolyDataMapper()
    #cubeMapper.SetInput(cube.GetOutput())
    if vtk.VTK_MAJOR_VERSION <= 5:
        cubeMapper.SetInput(cube.GetOutput())
    else:
        cubeMapper.SetInputConnection(cube.GetOutputPort())  

    # actor
    cubeActor = vtk.vtkActor()
    cubeActor.SetMapper(cubeMapper)

    # assign actor to the renderer
    ren.AddActor(cubeActor)

    # enable user interface interactor
    iren.Initialize()
    renWin.Render()
    iren.Start()

    You can find many more examples by googling.

2014년 3월 18일 화요일

R integer factorization code

# simple but ineffective.

factor =function (x) {
  limit = ceiling(sqrt(x))
  g = x/(1:limit)
  k = x/g[g%%1==0]
  c(k, rev(x/k))
}

2013년 8월 8일 목요일

intersection speed test

I want to get intersection of files of different two folders.(A∩B)
environment is as follows

$ ls fd1 |wc -l
7254

$ ls fd2 | wc -l
6797

$ uname -a

Linux cent.desktop 2.6.32-358.11.1.el6.x86_64 #1 SMP Wed Jun 12 03:34:52 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

$ cat /proc/cpuinfo 
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
stepping : 7
cpu MHz : 1600.000
cache size : 8192 KB
physical id : 0
siblings : 8
core id : 0
cpu cores : 4
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm ida arat epb xsaveopt pln pts dts tpr_shadow vnmi flexpriority ept vpid
bogomips : 6784.92
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual

power management:
(total 8 core)

$ bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

$ go version
go version go1.1rc3 linux/amd64

$ gcc --version
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


$ R --version
R version 2.15.1 (2012-06-22) -- "Roasted Marshmallows"
Copyright (C) 2012 The R Foundation for Statistical Computing
ISBN 3-900051-07-0
Platform: x86_64-unknown-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under the terms of the
GNU General Public License versions 2 or 3.
For more information about these matters see
http://www.gnu.org/licenses/.


$ python --version
Python 2.6.6

$ java -version
java version "1.7.0_07"
Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
Java HotSpot(TM) 64-Bit Server VM (build 23.3-b01, mixed mode)

$ ruby --version

ruby 1.9.3p385 (2013-02-06) [x86_64-linux]


No file name is duplicated. So searching time should be the worst case.(There is no need to break as soon as we find the target file.)



comm command


$ time comm -12 <(ls fd1) <(ls fd2)

real 0m0.023s
user 0m0.035s
sys 0m0.003s


easiest way, and very fast.


bash

$ cat diff.sh
#!/bin/bash
FD1=`ls fd1`
FD2=`ls fd2`
for i in $FD1
    do for j in $FD2
        do if [[ $i == $j ]]
            then echo $j
        fi
    done
done


$ time ./diff.sh

real 7m16.008s
user 7m13.976s
sys 0m0.431s

tremendously slow.


go

$ cat diff.go
package main

import "io/ioutil"
import "fmt"

func main() {
    files1, _ := ioutil.ReadDir("fd1")
    files2, _ := ioutil.ReadDir("fd2")
    for _, fi1 := range files1 {
        for _, fi2 := range files2 {
            if fi1.Name() == fi2.Name() {
                fmt.Println(fi1.Name())
            }
        }
    }
}

$ go build diff.go
$ time ./diff

real 0m0.808s
user 0m0.762s

sys 0m0.043s


C++

$ cat diff.cpp
#include <iostream>
#include <boost/filesystem.hpp>

// I will use boost library
using namespace boost::filesystem;

int main() {
    path fd1("fd1");
    path fd2("fd2");
    for(directory_iterator dit1(fd1); dit1 != directory_iterator(); dit1++) {
        for(directory_iterator dit2(fd2); dit2 != directory_iterator(); dit2++) {
            if(dit1->path().filename().compare( dit2->path().filename() ) == 0)
            {
                std::cout << dit1->path().filename() << std::endl;
            }
        }
    }
    return 0;
}

$ time ./a.out 

real 1m12.773s
user 1m0.730s
sys 0m11.786s


Looks weird. 
slower then go?
maybe because of use of iterators.
(std::set_intersection uses iterators too. So I think using STL would not make big difference. Moreover, it needs sorting. Same is true for std::set_difference.)


C

$ cat diff.c
#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 10000

#define MAX_CHAR 100

int main() {

    char *flist1[MAX_SIZE], *flist2[MAX_SIZE];
    int i, j;
    for(i=0; i<MAX_SIZE; i++) {
        flist1[i] = (char*)malloc(sizeof(char)*MAX_CHAR);
        flist2[i] = (char*)malloc(sizeof(char)*MAX_CHAR);
    }

    DIR *dir = opendir("fd1");

    DIR *dir2 = opendir("fd2");
    struct dirent *ent;
    int list1size = 0, list2size = 0;
    for(; (ent = readdir(dir)) != 0; list1size++) {
        strncpy(flist1[list1size], ent->d_name, MAX_CHAR);
    }
    closedir(dir);
    for(; (ent = readdir(dir2)) != 0; list2size++) {
        strncpy(flist2[list2size], ent->d_name, MAX_CHAR);
    }
    closedir(dir2);

    for(i=0; i<list1size; i++) {

        for(j=0; j<list2size; j++) {
            if(strcmp(flist1[i], flist2[j]) == 0) {
                printf("%s\n", flist1[i]);
            }
        }
    }
    return 0;
}

$ time ./diffc.out 
.
..

real 0m0.272s
user 0m0.266s
sys 0m0.004s


very long and tedious code.
but fast.


python

$ cat diff.py
import os
print set(os.listdir('fd1')) & set(os.listdir('fd2'))

$ time python diff.py
set([])

real 0m0.015s
user 0m0.006s
sys 0m0.008s


much faster then C !
(why?)


Java


$ cat Diff.java 
import java.io.File;

public class Diff {
    public static void main(String[] args) {
        String[] fns1 = new File("fd1").list();
        String[] fns2 = new File("fd2").list();
        for(String a: fns1)
            for(String b: fns2)
                if(a.equals(b))
                    System.out.println(a);
    }
}


$ time java Diff

real 0m0.357s
user 0m0.400s
sys 0m0.013s

Interestingly, user time is bigger than real time. It may means JVM optimised this code to use multicore functionality.



$ cat Diff2.java 
import java.io.File;
import java.util.Arrays;
import java.util.Set;
import java.util.HashSet;

public class Diff2 {
    public static void main(String[] args) {
        Set<String> s1 = new HashSet<String>(Arrays.asList(new File("fd1").list()));
        Set<String> s2 = new HashSet<String>(Arrays.asList(new File("fd2").list()));
        s1.retainAll(s2);
        for(String a: s1)
            System.out.println(a);
    }
}


$ time java Diff2

real 0m0.141s
user 0m0.180s
sys 0m0.020s


very fast.(considering it's Java)


R

(at R console)
> diff <- function() {
+ fd1 = list.files('fd1')
+ fd2 = list.files('fd2')
+ fd1[fd1 %in% fd2]

+ }
> a = proc.time(); diff(); proc.time()-a
character(0)
user  sys  real  

  0.050   0.002   0.053


> a = proc.time(); intersect(list.files('fd1'), list.files('fd2')); proc.time()-a
character(0)
user  sys  real  

  0.044   0.003   0.048


not bad.

ruby

$ cat diff.rb
puts Dir.entries('fd1') & Dir.entries('fd2')

$ time ruby diff.rb
.
..

real 0m0.021s
user 0m0.014s
sys 0m0.006s


I knew ruby is slow. It looks like somehow basic set operation is well written.
And the most simple code ever. (except comm command)



coarse speed test result

languagetime(sec, min(real, user))
python0.006
ruby0.014
comm(command)0.023
R0.044
Java0.141
C0.266
go0.762
C++(using boost)60.730
bash433.976


Then, how about 'difference of sets'(A-B)

Some scripts(or languages) will be a little more complicated.(and a bit slower. I guess)
I have tested it using and ruby.
(R: fd1[!(fd1 %in% fd2)]
ruby: Dir.entries('fd1') - Dir.entries('fd2') )
Results was almost same with the cases of getting intersection.



Conclusion

It seems like languages which have their own built-in function about set operations are more advantageous for this speed test. Top five ​​all had a built-in function in any way.