001/*
002 * $Id: HistogramField.java,v 1.8 2011/03/24 16:06:33 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2011
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 * 
012 * All Rights Reserved
013 * 
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.  
016 * 
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 * 
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
025 * GNU Lesser Public License for more details.
026 * 
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program.  If not, see http://www.gnu.org/licenses.
029 */
030
031package edu.wisc.ssec.mcidasv.data.hydra;
032
033import visad.*;
034                                                                                                                                          
035                                                                                                                                          
036public class HistogramField
037{
038  Linear2DSet histSet;
039  Linear1DSet    set0;
040  Linear1DSet    set1;
041  int            len0;
042  int            len1;
043  int[] count;
044  int[][] indexes;
045  FlatField field_0;
046  FlatField field_1;
047  FlatField mask_field;
048  float[][] maskRange;
049
050  Class rangeType;
051                                                                                                                                          
052                                                                                                                                          
053  public HistogramField(FlatField field_0, FlatField field_1,
054                        FlatField mask_field,
055                        int n_bins, int bin_size)
056         throws Exception
057  {
058    this.field_0 = field_0;
059    this.field_1 = field_1;
060    this.mask_field = mask_field;
061    maskRange = mask_field.getFloats(false);
062
063    Set[] rangeSets = field_0.getRangeSets();
064    Set rngSet = rangeSets[0];
065
066    if (rngSet instanceof FloatSet) {
067      rangeType = Float.TYPE; 
068    } 
069    else if (rngSet instanceof DoubleSet) {
070      rangeType = Double.TYPE;
071    }
072                                                                                                                                          
073    double[] minmax_0 = {Double.MAX_VALUE, -Double.MAX_VALUE};
074    double[] minmax_1 = {Double.MAX_VALUE, -Double.MAX_VALUE};
075
076    indexes   = new int[n_bins*n_bins][bin_size];
077    count     = new int[n_bins*n_bins];
078    double[][] val  = new double[2][1];
079    int[] histIdx  = null;
080
081    if (rangeType == Double.TYPE) {
082      double[][] vals_0  = field_0.getValues(false);
083      double[][] vals_1  = field_1.getValues(false);
084                                                                                                                                          
085      int n_samples = vals_0[0].length;
086                                                                                                                                          
087      for (int k = 0; k < n_samples; k++) {
088        double v0 = vals_0[0][k];
089        if (v0 < minmax_0[0]) minmax_0[0] = v0;
090        if (v0 > minmax_0[1]) minmax_0[1] = v0;
091                                                                                                                                          
092        double v1 = vals_1[0][k];
093        if (v1 < minmax_1[0]) minmax_1[0] = v1;
094        if (v1 > minmax_1[1]) minmax_1[1] = v1;
095      }
096
097      histSet = new Linear2DSet(minmax_0[0], minmax_0[1], n_bins,
098                                minmax_1[0], minmax_1[1], n_bins);
099
100      for (int k = 0; k < n_samples; k++) {
101        val[0][0] = vals_0[0][k];
102        val[1][0] = vals_1[0][k];
103        histIdx = histSet.doubleToIndex(val);
104        if (histIdx[0] >= 0) {
105          int len = indexes[histIdx[0]].length;
106          if (count[histIdx[0]] > len-1) { //-grow array
107            int[] tmp = new int[len+bin_size];
108            System.arraycopy(indexes[histIdx[0]], 0, tmp, 0, len);
109            indexes[histIdx[0]] = tmp;
110          }
111          indexes[histIdx[0]][count[histIdx[0]]++] = k;
112        }
113      }
114    }
115    else if (rangeType == Float.TYPE) {
116      float[][] vals_0 = field_0.getFloats(false);
117      float[][] vals_1 = field_1.getFloats(false);
118
119      int n_samples = vals_0[0].length;
120      for (int k = 0; k < n_samples; k++) {
121        double v0 = vals_0[0][k];
122        if (v0 < minmax_0[0]) minmax_0[0] = v0;
123        if (v0 > minmax_0[1]) minmax_0[1] = v0;
124                                                                                                                                                           
125        double v1 = vals_1[0][k];
126        if (v1 < minmax_1[0]) minmax_1[0] = v1;
127        if (v1 > minmax_1[1]) minmax_1[1] = v1;
128      }
129
130      histSet = new Linear2DSet(minmax_0[0], minmax_0[1], n_bins,
131                                minmax_1[0], minmax_1[1], n_bins);
132
133      for (int k = 0; k < n_samples; k++) {
134        val[0][0] = vals_0[0][k];
135        val[1][0] = vals_1[0][k];
136        histIdx = histSet.doubleToIndex(val);
137        if (histIdx[0] >= 0) {
138          int len = indexes[histIdx[0]].length;
139          if (count[histIdx[0]] > len-1) { //-grow array
140            int[] tmp = new int[len+bin_size];
141            System.arraycopy(indexes[histIdx[0]], 0, tmp, 0, len);
142            indexes[histIdx[0]] = tmp;
143          }
144          indexes[histIdx[0]][count[histIdx[0]]++] = k;
145        }
146      }
147
148    }
149                                                                                                                                          
150    set0 = histSet.getLinear1DComponent(0);
151    set1 = histSet.getLinear1DComponent(1);
152    len0 = set0.getLength();
153    len1 = set1.getLength();
154  }
155
156  public FlatField markMaskFieldByRange(double[] lowhi_0, double[] lowhi_1, float maskVal)
157       throws Exception {
158
159    int[] hist0 = set0.doubleToIndex(new double[][] {{lowhi_0[0], lowhi_0[1]}});
160    int[] hist1 = set1.doubleToIndex(new double[][] {{lowhi_1[0], lowhi_1[1]}});
161                                                                                                                                          
162    if (hist0[0] < 0) {
163      if (lowhi_0[0] < lowhi_0[1]) {
164        hist0[0] = 0;
165      }
166      else {
167        hist0[0] = len0 - 1;
168      }
169    }
170    if (hist0[1] < 0) {
171      if (lowhi_0[0] < lowhi_0[1]) {
172        hist0[1] = len0 - 1;
173      }
174      else {
175        hist0[1] = 0;
176      }
177    }
178                                                                                                                                          
179    if (hist1[0] < 0) {
180      if (lowhi_1[0] < lowhi_1[1]) {
181        hist1[0] = 0;
182      }
183      else {
184        hist1[0] = len1 - 1;
185      }
186    }
187    if (hist1[1] < 0) {
188      if (lowhi_1[0] < lowhi_1[1]) {
189        hist1[1] = len1 - 1;
190      }
191      else {
192        hist1[1] = 0;
193      }
194    }
195                                                                                                                                          
196    int h00, h01, h10, h11;
197
198    h10 = hist1[1];
199    h11 = hist1[0];
200    if (hist1[0] < hist1[1]) {
201      h10 = hist1[0];
202      h11 = hist1[1];
203    }
204
205    h00 = hist0[1];
206    h01 = hist0[0];
207    if (hist0[0] < hist0[1]) {
208      h00 = hist0[0];
209      h01 = hist0[1];
210    }
211
212    for (int k=0; k<maskRange[0].length; k++) {
213       if (maskRange[0][k] == maskVal) {
214         maskRange[0][k] = Float.NaN;
215       }
216    }
217
218    for (int j = h10; j <= h11; j++) {
219      for (int i = h00; i <= h01; i++) {
220        int idx = j*set0.getLengthX() + i;
221        for (int k = 0; k < count[idx]; k++) {
222          maskRange[0][indexes[idx][k]] = maskVal;
223        }
224      }
225    }
226
227    mask_field.setSamples(maskRange, false);
228    return mask_field;
229  }
230
231  public FlatField markMaskFieldByCurve(float[][] curve, float maskVal) throws Exception {
232    int all  = 2;
233    int some = 1;
234    int none = 0;
235                                                                                                                                             
236    float[][] samples0 = set0.getSamples();
237    float[][] samples1 = set1.getSamples();
238                                                                                                                                             
239    int len = set0.getLength();
240
241
242    boolean[][] checked = new boolean[len][len];
243    boolean[][] inside  = new boolean[len][len];
244                                                                                                                                             
245    for (int jj=0; jj<len; jj++) {
246      for (int ii=0; ii<len; ii++) {
247        checked[ii][jj] = false;
248        inside[ii][jj]  = false;
249      }
250    }
251
252    for (int jj=0; jj<len-1; jj++) {
253      for (int ii=0; ii<len-1; ii++) {
254        int inside_cnt = 0;
255                                                                                                                                             
256        if (!checked[ii][jj]) {
257          float x = samples0[0][ii];
258          float y = samples1[0][jj];
259          if (DelaunayCustom.inside(curve, x, y)) {
260            inside_cnt++;
261            inside[ii][jj] = true;
262          }
263          checked[ii][jj] = true;
264        }
265        else if (inside[ii][jj]) {
266          inside_cnt++;
267        }
268                                                                                                                                             
269        if (!checked[ii+1][jj]) {
270          float x = samples0[0][ii+1];
271          float y = samples1[0][jj];
272          if (DelaunayCustom.inside(curve, x, y)) {
273            inside_cnt++;
274            inside[ii+1][jj] = true;
275          }
276          checked[ii+1][jj] = true;
277        }
278        else if (inside[ii+1][jj]) {
279          inside_cnt++;
280        }
281                                                                                                                                             
282        if (!checked[ii][jj+1]) {
283          float x = samples0[0][ii];
284          float y = samples1[0][jj+1];
285          if (DelaunayCustom.inside(curve, x, y)) {
286            inside_cnt++;
287            inside[ii][jj+1] = true;
288          }
289          checked[ii][jj+1] = true;
290        }
291        else if (inside[ii][jj+1]) {
292          inside_cnt++;
293        }
294                                                                                                                                             
295        if (!checked[ii+1][jj+1]) {
296          float x = samples0[0][ii+1];
297          float y = samples1[0][jj+1];
298          if (DelaunayCustom.inside(curve, x, y)) {
299            inside_cnt++;
300            inside[ii+1][jj+1] = true;
301          }
302          checked[ii+1][jj+1] = true;
303        }
304        else if (inside[ii+1][jj+1]) {
305          inside_cnt++;
306        }
307
308        if (rangeType == Float.TYPE) {
309        float[][] vals_0 = field_0.getFloats(false);
310        float[][] vals_1 = field_1.getFloats(false);
311        if (inside_cnt == 4) {
312          int idx = jj*set0.getLengthX() + ii;
313          for (int k = 0; k < count[idx]; k++) {
314            maskRange[0][indexes[idx][k]] = maskVal;
315          }
316        }
317        if (inside_cnt > 0 && inside_cnt < 4) {
318          int idx = jj*set0.getLengthX() + ii;
319          for (int k = 0; k < count[idx]; k++) {
320            float xx = vals_0[0][indexes[idx][k]];
321            float yy = vals_1[0][indexes[idx][k]];
322            if (DelaunayCustom.inside(curve, xx, yy)) {
323              maskRange[0][indexes[idx][k]] = maskVal;
324            }
325          }
326        }
327        }
328        else if (rangeType == Double.TYPE) {
329        double[][] vals_0 = field_0.getValues(false);
330        double[][] vals_1 = field_1.getValues(false);
331        if (inside_cnt == 4) {
332          int idx = jj*set0.getLengthX() + ii;
333          for (int k = 0; k < count[idx]; k++) {
334            maskRange[0][indexes[idx][k]] = maskVal;
335          }
336        }
337        if (inside_cnt > 0 && inside_cnt < 4) {
338          int idx = jj*set0.getLengthX() + ii;
339          for (int k = 0; k < count[idx]; k++) {
340            double xx = vals_0[0][indexes[idx][k]];
341            double yy = vals_1[0][indexes[idx][k]];
342            if (DelaunayCustom.inside(curve, (float)xx, (float)yy)) {
343              maskRange[0][indexes[idx][k]] = maskVal;
344            }
345          }
346        }
347        }
348      }
349    }
350
351    mask_field.setSamples(maskRange, false);
352    return mask_field;
353  }
354
355  public void clearMaskField(float maskVal) {
356    for (int k=0; k<maskRange[0].length; k++) {
357      if (maskRange[0][k] == maskVal) {
358         maskRange[0][k] = Float.NaN;
359      }
360    }
361  }
362
363  public void resetMaskField(float maskVal) throws Exception {
364    clearMaskField(maskVal);
365    mask_field.setSamples(maskRange, false);
366  }
367}