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}