001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.tools.clusterquantiser.samplebatch; 031 032import java.io.BufferedInputStream; 033import java.io.BufferedOutputStream; 034import java.io.DataInput; 035import java.io.DataInputStream; 036import java.io.DataOutput; 037import java.io.DataOutputStream; 038import java.io.File; 039import java.io.FileInputStream; 040import java.io.FileOutputStream; 041import java.io.IOException; 042import java.util.ArrayList; 043import java.util.Arrays; 044import java.util.List; 045 046import org.openimaj.io.IOUtils; 047import org.openimaj.io.ReadWriteableBinary; 048import org.openimaj.tools.clusterquantiser.FileType; 049 050/** 051 * A batch of samples 052 * 053 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 054 */ 055public class SampleBatch implements ReadWriteableBinary { 056 /** 057 * Header for SampleBatch files 058 */ 059 public static final byte[] HEADER = "SAMPLEBATCH".getBytes(); 060 061 private FileType type; 062 private File sampleSource; 063 private int startIndex; 064 private int endIndex; 065 private int[] relativeIndexList; 066 067 /** 068 * Default constructor 069 */ 070 public SampleBatch(){ 071 072 } 073 /** 074 * Default constructor 075 * @param type 076 * @param sampleSource 077 * @param startIndex 078 * @param endIndex 079 * @param relativeIndexList 080 */ 081 public SampleBatch(FileType type, File sampleSource, int startIndex, int endIndex, int[] relativeIndexList){ 082 this.endIndex = endIndex; 083 this.startIndex = startIndex; 084 this.type = type; 085 this.sampleSource = sampleSource; 086 this.relativeIndexList = relativeIndexList; 087 } 088 089 /** 090 * Default constructor 091 * @param type 092 * @param sampleSource 093 * @param startIndex 094 * @param endIndex 095 */ 096 public SampleBatch(FileType type, File sampleSource, int startIndex,int endIndex) { 097 this.type = type; 098 this.startIndex = startIndex; 099 this.endIndex = endIndex; 100 this.sampleSource = sampleSource; 101 this.relativeIndexList = null; 102 } 103 104 /** 105 * @return the stored samples 106 * @throws IOException 107 */ 108 public byte[][] getStoredSamples() throws IOException{ 109 byte [][] f = null; 110 if(relativeIndexList == null){ 111 f = type.readFeatures(sampleSource); 112 } 113 else 114 { 115 f = type.readFeatures(sampleSource, relativeIndexList); 116 } 117 return f; 118 } 119 120 /** 121 * Get the stored samples 122 * @param indices 123 * @return the stored samples 124 * @throws IOException 125 */ 126 public byte[][] getStoredSamples(int[] indices) throws IOException{ 127 byte [][] f = null; 128 int[] corrected = new int[indices.length]; 129 for(int i = 0; i < corrected.length;i++) corrected[i] = this.relativeIndexList == null ? indices[i] : this.relativeIndexList[indices[i]]; 130 f = type.readFeatures(sampleSource, corrected); 131 return f; 132 } 133 134 /** 135 * Get the stored samples 136 * @param interestedStart 137 * @param interestedEnd 138 * @return the stored samples 139 * @throws IOException 140 */ 141 public byte[][] getStoredSamples(int interestedStart, int interestedEnd) throws IOException { 142 int[] interestedList = new int[interestedEnd - interestedStart]; 143 int j = 0; 144 for(int i = interestedStart; i < interestedEnd; i++,j++) 145 interestedList[j] = this.relativeIndexList == null ? j : this.relativeIndexList[j]; 146 return type.readFeatures(sampleSource, interestedList); 147 } 148 149 /** 150 * @return the start index of the batch 151 */ 152 public int getStartIndex() { 153 return startIndex; 154 } 155 156 /** 157 * @return the end index of the batch 158 */ 159 public int getEndIndex() { 160 return endIndex; 161 } 162 163 /** 164 * Write batches to a file 165 * @param sampleBatches 166 * @param sampleBatchOut 167 */ 168 public static void writeSampleBatches(List<SampleBatch> sampleBatches,File sampleBatchOut) { 169 DataOutputStream dos = null; 170 try{ 171 FileOutputStream fos = new FileOutputStream(sampleBatchOut); 172 BufferedOutputStream bos = new BufferedOutputStream(fos); 173 dos = new DataOutputStream(bos); 174 dos.writeInt(sampleBatches.size()); 175 for(SampleBatch sb : sampleBatches){ 176 IOUtils.writeBinary(bos, sb); 177 dos.flush(); 178 } 179 180 } catch (IOException e) { 181 e.printStackTrace(); 182 } 183 finally{ 184 try { 185 dos.close(); 186 } catch (IOException e) { 187 e.printStackTrace(); 188 } 189 } 190 } 191 192 /** 193 * Read batches from a file 194 * @param sampleBatchOut 195 * @return batches 196 */ 197 public static List<SampleBatch> readSampleBatches(File sampleBatchOut) { 198 FileInputStream fis = null; 199 List<SampleBatch> sbl = new ArrayList<SampleBatch>(); 200 try{ 201 fis = new FileInputStream(sampleBatchOut); 202 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis)); 203 int toRead = dis.readInt(); 204 for(int i = 0; i < toRead; i++){ 205 dis.read(new byte[SampleBatch.HEADER.length]); 206 SampleBatch sb = new SampleBatch(); 207 sb.readBinary(dis); 208 sbl.add(sb); 209 System.err.printf("\r%8d / %8d", i, toRead); 210 } 211 } catch (IOException e) { 212 } 213 finally{ 214 try { 215 fis.close(); 216 } catch (IOException e) { 217 218 } 219 } 220 System.out.println(" Done!"); 221 return sbl; 222 } 223 224 @Override 225 public boolean equals(Object o){ 226 if(!(o instanceof SampleBatch)) return false; 227 SampleBatch sbo = (SampleBatch) o; 228 229 return sbo.endIndex == this.endIndex && 230 sbo.startIndex == this.startIndex && 231 Arrays.equals(sbo.relativeIndexList, this.relativeIndexList) && 232 sbo.sampleSource.getAbsolutePath().equals(this.sampleSource.getAbsolutePath()) && 233 sbo.type.equals(this.type); 234 } 235 236 /** 237 * @return list of relative indices 238 */ 239 public int[] getRelativeIndexList() { 240 return this.relativeIndexList; 241 } 242 243 @Override 244 public String toString(){ 245 String out = ""; 246 out += "|" + this.startIndex + "->" + this.endIndex + "| == " + (this.endIndex - this.startIndex); 247 return out; 248 249 } 250 251 @Override 252 public void writeBinary(DataOutput out) throws IOException { 253 out.writeInt(type.ordinal()); 254 out.writeInt(sampleSource.getAbsolutePath().length()); 255 byte[] path = sampleSource.getAbsolutePath().getBytes(); 256 out.write(path, 0, path.length); 257 out.writeInt(startIndex); 258 out.writeInt(endIndex); 259 if(relativeIndexList == null) 260 out.writeInt(0); 261 else 262 { 263 out.writeInt(relativeIndexList.length); 264 for(int i = 0; i < relativeIndexList.length; i++){ 265 out.writeInt(relativeIndexList[i]); 266 } 267 } 268 269 } 270 271 @Override 272 public void readBinary(DataInput in) throws IOException { 273 type = FileType.values()[in.readInt()]; 274 int pathLen = in.readInt(); 275 byte[] path = new byte[pathLen]; 276 in.readFully(path, 0, pathLen); 277 sampleSource = new File(new String(path)); 278 startIndex = in.readInt(); 279 endIndex = in.readInt(); 280 int nRelativeIndexList = in.readInt(); 281 if(nRelativeIndexList == 0){ 282 relativeIndexList = null; 283 } 284 else{ 285 relativeIndexList = new int[nRelativeIndexList]; 286 for(int i = 0 ; i < nRelativeIndexList; i++){ 287 relativeIndexList[i] = in.readInt(); 288 } 289 } 290 } 291 292 @Override 293 public byte[] binaryHeader() { 294 return SampleBatch.HEADER; 295 } 296}