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