package mil.nga.giat.geowave.analytic.mapreduce.kde.compare;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import mil.nga.giat.geowave.analytic.mapreduce.kde.GaussianCellMapper;
import mil.nga.giat.geowave.analytic.mapreduce.kde.GaussianFilter;
import org.opengis.feature.simple.SimpleFeature;
import com.vividsolutions.jts.geom.Point;
public class ComparisonGaussianCellMapper extends
GaussianCellMapper
{
protected static final String TIME_ATTRIBUTE_KEY = "TIME_ATTRIBUTE";
private String timeAttribute;
private final Map<Integer, LevelStore> winterLevelStoreMap = new HashMap<Integer, LevelStore>();
@Override
protected void setup(
final Context context )
throws IOException,
InterruptedException {
super.setup(context);
timeAttribute = context.getConfiguration().get(
TIME_ATTRIBUTE_KEY);
}
@Override
protected void populateLevelStore(
final org.apache.hadoop.mapreduce.Mapper.Context context,
final int numXPosts,
final int numYPosts,
final int level ) {
super.populateLevelStore(
context,
numXPosts,
numYPosts,
level);
winterLevelStoreMap.put(
level,
new LevelStore(
numXPosts,
numYPosts,
new NegativeCellIdCounter(
context,
level,
minLevel,
maxLevel)));
}
@Override
protected void incrementLevelStore(
final int level,
final Point pt,
final SimpleFeature feature ) {
final Object obj = feature.getAttribute(timeAttribute);
if ((obj != null) && (obj instanceof Date)) {
double contribution = 0;
LevelStore levelStore = null;
final Calendar cal = Calendar.getInstance();
cal.setTime((Date) obj);
// the seasonal variance algorithm we'll use will apply a gaussian
// function to winter months (October - March), incrementing the
// winter counter
// and apply a gaussian function to April and September incrementing
// the summer counter
// the other months increment the summer counter
final int featureMonth = cal.get(Calendar.MONTH);
if (featureMonth < 3) {
final Calendar baseDate = Calendar.getInstance();
baseDate.set(
cal.get(Calendar.YEAR),
0,
0,
0,
0,
0);
final double deltaTime = cal.getTime().getTime() - baseDate.getTime().getTime();
// now normalize so the value is between 0 and 3 (somewhat
// arbitrary but e^-(x*x) asymptotically approaches 0 near 3 and
// -3)
final Calendar maxDate = Calendar.getInstance();
maxDate.set(
cal.get(Calendar.YEAR),
3,
0,
0,
0,
0);
final double normalizedTime = (deltaTime * 3)
/ (maxDate.getTimeInMillis() - baseDate.getTimeInMillis());
contribution = Math.pow(
Math.E,
-(normalizedTime * normalizedTime));
levelStore = winterLevelStoreMap.get(level);
}
else if (featureMonth > 8) {
final Calendar baseDate = Calendar.getInstance();
baseDate.set(
cal.get(Calendar.YEAR) + 1,
0,
0,
0,
0,
0);
final double deltaTime = baseDate.getTime().getTime() - cal.getTime().getTime();
// now normalize so the value is between 0 and 3 (somewhat
// arbitrary but e^-(x*x) asymptotically approaches 0 near 3 and
// -3)
final Calendar minDate = Calendar.getInstance();
minDate.set(
cal.get(Calendar.YEAR),
9,
0,
0,
0,
0);
final double normalizedTime = (deltaTime * 3)
/ (baseDate.getTimeInMillis() - minDate.getTimeInMillis());
contribution = Math.pow(
Math.E,
-(normalizedTime * normalizedTime));
levelStore = winterLevelStoreMap.get(level);
}
else if ((featureMonth == 3) || (featureMonth == 8)) {
final Calendar maxDate = Calendar.getInstance();
maxDate.set(
cal.get(Calendar.YEAR),
featureMonth + 1,
0,
0,
0,
0);
final double deltaTime;
final Calendar minDate = Calendar.getInstance();
minDate.set(
cal.get(Calendar.YEAR),
featureMonth,
0,
0,
0,
0);
if (featureMonth == 3) {
deltaTime = maxDate.getTime().getTime() - cal.getTime().getTime();
}
else {
deltaTime = cal.getTime().getTime() - minDate.getTime().getTime();
}
final double normalizedTime = (deltaTime * 3) / (maxDate.getTimeInMillis() - minDate.getTimeInMillis());
contribution = Math.pow(
Math.E,
-(normalizedTime * normalizedTime));
levelStore = levelStoreMap.get(level);
}
else {
contribution = 1;
levelStore = levelStoreMap.get(level);
}
GaussianFilter.incrementPt(
pt.getY(),
pt.getX(),
levelStore.counter,
levelStore.numXPosts,
levelStore.numYPosts,
contribution);
}
}
}