package hex;
import water.*;
import water.api.DocGen;
import water.fvec.*;
import water.util.FrameUtils;
import water.util.Log;
import water.util.RString;
import java.util.Random;
/**
* Create a Frame from scratch
* If randomize = true, then the frame is filled with Random values.
*
*/
public class CreateFrame extends Request2 {
static final int API_WEAVER=1; // This file has auto-gen'd doc & json fields
static public DocGen.FieldDoc[] DOC_FIELDS; // Initialized from Auto-Gen code.
@API(help = "Name (Key) of frame to be created", required = true, filter = Default.class, json=true)
public String key;
@API(help = "Number of rows", required = true, filter = Default.class, lmin = 1, json=true)
public long rows = 10000;
@API(help = "Number of data columns (in addition to the first response column)", required = true, filter = Default.class, lmin = 1, json=true)
public int cols = 10;
@API(help = "Random number seed", filter = Default.class, json=true)
public long seed = new Random().nextLong();
@API(help = "Whether frame should be randomized", filter = Default.class, json=true)
public boolean randomize = true;
@API(help = "Constant value (for randomize=false)", filter = Default.class, json=true)
public long value = 0;
@API(help = "Range for real variables (-range ... range)", filter = Default.class, json=true)
public long real_range = 100;
@API(help = "Fraction of categorical columns (for randomize=true)", filter = Default.class, dmin = 0, dmax = 1, json=true)
public double categorical_fraction = 0.2;
@API(help = "Factor levels for categorical variables", filter = Default.class, lmin = 2, json=true)
public int factors = 100;
@API(help = "Fraction of integer columns (for randomize=true)", filter = Default.class, dmin = 0, dmax = 1, json=true)
public double integer_fraction = 0.2;
@API(help = "Range for integer variables (-range ... range)", filter = Default.class, json=true)
public long integer_range = 100;
@API(help = "Fraction of binary columns (for randomize=true)", filter = Default.class, dmin = 0, dmax = 1, json=true)
public double binary_fraction = 0.1;
@API(help = "Fraction of 1's in binary columns", filter = Default.class, dmin = 0, dmax = 1, json=true)
public double binary_ones_fraction = 0.02;
@API(help = "Fraction of missing values", filter = Default.class, dmin = 0, dmax = 1, json=true)
public double missing_fraction = 0.01;
@API(help = "Number of factor levels of the first column (1=real, 2=binomial, N=multinomial)", filter = Default.class, lmin = 1, json=true)
public int response_factors = 2;
public boolean positive_response; // only for response_factors=1
@API(help = "Whether an additional response column should be generated", filter = Default.class, json=true)
public boolean has_response = false;
@Override public Response serve() {
try {
if (integer_fraction + binary_fraction + categorical_fraction > 1) throw new IllegalArgumentException("Integer, binary and categorical fractions must add up to <= 1.");
if (Math.abs(missing_fraction) > 1) throw new IllegalArgumentException("Missing fraction must be between 0 and 1.");
if (Math.abs(integer_fraction) > 1) throw new IllegalArgumentException("Integer fraction must be between 0 and 1.");
if (Math.abs(binary_fraction) > 1) throw new IllegalArgumentException("Binary fraction must be between 0 and 1.");
if (Math.abs(binary_ones_fraction) > 1) throw new IllegalArgumentException("Binary ones fraction must be between 0 and 1.");
if (Math.abs(categorical_fraction) > 1) throw new IllegalArgumentException("Categorical fraction must be between 0 and 1.");
if (categorical_fraction > 0 && factors <= 1) throw new IllegalArgumentException("Factors must be larger than 2 for categorical data.");
if (response_factors < 1) throw new IllegalArgumentException("Response factors must be either 1 (real-valued response), or >=2 (factor levels).");
if (cols <= 0 || rows <= 0) throw new IllegalArgumentException("Must have number of rows > 0 and columns > 1.");
if (key.length() == 0) throw new IllegalArgumentException("Output key must be provided.");
if (!randomize) {
if (integer_fraction != 0 || categorical_fraction != 0)
throw new IllegalArgumentException("Cannot have integer or categorical fractions > 0 unless randomize=true.");
} else {
if (value != 0)
throw new IllegalArgumentException("Cannot set data to a constant value if randomize=true.");
}
final FrameCreator fct = new FrameCreator(this);
H2O.submitTask(fct);
fct.join();
Log.info("Created frame '" + key + "'.");
Log.info(FrameUtils.chunkSummary((Frame)UKV.get(Key.make(key))).toString());
return Response.done(this);
} catch( Throwable t ) {
return Response.error(t);
}
}
@Override public boolean toHTML( StringBuilder sb ) {
Frame fr = UKV.get(Key.make(key));
if (fr==null) {
return false;
}
RString aft = new RString("<a href='Inspect2.html?src_key=%$key'>%key</a>");
aft.replace("key", key);
DocGen.HTML.section(sb, "Frame creation done.<br/>Frame '" + aft.toString()
+ "' now has " + fr.numRows() + " rows and " + (fr.numCols()-1)
+ " data columns, as well as a " + (response_factors == 1 ? "real-valued" : (response_factors == 2 ? "binomial" : "multi-nomial"))
+ " response variable as the first column.<br/>Number of chunks: " + fr.anyVec().nChunks() + ".");
DocGen.HTML.paragraph(sb, FrameUtils.chunkSummary((Frame)UKV.get(Key.make(key))).toString().replace("\n","<br/>"));
return true;
}
}