001package com.astrolabsoftware.FinkBrowser.Januser; 002 003import com.Lomikel.Utils.LomikelException; 004import com.astrolabsoftware.FinkBrowser.HBaser.Clusteriser.ClusterFinder; 005 006// Java 007import java.util.Arrays; 008import java.util.Set; 009import java.util.TreeSet; 010import java.util.Map; 011import java.util.TreeMap; 012import java.util.List; 013import java.util.ArrayList; 014import java.io.IOException; 015 016// Log4J 017import org.apache.logging.log4j.Logger; 018import org.apache.logging.log4j.LogManager; 019 020/** <code>FeaturesClassifier</code> classifies sources according to 021 * HBase <tt>lc_features_*</tt> field. 022 * <em>flavor</em> points to resource carrying model. 023 * @opt attributes 024 * @opt operations 025 * @opt types 026 * @opt visibility 027 * @author <a href="mailto:Julius.Hrivnac@cern.ch">J.Hrivnac</a> */ 028// BUG: jd should be String or long 029public class FeaturesClassifier extends ZTFClassifier { 030 031 @Override 032 public void classify(FinkGremlinRecipies recipies, 033 String oid) throws LomikelException { 034 String jd; 035 String cl; 036 Map<String, String> value; 037 String[] featuresS; 038 double[] featuresD; 039 String fg; 040 String fr; 041 Map<String, Set<String>> allInstances; // cl -> [jd] 042 Map<String, Double> allWeights; // jd -> w 043 Set<String> jds; 044 String key; 045 Map<String, Map<String, String>> alerts = recipies.fhclient().scan(null, 046 "key:key:" + oid + ":prefix", 047 "i:jd,d:lc_features_g,d:lc_features_r", 048 0, 049 0, 050 false, 051 false); 052 allInstances = new TreeMap<>(); 053 allWeights = new TreeMap<>(); 054 // get all alerts (jd) and their classses 055 boolean isClassified = false; 056 for (Map.Entry<String, Map<String, String>> entry : alerts.entrySet()) { 057 value = entry.getValue(); 058 jd = value.get("i:jd"); 059 if (value.containsKey("d:lc_features_g") && 060 value.containsKey("d:lc_features_r")) { 061 fg = value.get("d:lc_features_g").replaceFirst("\\[", "").replaceAll("]$", ""); 062 fr = value.get("d:lc_features_r").replaceFirst("\\[", "").replaceAll("]$", ""); 063 // BUG: some models replace by mean 064 featuresS = (fg + "," + fr).replaceAll("null", "0.0"). 065 replaceAll("NaN", "0.0"). 066 split(","); 067 featuresD = Arrays.stream(featuresS). 068 mapToDouble(Double::parseDouble). 069 toArray(); 070 cl = String.valueOf(finder().transformAndPredict(featuresD)); 071 if (!cl.equals("-1")) { 072 if (allInstances.containsKey(cl)) { 073 jds = allInstances.get(cl); 074 jds.add(jd); 075 } 076 else { 077 jds = new TreeSet<String>(); 078 jds.add(jd); 079 allInstances.put(cl, jds); 080 } 081 allWeights.put(jd, 1.0); 082 } 083 isClassified = true; 084 } 085 else { 086 //log.warn("Alert " + entry.getKey() + " has no features"); 087 } 088 } 089 // rearrange instances and weights and register 090 double weight; 091 double totalWeight; 092 double w; 093 totalWeight = 0; 094 List<String> instancesL; 095 List<Double> weightsL; 096 for (Map.Entry<String, Set<String>> cls : allInstances.entrySet()) { 097 for (String instance : cls.getValue()) { 098 totalWeight += allWeights.get(instance); 099 } 100 } 101 for (Map.Entry<String, Set<String>> cls : allInstances.entrySet()) { 102 key = "FC-" + cls.getKey(); 103 instancesL = new ArrayList<String>(cls.getValue()); 104 weightsL = new ArrayList<Double>(); 105 w = 0; 106 for (String instance : instancesL) { 107 weightsL.add(allWeights.get(instance)); 108 w += allWeights.get(instance); 109 } 110 weight = w / totalWeight; 111 recipies.registerOCol(this, key, oid, weight, instancesL, weightsL); 112 } 113 if (!isClassified) { 114 log.warn("Source " + oid + " cannot be classified because his alerts have no LC features"); 115 } 116 } 117 118 /** Give {@link ClusterFinder} to current database. Singleton. 119 * @return The corresponding {@link ClusterFinder}. 120 * @throws LomikelExceltion If {@link ClusterFinder} cannot be created. */ 121 private ClusterFinder finder() throws LomikelException { 122 if (_finder == null) { 123 try { 124 ClassLoader classLoader = getClass().getClassLoader(); 125 _finder = new ClusterFinder(classLoader.getResource("Clusters/ZTF/" + flavor() + "/scaler_params.json"), 126 classLoader.getResource("Clusters/ZTF/" + flavor() + "/pca_params.json"), 127 classLoader.getResource("Clusters/ZTF/" + flavor() + "/cluster_centers.json")); 128 } 129 catch (IOException | IllegalArgumentException e) { 130 throw new LomikelException("Cannot create Cluster Finder for " + flavor(), e); 131 } 132 } 133 return _finder; 134 } 135 136 private ClusterFinder _finder; 137 138 /** Logging . */ 139 private static Logger log = LogManager.getLogger(FeaturesClassifier.class); 140 141 } 142 143