/* Date: October 17, 2010
* Template: PluginScreenJavaTemplateGen.java.ftl
* generator: org.molgenis.generators.ui.PluginScreenJavaTemplateGen 3.3.3
*
* THIS FILE IS A TEMPLATE. PLEASE EDIT :-)
*/
package plugins.mazeexperiment;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.molgenis.framework.db.Database;
import org.molgenis.framework.db.Query;
import org.molgenis.framework.db.QueryRule;
import org.molgenis.framework.db.QueryRule.Operator;
import org.molgenis.framework.ui.PluginModel;
import org.molgenis.framework.ui.ScreenController;
import org.molgenis.maze.BinaryChannelData;
import org.molgenis.maze.ChannelMapping;
import org.molgenis.util.Entity;
import org.molgenis.util.Tuple;
public class plotActogram extends PluginModel<Entity>
{
/**
*
*/
private static final long serialVersionUID = 1983706633143335769L;
private List<ChannelMapping> channelList;
private int currChlListIdx = 0;
private String plot;
private int chlListSize;
private int currChlNr;
private int currChlId;
private String startDate = "first";
private String endDate = "first";
//private Date currDate;
//private List<Mazedata> ChannelMazedata;
/*
* some getters and setters:
*/
public int getCurrChlId() {
return currChlId;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public void setCurrChlId(int currChlId) {
this.currChlId = currChlId;
}
public int getCurrChlListIdx() {
return currChlListIdx;
}
public void setCurrChlListIdx(int currChlListIdx) {
this.currChlListIdx = currChlListIdx;
}
public int getChlListSize() {
return chlListSize;
}
public void setChlListSize(int chlListSize) {
this.chlListSize = chlListSize;
}
public int getCurrChlNr() {
return currChlNr;
}
public void setCurrChlNr(int currChlNr) {
this.currChlNr = currChlNr;
}
public String getPlot() {
return plot;
}
public void setPlot(String plot) {
this.plot = plot;
}
public List<ChannelMapping> getChannelList() {
return channelList;
}
public void setChannelList(List<ChannelMapping> channelList) {
this.channelList = channelList;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public plotActogram(String name, ScreenController<?> parent)
{
super(name, parent);
}
public String getCustomHtmlHeaders() {
return "<link rel=\"stylesheet\" style=\"text/css\" href=\"res/css/animaldb.css\">" +
"<script src=\"generated-res/scripts/datetimeinput.js\" type=\"text/javascript\" language=\"javascript\"></script>";
}
@Override
public String getViewName()
{
return "plugins_mazeexperiment_plotActogram";
}
@Override
public String getViewTemplate()
{
return "plugins/mazeexperiment/plotActogram.ftl";
}
@Override
public void handleRequest(Database db, Tuple request)
{
SimpleDateFormat sdf = new SimpleDateFormat("MMMM d, yyyy, HH:mm:ss", Locale.US);
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
SimpleDateFormat sdfMysqlStamp = new SimpleDateFormat("yyyy-MM-dd HH:MM:SS", Locale.US);
String action = request.getString("__action");
// set the dates
this.startDate = request.getString("startdate");
this.endDate = request.getString("enddate");
logger.debug("sd " + startDate + " ed " + endDate );
String tmpString = request.getString("channel").replace(".", "");
tmpString = tmpString.replace(",", "");
this.currChlListIdx = Integer.parseInt(tmpString); //get the index of the channel object in the channellist (not! the channel nr.)
// set the current channel id.
// handle the plot previous buton
if( action.equals("doPlotPrev") )
{
//check for if offset is at min value 1
if (this.currChlListIdx > 0 ) {
this.currChlListIdx--;
}else {
//msg = new ScreenMessage("You have reached the first channel...",null,false); //TODO fix freemarker error
}
action = "doPlot"; // fowared the corrected request to the plot routine
}
// handle the plot next button
if( action.equals("doPlotNext") )
{
//check for if offset is at min value 1
if (this.currChlListIdx < chlListSize-1) {
this.currChlListIdx++;
}else {
//msg = new ScreenMessage("You have reached the last channel...",null,false); //TODO fix freemarker error
}
action = "doPlot"; // fowared the corrected request to the plot routine
}
// get the channel id
this.currChlId = this.channelList.get(this.currChlListIdx).getId();
// handle the plot button and the forward requests from plotnext and plotprevious
if( action.equals("doPlot") )
{
try {
// set some variables
Date minDate;
Date maxDate;
Calendar c = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
Calendar c3 = Calendar.getInstance();
//TODO: Danny: Use or Loose
/*Calendar plotYaxisDate = */Calendar.getInstance();
//Calendar c4 = Calendar.getInstance();
int startyear = 0;
int startmonth = 0;
int startday = 0;
int rowCtr = 0;
int dataListSize;
//int[] currDayData = new int[720];
//int currBin = 0;
int currDayBin = 0;
int currDay = 0;
double[][] plotData;
double qualBarHeight = 75;
long binSize = 1000*60*2; //set the binsize for the plot (in milliseconds)
long currDpMs = 0;
long currDayOffsetMs =0;
long dpBin = 0;
long nrNewDays = 0;
long dayMs = 24*60*60*1000; // a long containing the amount of milliseconds in a day
long offsetMS = 0;
boolean firstIteration = true;
boolean startNewDay = false;
//List<int[]> plotData = Collections.emptyList();
// get all the data for the requested channel from the binaryconverted table
db.beginTx();
Query<BinaryChannelData> bcdq;
bcdq = db.query(BinaryChannelData.class);
bcdq.addRules(new QueryRule("channelid", Operator.EQUALS, this.currChlId));
bcdq.addRules(new QueryRule("timestamp", Operator.GREATER, sdfMysqlStamp.format(sdf.parse(this.startDate))));
bcdq.addRules(new QueryRule("timestamp", Operator.LESS, sdfMysqlStamp.format(sdf.parse(this.endDate))));
bcdq.addRules(new QueryRule(Operator.SORTASC,"timestamp"));
List<BinaryChannelData> channelSwitchData = bcdq.find();
db.commitTx();
dataListSize = channelSwitchData.size();
if (dataListSize > 0){
// get the date range for the channel:
//minDate = channelSwitchData.get(0).getTimestamp();
//maxDate = channelSwitchData.get(dataListSize-1).getTimestamp();
minDate = sdf.parse(this.startDate);
maxDate = sdf.parse(this.endDate);
logger.info("dataListSize is: "+ dataListSize);
long nrOfDays = (maxDate.getTime()-minDate.getTime()+ (dayMs-1))/(dayMs);
logger.info("nr of days to plot: "+ nrOfDays);
plotData = new double[(int)nrOfDays][720];
//String blaat ="";
//Create the data arrays per day
try{
Iterator<BinaryChannelData> BcdIterator = channelSwitchData.iterator();
while (BcdIterator.hasNext()) {
//accumulate the data per day in an array
rowCtr++;
// Do things specific for the first iteration
if(firstIteration){
//logger.info("FIRST iteration");
// fill the currentdata array with 0
Arrays.fill(plotData[currDay],0);
// set the offsets for the dataset
c.setTime(minDate);
//detect year-month-day
startyear = c.get(Calendar.YEAR);
startmonth = c.get(Calendar.MONTH);
startday = c.get(Calendar.DAY_OF_MONTH);
// and set the offset
c2.set(startyear,startmonth,startday,0,0,0);
currDayOffsetMs = c2.getTimeInMillis();
offsetMS = currDayOffsetMs;
// set the initial bin
currDpMs = c.getTimeInMillis();
//logger.debug("currDpMs = : "+ currDpMs);
//logger.debug("curr dpbin = : "+ dpBin);
//logger.debug("Curr day offset ms: "+ currDayOffsetMs);
dpBin = (currDpMs - currDayOffsetMs) / binSize;
//logger.debug("initial bin = : "+ dpBin);
currDayBin = (int)dpBin;
//logger.debug("initial currDaybin" + currDayBin);
//currBin = currDayBin;
//currBin = (int)(currDayOffsetMs / binSize);
//currDayBin = currBin;
//logger.info(currDayBin);
// end of the firstIteration
firstIteration = false;
}//endif firstIteration
// accumulate the (qualitative) plotdata in binsize(for now 2 min) bins
BinaryChannelData cr = BcdIterator.next(); //get the next datapoint
//logger.info("switch event["+ Integer.toString(rowCtr) +"]: " + cr.getTimestamp());
//check in which bin the point should go
c3.setTime(cr.getTimestamp());
currDpMs = c3.getTimeInMillis();
//logger.debug("next currDpMs: " + currDpMs );
dpBin = (currDpMs - currDayOffsetMs) / binSize;
//logger.info("dpBin = " + dpBin);
//logger.debug("next dpbin: " + dpBin );
//Check if a new day should be started:
if ((int)dpBin >= 720) {
//logger.info("setting startnewday to true");
startNewDay = true;
// check the amount of new days: (in case of no data on a day the dayNr should be increased correctly accordingly)
nrNewDays = dpBin / 720;
logger.debug("NR of new days : " + nrNewDays);
}
if (startNewDay) {
//plotData[currDay] = currDayData;
// add the correct amount of days to the plot
for (long d = 0; d < nrNewDays ; d++) {
// increase the daycounter
currDay++;
logger.debug("Current day:" + currDay);
// prefill all the bins of the new day wit 0
Arrays.fill(plotData[currDay],0);
// correct the day offset with the amount of ms in a day
currDayOffsetMs = currDayOffsetMs + (dayMs);
}
// correct the active bin for the new offset on the active day
dpBin = (currDpMs - currDayOffsetMs) / binSize;
currDayBin =(int)dpBin; //increase the daybincounter
// for qualitative plot : fill the bin with a standard bar height value
plotData[currDay][currDayBin] = qualBarHeight;
// set start new day fals to allow for adding new databins
startNewDay = false;
}
if ((int)dpBin == currDayBin) {
// do nothing for qualitative plot.
//optionally add accumulation code for quantitative plot
}else {
currDayBin =(int)dpBin; //increase the daybincounter
//logger.debug("cd: "+ currDay + " , cdbin: " + currDayBin );
plotData[currDay][currDayBin-1] = qualBarHeight;
// optionally add accumulation code for quantitative plot
}
}//end while
String data = "<table>";
GoogleBarChart chart = new GoogleBarChart();
int dc = 0;
for ( double[] day : plotData){
chart.createBarChart(day);
String chartString = "<img src=\"" + chart.getUrl() + "\" >";
String date = "";
try{
//date = sdf2.format(plotDates.get(dc));
c.setTimeInMillis(offsetMS + (dc * dayMs));
date = sdf2.format(c.getTime());
}catch(Exception e){
date = "-";
e.printStackTrace();
}
data = data + "<tr><td>" + date + "</td><td>" + chartString + "</td></tr>";
dc++;
}
data = data + "</table>";
this.plot = data;
}
catch (Exception e) {
e.printStackTrace();
this.plot = "Something went wrong... <br><hr> " ;
}
}else{
// the dataset is empty
logger.info("Dataset is empty");
this.plot = "The plot cannot be generated, because there is no data for this channel";
}//end if else
}//end try
catch (Exception e) {
this.plot = "something went horribly wrong";
e.printStackTrace();
}
// add status messages to the screen
//this.getMessages().add(msg); //TODO fix freemarker error
}
}
@Override
public void reload(Database db)
{
// Populate channel list
try {
// query the channelmapping table and harvest the available channels
Query<ChannelMapping> q;
q = db.query(ChannelMapping.class);
q.addRules(new QueryRule(Operator.SORTASC,"channelnumber"));
List<ChannelMapping> ChmpList = q.find();
// put the available channel objects in a list
this.setChannelList(ChmpList);
this.chlListSize = this.channelList.size();
}
catch (Exception e) {
e.printStackTrace();
}
// set the current channel id
try{
this.currChlId = this.channelList.get(this.currChlListIdx).getId();
this.currChlNr = this.channelList.get(this.currChlListIdx).getChannelnumber();
}catch(Exception e){
// setting from previous did not work so set defaults
logger.debug("Setting current channel did not work.");
e.printStackTrace();
}
// set the start & enddate
Calendar c = Calendar.getInstance(); // create a new calendar object
Date now = c.getTime(); // get the current date/time from it
c.add(Calendar.DAY_OF_MONTH, -30);
Date start = c.getTime();
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
SimpleDateFormat sdf = new SimpleDateFormat("MMMM d, yyyy, HH:mm:ss", Locale.US);
try{
if (this.startDate.equals("first")){ // check if startdate is set
// if not set put the default on 30 days before now
this.setStartDate(sdf.format(start));
}else {
// get the value from the input
this.setStartDate(this.startDate);
// TODO add code to recalculate the plot offsets because changing the date offsets invalidates array sizes resulting in a crash :(
}
if (this.endDate.equals("first")){ // check if startdate is set
// if not set put the default on now
this.setEndDate(sdf.format(now));
}else {
// get the value from the input
this.setEndDate(this.endDate);
}
}catch(Exception e){
// setting from previous did not work so set defaults
logger.debug("Setting start and enddate did not work.");
e.printStackTrace();
}
}
}