package matrix; import java.io.File; import java.io.PrintStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Locale; import jxl.Workbook; import jxl.WorkbookSettings; import jxl.write.Label; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import matrix.general.MatrixReadException; import org.apache.log4j.Logger; import org.molgenis.core.Nameable; import org.molgenis.data.Data; 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.matrix.MatrixException; import org.molgenis.pheno.ObservationElement; import org.molgenis.util.CsvWriter; //import com.pmstation.spss.SPSSWriter; /** * Abstract implementation for MatrixInterface. Some functions require XGAP * components, therefore this class should be seperated into Matrix.java, a * generic abstract class with functions that work on generic types, and * XgapMatrix.java, with functions that require a few XGAP specific data types. * * @author Morris Swertz, Joeri van der Velde * @param <E> * the generic type of the matrix. E.g. String, Double etc. */ public abstract class AbstractDataMatrixInstance<E> implements DataMatrixInstance { /** * Protected method for subclasses to add the Data description. This method * MUST be called in the constructor to instantiate the matrix. */ protected void setData(Data data) { this.data = data; } /** * Protected method for subclasses to label the columns. This method MUST be * called in the constructor to instantiate the matrix. */ protected void setColNames(List<String> list) { this.colNames = list; } /** * Protected method for subclasses to label the rows. This method MUST be * called in the constructor to instantiate the matrix. */ protected void setRowNames(List<String> list) { this.rowNames = list; } /** * Protected method to set number of columns. This method MUST be called in * the constructor to instantiate the matrix. */ protected void setNumberOfCols(int numberOfCols) { this.numberOfCols = numberOfCols; } /** * Protected method to set number of rows. This method MUST be called in the * constructor to instantiate the matrix. */ protected void setNumberOfRows(int numberOfRows) { this.numberOfRows = numberOfRows; } // Local variables Logger logger = Logger.getLogger(getClass().getSimpleName()); private Data data; private List<String> rowNames; private List<String> colNames; private int numberOfRows; private int numberOfCols; // Implementations of MatrixInterface public Data getData() { return data; } public Object[] getCol(String colName) throws Exception { return getCol(colNames.indexOf(colName)); } public Object[] getRow(String rowName) throws Exception { return getRow(rowNames.indexOf(rowName)); } /** * Helper to convert ObservationElement to String */ public DataMatrixInstance getSubMatrixByObservationElement(List<ObservationElement> rows, List<ObservationElement> cols) throws MatrixException { List<String> rowNames = new ArrayList<String>(); for (ObservationElement row : rows) { rowNames.add(row.getName()); } List<String> colNames = new ArrayList<String>(); for (ObservationElement col : cols) { colNames.add(col.getName()); } return getSubMatrix(rowNames, colNames); } public DataMatrixInstance getSubMatrix(List<String> rowNames, List<String> colNames) throws MatrixException { int[] rowIndices = new int[rowNames.size()]; int[] colIndices = new int[colNames.size()]; for (int i = 0; i < rowNames.size(); i++) { rowIndices[i] = this.rowNames.indexOf(rowNames.get(i)); } for (int i = 0; i < colNames.size(); i++) { colIndices[i] = this.colNames.indexOf(colNames.get(i)); } return getSubMatrix(rowIndices, colIndices); } public DataMatrixInstance getSubMatrixByOffset(String rowName, int nRows, String colName, int nCols) throws Exception { return getSubMatrixByOffset(this.rowNames.indexOf(rowName), nRows, this.colNames.indexOf(colName), nCols); } public int getRowIndexForName(String rowName) throws Exception { if (!rowNames.contains(rowName)) throw new MatrixReadException("rowname " + rowName + " not known in matrix"); return this.rowNames.indexOf(rowName); } public int getColIndexForName(String colName) throws Exception { if (!colNames.contains(colName)) throw new MatrixReadException("colname " + colName + " not known in matrix"); return this.colNames.indexOf(colName); } public Object getElement(String rowName, String colName) throws Exception { return getElement(this.getRowIndexForName(rowName), this.getColIndexForName(colName)); } public void toPrintStream(PrintStream p) { try { for (String col : getColNames()) { p.append("\t" + col); } p.append("\n"); // Object[][] elements = getElements(); for (int rowIndex = 0; rowIndex < this.getNumberOfRows(); rowIndex++) { Object[] row = this.getRow(rowIndex); p.append(getRowNames().get(rowIndex)); for (int colIndex = 0; colIndex < this.getNumberOfCols(); colIndex++) { if (row[colIndex] == null) { p.append("\t"); } else { p.append("\t" + row[colIndex]); } } p.append("\n"); p.flush(); } } catch (Exception e) { e.printStackTrace(); } } public String toString() { StringBuffer result = new StringBuffer(); try { for (String col : getColNames()) { result.append("\t" + col); } result.append("\n"); Object[][] elements = getElements(); for (int rowIndex = 0; rowIndex < this.getNumberOfRows(); rowIndex++) { result.append(getRowNames().get(rowIndex)); for (int colIndex = 0; colIndex < this.getNumberOfCols(); colIndex++) { if (elements[rowIndex][colIndex] == null) { result.append("\t"); } else { result.append("\t" + elements[rowIndex][colIndex]); } } result.append("\n"); } } catch (Exception e) { e.printStackTrace(); } return result.toString(); } @Override public String getAsRobject(boolean replaceNaWithZero) throws Exception { // e.g. // mdat <- matrix( // nrow = 2, // ncol=3, // byrow=TRUE, // dimnames = list(c( // "row1","row2"),c( // "C.1","C.2","C.3")), // data = c( // 1,2,3, // 11,12,13)) StringBuffer result = new StringBuffer(); result.append(this.getData().getName() + " <- matrix(\n"); result.append("\tnrow = " + this.getNumberOfRows() + ",\n"); result.append("\tncol = " + this.getNumberOfCols() + ",\n"); result.append("\tbyrow=TRUE,\n"); result.append("dimnames = list(c(\n"); for (String rowName : this.getRowNames()) { result.append("\"" + rowName + "\","); } result.insert(result.length() - 1, ")"); result.append("c(\n"); for (String colName : this.getColNames()) { result.append("\"" + colName + "\","); } result.insert(result.length() - 1, "))"); result.append("\n"); result.append("data = c("); try { Object[][] elements = getElements(); for (int rowIndex = 0; rowIndex < this.getNumberOfRows(); rowIndex++) { for (int colIndex = 0; colIndex < this.getNumberOfCols(); colIndex++) { Object val = elements[rowIndex][colIndex]; if (val == null) { if (replaceNaWithZero) { result.append("0,"); } else { result.append("NA,"); } } else { if (val instanceof Number) { result.append(val + ","); } else { result.append("\"" + val + "\","); } } } result.append("\n"); } result.setCharAt(result.length() - 2, ')'); result.append(")\n"); } catch (Exception e) { e.printStackTrace(); } return result.toString(); } public File getAsExcelFile() throws Exception { /* Create tmp file */ File excelFile = new File(System.getProperty("java.io.tmpdir") + File.separator + this.getData().getName() + ".xls"); /* Create new Excel workbook and sheet */ WorkbookSettings ws = new WorkbookSettings(); ws.setLocale(new Locale("en", "EN")); WritableWorkbook workbook = Workbook.createWorkbook(excelFile, ws); WritableSheet s = workbook.createSheet("Sheet1", 0); /* Format the fonts */ WritableFont headerFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.BOLD); WritableCellFormat headerFormat = new WritableCellFormat(headerFont); headerFormat.setWrap(false); WritableFont cellFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD); WritableCellFormat cellFormat = new WritableCellFormat(cellFont); cellFormat.setWrap(false); /* Write column headers */ List<String> colNames = this.getColNames(); for (int i = 0; i < colNames.size(); i++) { Label l = new Label(i + 1, 0, colNames.get(i), headerFormat); s.addCell(l); } /* Write row headers */ List<String> rowNames = this.getRowNames(); for (int i = 0; i < rowNames.size(); i++) { Label l = new Label(0, i + 1, rowNames.get(i), headerFormat); s.addCell(l); } /* Write elements */ Object[][] elements = getElements(); for (int i = 0; i < this.getNumberOfCols(); i++) { for (int j = 0; j < this.getNumberOfRows(); j++) { if (elements[j][i] != null) { Label l = new Label(i + 1, j + 1, elements[j][i].toString(), cellFormat); s.addCell(l); } else { s.addCell(new Label(i + 1, j + 1, "", cellFormat)); } } } /* Close workbook */ workbook.write(); workbook.close(); return excelFile; } public int getNumberOfCols() { return numberOfCols; } public int getNumberOfRows() { return numberOfRows; } public List<String> getColNames() { return colNames; } public List<String> getRowNames() { return rowNames; } public DataMatrixInstance getSubMatrixFilterByIndex(QueryRule... rules) throws Exception { return AbstractDataMatrixQueries.getSubMatrixFilterByIndex(this, rules); } public DataMatrixInstance getSubMatrixFilterByRowEntityValues(Database db, QueryRule... rules) throws Exception { return AbstractDataMatrixQueries.getSubMatrixFilterByRowEntityValues(this, db, rules); } public DataMatrixInstance getSubMatrixFilterByColEntityValues(Database db, QueryRule... rules) throws Exception { return AbstractDataMatrixQueries.getSubMatrixFilterByColEntityValues(this, db, rules); } public DataMatrixInstance getSubMatrixFilterByRowMatrixValues(QueryRule... rules) throws Exception { return AbstractDataMatrixQueries.getSubMatrixFilterByRowMatrixValues(this, rules); } public DataMatrixInstance getSubMatrixFilterByColMatrixValues(QueryRule... rules) throws Exception { return AbstractDataMatrixQueries.getSubMatrixFilterByColMatrixValues(this, rules); } @Override public DataMatrixInstance getSubMatrix2DFilterByRow(QueryRule... rules) throws Exception { return AbstractDataMatrixQueries.getSubMatrix2DFilterByRow(this, rules); } @Override public DataMatrixInstance getSubMatrix2DFilterByCol(QueryRule... rules) throws Exception { return AbstractDataMatrixQueries.getSubMatrix2DFilterByCol(this, rules); } public DataMatrixInstance getMatrixSortByRowEntityValues(boolean asc) throws Exception { throw new Exception("Unimplemented."); } public DataMatrixInstance getMatrixSortByColEntityValues(Database db, boolean asc) throws Exception { QueryRule sorting = null; if (asc) { sorting = new QueryRule(Operator.SORTASC); } else { sorting = new QueryRule(Operator.SORTDESC); } List<String> rowNames = this.getRowNames(); List<Nameable> subCol = (List<Nameable>) db.find(db.getClassForName(this.getData().getFeatureType()), sorting); List<String> colNames = new ArrayList<String>(); for (Nameable i : subCol) { colNames.add(i.getName()); } DataMatrixInstance res = this.getSubMatrix(rowNames, colNames); return res; } public DataMatrixInstance getMatrixSortByRowMatrixValues(boolean asc) throws Exception { throw new Exception("Unimplemented."); } public DataMatrixInstance getMatrixSortByColMatrixValues(Database db, boolean asc) throws Exception { List<Data> result = db.find(Data.class, new QueryRule("name", Operator.EQUALS, this.getData().getName())); Data thisData = null; if (result.size() < 1) { // no Data object for this one.. throw new Exception("Matrix has no 'Data' description"); } else if (result.size() > 1) { // multiple Data objects! throw new Exception("Multiple 'Data' descriptions for name '" + this.getData().getName() + "'."); } else { thisData = result.get(0); } Query q = null; q.addRules(new QueryRule("data", Operator.EQUALS, thisData.getId())); throw new Exception("Unimplemented."); } public DataMatrixInstance performUnion(DataMatrixInstance N) throws Exception { throw new Exception("Unimplemented."); } public DataMatrixInstance performIntersection(DataMatrixInstance N) throws Exception { throw new Exception("Unimplemented."); } public DataMatrixInstance performDifference(DataMatrixInstance I) throws Exception { throw new Exception("Unimplemented."); } public DataMatrixInstance performExclusion(DataMatrixInstance I) throws Exception { throw new Exception("Unimplemented."); } public DataMatrixInstance performTransposition(DataMatrixInstance I) throws Exception { throw new Exception("Unimplemented."); } public void writeToCsvWriter(PrintWriter out) throws Exception { CsvWriter cfr = new CsvWriter(out); cfr.writeMatrix(getRowNames(), getColNames(), getElements()); cfr.close(); } public void writeToPrintWriter(PrintWriter out) throws Exception { Object[][] elements = getElements(); for (String col : getColNames()) { out.write("\t" + col); } out.write("\n"); for (int rowIndex = 0; rowIndex < this.getNumberOfRows(); rowIndex++) { out.write(getRowNames().get(rowIndex)); for (int colIndex = 0; colIndex < this.getNumberOfCols(); colIndex++) { if (elements[rowIndex][colIndex] == null) { out.write("\t"); } else { out.write("\t" + elements[rowIndex][colIndex]); } } out.write("\n"); } } /** * Get the matrix in the shape of a one-dimensional list. Instead of a * 'grid' or values, just get a default importable CSV list of, for example * feature - target - value. * * @return * @throws Exception */ public List<String> getAsObservedValueList() throws Exception { List<String> res = new ArrayList<String>(); // get a shorthand to all the matrix values Object[][] elements = getElements(); // add header // TODO: finish this part // res.add(this.getData().getTarget_Name() + "\t" // + this.getData().getFeature_Name() + "\t" + "etc"); // iterate over all the values and add in the form of a list for (int rowIndex = 0; rowIndex < this.getNumberOfRows(); rowIndex++) { for (int colIndex = 0; colIndex < this.getNumberOfCols(); colIndex++) { res.add(getRowNames().get(rowIndex) + "\t" + getColNames().get(colIndex) + "\t" + elements[rowIndex][colIndex]); } } return res; } public static String render(ObservationElement o, String screenName) { String head = o.getName(); String content = ""; for (String f : o.getFields()) { content += f + " = " + o.get(f) + "<br>"; } return "<div style=\"display: inline; text-align: center;\" onmouseover=\"return overlib('" + content + "', CAPTION, '" + head + "')\" onmouseout=\"return nd();\"><nobr>" + "<a target=\"_blank\" href=?select=" + o.get__Type() + "s&__target=" + o.get__Type() + "s&__comebacktoscreen=" + screenName + "&__action=filter_set&__filter_attribute=" + o.get__Type() + "_name&__filter_operator=EQUALS&__filter_value=" + o.getName() + ">" + o.getName() + "</a></nobr></div>"; } }