MXRich Apodaca가 개발하고 있는 가벼운 화학정보학 툴킷이다. 이 툴킷은 화학 구조와 데이터 파일의 표준이라고도 말할 수 있는 sdf 파일을 읽고 쓰는데 사용될 수 있음을 이 기사에서 볼 수 있다. 문제는 해당 기사에 내가 코멘트를 남긴 것처럼 SDF 파일 안에 여러 줄로 된 데이터가 있을 경우에는 첫 줄만을 읽어온다는 것이다. 이런 현상은 이 프로그램에서만이 아니고 그가 적었던 다른 여러 코드에서도 공통적으로 볼 수 있는 현상이었다. PubChem의 sdf 파일들은 모두 PUBHCEM_BONDANNOTAIONS 라는 이름의 필드에 여러 줄로 된 데이터를 가지고 있기 때문에 나름 문제라고 볼 수 있는 현상이다.

우리 연구소에서 개발하고 있는 PreADMET에서는 이런 문제가 없기 때문에, 어떤 방식을 사용하고 있는지 물어봤더니 그냥 매 줄을 읽어서 바로 바로 처리를 한다는 말을 들었다. 그러면 빈 줄이 나와야만 데이터가 끝났다고 생각하기 때문에 여러 줄로 된 데이터를 읽는데 문제가 없게 된다.

곰곰히 생각을 해 봤더니, 데이터 부분에서 “\n” 두 개가 있으면 필드를 나눌 수 있는 셈이다. 그래서 그냥 “\n\n”로 필드 별로 나눠버리고 정규식을 쓰면 이름과 데이터 짝을 쉽게 얻을 수 있겠다는 생각이 들었다. 그래서 생각난 김에 Rich Apodaca의 ruby 코드를 조금 수정해 보았다. 그냥 작동은 하는 수준이지만, 이런 방법을 쓰면 나름 이 문제를 해결할 수 있을 것 같다.

This is my quick (and dirty) modification of Rich Apodaca’s ruby code for parsing multi-line data of sdf format file.


class SDFSplitter
  @@mol_stop = "$$$$\n"
  @@blank = ""
  
  def initialize(filename)
    @sdf = File.new(filename)
  end
  
  def each_record
    record = get_record
    
    while record != (@@blank || "\n")
      yield record
      record = get_record
    end
  end
  
  def get_record
    line = read_line
    record = [line]

    while !(@@mol_stop.eql?(line) || nil == line)
      line = read_line
      record << line
    end

    record.join
  end
  
  private
  
  def read_line
    begin
      line = @sdf.readline
    rescue EOFError
      return nil
    end
    line
  end
end

class DataExtractor
  @@desc_stop = "\n\n"
  
  def self.extract_molfile(record)
    record.match(/M  END$/).pre_match + "M  END\n"
  end
  
  def self.extract_data_hash(record)
    hash = {}
    all_data = record.match(/M  END$/).post_match
    pairs = all_data.split(@@desc_stop)
    pairs.delete("$$$$\n")
    pairs.each do |pair|
      pair.match(/^>\s+<(.+)>\s*\S*\n(.+)\n/m)
      key, data = $1, $2
      hash[key] = data
    end
    return hash
  end
end
크리에이티브 커먼즈 라이센스
Creative Commons License
2008/12/21 01:37 2008/12/21 01:37

트랙백을 보내세요

트랙백 주소 :: http://agile2robust.com/tc/trackback/54

댓글을 달아 주세요

[로그인][오픈아이디란?]
비밀글 (Serect)
댓글 달기 (Submit)