From 8ec31997a03a63a146cafb99edf7ecb9a2b10b72 Mon Sep 17 00:00:00 2001 From: kolacodes-db Date: Tue, 17 Jun 2025 16:46:30 +0100 Subject: [PATCH 1/2] water_quality_monitoring --- src/__pycache__/clean_data.cpython-311.pyc | Bin 0 -> 1227 bytes src/__pycache__/evaluate.cpython-311.pyc | Bin 0 -> 3211 bytes src/__pycache__/load_data.cpython-311.pyc | Bin 0 -> 1536 bytes src/clean_data.py | 31 +++++++-- src/evaluate.py | 75 +++++++++++++++++++-- src/load_data.py | 28 ++++++-- src/main.py | 31 +++++++++ 7 files changed, 149 insertions(+), 16 deletions(-) create mode 100644 src/__pycache__/clean_data.cpython-311.pyc create mode 100644 src/__pycache__/evaluate.cpython-311.pyc create mode 100644 src/__pycache__/load_data.cpython-311.pyc diff --git a/src/__pycache__/clean_data.cpython-311.pyc b/src/__pycache__/clean_data.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..196f120163a69629256a5d05e39ab017c60b07ba GIT binary patch literal 1227 zcmZ`&O-S5O5T2Kxb#*H$23L_nszr>@^;Fs}BKQZT+E)9EvPI(N=|*;w^(E`pHiCy9 zJb180(4&W9E%wl3uikrDi% z*%kqQ^G#XgGv&A!m31({AX&(f36c{g1OkRY2^Ct((O`&|_tTOgy^|(HLw*Wca2Hs+{-4%XtW_%y|SaOMLUIMnxIOQr%MB3{@R!IW|-I zeW_CmYDTw=tZB`tIn#0YcV5pHsH37;P21KyWiGe63wi1!LaGq@*o>15HO|h-k}4mE zYEP>M4#c!Aotemk9IkF!oP+7bi`malhsu+1au+zSWGk9(Mosfxs1arj&uXGCOg(ofb5i$5Q!jOwvdOW6p2Zp_AKI4b+6+5S z6+_3|nIl(mI4qqC`NM<>tg)uDWeTR@<92otmLO0-X<8aNs%s3OR@OpT77v|X5I*P?hQrv04F1|GP$yCaAMBx-nj_N zNIayHRaGjARDtrL@RU;Zg~$9Ec63s$lUhY-`_MO6=~JFMduI%GfHqavce6XYGqbbf zncv>`g5X2Y$j_4tU0#HKrOZy_s)N^kFjz+zVJ3wZnK-k^##sij=o5t5`v^Opu?YPL zuifGf%uS()^AE~KSd)t;6T0cSkabuU_p5w6lJ{R|3kHvd|_X6+3KG@K2hHlBaLO#pNsieL<@}->0%6gjQ27My5 zDz9kb5|t9au*JkXvZi1$t%{nWYH1=8MaD^WUhB2A=522~u2l!`?F=d(nSNVC!m=)# zE~4mJq9$r#07WOf4tQTjVRjwmnN48cZkTz-Kmg&j+ktXyy&QJTBg{SKR@ehIob?(j zj=W>_1a{|H?70e?LGKOkY>PH)9@M5_fPM8g7^L3HJM!pm?WFfCaq_Nq{cqVlYuTj{ zv)Vl?JBav>{_>4>4~&jbFS)|yxp$6EQ@ss{&e=Q%(b>st^dC`l zbJMDV2IG6|EhY5@QL#%Cwt#BWvMF7w>6_lFCrNC2Qt5QdBkwi;fgH?wR8b{NTyYwpy(7}?t(M&qbW03NKON*n4p^|b3@ z*VeI8__7hcTyF1q8h9Ak@|D^z8toU$M~{`;+ACgXi?4!!6kL^N)D-?!`dZqUE(zU+ z&|P55exWc>7EcvoYyBnuc$sfmyJGO2Kk+>;_@2#AOZ<6*KVP(-vJhB1X|!~|5W0&( z_y4LhUg9qp{DmTaq2fXzas9@F8=Kcl!9F9{SMZko!J@zOp#6#`KP>U!@|B|Xl!dm9 zpb_qSA@mi6zJrynl=yyw?=SNGF9V^1@EXF3Oy6$)*IgGhH>~U8Hy9jtU0}BU#y#W$ zfV;Rs){$qha~Jdpi(M*%-2i?J_UxJO#$N2(|4OKrtOu$b_>TRQt~gZ|^D9m)%2EKL?=UDOwpxA8%gH9$FfGs|}<&grxW{uQq6hPn>c z{t1R?Db_sO7t?Hab@+6!y%8;w_1@PkSmS-;P25oD%wYqJ$>(1biNPBuSMQ6-hFE5@06Irs$ZLEF7(_xFrdv6Ou$) zK#8_J1ySNdt!=B<%Pk=w z;m#u0R^d)N+qN!M5Omv7t7{~aOsjK*+2SgQ_S>y?e>k;0qfSjkIMbysXP{v0LvTBu zk~4HfgJT`xjpwQzlOYm;Ir=TAC4f{M48xSsiQ;}wg&Sd*5vGC;?*6pb{yId&a^i3N CLjmUi literal 0 HcmV?d00001 diff --git a/src/__pycache__/load_data.cpython-311.pyc b/src/__pycache__/load_data.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7cea8ed51e60e33daac4565598dbea1cbe16c3c0 GIT binary patch literal 1536 zcmZ`(%TF6e82@G;W{oky6bDC1=pYc1C7`NGFILrxgrFW$L~)u5%dNHYt{;`X>&^~! zKz79;2M#?%RV$F9NF1t^D*Y$OsZuYtOSP5PJ+NMoT%Y*epg=NqhDb^EgwQ%;R1D5zUlAOl$VHo)yLP>nz{mCP1dy4 zM*`He%LoEL#DZw7sF!ag;Dl!2eekrZ@X;I7MCe1OoOig+}`Iw5((4xa#oR=_U)Xh-~gI07MlND`mQ9`9yW_d3mHNn=8 zX@ag}WGOQ6g5BrrpOealjQRz%$d0R5QD#?|?b!}5I(cfF*#c#5Ri45}OCF!FIPtZz zYuRf%BM%sJS%R(#6Lvz>aXHPoTaLB36O&uCgcb{~b3+p}KICg|#ddr(>wV`Bi}c*E zP0MC}z^vf9VQy=UZl}$hR|}xlWP0NS{wv<;J&X8|A@<$FgZ* zNk-hZSlRZ&a)t(E#La9HZ_==P^O*Cy(4Byh(cP7<64J*z;mEW2;Y=eu*9_0K!gF0v zgVRT|ooMW*uMbz6(ReEw-&<`@-t7VjPfPJkZI4athkgtl+;5K2));Nb)>Xv;9pREg zihl*$8zBa3*J-_8@4Dr#0b>(;p*wQofB zf}(ap6NB?olc4#dNMm#!Thmx*84C?#p^rGl;ahrL9dEW&+jcq)MI@F z)#He^93482szQ$uq2JPkKK1UsIraFHAj;RqJNKs5*SCq#r*)K=5#mGl1AM!J!DQk; z!$eSg)#FTt=r=gQIk1~3-Wnfa4sVt0kJ%lZihq^&7zKKnkTwkO%G!pzjq6%hyGh0m Vl3l>z@X^uiFDa@1uVA;4`acz$elY+5 literal 0 HcmV?d00001 diff --git a/src/clean_data.py b/src/clean_data.py index da613640a..32a1b3b5c 100644 --- a/src/clean_data.py +++ b/src/clean_data.py @@ -1,7 +1,30 @@ -def clean_sensor_data(df: pd.DataFrame) -> pd.DataFrame: - """ - Clean sensor data by handling missing or invalid values. +from typing import List, Dict +def clean_data(data: List[Dict]) -> List[Dict]: + """ + Clean the sensor data by handling missing values and converting types. + + Args: + data: List of dictionaries containing raw sensor data + Returns: - pd.DataFrame: Cleaned data. + List of dictionaries with cleaned data """ + cleaned_data = [] + + for row in data: + cleaned_row = row.copy() + + # Convert numeric fields to float if they exist, else None + for field in ['ph', 'turbidity', 'temperature']: + if field in cleaned_row and cleaned_row[field]: + try: + cleaned_row[field] = float(cleaned_row[field]) + except ValueError: + cleaned_row[field] = None + else: + cleaned_row[field] = None + + cleaned_data.append(cleaned_row) + + return cleaned_data diff --git a/src/evaluate.py b/src/evaluate.py index 006256224..8c8edb09a 100644 --- a/src/evaluate.py +++ b/src/evaluate.py @@ -1,9 +1,72 @@ -class WaterQualityEvaluator: - def __init__(self, ph_range=(6.5, 8.5), turbidity_threshold=1.0): - self.ph_range = ph_range - self.turbidity_threshold = turbidity_threshold +from typing import Dict, Optional - def is_safe(self, row: pd.Series) -> bool: +class WaterQualityEvaluator: + """ + Evaluates water quality based on sensor readings. + """ + + # Safe ranges + SAFE_PH_MIN = 6.5 + SAFE_PH_MAX = 7.5 + SAFE_TURBIDITY_MAX = 1.0 + + def evaluate_sensor(self, sensor_data: Dict) -> Dict: + """ + Evaluate a single sensor's water quality. + + Args: + sensor_data: Dictionary containing sensor readings + + Returns: + Dictionary with evaluation results + """ + result = { + 'sensor_id': sensor_data.get('sensor_id'), + 'location': sensor_data.get('location'), + 'is_safe': True, + 'issues': [] + } + + # Check pH + ph = sensor_data.get('ph') + if ph is None: + result['is_safe'] = False + result['issues'].append('missing pH') + elif ph < self.SAFE_PH_MIN: + result['is_safe'] = False + result['issues'].append('pH too low') + elif ph > self.SAFE_PH_MAX: + result['is_safe'] = False + result['issues'].append('pH too high') + + # Check turbidity + turbidity = sensor_data.get('turbidity') + if turbidity is None: + result['is_safe'] = False + result['issues'].append('missing turbidity') + elif turbidity > self.SAFE_TURBIDITY_MAX: + result['is_safe'] = False + result['issues'].append('turbidity too high') + + return result + + def format_result(self, evaluation: Dict) -> str: """ - Determine if a row of water data is safe. + Format the evaluation result as a readable string. + + Args: + evaluation: Dictionary with evaluation results + + Returns: + Formatted string with the evaluation """ + sensor_id = evaluation.get('sensor_id', 'Unknown') + location = evaluation.get('location', 'Unknown location') + status = "✅ Safe" if evaluation['is_safe'] else "❌ Unsafe" + + if evaluation['issues']: + issues = " (" + ", ".join(evaluation['issues']) + ")" + else: + issues = "" + + return f"Sensor {sensor_id} at {location}: {status}{issues}" \ No newline at end of file diff --git a/src/load_data.py b/src/load_data.py index c0126703a..3ea251982 100644 --- a/src/load_data.py +++ b/src/load_data.py @@ -1,10 +1,26 @@ -def load_csv(filepath: str) -> pd.DataFrame: - """ - Load sensor data from a CSV file. +import csv +from typing import List, Dict +def load_csv_file(file_path: str) -> List[Dict]: + """ + Load data from a CSV file into a list of dictionaries. + Args: - filepath (str): Path to the CSV file. - + file_path: Path to the CSV file + Returns: - pd.DataFrame: Loaded data as a pandas DataFrame. + List of dictionaries representing each row of data """ + data = [] + try: + with open(file_path, mode='r') as file: + reader = csv.DictReader(file) + for row in reader: + data.append(row) + return data + except FileNotFoundError: + print(f"Error: File {file_path} not found.") + return [] + except Exception as e: + print(f"Error loading CSV file: {e}") + return [] \ No newline at end of file diff --git a/src/main.py b/src/main.py index e69de29bb..77a1ee54d 100644 --- a/src/main.py +++ b/src/main.py @@ -0,0 +1,31 @@ +from load_data import load_csv_file +from clean_data import clean_data +from evaluate import WaterQualityEvaluator + +def main(): + # File paths + input_file = r"C:\Users\HP\Water_Quality_Monitoring\water_quality_monitoring\data\sensor_data.csv" + + # Load data + raw_data = load_csv_file(input_file) + if not raw_data: + print("No data loaded. Exiting.") + return + + # Clean data + cleaned_data = clean_data(raw_data) + + # Evaluate data + evaluator = WaterQualityEvaluator() + results = [] + + for sensor in cleaned_data: + evaluation = evaluator.evaluate_sensor(sensor) + results.append(evaluator.format_result(evaluation)) + + # Print results + for result in results: + print(result) + +if __name__ == "__main__": + main() \ No newline at end of file From 387bd29b22a0d022c2b1c6e911871d315684aa64 Mon Sep 17 00:00:00 2001 From: kolacodes-db Date: Tue, 17 Jun 2025 16:55:25 +0100 Subject: [PATCH 2/2] kola-aderoju --- water_quality_monitoring | 1 + 1 file changed, 1 insertion(+) create mode 160000 water_quality_monitoring diff --git a/water_quality_monitoring b/water_quality_monitoring new file mode 160000 index 000000000..d8e01fac7 --- /dev/null +++ b/water_quality_monitoring @@ -0,0 +1 @@ +Subproject commit d8e01fac730cad564e68aef22682011e0fb721ed