package edu.hawaii.jmotif.sax.datastructures; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * The motif records collection. * * @author Pavel Senin * */ public class MotifRecords implements Iterable<MotifRecord> { /** Default capacity. */ private static final Integer defaultCapacity = 10; /** Storage container. */ private final LinkedList<MotifRecord> motifs; // max capacity var private Integer maxCapacity; /** * Constructor. */ public MotifRecords() { this.maxCapacity = defaultCapacity; this.motifs = new LinkedList<MotifRecord>(); } /** * Constructor. * * @param capacity The initial capacity. */ public MotifRecords(int capacity) { this.maxCapacity = capacity; this.motifs = new LinkedList<MotifRecord>(); } /** * Set the max capacity of this collection. The overflow elements will be pushed into the * collection pushing out ones with less distance value. * * @param newSize The size to set. */ public void setMaxCapacity(int newSize) { this.maxCapacity = newSize; } /** * Add a new motif to the list. Here is a trick. This method will also check if the current * distance is less than best so far (best in the table). If so - there is no need to continue * that inner loop - the MAGIC optimization. * * @param motif The motif instance to add. * @return if the motif got added. */ public boolean add(MotifRecord motif) { // System.out.println(" + discord record " + discord); // check if here is still a room for the new element // if (this.motifs.size() < this.maxCapacity) { if (this.motifs.size() == 0) { assert true; } // if so - just add it in this.motifs.add(motif); } else { // more complicated - need to check if it will fit in there // DiscordRecord last = discords.get(discords.size() - 1); MotifRecord first = motifs.get(0); if (first.getFrequency() < motif.getFrequency()) { // System.out.println(" - discord record " + discords.get(0)); motifs.remove(0); motifs.add(motif); } } Collections.sort(motifs); if (this.motifs.get(0).compareTo(motif) > 0) { return true; } return false; } /** * Returns the number of the top hits. * * @param num The number of instances to return. If the number larger than the storage size - * returns the storage as is. * @return the top motif hits. */ public List<MotifRecord> getTopHits(Integer num) { Collections.sort(this.motifs); if (num >= this.motifs.size()) { Collections.reverse(this.motifs); return this.motifs; } List<MotifRecord> res = this.motifs.subList(this.motifs.size() - num, this.motifs.size()); Collections.reverse(res); return res; } /** * Get the minimal distance found among all instances in the collection. * * @return The minimal distance found among all instances in the collection. */ public double getMinDistance() { if (this.motifs.size() > 0) { return motifs.get(0).getFrequency(); } return -1; } @Override public String toString() { StringBuilder sb = new StringBuilder(1024); for (MotifRecord r : motifs) { sb.append(r.getFrequency()).append(" at "); sb.append(Arrays.toString(r.getPositions())).append("\n"); } return sb.toString(); } @Override public Iterator<MotifRecord> iterator() { return this.motifs.iterator(); } }