Skip to content

Commit da644a8

Browse files
matakleotdrwenskiHailey Johnson
authored
Classifier (#1357)
* 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 <tdrwenski@users.noreply.github.com> Co-authored-by: Hailey Johnson <hajohns@ucar.edu>
1 parent c2058b2 commit da644a8

5 files changed

Lines changed: 165 additions & 220 deletions

File tree

Lines changed: 84 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,63 @@
11
package ucar.nc2.filter;
22

3-
import java.io.IOException;
3+
44
import ucar.ma2.Array;
5-
import ucar.ma2.DataType;
65
import ucar.ma2.IndexIterator;
7-
import ucar.nc2.dataset.VariableDS;
6+
import ucar.nc2.Variable;
7+
import ucar.nc2.constants.CDM;
8+
import ucar.nc2.Attribute;
9+
import ucar.nc2.util.Misc;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
813

914
public class Classifier implements Enhancement {
10-
private Classifier classifier = null;
11-
private static Classifier emptyClassifier;
12-
private int classifiedVal;
13-
private int[] classifiedArray;
14-
15-
public static Classifier createFromVariable(VariableDS var) {
16-
try {
17-
Array arr = var.read();
18-
// DataType type = var.getDataType();
19-
return emptyClassifier();
20-
} catch (IOException e) {
21-
return emptyClassifier();
22-
}
15+
private String[] AttCat;
16+
private List<int[]> rules = new ArrayList<>();
17+
18+
public Classifier() {
19+
this.AttCat = new String[0];
20+
this.rules = new ArrayList<>();
2321
}
2422

25-
public static Classifier emptyClassifier() {
26-
emptyClassifier = new Classifier();
27-
return emptyClassifier;
23+
// Constructor with attributes
24+
public Classifier(String[] AttCat) {
25+
this.AttCat = AttCat;
26+
this.rules = loadClassificationRules();
2827
}
2928

30-
/** Enough of a constructor */
31-
public Classifier() {}
29+
// Factory method to create a Classifier from a Variable
30+
public static Classifier createFromVariable(Variable var) {
31+
List<Attribute> attributes = var.attributes().getAttributes();
32+
33+
for (Attribute attribute : attributes) {
34+
// check like this, or something else?
35+
if (attribute == var.attributes().findAttribute(CDM.CLASSIFY)) {
36+
String[] sets = attribute.getStringValue().split(";");
37+
for (int i = 0; i < sets.length; i++) {
38+
// trim and clean so it's ready
39+
sets[i] = sets[i].trim();
40+
}
41+
return new Classifier(sets);
42+
}
43+
}
44+
45+
return new Classifier();
46+
47+
}
48+
49+
3250

33-
/** Classify double array */
34-
public int[] classifyDoubleArray(Array arr) {
51+
public int[] classifyWithAttributes(Array arr) {
3552
int[] classifiedArray = new int[(int) arr.getSize()];
36-
int i = 0;
3753
IndexIterator iterArr = arr.getIndexIterator();
54+
int i = 0;
3855
while (iterArr.hasNext()) {
3956
Number value = (Number) iterArr.getObjectNext();
4057
if (!Double.isNaN(value.doubleValue())) {
41-
42-
classifiedArray[i] = classifyArray(value.doubleValue());
58+
classifiedArray[i] = classifyArrayAttribute(value.doubleValue());
59+
} else {
60+
classifiedArray[i] = Integer.MIN_VALUE;
4361
}
4462
i++;
4563
}
@@ -48,23 +66,54 @@ public int[] classifyDoubleArray(Array arr) {
4866

4967

5068

51-
/** for a single double */
52-
public int classifyArray(double val) {
53-
if (val >= 0) {
54-
classifiedVal = 1;
55-
} else {
56-
classifiedVal = 0;
69+
public int classifyArrayAttribute(double val) {
70+
for (int[] rule : rules) {
71+
if (val > rule[0] && val <= rule[1] + Misc.defaultMaxRelativeDiffFloat) {
72+
return rule[2];
73+
}
5774
}
75+
// Return min possible int if no rule matches
76+
return Integer.MIN_VALUE;
77+
}
5878

59-
return classifiedVal;
79+
// Method to load classification rules from the attributes
80+
private List<int[]> loadClassificationRules() {
81+
for (String rules : this.AttCat) {
82+
int[] rule = stringToIntArray(rules);
83+
this.rules.add(rule);
84+
}
85+
return rules;
6086
}
6187

6288
@Override
6389
public double convert(double val) {
64-
return emptyClassifier.classifyArray(val);
90+
return classifyArrayAttribute(val);
6591
}
6692

93+
public static int[] stringToIntArray(String str) {
94+
String[] stringArray = str.split(" "); // Split the string by spaces
95+
int[] intArray = new int[stringArray.length]; // Create an array to hold the parsed integers
96+
97+
for (int i = 0; i < stringArray.length; i++) {
98+
99+
double value = Double.parseDouble(stringArray[i]); // Parse each string to a double
100+
101+
if (Double.isNaN(value)) {
102+
// Check if the entry is NaN and assign Integer.MIN_VALUE or Integer.MAX_VALUE based on the index
103+
if (i == 0) {
104+
intArray[i] = Integer.MIN_VALUE;
105+
} else if (i == 1) {
106+
intArray[i] = Integer.MAX_VALUE;
107+
} else {
108+
intArray[i] = -99999; // Default value for other indices if needed
109+
}
110+
} else {
111+
intArray[i] = (int) value; // Convert the value to int if it is not NaN
112+
}
67113

68-
}
114+
}
69115

116+
return intArray;
117+
}
70118

119+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<!--
4+
~ Copyright (c) 1998-2020 John Caron and University Corporation for Atmospheric Research/Unidata
5+
~ See LICENSE for license information.
6+
-->
7+
8+
<netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2" enhance="all">
9+
10+
<variable name="class_specs" shape="17" type="double">
11+
<attribute name="classify" value="NaN 0 0; 0 10 10; 10 100 100; 100 NaN 1000"/>
12+
<values>-500000 NaN -10 0 1 2 3 11 25 29 NaN 100 150 121 102 199999 12211</values>
13+
</variable>
14+
15+
<variable name="classify_ints" shape="5" type="int">
16+
<attribute name="classify" value="NaN 0 0; 0 NaN 1"/>
17+
<values>1 -2 0 4 -5</values>
18+
</variable>
19+
20+
<variable name="classify_floats" shape="5" type="float">
21+
<attribute name="classify" value="NaN 0 0; 0 NaN 1"/>
22+
<values>1.0 -2.0 0.0 4.0 -5.0</values>
23+
</variable>
24+
25+
26+
27+
28+
29+
</netcdf>

cdm/core/src/test/data/ncml/enhance/testClassifier.ncml

Lines changed: 0 additions & 54 deletions
This file was deleted.

cdm/core/src/test/java/ucar/nc2/filter/TestClassifier.java

Lines changed: 0 additions & 51 deletions
This file was deleted.

0 commit comments

Comments
 (0)