001 /* 002 * $Id: HistogramField.java,v 1.11 2012/02/19 17:35:40 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2012 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 package edu.wisc.ssec.mcidasv.data.hydra; 031 032 import visad.*; 033 034 public class HistogramField { 035 036 Linear2DSet histSet; 037 Linear1DSet set0; 038 Linear1DSet set1; 039 int len0; 040 int len1; 041 int[] count; 042 int[][] indexes; 043 FlatField field_0; 044 FlatField field_1; 045 FlatField mask_field; 046 float[][] maskRange; 047 Class rangeType; 048 049 public HistogramField(FlatField field_0, FlatField field_1, 050 FlatField mask_field, 051 int n_bins, int bin_size) 052 throws Exception { 053 this.field_0 = field_0; 054 this.field_1 = field_1; 055 this.mask_field = mask_field; 056 maskRange = mask_field.getFloats(false); 057 058 Set[] rangeSets = field_0.getRangeSets(); 059 Set rngSet = rangeSets[0]; 060 061 if (rngSet instanceof FloatSet) { 062 rangeType = Float.TYPE; 063 } else if (rngSet instanceof DoubleSet) { 064 rangeType = Double.TYPE; 065 } else if (rngSet instanceof IntegerSet) { 066 rangeType = Integer.TYPE; 067 } 068 069 double[] minmax_0 = {Double.MAX_VALUE, -Double.MAX_VALUE}; 070 double[] minmax_1 = {Double.MAX_VALUE, -Double.MAX_VALUE}; 071 072 073 if (rangeType == Integer.TYPE) { 074 //Ghansham: Dont do any allocation here. Do based on the individual ranges of fieldX and fieldY respectively 075 } else { 076 indexes = new int[n_bins * n_bins][bin_size]; 077 count = new int[n_bins * n_bins]; 078 } 079 080 081 double[][] val = new double[2][1]; 082 int[] histIdx = null; 083 084 if (rangeType == Double.TYPE) { 085 double[][] vals_0 = field_0.getValues(false); 086 double[][] vals_1 = field_1.getValues(false); 087 int n_samples = vals_0[0].length; 088 for (int k = 0; k < n_samples; k++) { 089 double v0 = vals_0[0][k]; 090 if (v0 < minmax_0[0]) { 091 minmax_0[0] = v0; 092 } else if (v0 > minmax_0[1]) { 093 minmax_0[1] = v0; 094 } 095 096 double v1 = vals_1[0][k]; 097 if (v1 < minmax_1[0]) { 098 minmax_1[0] = v1; 099 } else if (v1 > minmax_1[1]) { 100 minmax_1[1] = v1; 101 } 102 } 103 104 histSet = new Linear2DSet(minmax_0[0], minmax_0[1], n_bins, 105 minmax_1[0], minmax_1[1], n_bins); 106 107 for (int k = 0; k < n_samples; k++) { 108 val[0][0] = vals_0[0][k]; 109 val[1][0] = vals_1[0][k]; 110 histIdx = histSet.doubleToIndex(val); 111 if (histIdx[0] >= 0) { 112 int len = indexes[histIdx[0]].length; 113 if (count[histIdx[0]] > len - 1) { //-grow array 114 int[] tmp = new int[len + bin_size]; 115 System.arraycopy(indexes[histIdx[0]], 0, tmp, 0, len); 116 indexes[histIdx[0]] = tmp; 117 } 118 indexes[histIdx[0]][count[histIdx[0]]++] = k; 119 } 120 } 121 } else if (rangeType == Float.TYPE) { 122 float[][] vals_0 = field_0.getFloats(false); 123 float[][] vals_1 = field_1.getFloats(false); 124 int n_samples = vals_0[0].length; 125 for (int k = 0; k < n_samples; k++) { 126 double v0 = vals_0[0][k]; 127 if (v0 < minmax_0[0]) { 128 minmax_0[0] = v0; 129 } else if (v0 > minmax_0[1]) { 130 minmax_0[1] = v0; 131 } 132 double v1 = vals_1[0][k]; 133 if (v1 < minmax_1[0]) { 134 minmax_1[0] = v1; 135 } else if (v1 > minmax_1[1]) { 136 minmax_1[1] = v1; 137 } 138 139 } 140 histSet = new Linear2DSet(minmax_0[0], minmax_0[1], n_bins, minmax_1[0], minmax_1[1], n_bins); 141 for (int k = 0; k < n_samples; k++) { 142 val[0][0] = vals_0[0][k]; 143 val[1][0] = vals_1[0][k]; 144 histIdx = histSet.doubleToIndex(val); 145 if (histIdx[0] >= 0) { 146 int len = indexes[histIdx[0]].length; 147 if (count[histIdx[0]] > len - 1) { //-grow array 148 149 int[] tmp = new int[len + bin_size]; 150 System.arraycopy(indexes[histIdx[0]], 0, tmp, 0, len); 151 indexes[histIdx[0]] = tmp; 152 } 153 indexes[histIdx[0]][count[histIdx[0]]++] = k; 154 } 155 } 156 } else if (rangeType == Integer.TYPE) { 157 float[][] vals_0 = field_0.getFloats(false); 158 float[][] vals_1 = field_1.getFloats(false); 159 int n_samples = vals_0[0].length; 160 for (int k = 0; k < n_samples; k++) { 161 double v0 = vals_0[0][k]; 162 if (v0 < minmax_0[0]) { 163 minmax_0[0] = v0; 164 } else if (v0 > minmax_0[1]) { 165 minmax_0[1] = v0; 166 } 167 double v1 = vals_1[0][k]; 168 if (v1 < minmax_1[0]) { 169 minmax_1[0] = v1; 170 } else if (v1 > minmax_1[1]) { 171 minmax_1[1] = v1; 172 } 173 } 174 175 176 int startX = (int) minmax_0[0]; 177 int endX = (int) minmax_0[1]; 178 int startY = (int) minmax_1[0]; 179 int endY = (int) minmax_1[1]; 180 int lenX = endX - startX + 1; 181 int lenY = endY - startY + 1; 182 histSet = new Linear2DSet(startX, endX, lenX, startY, endY, lenY); 183 184 185 186 //Ghansham:Allocate here based on length of lenghts of XField and YField 187 indexes = new int[lenY * lenX][]; //Ghansham:Dont allocate here if not required. 188 count = new int[lenY * lenX]; 189 190 //First calculate frequency of each grey count. 191 for (int k = 0; k < n_samples; k++) { 192 val[0][0] = vals_0[0][k]; 193 val[1][0] = vals_1[0][k]; 194 histIdx = histSet.doubleToIndex(val); 195 if (histIdx[0] >= 0) { 196 count[histIdx[0]]++; 197 } 198 } 199 200 for (int k = 0; k < n_samples; k++) { 201 val[0][0] = vals_0[0][k]; 202 val[1][0] = vals_1[0][k]; 203 histIdx = histSet.doubleToIndex(val); 204 if (histIdx[0] >= 0) { 205 if (indexes[histIdx[0]] == null) { //Tricky stuff is here: encountering a particular grey count first time. 206 indexes[histIdx[0]] = new int[count[histIdx[0]]]; //Allocating the values based on the frequency of this grey count (calculate earlier). No extra allocation at all 207 count[histIdx[0]] = 0; //Resetting the frequency to 0. 208 } 209 indexes[histIdx[0]][count[histIdx[0]]++] = k; 210 } 211 } 212 } 213 214 215 set0 = histSet.getLinear1DComponent(0); 216 set1 = histSet.getLinear1DComponent(1); 217 len0 = set0.getLength(); 218 len1 = set1.getLength(); 219 } 220 221 public void markMaskFieldByRange(double[] lowhi_0, double[] lowhi_1, float maskVal) 222 throws Exception { 223 224 int[] hist0 = set0.doubleToIndex(new double[][] {{lowhi_0[0], lowhi_0[1]}}); 225 int[] hist1 = set1.doubleToIndex(new double[][] {{lowhi_1[0], lowhi_1[1]}}); 226 227 if (hist0[0] < 0) { 228 if (lowhi_0[0] < lowhi_0[1]) { 229 hist0[0] = 0; 230 } else { 231 hist0[0] = len0 - 1; 232 } 233 } 234 if (hist0[1] < 0) { 235 if (lowhi_0[0] < lowhi_0[1]) { 236 hist0[1] = len0 - 1; 237 } else { 238 hist0[1] = 0; 239 } 240 } 241 242 if (hist1[0] < 0) { 243 if (lowhi_1[0] < lowhi_1[1]) { 244 hist1[0] = 0; 245 } else { 246 hist1[0] = len1 - 1; 247 } 248 } 249 if (hist1[1] < 0) { 250 if (lowhi_1[0] < lowhi_1[1]) { 251 hist1[1] = len1 - 1; 252 } else { 253 hist1[1] = 0; 254 } 255 } 256 257 int h00, h01, h10, h11; 258 259 260 h10 = hist1[1]; 261 h11 = hist1[0]; 262 if (hist1[0] < hist1[1]) { 263 h10 = hist1[0]; 264 h11 = hist1[1]; 265 } 266 267 h00 = hist0[1]; 268 h01 = hist0[0]; 269 if (hist0[0] < hist0[1]) { 270 h00 = hist0[0]; 271 h01 = hist0[1]; 272 } 273 274 for (int k = 0; k < maskRange[0].length; k++) { 275 if (maskRange[0][k] == maskVal) { 276 maskRange[0][k] = Float.NaN; 277 } 278 } 279 280 281 282 int lenX = set0.getLengthX(); 283 284 for (int j = h10; j <= h11; j++) { 285 int col_factor = j * lenX; 286 for (int i = h00; i <= h01; i++) { 287 int idx = col_factor + i; 288 for (int k = 0; k < count[idx]; k++) { 289 maskRange[0][indexes[idx][k]] = maskVal; 290 } 291 } 292 } 293 294 mask_field.setSamples(maskRange, false); 295 } 296 297 public void markMaskFieldByCurve(float[][] curve, float maskVal) throws Exception { 298 float[][] samples0 = set0.getSamples(); 299 float[][] samples1 = set1.getSamples(); 300 301 boolean[][] checked = null; 302 boolean[][] inside = null; 303 304 305 if (rangeType == Integer.TYPE) { //Dealing with rangeSet constructed fields separately. 306 float[][] vals_0 = field_0.getFloats(false); 307 float[][] vals_1 = field_1.getFloats(false); 308 int lenX = set0.getLength(); 309 int lenY = set1.getLength(); 310 checked = new boolean[lenX][lenY]; 311 inside = new boolean[lenX][lenY]; 312 for (int jj = 0; jj < lenX; jj++) { 313 java.util.Arrays.fill(checked[jj], false); 314 java.util.Arrays.fill(inside[jj], false); 315 } 316 for (int jj = 0; jj < lenY - 1; jj++) { 317 for (int ii = 0; ii < lenX - 1; ii++) { 318 int idx = jj * lenX + ii; //Calclualting the index value in the start only. 319 if (count[idx] > 0) { //No need to do go further if the frequency of particular grey count is zero. 320 int inside_cnt = 0; 321 if (!checked[ii][jj]) { 322 float x = samples0[0][ii]; 323 float y = samples1[0][jj]; 324 if (DelaunayCustom.inside(curve, x, y)) { 325 inside_cnt++; 326 inside[ii][jj] = true; 327 } 328 checked[ii][jj] = true; 329 } else if (inside[ii][jj]) { 330 inside_cnt++; 331 } 332 333 if (!checked[ii + 1][jj]) { 334 float x = samples0[0][ii + 1]; 335 float y = samples1[0][jj]; 336 if (DelaunayCustom.inside(curve, x, y)) { 337 inside_cnt++; 338 inside[ii + 1][jj] = true; 339 } 340 checked[ii + 1][jj] = true; 341 } else if (inside[ii + 1][jj]) { 342 inside_cnt++; 343 } 344 345 if (!checked[ii][jj + 1]) { 346 float x = samples0[0][ii]; 347 float y = samples1[0][jj + 1]; 348 if (DelaunayCustom.inside(curve, x, y)) { 349 inside_cnt++; 350 inside[ii][jj + 1] = true; 351 } 352 checked[ii][jj + 1] = true; 353 } else if (inside[ii][jj + 1]) { 354 inside_cnt++; 355 } 356 357 if (!checked[ii + 1][jj + 1]) { 358 float x = samples0[0][ii + 1]; 359 float y = samples1[0][jj + 1]; 360 if (DelaunayCustom.inside(curve, x, y)) { 361 inside_cnt++; 362 inside[ii + 1][jj + 1] = true; 363 } 364 checked[ii + 1][jj + 1] = true; 365 } else if (inside[ii + 1][jj + 1]) { 366 inside_cnt++; 367 } 368 369 if (inside_cnt == 0) { 370 continue; 371 } else if (inside_cnt == 4) { 372 for (int k = 0; k < count[idx]; k++) { 373 maskRange[0][indexes[idx][k]] = maskVal; 374 } 375 } else if (inside_cnt > 0 && inside_cnt < 4) { 376 for (int k = 0; k < count[idx]; k++) { 377 float xx = vals_0[0][indexes[idx][k]]; 378 float yy = vals_1[0][indexes[idx][k]]; 379 if (DelaunayCustom.inside(curve, xx, yy)) { 380 maskRange[0][indexes[idx][k]] = maskVal; 381 } 382 } 383 } 384 } 385 } 386 } 387 } else { 388 int len = set0.getLength(); 389 checked = new boolean[len][len]; 390 inside = new boolean[len][len]; 391 for (int jj = 0; jj < len; jj++) { 392 java.util.Arrays.fill(checked[jj], false); 393 java.util.Arrays.fill(inside[jj], false); 394 } 395 for (int jj = 0; jj < len - 1; jj++) { 396 for (int ii = 0; ii < len - 1; ii++) { 397 int idx = jj * set0.getLengthX() + ii; //Calclualting the index value in the start only. 398 if (count[idx] > 0) { //No need to do go further if the frequency of particular value is zero. 399 int inside_cnt = 0; 400 if (!checked[ii][jj]) { 401 float x = samples0[0][ii]; 402 float y = samples1[0][jj]; 403 if (DelaunayCustom.inside(curve, x, y)) { 404 inside_cnt++; 405 inside[ii][jj] = true; 406 } 407 checked[ii][jj] = true; 408 } else if (inside[ii][jj]) { 409 inside_cnt++; 410 } 411 412 if (!checked[ii + 1][jj]) { 413 float x = samples0[0][ii + 1]; 414 float y = samples1[0][jj]; 415 if (DelaunayCustom.inside(curve, x, y)) { 416 inside_cnt++; 417 inside[ii + 1][jj] = true; 418 } 419 checked[ii + 1][jj] = true; 420 } else if (inside[ii + 1][jj]) { 421 inside_cnt++; 422 } 423 424 if (!checked[ii][jj + 1]) { 425 float x = samples0[0][ii]; 426 float y = samples1[0][jj + 1]; 427 if (DelaunayCustom.inside(curve, x, y)) { 428 inside_cnt++; 429 inside[ii][jj + 1] = true; 430 } 431 checked[ii][jj + 1] = true; 432 } else if (inside[ii][jj + 1]) { 433 inside_cnt++; 434 } 435 436 if (!checked[ii + 1][jj + 1]) { 437 float x = samples0[0][ii + 1]; 438 float y = samples1[0][jj + 1]; 439 if (DelaunayCustom.inside(curve, x, y)) { 440 inside_cnt++; 441 inside[ii + 1][jj + 1] = true; 442 } 443 checked[ii + 1][jj + 1] = true; 444 } else if (inside[ii + 1][jj + 1]) { 445 inside_cnt++; 446 } 447 if (inside_cnt == 0) { 448 continue; 449 } 450 451 if (rangeType == Float.TYPE) { 452 float[][] vals_0 = field_0.getFloats(false); 453 float[][] vals_1 = field_1.getFloats(false); 454 if (inside_cnt == 4) { 455 456 for (int k = 0; k < count[idx]; k++) { 457 maskRange[0][indexes[idx][k]] = maskVal; 458 } 459 } 460 if (inside_cnt > 0 && inside_cnt < 4) { 461 462 for (int k = 0; k < count[idx]; k++) { 463 float xx = vals_0[0][indexes[idx][k]]; 464 float yy = vals_1[0][indexes[idx][k]]; 465 if (DelaunayCustom.inside(curve, xx, yy)) { 466 maskRange[0][indexes[idx][k]] = maskVal; 467 } 468 } 469 } 470 } else if (rangeType == Double.TYPE) { 471 double[][] vals_0 = field_0.getValues(false); 472 double[][] vals_1 = field_1.getValues(false); 473 if (inside_cnt == 4) { 474 for (int k = 0; k < count[idx]; k++) { 475 maskRange[0][indexes[idx][k]] = maskVal; 476 } 477 } 478 if (inside_cnt > 0 && inside_cnt < 4) { 479 480 for (int k = 0; k < count[idx]; k++) { 481 double xx = vals_0[0][indexes[idx][k]]; 482 double yy = vals_1[0][indexes[idx][k]]; 483 if (DelaunayCustom.inside(curve, (float) xx, (float) yy)) { 484 maskRange[0][indexes[idx][k]] = maskVal; 485 } 486 } 487 } 488 } 489 } 490 } 491 } 492 } 493 494 mask_field.setSamples(maskRange, false); 495 } 496 497 public void clearMaskField(float maskVal) { 498 for (int k = 0; k < maskRange[0].length; k++) { 499 if (maskRange[0][k] == maskVal) { 500 maskRange[0][k] = Float.NaN; 501 } 502 } 503 } 504 505 public void resetMaskField(float maskVal) throws Exception { 506 clearMaskField(maskVal); 507 mask_field.setSamples(maskRange, false); 508 } 509 }