package visad.data;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import visad.VisADException;
import edu.wisc.ssec.mcidas.AreaFile;
import edu.wisc.ssec.mcidas.AreaFileException;
import edu.wisc.ssec.mcidas.AreaFileFactory;
import edu.wisc.ssec.mcidas.adde.AddeImageURL;
import edu.wisc.ssec.mcidas.adde.AddeURLException;
/**
* Knows how to read local satellite data to be used by a cache adaptor.
*
* TODO: Add capability to work in conjunciton with ADDE data sources
* including the IDV <code>ucar.visad.data.CachedFlatField</code>.
*/
public class AreaImageAccessor implements FlatFieldCacheAccessor,
Comparable<AreaImageAccessor> {
private static Logger log = Logger.getLogger(AreaImageAccessor.class.getName());
private final int band;
private final String source;
private int startLine;
private int numLines;
private int lineMag;
private int startElem;
private int numElems;
private int elemMag;
private Date nominalTime;
private int[][][] readCache;
private boolean isAddeSource;
/**
* Create an instance. No data is read at this time.
*
* @param source As described in {@link AreaFileFactory#getAreaFileInstance(String)}.
* @param band The band number of the image.
* @param readCache Array to use as a cache for reading AREA data into. If null data will
* not be read by-reference. See {@link AreaFile#getData(int[][][])}.
* @throws VisADException
*/
public AreaImageAccessor(String source, int band, int[][][] readCache) throws VisADException {
super();
this.band = band;
this.source = source;
this.readCache = readCache;
if (this.readCache == null) {
log.fine("readCache is null, by-reference data reading is disabled");
}
try {
new AddeImageURL(source, AddeImageURL.REQ_IMAGEDATA, "", "");
isAddeSource = true;
throw new IllegalArgumentException("adde sources are not currently supported");
} catch (Exception e) {
isAddeSource = false;
}
}
/**
* Set AREA file subsetting parameters.
*
* @param startLine
* @param numLines
* @param lineMag
* @param startElem
* @param numElems
* @param elemMag
*/
public void setAreaParams(int startLine, int numLines, int lineMag, int startElem, int numElems,
int elemMag) {
this.startLine = startLine;
this.numLines = numLines;
this.lineMag = lineMag;
this.startElem = startElem;
this.numElems = numElems;
this.elemMag = elemMag;
}
public boolean isAddeSource() {
return isAddeSource;
}
protected int[][][] getAreaData() throws AreaFileException, AddeURLException {
AreaFile af = null;
if (!isAddeSource) {
af = AreaFileFactory.getAreaFileInstance(source.toString(), startLine, numLines, lineMag,
startElem, numElems, elemMag, band);
} else {
// expect sub-setting to be done in URL
af = AreaFileFactory.getAreaFileInstance(source.toString());
}
if (nominalTime == null) {
nominalTime = af.getAreaDirectory().getNominalTime();
} else if (nominalTime.equals(af.getAreaDirectory())) {
throw new FlatFieldCacheError("nominal time mismatch on subsequent reads", null);
}
// use by-reference if possible
int[][][] raw = null;
if (readCache != null) {
raw = af.getData(readCache);
} else {
raw = af.getData();
}
return raw;
}
public String getSource() {
return source;
}
public double[][] readFlatField() {
double[][] range = null;
try {
int[][][] raw = getAreaData();
range = new double[1][numLines * numElems];
int idx = 0;
for (int line = 0; line < raw[0].length; line++) {
for (int elem = 0; elem < raw[0][0].length; elem++) {
range[0][idx++] = (double) raw[0][line][elem];
}
}
} catch (Exception e) {
log.log(Level.SEVERE, "Could not read image data: " + source.toString(), e);
}
return range;
}
public float[][] readFlatFieldFloats() {
float[][] range = null;
try {
int[][][] raw = getAreaData();
range = new float[1][numLines * numElems];
int idx = 0;
for (int line = 0; line < raw[0].length; line++) {
for (int elem = 0; elem < raw[0][0].length; elem++) {
range[0][idx++] = (float) raw[0][line][elem];
}
}
} catch (Exception e) {
log.log(Level.SEVERE, "Could not read AREA file: " + source.toString(), e);
}
return range;
}
public Date getNominalTime() {
if (nominalTime == null) {
AreaFile af;
try {
af = AreaFileFactory.getAreaFileInstance(source.toString());
} catch (Exception e) {
throw new FlatFieldCacheError("Error getting nominal time from AREA file", e);
}
nominalTime = af.getAreaDirectory().getNominalTime();
}
return nominalTime;
}
public int compareTo(AreaImageAccessor that) {
long myTime = getNominalTime().getTime();
long yourTime = that.getNominalTime().getTime();
if (myTime > yourTime) {
return 1;
} else if (myTime < yourTime) {
return -1;
}
return 0;
}
}