Skip to content

Commit

Permalink
Classifier (#1357)
Browse files Browse the repository at this point in the history
* the best version so far

* matche python mostly

* before major change, kinda works

* long one, all numpy stuff

* classfier v1

* Seems to be working

* stlye check

* removed some not used stuff

* add additional convert methods

* some test fixes

* rehaul

* changes from code review comments

* starting to work

* trying new ncml

* new tests

* all seems to work

* all seems to be working!

* applied style

* final style update

* fix the shape of class_specs to 17

* fix pr comments

* fix the flaky test

* delete tests, modify constructor

* remove unused ncml, add int and float test

* update variable length to correct num

* Suppress spurious/not relevant jfreechart CVEs (#1358)

finalize reviews

---------

Co-authored-by: Tara Drwenski <[email protected]>
Co-authored-by: Hailey Johnson <[email protected]>
  • Loading branch information
3 people committed Jul 1, 2024
1 parent c2058b2 commit da644a8
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 220 deletions.
119 changes: 84 additions & 35 deletions cdm/core/src/main/java/ucar/nc2/filter/Classifier.java
Original file line number Diff line number Diff line change
@@ -1,45 +1,63 @@
package ucar.nc2.filter;

import java.io.IOException;

import ucar.ma2.Array;
import ucar.ma2.DataType;
import ucar.ma2.IndexIterator;
import ucar.nc2.dataset.VariableDS;
import ucar.nc2.Variable;
import ucar.nc2.constants.CDM;
import ucar.nc2.Attribute;
import ucar.nc2.util.Misc;
import java.util.ArrayList;
import java.util.List;


public class Classifier implements Enhancement {
private Classifier classifier = null;
private static Classifier emptyClassifier;
private int classifiedVal;
private int[] classifiedArray;

public static Classifier createFromVariable(VariableDS var) {
try {
Array arr = var.read();
// DataType type = var.getDataType();
return emptyClassifier();
} catch (IOException e) {
return emptyClassifier();
}
private String[] AttCat;
private List<int[]> rules = new ArrayList<>();

public Classifier() {
this.AttCat = new String[0];
this.rules = new ArrayList<>();
}

public static Classifier emptyClassifier() {
emptyClassifier = new Classifier();
return emptyClassifier;
// Constructor with attributes
public Classifier(String[] AttCat) {
this.AttCat = AttCat;
this.rules = loadClassificationRules();
}

/** Enough of a constructor */
public Classifier() {}
// Factory method to create a Classifier from a Variable
public static Classifier createFromVariable(Variable var) {
List<Attribute> attributes = var.attributes().getAttributes();

for (Attribute attribute : attributes) {
// check like this, or something else?
if (attribute == var.attributes().findAttribute(CDM.CLASSIFY)) {
String[] sets = attribute.getStringValue().split(";");
for (int i = 0; i < sets.length; i++) {
// trim and clean so it's ready
sets[i] = sets[i].trim();
}
return new Classifier(sets);
}
}

return new Classifier();

}



/** Classify double array */
public int[] classifyDoubleArray(Array arr) {
public int[] classifyWithAttributes(Array arr) {
int[] classifiedArray = new int[(int) arr.getSize()];
int i = 0;
IndexIterator iterArr = arr.getIndexIterator();
int i = 0;
while (iterArr.hasNext()) {
Number value = (Number) iterArr.getObjectNext();
if (!Double.isNaN(value.doubleValue())) {

classifiedArray[i] = classifyArray(value.doubleValue());
classifiedArray[i] = classifyArrayAttribute(value.doubleValue());
} else {
classifiedArray[i] = Integer.MIN_VALUE;
}
i++;
}
Expand All @@ -48,23 +66,54 @@ public int[] classifyDoubleArray(Array arr) {



/** for a single double */
public int classifyArray(double val) {
if (val >= 0) {
classifiedVal = 1;
} else {
classifiedVal = 0;
public int classifyArrayAttribute(double val) {
for (int[] rule : rules) {
if (val > rule[0] && val <= rule[1] + Misc.defaultMaxRelativeDiffFloat) {
return rule[2];
}
}
// Return min possible int if no rule matches
return Integer.MIN_VALUE;
}

return classifiedVal;
// Method to load classification rules from the attributes
private List<int[]> loadClassificationRules() {
for (String rules : this.AttCat) {
int[] rule = stringToIntArray(rules);
this.rules.add(rule);
}
return rules;
}

@Override
public double convert(double val) {
return emptyClassifier.classifyArray(val);
return classifyArrayAttribute(val);
}

public static int[] stringToIntArray(String str) {
String[] stringArray = str.split(" "); // Split the string by spaces
int[] intArray = new int[stringArray.length]; // Create an array to hold the parsed integers

for (int i = 0; i < stringArray.length; i++) {

double value = Double.parseDouble(stringArray[i]); // Parse each string to a double

if (Double.isNaN(value)) {
// Check if the entry is NaN and assign Integer.MIN_VALUE or Integer.MAX_VALUE based on the index
if (i == 0) {
intArray[i] = Integer.MIN_VALUE;
} else if (i == 1) {
intArray[i] = Integer.MAX_VALUE;
} else {
intArray[i] = -99999; // Default value for other indices if needed
}
} else {
intArray[i] = (int) value; // Convert the value to int if it is not NaN
}

}
}

return intArray;
}

}
29 changes: 29 additions & 0 deletions cdm/core/src/test/data/ncml/enhance/testAddToClassifier.ncml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>

<!--
~ Copyright (c) 1998-2020 John Caron and University Corporation for Atmospheric Research/Unidata
~ See LICENSE for license information.
-->

<netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2" enhance="all">

<variable name="class_specs" shape="17" type="double">
<attribute name="classify" value="NaN 0 0; 0 10 10; 10 100 100; 100 NaN 1000"/>
<values>-500000 NaN -10 0 1 2 3 11 25 29 NaN 100 150 121 102 199999 12211</values>
</variable>

<variable name="classify_ints" shape="5" type="int">
<attribute name="classify" value="NaN 0 0; 0 NaN 1"/>
<values>1 -2 0 4 -5</values>
</variable>

<variable name="classify_floats" shape="5" type="float">
<attribute name="classify" value="NaN 0 0; 0 NaN 1"/>
<values>1.0 -2.0 0.0 4.0 -5.0</values>
</variable>





</netcdf>
54 changes: 0 additions & 54 deletions cdm/core/src/test/data/ncml/enhance/testClassifier.ncml

This file was deleted.

51 changes: 0 additions & 51 deletions cdm/core/src/test/java/ucar/nc2/filter/TestClassifier.java

This file was deleted.

Loading

0 comments on commit da644a8

Please sign in to comment.