apmtools 0.2.32__tar.gz → 0.2.33__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: apmtools
3
- Version: 0.2.32
3
+ Version: 0.2.33
4
4
  Summary: A collection of tools for processing air pollution monitoring data
5
5
  Project-URL: Homepage, https://github.com/federlorenz/apmtools
6
6
  Author-email: Federico Lorenzetti <lorenzetti.federico@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "apmtools"
7
- version = "0.2.32"
7
+ version = "0.2.33"
8
8
  authors = [
9
9
  { name="Federico Lorenzetti", email="lorenzetti.federico@gmail.com" },
10
10
  ]
@@ -8,7 +8,7 @@ from io import StringIO
8
8
  from csv import writer
9
9
  from dateutil.parser import parse
10
10
 
11
- from .units import upas_units,lascar_units,purple_units
11
+ from .units import upas_units, lascar_units, purple_units, lcm_units
12
12
 
13
13
  class DictionaryPlus(dict):
14
14
  def __init__(self, *args, **kwargs):
@@ -451,11 +451,11 @@ class Dataset(DictionaryPlus):
451
451
 
452
452
  def scan_folder(self, directory="./", levels=[], level=0, monitor=None, levels_dict=None, gmt_timezone_shift=0, interpolate=False, add_m={}):
453
453
 
454
- from .data_processing import upas_processing, lascar_processing, purple_processing
454
+ from .data_processing import upas_processing, lascar_processing, purple_processing, lcm_processing
455
455
 
456
- if len(set(levels).intersection(set(["identifier", "start", "end", "length", "time", "pm25", "pm25correctedrh", "pm25correctedrhandgrav", "filterid", "grav_not", "grav"]))) > 0:
456
+ if len(set(levels).intersection(set(["identifier", "start", "end", "length", "time", "pm25", "pm25correctedrh", "pm25correctedrhandgrav", "filterid", "grav_not", "grav","PM2.5","PM10","C02","NO2"]))) > 0:
457
457
  print(
458
- f"the following levels names are not allowed: {set(levels).intersection(set(["identifier", "start", "end", "length", "time", "pm25", "pm25correctedrh", "pm25correctedrhandgrav", "filterid", "grav_not", "grav"]))}. Please choose different level names")
458
+ f"the following levels names are not allowed: {set(levels).intersection(set(["identifier", "start", "end", "length", "time", "pm25", "pm25correctedrh", "pm25correctedrhandgrav", "filterid", "grav_not", "grav","PM2.5","PM10","C02","NO2"]))}. Please choose different level names")
459
459
  return
460
460
  if levels_dict == None:
