package pl.edu.fuw.MP.Core; import java.io.*; import java.util.Enumeration; import java.util.HashSet; import java.util.Vector; import org.signalml.domain.book.BookFormatException; import org.signalml.domain.book.StandardBookSegment; class CPair { public long x, y; public int channel; public CPair(long x, long y, int channel) { this.x=x; this.y=y; this.channel=channel; } public CPair(long x, int channel) { this.x=x; y=-1L; this.channel=channel; } } class BookLibraryV5IndexElement { public int type; public int channel; public int offset; public long filePosition; public BookLibraryV5IndexElement parent=null; @Override public String toString() { StringBuffer buf=new StringBuffer(); buf.append("type="); buf.append(type); buf.append(" ("); buf.append(FormatComponentV5.toName(type)); buf.append(") channel="); buf.append(channel); buf.append(" offset="); buf.append(offset); buf.append(" pos="); buf.append(filePosition); return buf.toString(); } } public class BookLibraryV5 implements BookLibraryInterface { public static final int VERSION_NONE=-1,VERSION_III=1,VERSION_IV=2,VERSION_V=3; private FormatComponentV5 fields[]; private int fieldsCount; private SegmentHeaderV5 segment=new SegmentHeaderV5(this); private RandomAccessFile streamClass=null; private int version=VERSION_NONE; private Vector<BookLibraryV5IndexElement> index=new Vector<BookLibraryV5IndexElement>(); private int epochDim; public void setFields(FormatComponentV5 fields[]) { fieldsCount=0; for (int i=0 ; i<fields.length ; i++) { if (fields[i]!=null) { this.fields[fieldsCount++]=fields[i]; } } } private void splitIndex() { int len=index.size(); for (int i=0 ; i<len ; i++) { BookLibraryV5IndexElement x=index.elementAt(i); if (x.parent==null) { for (int j=i+1 ; j<len ; j++) { BookLibraryV5IndexElement y=index.elementAt(j); if (x.channel==y.channel && x.offset==y.offset && x.type!=y.type) { x.parent=y; y.parent=x; break; } } } } } public final int getChannel() { return segment.channelNumber; } /* public BookAtom []getAtoms() { if(segment.type==FormatComponentV5.ATOMS_SEGMENT_IDENTITY) { int len=segment.atoms.size(); BookAtom []atoms=new BookAtom[len]; for(int i=0 ; i<len ; i++) { AtomV5 stmp=segment.atoms.elementAt(i); atoms[i]=new BookAtom(); atoms[i].scale=stmp.scale; atoms[i].frequency=stmp.frequency; atoms[i].position=stmp.position; atoms[i].modulus=stmp.modulus; atoms[i].amplitude=stmp.amplitude; atoms[i].phase=stmp.phase; atoms[i].index=stmp.iteration; } return atoms; } return null; } */ public float []getSignal() { if (segment.type==FormatComponentV5.SIGNAL_SEGMENT_IDENTITY) { return segment.signal; } return null; } public int getSignalSize() { return getDimBase(); } public BookLibraryV5() { fields=new FormatComponentV5[256]; fieldsCount=0; for (int i=0 ; i<256 ; i++) { fields[i]=null; } } public BookLibraryV5(BookLibraryV5Writer lib) { fields=new FormatComponentV5[256]; fieldsCount=0; for (int i=0 ; i<256 ; i++) { FormatComponentV5 c=lib.getFields(i); if (c!=null) { fields[fieldsCount++]=c;; } } } public void Close() { try { if (streamClass!=null) { streamClass.close(); streamClass=null; } } catch (IOException e) { } } private static int checkFormat(RandomAccessFile stream) throws IOException { byte s[]=new byte[4]; stream.read(s,0,4); String string=new String(s); if (string.equals("MPv3")) { return VERSION_III; } else if (string.equals("MPv4")) { return VERSION_IV; } else if (string.equals("MPv5")) { stream.read(s, 0, 2); /* .0 */ return VERSION_V; } return VERSION_NONE; } public static int checkFormat(String filename) { try { RandomAccessFile stream=new RandomAccessFile(filename, "r"); int ok=checkFormat(stream); stream.close(); return ok; } catch (IOException e) { Utils.log(e.toString()); return VERSION_NONE; } } private void readBook(RandomAccessFile stream) throws IOException { segment=new SegmentHeaderV5(this); segment.read(stream); } private CPair[] getOffset(int segNo) { Vector<CPair> v=new Vector<CPair>(); int len=index.size(); for (int i=0 ; i<len ; i++) { BookLibraryV5IndexElement e=index.elementAt(i); if (e.offset==segNo) { if (!exists(v, e.channel)) { if (e.parent==null) { v.add(new CPair(e.filePosition, e.channel)); } else { v.add(new CPair(e.filePosition, e.parent.filePosition, e.channel)); } } } } CPair []arr=new CPair[v.size()]; return v.toArray(arr); } private boolean exists(Vector<CPair> v, int channel) { Enumeration<CPair> e=v.elements(); while (e.hasMoreElements()) { CPair p=e.nextElement(); if (p.channel==channel) { return true; } } return false; } private long getOffset(int segNo, int chnNo, int type) { int len=index.size(); for (int i=0 ; i<len ; i++) { BookLibraryV5IndexElement e=index.elementAt(i); if (e.offset==segNo && e.channel==chnNo && e.type==type) { return e.filePosition; } } return -1; } private int countBook(RandomAccessFile stream) throws IOException { int k=0; try { SegmentHeaderV5 segHead=new SegmentHeaderV5(this); for (; ; k++) { long off=stream.getFilePointer(); segHead.skipSegment(stream); BookLibraryV5IndexElement element=new BookLibraryV5IndexElement(); element.filePosition=off; element.channel=segHead.getChannelNumber(); element.offset=segHead.getSegmentNumber(); element.type=segHead.type; index.add(element); Utils.log(element.toString()); } } catch (IOException e) { return k; } finally { splitIndex(); } } public boolean NextBook() { try { readBook(streamClass); } catch (IOException e) { return false; } return true; } private boolean readFileHeader(RandomAccessFile stream) throws IOException { int code, s, size; if ((version=checkFormat(stream))==VERSION_NONE) { return false; } code=(int)stream.readByte(); size=(int)stream.readInt(); Utils.log("code: "+code+" "+FormatComponentV5.toName(code)+" size: "+size); if (code==FormatComponentV5.COMMENT_SEGMENT_IDENTITY) { stream.skipBytes(size); code=(int)stream.readByte(); size=(int)stream.readInt(); Utils.log("Skip commnet, code: "+code+" "+FormatComponentV5.toName(code)+" size: "+size); } else if (code!=FormatComponentV5.FILE_HEADER) { ; } byte buff[]=new byte[size]; DataArrayInputStream block=new DataArrayInputStream(stream, buff); fieldsCount=0; s=0; while (s<size) { code= block.readUnsignedByte(); int fieldSize=block.readUnsignedByte(); Utils.log("code: "+code+" "+FormatComponentV5.toName(code)+" size: "+fieldSize); switch (code) { case FormatComponentV5.TEXT_INFO: (fields[fieldsCount++]=new TextInfoV5()).Read(block, fieldSize); break; case FormatComponentV5.DATE_INFO: (fields[fieldsCount++]=new DateInfoV5()).Read(block, fieldSize); break; case FormatComponentV5.SIGNAL_INFO: (fields[fieldsCount++]=new SignalInfoV5()).Read(block); break; case FormatComponentV5.DECOMP_INFO: (fields[fieldsCount++]=new DecompositionInfoV5()).Read(block); break; case FormatComponentV5.WEB_SITE_INFO: (fields[fieldsCount++]=new WebSiteInfoV5()).Read(block, fieldSize); break; default: block.skipBytes(fieldSize); break; } s+=fieldSize+2; } return true; } public void setDimBase(int dim) { this.epochDim=dim; } public int getDimBase() { // if(segment.signal!=null) { // return segment.signal.length; // } return epochDim; } public int getNumOfAtoms() { return segment.atoms.size(); } public String getDate() { for (int i=0 ; i<fieldsCount ; i++) if (fields[i].type==FormatComponent.DATE_INFO) { return ((DateInfoV5)fields[i]).date; } return null; } public String getText() { for (int i=0 ; i<fieldsCount ; i++) if (fields[i].type==FormatComponentV5.TEXT_INFO) { return ((TextInfoV5)fields[i]).text; } return null; } public float getEnergyPercent() { for (int i=0 ; i<fieldsCount ; i++) { if (fields[i].type==FormatComponentV5.DECOMP_INFO) { return ((DecompositionInfoV5)fields[i]).energy_percent; } } return -1.0F; } public int getMaxNumberOfIteration() { for (int i=0 ; i<fieldsCount ; i++) { if (fields[i].type==FormatComponentV5.DECOMP_INFO) { return ((DecompositionInfoV5)fields[i]).max_number_of_iterations; } } return -1; } public int getDictionarySize() { for (int i=0 ; i<fieldsCount ; i++) { if (fields[i].type==FormatComponentV5.DECOMP_INFO) { return ((DecompositionInfoV5)fields[i]).dictionary_size; } } return -1; } public int getMaxChannel() { for (int i=0 ; i<fieldsCount ; i++) { if (fields[i].type==FormatComponentV5.SIGNAL_INFO) { return ((SignalInfoV5)fields[i]).number_of_chanels_in_file; } } return -1; } public char getDictionaryType() { for (int i=0 ; i<fieldsCount ; i++) { if (fields[i].type==FormatComponentV5.DECOMP_INFO) { return (char)((DecompositionInfoV5)fields[i]).dictionary_type; } } return '0'; } public float getConvFactor() { for (int i=0 ; i<fieldsCount ; i++) { if (fields[i].type==FormatComponentV5.SIGNAL_INFO) { return ((SignalInfoV5)fields[i]).points_per_microvolt; } } return 1.0F; } public float getSamplingFreq() { for (int i=0 ; i<fieldsCount ; i++) { if (fields[i].type==FormatComponentV5.SIGNAL_INFO) { return ((SignalInfoV5)fields[i]).sampling_freq; } } return 1.0F; } public String getWebSize() { for (int i=0 ; i<fieldsCount ; i++) { if (fields[i].type==FormatComponentV5.WEB_SITE_INFO) { return ((WebSiteInfoV5)fields[i]).www; } } return null; } public String getVersion() { switch (version) { case VERSION_III: return "III"; case VERSION_IV: return "IV"; case VERSION_V: return "V"; } return "UNKNOWN"; } public String getString() { String mydate=getDate(),mytext=getText(); if (mydate==null) mydate="(null)"; if (mytext==null) mytext="(null)"; return ("\nSampling frequency: "+getSamplingFreq()+" Hz\n"+ "Version : "+getVersion()+"\n"+ "Conversion : "+getConvFactor()+" points/uV\n"+ "Dictionary Type : "+getDictionaryType()+"\n"+ "Dictionary Size : "+getDictionarySize()+"\n"+ "Energy Percent : "+getEnergyPercent()+" %\n"+ "Number of channels: "+getMaxChannel()+"\n"+ "Text : "+mytext+"\n"+ "Date : "+mydate+"\n" ); } public boolean Open(String filename, int off) throws BookFormatException { try { Close(); streamClass=new RandomAccessFile(filename, "r"); readFileHeader(streamClass); long pos=streamClass.getFilePointer(); countBook(streamClass); streamClass.seek(pos); readBook(streamClass); } catch (IOException e) { throw new BookFormatException(e); } return true; } public int getSegmentCount() { HashSet<Integer> set=new HashSet<Integer>(); int len=index.size(); for (int i=0 ; i<len ; i++) { set.add(new Integer(index.elementAt(i).offset)); } return set.size(); } public StandardBookSegment []getCurrentSegment(int segmentIndex) { CPair off[]=getOffset(segmentIndex); if (off!=null) { int len=off.length; SegmentHeaderV5 []arr=new SegmentHeaderV5[len]; for (int i=0 ; i<len ; i++) { try { CPair p=off[i]; SegmentHeaderV5 seg1=null, seg2=null; Utils.log("off= "+p.x+" "+p.y); if (p.x>=0L) { streamClass.seek(p.x); readBook(streamClass); seg1=segment; } int offSetDimension = segment.offsetDimension; int offsetNumber = segment.offsetNumber; if (p.y>=0L) { streamClass.seek(p.y); readBook(streamClass); seg2=segment; segment.offsetDimension = offSetDimension; segment.offsetNumber = offsetNumber; } if (seg1!=null && seg2!=null) { if (seg1.hasSignal()) { seg2.setSignalSamples(seg1.getSignalSamples()); arr[i]=seg2; } else { seg1.setSignalSamples(seg2.getSignalSamples()); arr[i]=seg1; } } else { if (seg1!=null) { arr[i]=seg1; } else if (seg2!=null) { arr[i]=seg2; } } } catch (IOException e) { return null; } } return arr; } return null; } public StandardBookSegment getCurrentSegment(int segmentIndex, int channelIndex) { long off=getOffset(segmentIndex, channelIndex, FormatComponentV5.ATOMS_SEGMENT_IDENTITY); SegmentHeaderV5 seg=null; if (off>=0L) { try { streamClass.seek(off); readBook(streamClass); } catch (IOException e) { return null; } seg=segment; } else { Utils.log("Books not found!"); } off=getOffset(segmentIndex, channelIndex, FormatComponentV5.SIGNAL_SEGMENT_IDENTITY); if (off>=0L) { try { streamClass.seek(off); readBook(streamClass); } catch (IOException e) { return null; } if (seg!=null) { seg.setSignalSamples(segment.getSignalSamples()); } else { seg=segment; } } else { Utils.log("Signals not found!"); } return seg; } }