001package com.astrolabsoftware.FinkBrowser.Januser; 002 003import com.Lomikel.HBaser.HBaseClient; 004import com.Lomikel.Utils.LomikelException; 005import com.astrolabsoftware.FinkBrowser.FinkPortalClient.FPC; 006import com.astrolabsoftware.FinkBrowser.HBaser.Clusteriser.ClusterFinder; 007 008// org.json 009import org.json.JSONArray; 010import org.json.JSONObject; 011 012// Java 013import java.util.Arrays; 014import java.util.Set; 015import java.util.TreeSet; 016import java.util.Map; 017import java.util.TreeMap; 018import java.io.IOException; 019 020// Log4J 021import org.apache.logging.log4j.Logger; 022import org.apache.logging.log4j.LogManager; 023 024/** <code>FeaturesClassifier</code> classifies sources according to 025 * HBase <tt>lc_features_*</tt> field. 026 * @opt attributes 027 * @opt operations 028 * @opt types 029 * @opt visibility 030 * @author <a href="mailto:Julius.Hrivnac@cern.ch">J.Hrivnac</a> */ 031// BUG: jd should be String or long 032public class FeaturesClassifier implements Classifier { 033 034 @Override 035 public void classify(FinkGremlinRecipies recipies, 036 String oid, 037 boolean enhance, 038 String columns) throws LomikelException { 039 log.info(oid); 040 double jd; 041 String cl; 042 Map<String, String> value; 043 String[] featuresS; 044 double[] featuresD; 045 String fg; 046 String fr; 047 Map<String, Set<Double>> classes; // cl -> [jd] 048 Set<Double> jds; 049 String key; 050 Set<Double> val; 051 double weight; 052 double totalWeight; 053 Map<String, Map<String, String>> alerts = recipies.fhclient().scan(null, 054 "key:key:" + oid + ":prefix", 055 "i:jd,d:lc_features_g,d:lc_features_r", 056 0, 057 0, 058 false, 059 false); 060 classes = new TreeMap<>(); 061 // get all alerts (jd) and their classses 062 boolean isClassified = false; 063 for (Map.Entry<String, Map<String, String>> entry : alerts.entrySet()) { 064 value = entry.getValue(); 065 jd = Double.parseDouble(value.get("i:jd")); 066 if (value.containsKey("d:lc_features_g") && 067 value.containsKey("d:lc_features_r")) { 068 fg = value.get("d:lc_features_g").replaceFirst("\\[", "").replaceAll("]$", ""); 069 fr = value.get("d:lc_features_r").replaceFirst("\\[", "").replaceAll("]$", ""); 070 featuresS = (fg + "," + fr).replaceAll("null", "0.0"). 071 replaceAll("NaN", "0.0"). 072 split(","); 073 featuresD = Arrays.stream(featuresS). 074 mapToDouble(Double::parseDouble). 075 toArray(); 076 cl = String.valueOf(finder().transformAndPredict(featuresD)); 077 if (!cl.equals("-1")) { 078 if (classes.containsKey(cl)) { 079 jds = classes.get(cl); 080 jds.add(jd); 081 } 082 else { 083 jds = new TreeSet<Double>(); 084 jds.add(jd); 085 classes.put(cl, jds); 086 } 087 } 088 isClassified = true; 089 } 090 else { 091 //log.warn("Alert " + entry.getKey() + " has no features"); 092 } 093 } 094 totalWeight = 0; 095 for (Map.Entry<String, Set<Double>> cls : classes.entrySet()) { 096 totalWeight += cls.getValue().size(); 097 } 098 for (Map.Entry<String, Set<Double>> cls : classes.entrySet()) { 099 key = "FC-" + cls.getKey(); 100 val = cls.getValue(); 101 weight = val.size() / totalWeight; 102 recipies.registerSourcesOfInterest(Classifiers.FEATURES, key, oid, weight, val, enhance, columns); 103 } 104 if (!isClassified) { 105 log.warn("Source " + oid + " cannot be classified because his alerts have no LC features"); 106 } 107 } 108 109 /** Give {@link ClusterFinder} to current database. Singleton. 110 * @return The corresponding {@link ClusterFinder}. 111 * @throws LomikelExceltion If {@link ClusterFinder} cannot be created. */ 112 private ClusterFinder finder() throws LomikelException { 113 if (_finder == null || _reset) { 114 if (_resourceName == null && _dirName == null) { 115 _resourceName = "Clusters/2025/13-50-known"; 116 } 117 try { 118 if (_resourceName != null) { 119 ClassLoader classLoader = getClass().getClassLoader(); 120 _finder = new ClusterFinder(classLoader.getResource(_resourceName + "/scaler_params.json"), 121 classLoader.getResource(_resourceName + "/pca_params.json"), 122 classLoader.getResource(_resourceName + "/cluster_centers.json")); 123 } 124 else { 125 _finder = new ClusterFinder(_dirName + "/scaler_params.json", 126 _dirName + "/pca_params.json", 127 _dirName + "/cluster_centers.json"); 128 } 129 _reset = false; 130 } 131 catch (IOException e) { 132 throw new LomikelException("Cannot create Cluster Finder", e); 133 } 134 } 135 return _finder; 136 } 137 138 /** Set the directory for model json files 139 * <tt>scaler_params.json, pca_params.json, cluster_centers.json</tt>. 140 * If not set, <tt>/tmp</tt> will be used. 141 * @param dirName The directory for model json files. */ 142 public static void setModelDirectory(String dirName) { 143 _dirName = dirName; 144 _reset = true; 145 } 146 147 /** Set the resource directory for model json files 148 * <tt>scaler_params.json, pca_params.json, cluster_centers.json</tt>. 149 * If not set, {@link #setModelDirectory} will be used. 150 * @param resourceName The resource directory for model json files. */ 151 public static void setModelResource(String resourceName) { 152 _resourceName = resourceName; 153 _reset = true; 154 } 155 156 private static ClusterFinder _finder; 157 158 private static String _dirName; 159 160 private static String _resourceName; 161 162 private static boolean _reset; 163 164 /** Logging . */ 165 private static Logger log = LogManager.getLogger(FeaturesClassifier.class); 166 167 } 168 169