Jonghyuk

게시판 답변이 생성됐습니다

15 글 보임 - 151 에서 165 까지 (총 174 중에서)
  • 글쓴이
  • Jonghyuk
    회원

    며칠 전에 이 사이트에 포스팅된 바 있는 FILE_SEARCH() 함수로 간단히 해결하실 수 있습니다.

    http://idl.selab.re.kr/?p=668

    Jonghyuk
    회원

    1. 에러 메시지로 보았을 때, avg_nd=sum_nd/sum_nu 에서 sum_nd와 sum_nu 가 모두 초기치인 0.0 그대로여서 발생하는 문제로 추측됩니다.
    IDL> print, 0.0/0.0
    -NaN
    % Program caused arithmetic error: Floating illegal operand

    2. if (interval[ii] eq 0.7) then begin
    위와 같이 값을 지정하여 실행하시면 작동하는 것으로 보아 Floating Point 정밀도 문제인 것 같습니다.

    IDL> print, 0.7 eq 0.7 ;당연하지만
    1
    IDL> print, (0.1+(0.2*3))
    0.700000
    IDL> print, (0.1+(0.2*3))
    0.700000
    IDL> print, 0.7 eq (0.1+(0.2*3)) ;이 부분이 아마 문제의 핵심이 아닐까 생각합니다.
    0

    0.7과 0.7이 같은지 확인했는데 False(0) 이 나옵니다. 이유는 Float(Double도 마찬가지입니다)형 데이터의 정밀도에 한계가 있기 때문입니다(이는 현재 우리가 사용하는 모든 전산 장비가 가지는 한계입니다).

    IDL> print, (0.1+(0.2*3)), format='(D20.15)’
    0.700000047683716
    IDL> print, 0.7, format='(D20.15)’
    0.699999988079071

    0.7과 (0.1+(0.2*3)) 이 예상과 달리 ‘다른 값’ 이라는 것이죠.

    이것이 IDL만의 문제가 아니어서, 이와 관련된 글들은 구글 검색으로 쉽게 찾아볼 수 있습니다.

    일반적으로 이런 문제의 회피 방법은 유효 범위 이내에서 비교를 하는 것입니다. 다시 말해, 두 값이 같은지를 비교하는 것이 아니라, 두 값의 차이가 오차 범위 이내인지를 검사하는 것이죠.

    IDL> print, abs(0.7 – (0.1+(0.2*3)))
    5.96046e-008
    IDL> print, abs(0.7 – (0.1+(0.2*3))) lt 0.001
    1

    그래서,
    if abs(interval[ii] – kk) lt 0.001 then begin
    위와 같이 문제가 되는 부분을 수정해 보시면 어떨까 생각합니다.

    답변: cvs로 배열 저장 #685
    Jonghyuk
    회원

    strjoin 을 사용면 되지 않을까요?
    IDL> print, indgen(5)
    0 1 2 3 4
    IDL> print, strjoin(indgen(5), ‘,’)
    0, 1, 2, 3, 4

    아니면 도움말에서 write_csv를 검토해 보십시오. 이게 더 편할 수도 있습니다.

    답변: 포인터 관련 질문입니다. #684
    Jonghyuk
    회원

    기본적으로 동적 타이핑 언어들은 변수의 값이 Heap 영역에 저장된다고 보는 것이 맞습니다. 그렇지 않다면,
    a=fltarr(100)
    a=’abc’

    와 같은 것이 어렵겠지요(C에서 위와 같은 장난은 용납하지 않습니다만 IDL이나, PYTHON 같은 언어들은 이게 허용 됩니다. PYTHON은 사실상 모든 변수가 Object죠).

    어쨌든 간에, 제기하신 내용은 사실입니다. 이 사이트에 포스팅 된 글 Call by Value, Call by reference를 보시면, IDL에서 변수명을 넘겨주면 이것은 Call by Reference 로 작동합니다. C로 얘기하자면 포인터를 넘겨 주는 것과 같아요.

    그러면 포인터는 없어도 되는 거네요. 대부분 그렇습니다. 포인터 없이 IDL 을 사용하는 데 불편함이 거의 없습니다. 대부분의 IDL 사용자가 포인터를 모르고 사는 것도 그 이유입니다. 그리고 어차피 IDL의 포인터는 C의 포인터와 달라, 고속 Indexing 같은 개념으로 사용되지 않습니다(포인터 연산 없습니다). 정말 그럼 없어도 되는 건가요?

    1. 구조체의 필드는 한번 설정되면 Type을 바꿀 수 없습니다. 이 때 포인터를 사용합니다. GUI 영상 처리 프로그램을 만들 때, 사용자가 어떤 크기의 영상을 읽을지 모르지요. 이 때 영상 자료는 포인터를 이용하여 Heap 에 저장합니다. (IDL GUI에서 각각의 컴포넌트는 단 하나의 사용자 변수(uvalue)를 가집니다. GUI에서 어떤 이벤트가 발생하더라도, 이벤트 처리 프로그램으로 TOP GUI의 ID가 넘어갑니다. WIDGET_CONTROL을 이용하면 지정 위젯 ID에서 UVALUE를 가져올 수 있구요. 그래서 거의 표준 GUI 프로그래밍은 TOP GUI Component에 모든 GUI 정보를 때려 넣습니다). 그러니 영상 자료도 TOP GUI의 UVALUE 변수에 들어가야 하니 구조체의 필드로 들어가야 하고, 구조체의 필드는 한번 정해지면 타입, 배열의 크기 등을 바꿀 수 없으니, 자유를 얻기 위해 포인터를 사용합니다. 포인터가 가리키는 곳은 어떤 데이터든 들어올 수 있으니까요.

    2. WIDGET_CONTROL에 의해서 UVALUE를 넣거나 뽑아오는 과정은 일반적으로 복제가 일어납니다. 왜냐하면, 서브루틴과 서브루틴 간의 직접적 변수 교환이 아닌, “이벤트 처리 서브루틴”을 통한 자료 교환이거든요. 물론 이 때도 /NO_COPY 키워드를 이용해서 복제가 아닌, 그냥 REFERENCE 처럼 넘기는 방법도 있습니다(WIDGET_CONTROL의 /NO_COPY 키워드가 분명히 있어요. 이것의 위험성이 있어서 포인터를 씁니다. 잠시 후 설명하지요). 그러므로 GUI의 모든 정보를 담고 있는 변수(보통 state 변수를 씁니다. 당연히 일반적으로 구조체입니다)를 직접 던지고 받아도 됩니다. 만일 이 때 /NO_COPY를 안쓰면 이벤트 발생시마다 데이터 복제가 일어나서 속도 저하 있습니다.
    그럼 왜 /NO_COPY가 위험한가? GUI는 사용자의 예기치 못한 입력도 있으므로 Error Handling 이 적절히 이루어져야 합니다. 잘만든 프로그램은 이벤트 처리 루틴에서 잘못된 경우 뻗어버리지 않고, 아무일도 없다는 듯이 넘어가지요(호출했던 프로그램으로 그냥 돌아갑니다). 이런 상황에서 /NO_COPY 를 했다고 생각해 보십시오. 이벤트 처리 루틴에서 다시 SET_UVALUE를 못한 채 죽어버리는 경우라면 state 변수는 흔적도 없이 사라지는 셈입니다. (이래서는 안전한 에러처리의 방법이 없습니다).
    포인터를 쓰는 경우라면, 문제 없지요. Heap 에 자료는 그대로 보존되어 있으니까요.

    답변: 문자형 숫자형 분리 #683
    Jonghyuk
    회원

    문자열 다루는 기능들을 조금 더 검토하시면 유용한 기능들이 있습니다.
    1. STRSPLIT() 함수는 입력 문자열을, 구문자 문자열을 기준으로 끊어냅니다.
    2. 정규식(Regular Expression) 이라는 게 있습니다. 이 것만 가지고 책 한권 분량 나오지만, 유용한 거 몇개 만 배우시면 쓸모가 꽤 있습니다. 예를 들어 [0-9] 는 0,1,2,3,4,5,6,7,8,9 중 하나를 의미하고, +는 바로 앞의 문자가 하나 또는 여러개가 연속해서 등장하는 것을 의미합니다. 그래서 [0-9]+ 는 숫자가 뭉쳐있는 곳을 의미합니다.
    3. STRJOIN() 함수는 입력 문자열 배열 사이사이에 구분자 문자열을 끼워 넣어 하나의 문자열로 연결합니다.

    아래 예제를 보십시오.
    IDL> a=’A_DDE_123_DEF13QP45AV’
    IDL> splt=strsplit(a, ‘[0-9]+’, /REGEX, /EXTRACT)
    IDL> print, splt
    A_DDE_ _DEF QP AV
    IDL> print, strjoin(splt)
    A_DDE__DEFQPAV

    a 문자열을 숫자가 있는 부분을 구분자라고 생각하고 끊어냅니다. /REGEX 는 구분자 문자열로 제공되는 것이 “정규식”이라는 것을 의미하고, 끊어낸 각각을 문자열 배열로 리턴하라는 의미로 /EXTRACT 가 사용되었습니다.
    그 결과는 보시다 시피 끊어져 나왔구요. 이걸 연결하면 구분자(이 예제에서는 숫자 덩어리들)만 쏙 빠지는 결과가 됩니다.

    Jonghyuk
    회원

    자료의 구간이 등간격이 아니어서 hist_2d()를 사용할 수 있는 상황은 아닌 것 같습니다. 2차원 구조의 각 계급구간에 대해 COUNT를 수행하는 과정이 필요할 것 같습니다.

    bd=[0, 1, 3, 9, 20]
    bv=[0, 0.4, 0.9, 2]

    nbd=n_elements(bd)
    nbv=n_elements(bv)
    count=lonarr(nbd-1, nbv-1)

    ;make sample data
    ;
    d=randomn(seed, 1000)*20 ;0~20
    v=randomn(seed, 1000)*2 ;0~2

    for i=0, nbd-2 do begin
    for j=0, nbv-2 do begin
    ok=where(d ge bd[i] and d lt bd[i+1] and v ge bv[j] and v lt [j+1], ct)
    count[i, j] = ct
    endfor
    endfor

    end

    이후에 같은 계급 구간으로 box를 그려가면서 box 내부를 도수에 따라 색으로 채워 넣으면 될 것 같습니다.

    답변: colocation 방법 #607
    Jonghyuk
    회원

    올려 주신 코드대로 한다면 처리 시간이 많이 걸릴 것 같습니다. 최악의 경우에는 정말 이렇게 해야 하는 경우가 있을 수도 있습니다.
    좌표에 어떤 규칙이 있지는 않을까요? a 배열과 b 배열의 같은 위경도 위치가 a와 b의 index에 대한 함수로 구해질 수 있는 경우 같은 거죠. 이런 규칙이 존재한다면 가장 빠를 것입니다. 250*251과 1000*1004가 각각 4*4배인 것으로 이렇게 할 수 있지 않을까 하는 희망이 보입니다(올려 주신 내용만으로는 확인이 안됩니다만, 배열의 크기는 매우 희망적으로 보입니다).

    그렇지 않다면 어떤 순서로 하든 두 배열을 어떤 기준에 맞추어 소팅을 한번 하는 것이 좋겠습니다. 경도순으로 소팅하고 같은 경도라면 위도순으로 소팅하는 것이 그 예가 될 것 같습니다. 그렇게 해서 sort_a와 sort_b를 한번 구축해 놓으면 sort_a[0]을 sort_b에서 찾고나서(그 때 인덱스를 k라고 하면) sort_a[1]을 찾을 때는 k+1번부터 검색을 하면 됩니다. 이렇게 나간다면 sort_a 변수와 sort_b 변수를 한번씩만 훑으면 됩니다.

    Jonghyuk
    회원

    예, 복잡합니다. ㅎㅎ

    Call by Value와 Call by Reference 의 차이에서 발생하는 문제인 것 같습니다.

    다음과 같은 문장을 적어 주셨는데요, 이 경우 read_analyze75는 info.mImageA에 아무 값도 넣지를 못합니다.
    read_analyze75, file[0], imageinfo=info.mImageA

    구조체의 필드를 인자로 넘겨줄 경우 IDL은 이를 Call by Value로 처리합니다. 즉, info.mImageA의 값을 프로시저로 넘겨줄 수는 있되, 이 프로시저에서 info.mImageA로 값을 넣어줄 수는 없습니다. 다음 예제를 보세요.

    pro change_val, test_key=t
    t=30
    end

    pro test_pass_param
    a={x:0, y:0}
    change_val, test_key=c
    print, c
    change_val, test_key=a.x
    print, a.x
    change_val, test_key=b
    a.x=b
    print, a.x
    end

    실행 결과는
    IDL> test_pass_param
    % Compiled module: CHANGE_VAL.
    % Compiled module: TEST_PASS_PARAM.
    30
    0
    30
    IDL>
    입니다. 즉, 변수를 넘겨 주는 경우 프로시저(함수)는 해당 변수에 어떤 값이든 넣을 수 있습니다. 하지만 구조체의 필드를 넣는 경우는 프로시저(함수)가 값을 넣어줄 수 없어요. 그래서 두 번째 호출에서 a.x는 그대로 0입니다. 이런 경우에 가장 간단한 방법은 세 번째 호출처럼 그냥 변수를 던져서 값을 받아 온 후, 이 값을 구조체 필드에 넣는 것입니다.

    숫자, 수식, 배열의 일부(예를 들면 a[0] 같은), 구조체의 필드(예를 들면 info.data 같은)를 parameter로 넘겨 줄 경우 Call by Value라 하여 값을 받아서 이용은 하되 값을 돌려주는 방법으로는 사용할 수 없습니다.

    답변: widget button 으로 dialog_pickfile #543
    Jonghyuk
    회원

    상황을 잘 모르겠습니다만, 아래와 같이 간단한 예제에서는 잘 작동합니다. 분명히 이보다는 훨씬 복잡한 프로그램을 만들고 계실 것으로 예상합니다만, GUI 버튼을 통해 Dialog_pickfile을 호출하는 것은 가능합니다.

    pro test_dipifi_event, event
    widget_control, event.top, GET_UVALUE=state
    widget_control, event.id, GET_UVALUE=uval
    case uval of
    ‘exit’ : widget_control, event.top, /DESTROY
    ‘DPF’ : begin
    file=dialog_pickfile()
    state.filename=file
    widget_control, event.top, SET_UVALUE=state
    end
    ‘check’ : print, state.filename
    else :
    endcase
    end

    pro test_dipifi
    tlb=widget_base(/COLUMN)
    btn1=widget_button(tlb, value=’Select File’, UVALUE=’DPF’)
    btn2=widget_button(tlb, value=’Check selected’, UVALUE=’check’)
    btn3=widget_button(tlb, value=’Exit’, UVALUE=’exit’)
    state={filename:’Default’}
    widget_control, tlb, SET_UVALUE=state
    widget_control, tlb, /REALIZE
    xmanager, ‘test_dipifi’, tlb
    end

    답변: Log polar #542
    Jonghyuk
    회원

    IDL에 기본함수로는 LogPolar가 있는 것 같지 않습니다.

    ENVI로 되었다는 것은 IDL로 되어 있다는 것과 완전히 같은 의미입니다. 올려 주신 코드에는 ENVI 특화된 라이브러리가 보이지 않습니다.

    답변: binary 파일 읽기 질문입니다. #520
    Jonghyuk
    회원

    데이터 사이즈가 그만하다면, 부분별로 처리해야 하는 것이 맞겠습니다.

    Byte 단위의 파일 입출력은 당연히 가능합니다.

    block=intarr(3000, 200)

    openr, 1, ‘myfile.dat’

    for i=0, 19 do begin

    readu, 1, block

    ;;;do something

    endfor

    close, 1

    이곳은 관심있는 사람들의 토론의 장소이므로 바쁜 것은 문제될 것이 없습니다.

    환영합니다.

    답변: readcol format 사용.. #483
    Jonghyuk
    회원

    어떤식으로 안되는지 잘 모르겠습니다. 에러가 나는 건지, 잘못 읽히는 건지…

    FORMAT 부분만 봐서는 될 거 같은데요.

    A 포맷을 이용하여 특수 문자를 읽을 수는 있는데, 구분자(어떤 것이 컬럼을 구분하는 문자인지, 예를 들어 콤마인지, 띄어쓰기인지, # 같은 문자인지)가 확실해야 합니다.

    답변: ASCII 파일쓰기 에서 79컬럼 #482
    Jonghyuk
    회원

    도움말에서 OPENW 를 찾아보시고, WIDTH 키워드를 확인해 보시면 답을 찾으실 수 있습니다.

    답변: readcol 에서 공백 읽기 #481
    Jonghyuk
    회원

    PRESERVE_NULL 키워드를 활용하시면 될 것 같습니다

    답변: mac 용 idl6.4 설치 파일 부탁드려요 #464
    Jonghyuk
    회원

    메일로 답변 드렸습니다.

    오래된 버전이어서 최근 Mac OS X와의 호환성 여부는 확인되지 않았습니다.

15 글 보임 - 151 에서 165 까지 (총 174 중에서)