package gov.nih.ncgc.bard.tools;
import gov.nih.ncgc.search.SearchCallback;
import gov.nih.ncgc.search.SearchParams;
import gov.nih.ncgc.search.SearchService2;
import gov.nih.ncgc.search.SearchService2.MolEntry;
import java.io.PrintWriter;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import chemaxon.struc.Molecule;
/**
* A one line summary.
*
* @author Dac-Trung Nguyen
*/
public class SearchResultHandler implements SearchCallback<MolEntry> {
static class MolEntryComparator implements Comparator<MolEntry> {
MolEntryComparator () {
}
public int compare (MolEntry e1, MolEntry e2) {
if (e1.getRank() < e2.getRank()) return -1;
if (e1.getRank() > e2.getRank()) return 1;
return e1.getPartitionSig() - e2.getPartitionSig();
}
}
PrintWriter pw;
SearchParams params;
volatile int start, top, matches;
volatile PriorityQueue<MolEntry> queue = new PriorityQueue<MolEntry>
(100, new MolEntryComparator ());
volatile Map<Integer, Integer> partitions =
new HashMap<Integer, Integer>();
public SearchResultHandler(SearchParams params, PrintWriter pw,
Integer start, Integer top) {
this.params = params;
this.pw = pw;
this.start = start != null ? start : 0;
this.top = top != null ? top : 10000;
}
/**
* SearchCallback interface. Note that this method is called from
* multiple thread, so it should be thread safe!
*/
public synchronized boolean matched (SearchService2.MolEntry entry) {
if (start >= 0 && queue.size() >= start) {
// remove these elements
for (int i = 0; i < start; ++i) {
queue.poll();
}
start = -1; // don't execute this block again
}
queue.add(entry);
Integer c = partitions.get(entry.getPartitionSig());
partitions.put(entry.getPartitionSig(), c!=null ? (c+1) : 1);
if (partitions.size() >= entry.getPartitionCount()) {
// now empty the queue
for (SearchService2.MolEntry e;
(e = queue.poll()) != null; ++matches) {
writeOutput (getMol (e));
}
partitions.clear();
}
return matches < top;
}
public void complete () {
for (SearchService2.MolEntry e;
matches < top && (e = queue.poll()) != null; ++matches) {
writeOutput (getMol (e));
}
}
protected Molecule getMol (SearchService2.MolEntry entry) {
int[][] hits = entry.getAtomMappings();
Molecule mol = entry.getMol();
switch (params.getType()) {
case Substructure: {
for (int[] h : hits) {
for (int i = 0; i < h.length; ++i) {
// can happen when the query contains explicit Hs
if (h[i] >= 0) {
mol.getAtom(h[i]).setAtomMap(i + 1);
}
}
}
mol.setProperty("HIGHLIGHT", mol.toFormat("smiles:q"));
}
break;
case Superstructure: {
for (int[] h : hits) {
for (int i = 0; i < h.length; ++i) {
if (h[i] >= 0)
mol.getAtom(i).setAtomMap(h[i] + 1);
}
}
mol.setProperty("HIGHLIGHT", mol.toFormat("smiles:q"));
}
break;
}
mol.setProperty("SIMILARITY",
String.format("%1$.3f", entry.getSimilarity()));
mol.setProperty("RANKING",
String.format("%1$.3f", entry.getRank()));
return mol;
}
void writeOutput (Molecule mol) {
//logger.info(Thread.currentThread()+": "+mol.getName());
//pw.print(mol.toFormat("sdf"));
String highlight = mol.getProperty("HIGHLIGHT");
pw.println(mol.getName()+(highlight != null ? ("\t"+highlight) : ""));
}
}