/*
* Debellor
*
* Copyright (C) 2008-2009 by Marcin Wojnarski
*
* 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.debellor.rseslib;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import org.debellor.core.DataObject;
import org.debellor.core.DataType;
import org.debellor.core.Sample;
import org.debellor.core.Sample.SampleType;
import org.debellor.core.data.DataVector;
import org.debellor.core.data.NumericFeature;
import org.debellor.core.data.SymbolicFeature;
import org.debellor.core.data.DataVector.DataVectorType;
import org.debellor.core.exception.data.DataCastException;
import org.debellor.core.exception.data.DataException;
import rseslib.structure.attribute.ArrayHeader;
import rseslib.structure.attribute.Header;
import rseslib.structure.attribute.NominalAttribute;
import rseslib.structure.data.DoubleDataObject;
/**
* Conversion of data structures between Rseslib and Debellor representation.
*
* @author Marcin Wojnarski
*
*/
public class DataConverter {
public static Header headerFrom(SampleType type)
throws RseslibConversionException
{
// write Rseslib header to a string, then pass it to ArrayHeader constructor
try {
Writer buf = new StringWriter(1024);
buf.write("missing_value ?\n");
// write description of input features
DataVectorType data = (DataVectorType) type.data;
for(int i = 0; i < data.size(); i++)
writeAttrHeader(buf, false, "a" + (i+1), data.get(i));
// write description of decision feature
if(type.hasDecision())
writeAttrHeader(buf, true, "decision", type.decision);
LineNumberReader reader = new LineNumberReader(new StringReader(buf.toString()));
return new ArrayHeader(reader);
}
catch(Exception e) {
throw new RseslibConversionException(e);
}
}
private static void writeAttrHeader(Writer header, boolean isDecision, String name, DataType attr)
throws IOException, RseslibConversionException
{
header.write(name + " ");
if(isDecision) header.write("decision");
else header.write("conditional");
header.write(",");
if(attr.dataClass == NumericFeature.class)
header.write("numeric");
else if(attr.dataClass == SymbolicFeature.class)
header.write("nominal");
else
throw new RseslibConversionException("Debellor to Rseslib conversion error. Unsupported feature type.");
header.write("\n");
}
public static DoubleDataObject doubledataFrom(Sample sample, SampleType type, Header header) throws DataCastException
{
DataVector data = (DataVector) sample.data;
DoubleDataObject dd = new DoubleDataObject(header);
// insert input features
int i = 0;
for(; i < data.size(); i++)
if(data.isMissing(i))
dd.set(i, Double.NaN);
else
dd.set(i, rseslibValueFrom(data.get(i), header.attribute(i)));
// insert decision attribute at the end
if(type.hasDecision())
if(sample.decision == null)
dd.set(i, Double.NaN);
else
dd.set(i, rseslibValueFrom((DataObject) sample.decision, header.attribute(i)));
return dd;
}
private static double rseslibValueFrom(DataObject v,
rseslib.structure.attribute.Attribute rseslibAttr) throws DataCastException
{
try {
return v.asNumericFeature().value;
}
catch(DataCastException e) {}
SymbolicFeature sv = v.asSymbolicFeature();
rseslib.structure.attribute.NominalAttribute nominalAttr =
(rseslib.structure.attribute.NominalAttribute) rseslibAttr;
return nominalAttr.globalValueCode(sv.value);
}
public static DataObject attrFromRseslibValue(double v, DataType attrType)
throws DataException
{
if(attrType.dataClass == NumericFeature.class)
return new NumericFeature(v);
return new SymbolicFeature(NominalAttribute.stringValue(v), attrType);
}
}