001/*
002        AUTOMATICALLY GENERATED BY jTemp FROM
003        /Users/jsh2/Work/openimaj/target/checkout/core/core-feature/src/main/jtemp/org/openimaj/feature/#T#FV.jtemp
004*/
005/**
006 * Copyright (c) 2011, The University of Southampton and the individual contributors.
007 * All rights reserved.
008 *
009 * Redistribution and use in source and binary forms, with or without modification,
010 * are permitted provided that the following conditions are met:
011 *
012 *   *  Redistributions of source code must retain the above copyright notice,
013 *      this list of conditions and the following disclaimer.
014 *
015 *   *  Redistributions in binary form must reproduce the above copyright notice,
016 *      this list of conditions and the following disclaimer in the documentation
017 *      and/or other materials provided with the distribution.
018 *
019 *   *  Neither the name of the University of Southampton nor the names of its
020 *      contributors may be used to endorse or promote products derived from this
021 *      software without specific prior written permission.
022 *
023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
024 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
025 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
026 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
027 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
028 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
030 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
032 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
033 */
034package org.openimaj.feature;
035
036import java.io.DataInput;
037import java.io.DataOutput;
038import java.io.IOException;
039import java.io.PrintWriter;
040import java.util.Arrays;
041import java.util.List;
042import java.util.Scanner;
043
044import org.openimaj.util.concatenate.Concatenatable;
045
046/**
047 * Basic double single-dimensional feature vector implementation
048 *
049 * @author Jonathon Hare
050 */
051public class DoubleFV extends ArrayFeatureVector<double[]> implements Concatenatable<DoubleFV, DoubleFV>, Cloneable {
052        private static final long serialVersionUID = 1L;
053        
054        /**
055         * Construct an empty feature vector
056         */
057        public DoubleFV() {}
058
059        /**
060         * Construct empty FV with given number of bins
061         * @param nbins the number of bins in each dimension
062         */
063        public DoubleFV(int nbins) {
064                values = new double[nbins];
065        }
066        
067        /**
068         * Construct from flattened values array and dimensions 
069         * @param values the flat array of values
070         */
071        public DoubleFV(double [] values) {
072                this.values = values;
073        }
074        
075        /**
076         * Get the element at the given flat index
077         * @param x the flattened element index
078         * @return the value corresponding to x
079         */
080        public double get(int x) {
081                return values[x];
082        }
083
084    /**
085     * Set the element at the given flat index
086     * @param value the value to set
087     * @param x the flattened element index
088     */
089        void set(double value, int x) {
090         values[x] = value;
091        }
092        
093        /**
094         * Element-wise normalisation to 0..1 using separated expected
095         * minimum and maximum values for each element of the underlying
096         * feature vector.
097         *
098         * @param min an array containing the minimum expected values
099         * @param max an array containing the maximum expected values
100         * @return feature vector with each value normalised to 0..1 
101         */
102        @Override
103        public DoubleFV normaliseFV(double [] min, double [] max) {
104                double [] dvals = asDoubleVector();
105
106                for (int i=0; i<dvals.length; i++) {
107                        dvals[i] -= min[i];
108                        dvals[i] /= (max[i]-min[i]);
109                        
110                        if (dvals[i]<0) dvals[i] = 0;
111                        if (dvals[i]>1) dvals[i] = 1;
112                }
113                
114                return new DoubleFV(dvals);
115        }
116        
117        /**
118         * Min-Max normalisation of the FV. Each element of the underlying
119         * feature vector is normalised to 0..1 based on the provided
120         * minimum and maximum expected values.
121         *
122         * @param min the minimum expected value
123         * @param max the maximum expected value
124         * @return feature vector with each value normalised to 0..1
125         */
126        @Override
127        public DoubleFV normaliseFV(double min, double max) {
128                double [] dvals = asDoubleVector();
129
130                for (int i=0; i<dvals.length; i++) {
131                        dvals[i] -= min;
132                        dvals[i] /= (max-min);
133                        
134                        if (dvals[i]<0) dvals[i] = 0;
135                        if (dvals[i]>1) dvals[i] = 1;
136                }
137                
138                return new DoubleFV(dvals);
139        }
140        
141        /**
142         * Normalise the FV to unit area.
143         *
144         * @return feature vector with all elements summing to 1.
145         */
146        @Override
147        public DoubleFV normaliseFV() {
148                double [] dvals = asDoubleVector();
149                double sum = 0;
150
151                for (int i=0; i<dvals.length; i++)
152                        sum += dvals[i];
153
154                for (int i=0; i<dvals.length; i++)
155                        dvals[i] /= sum;
156                
157                return new DoubleFV(dvals);
158        }
159        
160        /**
161         * Lp Norm of the FV.
162         *
163         * @param
164         *      p the norm to compute
165         * 
166         * @return feature vector normalised using the Lp norm
167         */
168        @Override
169        public DoubleFV normaliseFV(double p) {
170                double [] dvals = asDoubleVector();
171                double pnorm = 0;
172
173                for (int i=0; i<dvals.length; i++)
174                        pnorm += Math.pow(Math.abs(dvals[i]), p);
175                        
176                pnorm = Math.pow(pnorm, 1.0 / p);
177
178                for (int i=0; i<dvals.length; i++)
179                        dvals[i] /= pnorm;
180                
181                return new DoubleFV(dvals);
182        }
183
184        @Override
185        public DoubleFV clone() {
186            try {
187                DoubleFV model = (DoubleFV) super.clone();
188                model.values = values.clone();
189                return model;
190                }catch (CloneNotSupportedException e) {
191            throw new AssertionError(e);
192        }
193        }
194
195        @Override
196        public String toString() {
197                String ret = this.getClass().getName() + Arrays.toString(values);
198                
199                return ret;
200        }
201
202        /**
203         * Convert the FV to a DoubleFV representation
204         * @return the DoubleFV representation
205         */
206        @Override
207        public DoubleFV asDoubleFV() {
208                return new DoubleFV(asDoubleVector());
209        }
210        
211        /**
212         * Convert the FV to a 1-dimensional double array representation
213         * @return the double[] representation
214         */
215        @Override
216        public double [] asDoubleVector() {
217                double [] d = new double[values.length];
218                
219                for (int i=0; i<values.length; i++) {
220                        d[i] = values[i];
221                }
222                
223                return d;
224        }
225        
226        /**
227         * Compare this FV to another with the given method.
228         *
229         * @param h the feature to compare against.
230         * @param method the method to compare with. 
231         * @return a score determined by the comparison method.
232         */
233        public double compare(DoubleFV h, DoubleFVComparison method) {
234                return method.compare(this, h);
235        }
236
237        /* (non-Javadoc)
238         * @see org.openimaj.feature.FeatureVector#length()
239         */
240        @Override
241        public int length() {
242                return values.length;
243        }
244        
245        @Override
246        public void writeBinary(DataOutput out) throws IOException {
247                out.writeInt(values.length);
248                for (int i=0; i<values.length; i++) out.writeDouble(values[i]);
249        }
250
251        @Override
252        public void writeASCII(PrintWriter out) throws IOException {
253                out.println(values.length);
254                for (int i=0; i<values.length; i++) out.print( values[i] + " ");
255                out.println();
256        }
257
258        @Override
259        public void readBinary(DataInput in) throws IOException {
260                int nbins = in.readInt();
261                values = new double[nbins];
262                for (int i=0; i<nbins; i++) values[i] = in.readDouble();
263        }
264
265        @Override
266        public void readASCII(Scanner in) throws IOException {
267                int nbins = Integer.parseInt(in.nextLine());
268                values = new double[nbins];
269                String [] line = in.nextLine().trim().split(" ");
270                for (int i=0; i<nbins; i++) values[i] = Double.parseDouble(line[i]);
271        }
272
273        @Override
274        public byte[] binaryHeader() {
275                return (this.getClass().getName().substring(0,2) + "FV").getBytes();
276        }
277
278        @Override
279        public String asciiHeader() {
280                return this.getClass().getName() + " ";
281        }
282        
283        @Override
284        public DoubleFV concatenate(DoubleFV... ins) {
285                int l = values.length;
286                
287                for (int i=0; i<ins.length; i++)
288                        l += ins[i].values.length;
289                
290                double[] data = new double[l];
291                
292                System.arraycopy(values, 0, data, 0, values.length);
293                int offset = values.length;
294                for (int i=0; i<ins.length; i++) {
295                        System.arraycopy(ins[i].values, 0, data, offset, ins[i].values.length);
296                        offset += ins[i].values.length;
297                }
298                
299                return new DoubleFV(data);
300        }
301        
302        @Override
303        public DoubleFV concatenate(List<DoubleFV> ins) {
304                int l = values.length;
305                
306                for (int i=0; i<ins.size(); i++)
307                        l += ins.get(i).values.length;
308                
309                double[] data = new double[l];
310                
311                System.arraycopy(values, 0, data, 0, values.length);
312                int offset = values.length;
313                for (int i=0; i<ins.size(); i++) {
314                        System.arraycopy(ins.get(i).values, 0, data, offset, ins.get(i).values.length);
315                        offset += ins.get(i).values.length;
316                }
317                
318                return new DoubleFV(data);
319        }
320        
321        @Override
322        public int hashCode() {
323                return Arrays.hashCode(values);
324        }
325        
326        @Override
327        public boolean equals(Object obj) {
328                return Arrays.equals(values, ((DoubleFV)obj).values);
329        }
330        
331        @Override
332        public DoubleFV subvector(int beginIndex) {
333                return new DoubleFV(Arrays.copyOfRange(this.values, beginIndex, values.length));
334        }
335
336        @Override
337        public DoubleFV subvector(int beginIndex, int endIndex) {
338                return new DoubleFV(Arrays.copyOfRange(this.values, beginIndex, endIndex));
339        }
340
341        @Override
342        public double getAsDouble(int i) {
343                return values[i];
344        }
345
346        @Override
347        public void setFromDouble(int i, double v) {
348                values[i] = ((double) v);
349        }
350
351        @Override
352        public DoubleFV newInstance() {
353                return new DoubleFV(length());
354        }
355}