package de.lmu.ifi.dbs.elki.data.projection; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import java.util.BitSet; import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.data.type.TypeInformation; import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation; import de.lmu.ifi.dbs.elki.data.type.VectorTypeInformation; import de.lmu.ifi.dbs.elki.datasource.filter.transform.NumberVectorFeatureSelectionFilter; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntListParameter; /** * Projection class for number vectors. * * FIXME: Use int[] instead of a BitSet, to allow reordering? * * @author Erich Schubert * * @param Vector type */ public class NumericalFeatureSelection> implements Projection { /** * Minimum dimensionality required for projection. */ private int mindim; /** * Object factory. */ private NumberVector.Factory factory; /** * Output dimensionality. */ private int dimensionality; /** * Subspace. */ private BitSet bits; /** * Constructor. * * @param bits Dimensions */ public NumericalFeatureSelection(BitSet bits) { super(); this.bits = bits; this.dimensionality = bits.cardinality(); int mind = 0; for(int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i + 1)) { mind = Math.max(mind, i + 1); } this.mindim = mind; } @Override public void initialize(SimpleTypeInformation in) { final VectorFieldTypeInformation vin = (VectorFieldTypeInformation) in; factory = (NumberVector.Factory) vin.getFactory(); if(vin.getDimensionality() < mindim) { throw new AbortException("Data does not have enough dimensions for this projection!"); } } @Override public V project(V data) { double[] dbl = new double[dimensionality]; for(int i = bits.nextSetBit(0), j = 0; i >= 0; i = bits.nextSetBit(i + 1), j++) { dbl[j] = data.doubleValue(i); } return factory.newNumberVector(dbl); } @Override public SimpleTypeInformation getOutputDataTypeInformation() { return new VectorFieldTypeInformation<>(factory, dimensionality); } @Override public TypeInformation getInputDataTypeInformation() { return new VectorTypeInformation<>(NumberVector.class, mindim, Integer.MAX_VALUE); } /** * Parameterization class. * * @author Erich Schubert * * @apiviz.exclude */ public static class Parameterizer> extends AbstractParameterizer { /** * Dimensions to select. */ BitSet dims = new BitSet(); @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); IntListParameter selectedAttributesP = new IntListParameter(NumberVectorFeatureSelectionFilter.Parameterizer.SELECTED_ATTRIBUTES_ID); selectedAttributesP.addConstraint(CommonConstraints.GREATER_EQUAL_ZERO_INT_LIST); if(config.grab(selectedAttributesP)) { dims.clear(); for(int in : selectedAttributesP.getValue()) { dims.set(in); } } } @Override protected NumericalFeatureSelection makeInstance() { return new NumericalFeatureSelection<>(dims); } } }