/*
* Copyright (C) 2012 Addition, Lda. (addition at addition dot pt)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package org.addition.epanet.quality;
import org.addition.epanet.network.FieldsMap;
import org.addition.epanet.util.ENException;
import java.io.*;
import java.util.Iterator;
/**
* Binary quality file reader class.
*/
public class QualityReader implements Iterable<QualityReader.Step> {
/**
* Single step of the quality simulation, with the quality value for each
* link and node.
*/
public class Step {
/**
* Species quality values in the links
*/
private final float[] linkQ;
/**
* Species quality values in the nodes
*/
private final float[] nodeQ;
/**
* Constructor
*
* @param linkCount number of links
* @param nodeCount number of nodes
*/
private Step(int linkCount, int nodeCount) {
linkQ = new float[linkCount];
nodeQ = new float[nodeCount];
}
/**
* Get link quality values in user units.
*
* @param id Link sequential identification number.
* @return Species concentration, trace or age value in user units.
*/
public float getLinkQuality(int id) throws ENException {
return (float) fMap.revertUnit(FieldsMap.Type.QUALITY, linkQ[id]);
}
/**
* Get node quality values in user units.
*
* @param id Link sequential identification number.
* @return Specie concentration, trace or age value in user units.
*/
public float getNodeQuality(int id) throws ENException {
return (float) fMap.revertUnit(FieldsMap.Type.QUALITY, nodeQ[id]);
}
/**
* Read quality data from file stream.
*
* @throws IOException
*/
private void read() throws IOException {
for (int i = 0; i < nodeQ.length; i++)
nodeQ[i] = inputStream.readFloat();
for (int i = 0; i < linkQ.length; i++)
linkQ[i] = inputStream.readFloat();
}
/**
* Get node quality values in user units.
*
* @param id Link sequential identification number.
* @return Species concentration, trace or age value in simulation units.
*/
// public float getRawNodeQuality(int id) throws ENException {
// return (float) fMap.revertUnit(FieldsMap.Type.QUALITY, nodeQ[id]);
// }
/**
* Get link quality values in user units.
*
* @param id Link sequential identification number.
* @return Species concentration, trace or age value in simulation units.
*/
// public float getRawLinkQuality(int id) throws ENException {
// return (float) fMap.revertUnit(FieldsMap.Type.QUALITY, linkQ[id]);
// }
}
/**
* Step snapshot iterator class
*/
private class StepIterator implements Iterator<Step> {
/**
* Current step number.
*/
int current;
/**
* Initialize iterator.
*/
private StepIterator() {
current = 0;
}
/**
* Check for available steps to read.
*
* @return Step availability.
*/
public boolean hasNext() {
return current < nPeriods;
}
/**
* Read step data and advance to the next.
*
* @return Reference to step snapshot.
*/
public Step next() {
current++;
try {
qStep.read();
} catch (IOException e) {
throw new RuntimeException(e);
}
return qStep;
}
/**
* Not implemented.
*/
public void remove() {
throw new RuntimeException("not implemented");
}
}
/**
* Units conversion map.
*/
private final FieldsMap fMap;
/**
* input stream
*/
private DataInputStream inputStream;
/**
* Number of links.
*/
private int linkCount;
/**
* Number of nodes.
*/
private int nodeCount;
/**
* Number of report periods stored in this file.
*/
private int nPeriods;
/**
* Current quality step snapshot.
*/
private Step qStep;
/**
* Class constructor
*/
public QualityReader(FieldsMap fMap) {
this.fMap = fMap;
}
/**
* Close the inputStream.
*
* @throws IOException
*/
public void close() throws IOException {
inputStream.close();
}
/**
* Get the number of links in the file.
*
* @return Number of links.
*/
public int getLinks() {
return linkCount;
}
/**
* Get the number of nodes in the file.
*
* @return Number of nodes.
*/
public int getNodes() {
return nodeCount;
}
/**
* Get the number of reported quality step snapshots in the file.
*
* @return Number of periods.
*/
public int getPeriods() {
return nPeriods;
}
/**
* Get quality step snapshot iterator.
*
* @return StepSnapshot iterator.
*/
public Iterator<Step> iterator() {
return new StepIterator();
}
/**
* @param qualFile Abstract representation of the quality file.
*/
@SuppressWarnings({"ResultOfMethodCallIgnored"})
public void open(File qualFile) throws IOException {
// Read the last 4 bytes which contain the number of periods
inputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(qualFile)));
inputStream.skip(qualFile.length() - Integer.SIZE / 8);
nPeriods = inputStream.readInt();
inputStream.close();
inputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(qualFile)));
nodeCount = inputStream.readInt();
linkCount = inputStream.readInt();
qStep = new Step(linkCount, nodeCount);
}
}