001    package org.wdssii.polarmerger;
002    
003    import java.util.ArrayList;
004    import java.util.Date;
005    import java.util.List;
006    
007    import org.apache.commons.logging.Log;
008    import org.apache.commons.logging.LogFactory;
009    import org.wdssii.core.PolarGrid;
010    import org.wdssii.polarmerger.PolarMerger.MergerStrategy;
011    
012    /**
013     * Stores all the observations and provides operations on them.
014     * 
015     * @author lakshman
016     * 
017     */
018    public class MergeableObservations {
019            private static Log log = LogFactory.getLog(MergeableObservations.class);
020    
021            private static final int EXPECTED_MAX_OBSERVATIONS = 1000 * 1000 * 1;
022    
023            private List<Observation> observations;
024    
025            private ObservationMerger merger = null;
026    
027            private PowerDensityLookup lookup = null;
028    
029            public MergeableObservations(MergerStrategy mergerStrategy,
030                            PowerDensityLookup lookup) {
031                    if (log.isDebugEnabled()) {
032                            log.debug("Creating observation list of capacity "
033                                            + EXPECTED_MAX_OBSERVATIONS);
034                    }
035                    observations = new ArrayList<Observation>(EXPECTED_MAX_OBSERVATIONS);
036                    if (log.isInfoEnabled()) {
037                            log.info("Finished creating observation list of capacity "
038                                            + EXPECTED_MAX_OBSERVATIONS);
039                    }
040    
041                    this.lookup = lookup;
042    
043                    if (mergerStrategy == MergerStrategy.DistanceWeighted) {
044                            merger = new DistanceWeightedObservationMerger();
045                    } else if (mergerStrategy == MergerStrategy.NearestNeighbor) {
046                            merger = new NearestNeighborObservationMerger();
047                    } else {
048                            merger = new LatestObservationMerger();
049                    }
050    
051            }
052    
053            public int pruneBefore(Date date) {
054                    int capacity = Math.max(observations.size(), EXPECTED_MAX_OBSERVATIONS);
055                    if (log.isInfoEnabled()) {
056                            log.info("Creating observation list: capacity=" + capacity + " current=" + observations.size());
057                    }
058    
059                    List<Observation> keep = new ArrayList<Observation>(capacity);
060                    if (log.isDebugEnabled()) {
061                            log.debug("Finished creating observation list");
062                    }
063    
064                    for (Observation o : observations) {
065                            if (o.getTime().after(date)) {
066                                    keep.add(o);
067                            }
068                    }
069    
070                    int pruned = (observations.size() - keep.size());
071                    observations = keep;
072                    return pruned;
073            }
074    
075            public void fillMergedValues(PolarGrid[] mergedGrids) {
076                    if (observations.size() == 0) {
077                            return;
078                    }
079    
080                    float[][][] values = new float[mergedGrids.length][][];
081                    for (int i = 0; i < values.length; ++i) {
082                            values[i] = mergedGrids[i].getValues();
083                    }
084    
085                    int numElev = values.length;
086                    int numAz = values[0].length;
087                    int numRn = values[0][0].length;
088    
089                    merger.init(values);
090    
091                    for (Observation obs : observations) {
092                            int e = obs.getEIndex();
093                            int az = obs.getAzIndex();
094                            int rn = obs.getRnIndex();
095                            float[][][] weights = lookup.getWeights();
096                            for (int i = 0; i < weights.length; ++i) {
097                                    int w_e = e + i - weights.length / 2;
098                                    if (w_e < 0 || w_e >= numElev)
099                                            continue;
100                                    for (int j = 0; j < weights[i].length; ++j) {
101                                            int w_az = az + j - weights[i].length / 2;
102                                            // azimuth wraps around
103                                            if (w_az < 0)
104                                                    w_az += numAz;
105                                            else if (w_az >= numAz)
106                                                    w_az -= numAz;
107    
108                                            for (int k = 0; k < weights[i][j].length; ++k) {
109                                                    int w_rn = rn + k - weights[i][j].length / 2;
110                                                    if (w_rn < 0 || w_rn >= numRn)
111                                                            continue;
112                                                    merger.update(values, w_e, w_az, w_rn, obs,
113                                                                    weights[i][j][k]);
114                                            }
115                                    }
116                            }
117                    }
118    
119                    merger.finishComputation(values);
120            }
121    
122            public void add(Observation obs) {
123                    observations.add(obs);
124            }
125    }