001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.ml.timeseries; 031 032import org.openimaj.ml.timeseries.converter.TimeSeriesConverter; 033import org.openimaj.ml.timeseries.processor.TimeSeriesProcessor; 034import org.openimaj.ml.timeseries.processor.interpolation.TimeSeriesInterpolation; 035import org.openimaj.util.pair.IndependentPair; 036 037/** 038 * A time series defines data at discrete points in time. The time series has 039 * the ability to return data at a specific point in time, return neighbours 040 * within some window, closest neighbours or n neighbours before and after a 041 * time. 042 * <p> 043 * These values can be used by a {@link TimeSeriesInterpolation} to get specific 044 * moments in time 045 * 046 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 047 * 048 * @param <DATA> 049 * the type of the data at each point in time 050 * @param <SINGLE_TYPE> 051 * the type of the an element at a single point in time 052 * @param <RETURNTYPE> 053 * the time series returned by the get 054 * 055 */ 056public abstract class TimeSeries<DATA, SINGLE_TYPE, RETURNTYPE extends TimeSeries<DATA, SINGLE_TYPE, RETURNTYPE>> 057implements 058 Iterable<IndependentPair<Long, SINGLE_TYPE>> 059{ 060 061 /** 062 * Same as calling {@link #get(long, int, int)} with spans as 0 063 * 064 * @param time 065 * @return the requested data or null. 066 */ 067 public RETURNTYPE get(long time) { 068 return get(time, 0, 0); 069 } 070 071 /** 072 * returns the DATA at a specific point in time and those before and after 073 * to the number requested. This method may not return data for the specific 074 * requested time if it does not exists. If the time series is completely 075 * empty this function may return at an empty array however if at least 1 076 * data point exists and either nbefore and nafter are bigger than 1 then at 077 * least 1 datapoint will be returned. 078 * <p> 079 * Data should be returned in order 080 * 081 * @param time 082 * @param nbefore 083 * @param nafter 084 * @return all data found with these parameters 085 */ 086 public abstract RETURNTYPE get(long time, int nbefore, int nafter); 087 088 /** 089 * Same as {@link #get(long, int, int)} but instead of createing the output 090 * DATA instance, an existing data instance is handed which is filled. For 091 * convenience this output is also returned 092 * <p> 093 * Data should be returned in order 094 * 095 * @param time 096 * @param nbefore 097 * @param nafter 098 * @param output 099 * @return all data found with these parameters 100 */ 101 public abstract RETURNTYPE get(long time, int nbefore, int nafter, RETURNTYPE output); 102 103 /** 104 * returns the RETURNTYPE at a specific point in time and those before and 105 * after within the specified thresholds. This method may not return data 106 * for the specific requested time if it does not exists. Similarly this 107 * method may return an empty array if no time data is available within the 108 * window specified. 109 * <p> 110 * Data should be returned in order 111 * 112 * @param time 113 * @param threshbefore 114 * @param threshafter 115 * @return all data found with these parameters 116 */ 117 public abstract RETURNTYPE get(long time, long threshbefore, long threshafter); 118 119 /** 120 * returns the RETURNTYPE between the specified time periods. This method 121 * may not return data for the specific requested time if it does not 122 * exists. Similarly this method may return an empty array if no time data 123 * is available within the window specified. 124 * <p> 125 * Data should be returned in order 126 * 127 * @param start 128 * @param end 129 * @return all data found with these parameters 130 */ 131 public abstract RETURNTYPE get(long start, long end); 132 133 /** 134 * Set the data associated with each time. This function explicitly assumes 135 * that time.length == data.length and there exists a single data instance 136 * per time instance 137 * 138 * @param time 139 * instances of time 140 * @param data 141 * instances of data 142 * @throws TimeSeriesSetException 143 */ 144 public abstract void set(long[] time, DATA data) throws TimeSeriesSetException; 145 146 /** 147 * @return all times 148 */ 149 public abstract long[] getTimes(); 150 151 /** 152 * @return all data 153 */ 154 public abstract DATA getData(); 155 156 /** 157 * @return an empty new instance of this timeseries type 158 */ 159 public abstract RETURNTYPE newInstance(); 160 161 /** 162 * @return the number of valid time steps in this timeseries 163 */ 164 public abstract int size(); 165 166 /** 167 * @param interpolate 168 * assign this timeseries to the internal one, efforts should be 169 * made to copy the data, not simply assign it 170 */ 171 public abstract void internalAssign(RETURNTYPE interpolate); 172 173 /** 174 * @param times 175 * @param data 176 */ 177 public void internalAssign(long[] times, DATA data) { 178 try { 179 this.set(times, data); 180 } catch (final TimeSeriesSetException e) { 181 } 182 } 183 184 /** 185 * @return clone this time series 186 */ 187 @SuppressWarnings("unchecked") 188 public RETURNTYPE copy() { 189 final RETURNTYPE t = newInstance(); 190 t.internalAssign((RETURNTYPE) this); 191 return t; 192 } 193 194 /** 195 * process using the provided processor, return 196 * 197 * @param tsp 198 * @return a new instance processed 199 */ 200 public RETURNTYPE process(TimeSeriesProcessor<DATA, SINGLE_TYPE, RETURNTYPE> tsp) { 201 final RETURNTYPE copy = copy(); 202 tsp.process(copy); 203 return copy; 204 } 205 206 @SuppressWarnings("unchecked") 207 private RETURNTYPE self() { 208 return (RETURNTYPE) this; 209 } 210 211 /** 212 * Process using the provided processor 213 * 214 * @param tsp 215 * @return this object processed inplace 216 */ 217 public RETURNTYPE processInplace(TimeSeriesProcessor<DATA, SINGLE_TYPE, RETURNTYPE> tsp) { 218 tsp.process(self()); 219 return self(); 220 } 221 222 /** 223 * Convert a {@link TimeSeries} 224 * 225 * @param <OUTDATA> 226 * @param <OUTSING> 227 * @param <OUTRET> 228 * @param converter 229 * the converter 230 * @return the converted timeseries 231 */ 232 public <OUTDATA, OUTSING, OUTRET extends TimeSeries<OUTDATA, OUTSING, OUTRET>> OUTRET convert( 233 TimeSeriesConverter<DATA, SINGLE_TYPE, RETURNTYPE, OUTDATA, OUTSING, OUTRET> converter) 234 { 235 return converter.convert(self()); 236 } 237 238 /** 239 * Convert a {@link TimeSeries} 240 * 241 * @param <OUTDATA> 242 * @param <OUTSING> 243 * @param <OUTRET> 244 * @param converter 245 * the converter 246 * @param tsp 247 * the processor 248 * @return the converted timeseries 249 */ 250 public <OUTDATA, OUTSING, OUTRET extends TimeSeries<OUTDATA, OUTSING, OUTRET>> OUTRET convert( 251 TimeSeriesConverter<DATA, SINGLE_TYPE, RETURNTYPE, OUTDATA, OUTSING, OUTRET> converter, 252 TimeSeriesProcessor<OUTDATA, OUTSING, OUTRET> tsp) 253 { 254 return converter.convert(self(), tsp); 255 } 256 257 @Override 258 public abstract String toString(); 259}