461
461
  levels_dict = dict(
@@ -473,6 +473,8 @@ class Dataset(DictionaryPlus):
473
473
  return "purple"
474
474
  case ['Time', 'CO(ppm)']:
475
475
  return "lascar"
476
+ case ['sensorName', 'deviceId']:
477
+ return "lcm"
476
478
  case _:
477
479
  return None
478
480
  except:
@@ -518,6 +520,21 @@ class Dataset(DictionaryPlus):
518
520
  except:
519
521
  print(
520
522
  f"processing of file {directory}{j} failed. Is this a {monitor} file?")
523
+ case "lcm":
524
+ try:
525
+ processed = lcm_processing(
526
+ directory, file=j, interpolate_data=interpolate)
527
+ for k, v in levels_dict.items():
528
+ if (v not in ["None", "_", "-", None]) and (k not in ["monitor", "", None, "-", "_"]):
529
+ processed.m[k] = v
530
+ processed.m["rejected"] = False
531
+ processed.m["filename"] = j
532
+ for key, value in add_m.items():
533
+ processed.m[key] = value
534
+ self[str(uuid.uuid4())] = processed
535
+ except:
536
+ print(
537
+ f"processing of file {directory}{j} failed. Is this a {monitor} file?")
521
538
  case "purple":
522
539
  try:
523
540
  processed = purple_processing(
@@ -559,6 +576,8 @@ class Dataset(DictionaryPlus):
559
576
  return ("lascar", run_lascar())
560
577
  elif x is Purple:
561
578
  return ("purple", run_purple())
579
+ elif x is Lcm:
580
+ return ("lcm", run_lcm())
562
581
  # elif x is Apm:
563
582
  # return "Apm"
564
583
  # elif x is PolarH10:
@@ -572,6 +591,8 @@ class Dataset(DictionaryPlus):
572
591
  return "Upas"
573
592
  case Lascar():
574
593
  return "Lascar"
594
+ case Lcm():
595
+ return "Lcm"
575
596
  case Purple():
576
597
  return "Purple"
577
598
  case Apm():
@@ -702,6 +723,58 @@ class Dataset(DictionaryPlus):
702
723
  out["time"] = pd.to_datetime(out["time"])
703
724
  return (Summary(out, metadata=set(columns2)))
704
725
 
726
+ def run_lcm():
727
+ a = 0.524
728
+ b = -0.0862
729
+ c = 5.75
730
+ d = self.subset(condition=lambda x: match_monitor(x) == "Lcm")
731
+ columns1 = ["identifier", "monitor",
732
+ "start", "end", "length", "time"]
733
+ columns2 = list(set(d.meta()))
734
+ columns3 = ["sensorName", "deviceId", "resolution",
735
+ "PM2.5", "PM10", "CO2", "NO2", "Temperature", "Humidity"]
736
+ columns4 = ["pm25correctedrh"]
737
+
738
+ buffer = StringIO()
739
+ with buffer as file:
740
+ df = writer(file, delimiter=",")
741
+ df.writerow(columns1+columns2+columns3+columns4)
742
+ count = 0
743
+ for k, v in d.items():
744
+ print(f"processing Lcm {count+1} out of {len(d)}")
745
+ v = v.dropna(subset="PM2.5")
746
+ identifier = k
747
+ start = v.start
748
+ end = v.end
749
+ length = v.length
750
+ for i in range(len(v)):
751
+ app = []
752
+ app.append(identifier)
753
+ app.append("lcm")
754
+ app.append(start)
755
+ app.append(end)
756
+ app.append(length)
757
+ app.append(v.index[i])
758
+ for m in columns2:
759
+ if m in v.m.keys():
760
+ app.append(v.m[m] if v.m[m] != None else "")
761
+ else:
762
+ app.append("")
763
+ for m in columns3:
764
+ app.append(v[m].iloc[i])
765
+ xx = (a*v["PM2.5"].iloc[i])+(b*v["Humidity"].iloc[i])+c
766
+ app.append(xx)
767
+ df.writerow(list(map(str, app)))
768
+ count += 1
769
+ file.seek(0)
770
+ out = pd.read_csv(file)
771
+ out["start"] = pd.to_datetime(out["start"])
772
+ out["end"] = pd.to_datetime(out["end"])
773
+ out["length"] = pd.to_timedelta(out["length"])
774
+ out["time"] = pd.to_datetime(out["time"])
775
+ return (Summary(out, metadata=set(columns2)))
776
+
777
+
705
778
  def run_purple():
706
779
  d = self.subset(condition=lambda x: match_monitor(x) == "Purple")
707
780
  columns1 = ["identifier", "monitor",
@@ -819,6 +892,8 @@ class Dataset(DictionaryPlus):
819
892
  return "Upas"
820
893
  case Lascar():
821
894
  return "Lascar"
895
+ case Lcm():
896
+ return "Lcm"
822
897
  case Purple():
823
898
  return "Purple"
824
899
  case Apm():
@@ -1953,6 +2028,37 @@ class PurpleSeries(ApmSeries):
1953
2028
  def _constructor(self):
1954
2029
  return PurpleSeries
1955
2030
 
2031
+ class Lcm(Apm):
2032
+ monitor = "lcm"
2033
+
2034
+ def __init__(self, *args, **kwargs):
2035
+ Apm.__init__(self, *args, **kwargs)
2036
+ self.m = {}
2037
+ self.variable = "PM2.5"
2038
+
2039
+ @property
2040
+ def _constructor(self):
2041
+ return Lcm
2042
+
2043
+ @property
2044
+ def _constructor_sliced(self):
2045
+ return LcmSeries
2046
+
2047
+ @property
2048
+ def units(self):
2049
+ return lcm_units
2050
+
2051
+ class LcmSeries(ApmSeries):
2052
+ def __init__(self, *args, **kwargs):
2053
+ LcmSeries.__init__(self, *args, **kwargs)
2054
+ _metadata = ['m']
2055
+
2056
+ @property
2057
+ def _constructor(self):
2058
+ return LcmSeries
2059
+
2060
+
2061
+
1956
2062
  class PolarH10(dict):
1957
2063
  monitor = "polarh10"
1958
2064
  def __init__(self, *args, **kwargs):
@@ -4,7 +4,7 @@ import pandas as pd
4
4
  import numpy as np
5
5
  import datetime as dt
6
6
  import os as os
7
- from .classes import Apm, Sum, PolarH10, DictionaryPlus, Grav_Filter, Upas, Lascar, Purple
7
+ from .classes import Apm, Sum, PolarH10, DictionaryPlus, Grav_Filter, Upas, Lascar, Purple, Lcm
8
8
  from zipfile import ZipFile
9
9
  from copy import deepcopy
10
10
  from pandas.errors import EmptyDataError
@@ -841,6 +841,19 @@ def lascar_processing(directory, file, interpolation=1,interval="30 seconds", in
841
841
  out = Lascar(df)
842
842
  return out
843
843
 
844
+
845
+ def lcm_processing(directory, file, interpolation=1, interval="300 seconds", interpolate_data=True):
846
+ numeric = ["PM2.5", "PM10", "CO2", "NO2", "Temperature", "Humidity"]
847
+ dtformat = '%Y-%m-%dT%H:%M:%S'
848
+ df = pd.read_csv(directory+file, index_col="timestamp",
849
+ date_format={'Time': dtformat})
850
+ if interpolate_data:
851
+ df = interpolate(df, 300, interpolation, pd.Timedelta(
852
+ '00:06:00'), numeric_columns=numeric, add_binary_counter=False)
853
+ df = keep_interval(df, interval)
854
+ out = Lcm(df)
855
+ return out
856
+
844
857
  def sum_interpolation(file, interpolation=1, interval="5 minutes", timing=False):
845
858
  if timing:
846
859
  start = time.process_time()
@@ -277,6 +277,10 @@ upas_datatype = {'AccelComplianceCnt': 'integer',
277
277
 
278
278
  lascar_units = {"CO(ppm)":"ppm"}
279
279
 
280
+
281
+ lcm_units = {"sensorName": "-", "deviceId": "-", "resolution": "-", "PM2.5": "µg m-3",
282
+ "PM10": "µg m-3", "CO2": "ppm", "NO2": "ppm", "Temperature": "°C", "Humidity": "%"}
283
+
280
284
  lascar_datatype = {"CO(ppm)": "numeric",
281
285
  'start': "datetime",
282
286
  'end': "datetime",
File without changes
File without changes
File without changes