MX는 Rich 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


댓글을 달아 주세요