[Issue-Id:RICAPP-204] Bump version to 1.0.0 and push to staging area
[ric-app/ad.git] / src / ad_model.py
diff --git a/src/ad_model.py b/src/ad_model.py
new file mode 100644 (file)
index 0000000..617fc9f
--- /dev/null
@@ -0,0 +1,128 @@
+# ==================================================================================
+#  Copyright (c) 2020 HCL Technologies Limited.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+# ==================================================================================
+
+import joblib
+from mdclogpy import Logger
+
+logger = Logger(name=__name__)
+
+
+class modelling(object):
+    r""" Filter dataframe based on paramters that were used to train model
+    use transormer to transform the data
+    load model and predict the label(normal/anomalous)
+
+    Parameters:
+    data:DataFrame
+    """
+
+    def __init__(self, data=None):
+        self.data = data
+        self.load_model()
+        self.load_param()
+        self.load_scale()
+
+    def load_model(self):
+        try:
+            with open('src/model', 'rb') as f:
+                self.model = joblib.load(f)
+        except FileNotFoundError:
+            logger.error("Model Does not exsist")
+
+    def load_param(self):
+        try:
+            with open('src/num_params', 'rb') as f:
+                self.num = joblib.load(f)
+
+        except FileNotFoundError:
+            logger.error("Parameter file does not exsist")
+
+    def load_scale(self):
+        try:
+            with open('src/scale', 'rb') as f:
+                self.scale = joblib.load(f)
+        except FileNotFoundError:
+            logger.error("Scale file does not exsist")
+
+    def transformation(self):
+        self.data = self.scale.transform(self.data)
+
+    def predict(self, df):
+        """ Load the saved model and return predicted result.
+        Parameters
+        .........
+        name:str
+            name of model
+
+        Return
+        ......
+        pred:int
+            predict label on a given sample
+
+        """
+        self.data = df.loc[:, self.num]
+        self.transformation()
+        pred = self.model.predict(self.data)
+        pred = [1 if p == -1 else 0 for p in pred]
+        return pred
+
+
+class CAUSE(object):
+    r""""Rule basd method to find degradation type of anomalous sample
+
+    Attributes:
+    normal:DataFrame
+        Dataframe that contains only normal sample
+    """
+
+    def __init__(self):
+        self.normal = None
+
+    def cause(self, df, db):
+        """ Filter normal data for a particular ue-id to compare with a given sample
+            Compare with normal data to find and return degradaton type
+        """
+        sample = df.copy()
+        sample.index = range(len(sample))
+        for i in range(len(sample)):
+            if sample.iloc[i]['Anomaly'] == 1:
+                query = 'select * from {} where {} = \'{}\' and time<now() and time>now()-20s'.format(db.meas, db.ue, sample.iloc[i][db.ue])
+                normal = db.query(query)
+                if normal:
+                    normal = normal[db.meas][[db.thpt, db.rsrp, db.rsrq]]
+                    deg = self.find(sample.loc[i, :], normal.max(), db)
+                    if deg:
+                        sample.loc[i, 'Degradation'] = deg
+                        if 'Throughput' in deg and ('RSRP' in deg or 'RSRQ' in deg):
+                            sample.loc[i, 'Anomaly'] = 2
+                    else:
+                        sample.loc[i, 'Anomaly'] = 0
+        return sample[['Anomaly', 'Degradation']].values.tolist()
+
+    def find(self, row, l, db):
+        """ store if a particular parameter is below threshold and return """
+        deg = []
+        if row[db.thpt] < l[db.thpt]*0.5:
+            deg.append('Throughput')
+        if row[db.rsrp] < l[db.rsrp]-15:
+            deg.append('RSRP')
+        if row[db.rsrq] < l[db.rsrq]-10:
+            deg.append('RSRQ')
+        if len(deg) == 0:
+            deg = False
+        else:
+            deg = ' '.join(deg)
+        return deg