core-lens 0.1.dev189__tar.gz → 0.1.dev190__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.
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/PKG-INFO +1 -1
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/_version.py +2 -2
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/base/namespaces/stats.py +68 -44
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.github/ISSUE_TEMPLATE/blank-proposal.yaml +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.github/ISSUE_TEMPLATE/bug-report.yaml +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.github/ISSUE_TEMPLATE/feature-request.yaml +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.github/pull_request_template.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.github/workflows/ci.yml +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.github/workflows/gh-pages.yml +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.github/workflows/pre-release.yml +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.github/workflows/release.yml +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.gitignore +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.gitmessage +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.pre-commit-config.yaml +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/.python-version +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/CONTRIBUTING.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/LICENSE +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/README.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/SKILLS.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/README.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/bench_aoi.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/bench_entity.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/bench_export.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/bench_polars_utils.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/bench_result.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/bench_schema.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/bench_season.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/bench_spatial.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/bench_view.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/benchmarks/run_all.sh +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/Makefile +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/make.bat +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/concepts.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/conf.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/export.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/index.rst +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/intro.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/logging.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/plots.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/plugins.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/queries.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/quickstart.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/docs/source/stats.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/examples/demo_mws.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/examples/demo_tehsil.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/hooks/mypy.sh +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/hooks/no-parquet-outside-fixtures.sh +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/hooks/pytest.sh +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/pyproject.toml +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/__init__.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/__main__.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/aoi.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/base/__init__.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/base/entity.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/base/namespaces/__init__.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/base/namespaces/plot.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/base/result.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/base/view.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/entities/__init__.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/entities/farms.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/entities/mws.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/entities/tehsil.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/entities/waterbody.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/export/__init__.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/export/formats.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/py.typed +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/schema/__init__.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/schema/detection.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/schema/profile.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/utils/__init__.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/utils/paths.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/utils/polars_utils.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/utils/season.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/src/core_lens/utils/spatial.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/fixtures/generate_fixtures.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/conftest.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_aoi.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_entities.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_entity.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_export.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_main.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_plot.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_polars_utils.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_profile.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_result.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_schema_detection.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_schema_profile.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_season.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_season_config.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_spatial.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_stats.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/tests/unit/test_view.py +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/usage.md +0 -0
- {core_lens-0.1.dev189 → core_lens-0.1.dev190}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: core-lens
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.dev190
|
|
4
4
|
Summary: Query, analyse, and visualise CoreStack's microwatershed and Earth science data through a clean, composable Python API.
|
|
5
5
|
Project-URL: Homepage, https://github.com/ApoorvaKashyap/core-lens
|
|
6
6
|
Project-URL: Issues, https://github.com/ApoorvaKashyap/core-lens/issues
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.1.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 1, '
|
|
21
|
+
__version__ = version = '0.1.dev190'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 'dev190')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -741,6 +741,8 @@ class StatsNamespace:
|
|
|
741
741
|
}
|
|
742
742
|
return self._r._replace(data=data, has_geometry=False, metadata=metadata)
|
|
743
743
|
|
|
744
|
+
import warnings
|
|
745
|
+
|
|
744
746
|
def anomaly(
|
|
745
747
|
self,
|
|
746
748
|
column: str,
|
|
@@ -760,16 +762,17 @@ class StatsNamespace:
|
|
|
760
762
|
used as the reference/"normal" period. Required for timeseries; optional
|
|
761
763
|
for cross-sectional.
|
|
762
764
|
target_years (tuple[int, int] | None, optional): ``(from_year, to_year)`` inclusive,
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
765
|
+
years actually scored. Timeseries: defaults to "everything after
|
|
766
|
+
``baseline[1]``" if omitted. Cross-sectional: defaults to all rows.
|
|
767
|
+
Must not overlap ``baseline``.
|
|
766
768
|
threshold (float, optional): Sigma / score threshold for anomaly flag (default 2.0).
|
|
767
769
|
|
|
768
770
|
Returns:
|
|
769
771
|
Result: data has ``key_col | anomaly_score | is_anomaly`` (cross-sectional) or
|
|
770
|
-
``key_col |
|
|
771
|
-
restricted to ``target_years`` if given).
|
|
772
|
-
|
|
772
|
+
``key_col | <time_col> | anomaly_score | is_anomaly`` (timeseries, baseline
|
|
773
|
+
excluded, restricted to ``target_years`` if given). ``<time_col>`` is the
|
|
774
|
+
finer-grained date/period column when the data is sub-annual, falling back
|
|
775
|
+
to plain ``year`` for annual data. ``metadata`` includes ``n_entities_dropped``.
|
|
773
776
|
|
|
774
777
|
Raises:
|
|
775
778
|
ValueError: If ``mode``/``method`` invalid, observation count too low, or
|
|
@@ -784,8 +787,6 @@ class StatsNamespace:
|
|
|
784
787
|
f"target_years={target_years} overlap. They must be disjoint."
|
|
785
788
|
)
|
|
786
789
|
|
|
787
|
-
# Single explicit collect boundary — everything below is eager by necessity
|
|
788
|
-
# (numpy/scipy/statsmodels have no lazy path).
|
|
789
790
|
df = self._r.df()
|
|
790
791
|
if isinstance(df, pl.LazyFrame):
|
|
791
792
|
df = df.collect()
|
|
@@ -819,7 +820,6 @@ class StatsNamespace:
|
|
|
819
820
|
f"but only got {len(ref_vals)}."
|
|
820
821
|
)
|
|
821
822
|
|
|
822
|
-
# target_years scopes which rows get scored/returned; baseline stays reference-only.
|
|
823
823
|
eval_df = df
|
|
824
824
|
if target_years is not None and has_year:
|
|
825
825
|
eval_df = df.filter(
|
|
@@ -889,7 +889,6 @@ class StatsNamespace:
|
|
|
889
889
|
"threshold": threshold,
|
|
890
890
|
}
|
|
891
891
|
|
|
892
|
-
# Build straight from numpy — no .tolist() round-trip.
|
|
893
892
|
data = eval_df.select(pl.col(key)).with_columns(
|
|
894
893
|
pl.Series("anomaly_score", scores, dtype=pl.Float64),
|
|
895
894
|
pl.Series("is_anomaly", flags, dtype=pl.Boolean),
|
|
@@ -913,6 +912,13 @@ class StatsNamespace:
|
|
|
913
912
|
"Ensure data is at annual or sub_annual resolution."
|
|
914
913
|
)
|
|
915
914
|
|
|
915
|
+
# Finer-grained time column for sub-annual data, if present.
|
|
916
|
+
# `year_col` still drives baseline/target-year windowing regardless.
|
|
917
|
+
date_col = next(
|
|
918
|
+
(c for c in ("date", "period", "period_start") if c in df.columns), None
|
|
919
|
+
)
|
|
920
|
+
output_time_col = date_col or year_col
|
|
921
|
+
|
|
916
922
|
min_obs = _MIN_OBS[method.value]
|
|
917
923
|
n_dropped = 0
|
|
918
924
|
|
|
@@ -963,11 +969,11 @@ class StatsNamespace:
|
|
|
963
969
|
.with_columns(
|
|
964
970
|
(pl.col("anomaly_score").abs() > threshold).alias("is_anomaly")
|
|
965
971
|
)
|
|
966
|
-
.select(key,
|
|
972
|
+
.select(key, output_time_col, "anomaly_score", "is_anomaly")
|
|
967
973
|
.drop_nulls("anomaly_score")
|
|
968
974
|
)
|
|
969
975
|
|
|
970
|
-
# ---- CUSUM / STL: inherently sequential/per-entity,
|
|
976
|
+
# ---- CUSUM / STL: inherently sequential/per-entity, partition_by instead of filter-loop ----
|
|
971
977
|
else:
|
|
972
978
|
rows: list[dict[str, Any]] = []
|
|
973
979
|
for sub in df.sort(year_col).partition_by(key, maintain_order=True):
|
|
@@ -992,10 +998,15 @@ class StatsNamespace:
|
|
|
992
998
|
)
|
|
993
999
|
else:
|
|
994
1000
|
eval_sub = sub.filter(pl.col(year_col) > baseline[1])
|
|
995
|
-
|
|
996
|
-
|
|
1001
|
+
eval_sub = eval_sub.filter(pl.col(column).is_not_null())
|
|
1002
|
+
|
|
1003
|
+
eval_vals = eval_sub[column].to_numpy().astype(float)
|
|
1004
|
+
eval_years_lookup = eval_sub[
|
|
997
1005
|
year_col
|
|
998
|
-
].to_list()
|
|
1006
|
+
].to_list() # for baseline/dict matching
|
|
1007
|
+
eval_times = eval_sub[
|
|
1008
|
+
output_time_col
|
|
1009
|
+
].to_list() # for display in output
|
|
999
1010
|
|
|
1000
1011
|
ts_scores: list[float] = []
|
|
1001
1012
|
ts_flags: list[bool] = []
|
|
@@ -1013,30 +1024,42 @@ class StatsNamespace:
|
|
|
1013
1024
|
ts_flags.append(s > h)
|
|
1014
1025
|
|
|
1015
1026
|
else: # STL
|
|
1027
|
+
full = sub.filter(pl.col(column).is_not_null())
|
|
1028
|
+
full_vals = full[column].to_numpy().astype(float)
|
|
1029
|
+
full_years = full[year_col].to_list()
|
|
1030
|
+
|
|
1031
|
+
period = (
|
|
1032
|
+
26 if len(full_vals) >= 52 else max(2, len(full_vals) // 2)
|
|
1033
|
+
)
|
|
1034
|
+
min_required = 2 * period
|
|
1035
|
+
min_reliable = (
|
|
1036
|
+
3 * period
|
|
1037
|
+
) # want ~3 cycles minimum for a trustworthy seasonal fit, not just 2
|
|
1038
|
+
|
|
1039
|
+
if len(full_vals) < min_required:
|
|
1040
|
+
warnings.warn(
|
|
1041
|
+
f"StatsNamespace.anomaly: entity {eid!r} has {len(full_vals)} points, "
|
|
1042
|
+
f"period={period} needs >= {min_reliable} for a reliable STL fit. Skipping."
|
|
1043
|
+
)
|
|
1044
|
+
n_dropped += 1
|
|
1045
|
+
continue
|
|
1046
|
+
|
|
1047
|
+
if len(full_vals) < min_required:
|
|
1048
|
+
warnings.warn(
|
|
1049
|
+
f"StatsNamespace.anomaly: entity {eid!r} has {len(full_vals)} points, "
|
|
1050
|
+
f"needs >= {min_required} for period={period}. Skipping."
|
|
1051
|
+
)
|
|
1052
|
+
n_dropped += 1
|
|
1053
|
+
continue
|
|
1054
|
+
|
|
1016
1055
|
try:
|
|
1017
1056
|
from statsmodels.tsa.seasonal import STL # type: ignore[import-untyped]
|
|
1018
1057
|
|
|
1019
|
-
full = sub.filter(pl.col(column).is_not_null())
|
|
1020
|
-
full_vals = full[column].to_numpy().astype(float)
|
|
1021
|
-
full_years = full[year_col].to_list()
|
|
1022
|
-
if len(full_vals) < min_obs:
|
|
1023
|
-
n_dropped += 1
|
|
1024
|
-
continue
|
|
1025
|
-
|
|
1026
|
-
# Seasonal period: sub-annual cadence assumed 24 steps/year
|
|
1027
|
-
# (e.g. fortnightly). Falls back to half the series length
|
|
1028
|
-
# for shorter records. Adjust if your data's cadence differs.
|
|
1029
|
-
period = (
|
|
1030
|
-
24
|
|
1031
|
-
if len(full_vals) >= 24
|
|
1032
|
-
else max(2, len(full_vals) // 2)
|
|
1033
|
-
)
|
|
1034
1058
|
res = STL(full_vals, period=period).fit()
|
|
1035
1059
|
resid = res.resid
|
|
1036
1060
|
|
|
1037
|
-
# Match residuals to years EXPLICITLY
|
|
1038
|
-
#
|
|
1039
|
-
# baseline and eval rows.
|
|
1061
|
+
# Match residuals to years EXPLICITLY, not positionally —
|
|
1062
|
+
# avoids misalignment if there are gaps in the series.
|
|
1040
1063
|
resid_by_year = dict(zip(full_years, resid))
|
|
1041
1064
|
base_resid = [
|
|
1042
1065
|
resid_by_year[y]
|
|
@@ -1049,7 +1072,7 @@ class StatsNamespace:
|
|
|
1049
1072
|
float(resid_by_year[y] / std)
|
|
1050
1073
|
if y in resid_by_year
|
|
1051
1074
|
else float("nan")
|
|
1052
|
-
for y in
|
|
1075
|
+
for y in eval_years_lookup
|
|
1053
1076
|
]
|
|
1054
1077
|
ts_flags = [
|
|
1055
1078
|
abs(s) > threshold if s == s else False
|
|
@@ -1060,31 +1083,32 @@ class StatsNamespace:
|
|
|
1060
1083
|
warnings.warn(
|
|
1061
1084
|
f"StatsNamespace.anomaly: STL fit failed for entity {eid!r}: {e}"
|
|
1062
1085
|
)
|
|
1063
|
-
ts_scores = [float("nan")] * len(
|
|
1064
|
-
ts_flags = [False] * len(
|
|
1086
|
+
ts_scores = [float("nan")] * len(eval_years_lookup)
|
|
1087
|
+
ts_flags = [False] * len(eval_years_lookup)
|
|
1065
1088
|
|
|
1066
|
-
for
|
|
1089
|
+
for t, sc, fl in zip(eval_times, ts_scores, ts_flags):
|
|
1067
1090
|
rows.append(
|
|
1068
1091
|
{
|
|
1069
1092
|
key: eid,
|
|
1070
|
-
|
|
1093
|
+
output_time_col: t,
|
|
1071
1094
|
"anomaly_score": float(sc),
|
|
1072
1095
|
"is_anomaly": bool(fl),
|
|
1073
1096
|
}
|
|
1074
1097
|
)
|
|
1075
1098
|
|
|
1076
|
-
|
|
1077
|
-
pl.DataFrame(rows)
|
|
1078
|
-
|
|
1079
|
-
|
|
1099
|
+
if rows:
|
|
1100
|
+
data = pl.DataFrame(rows)
|
|
1101
|
+
else:
|
|
1102
|
+
data = pl.DataFrame(
|
|
1080
1103
|
{
|
|
1081
1104
|
key: pl.Series([], dtype=pl.String),
|
|
1082
|
-
|
|
1105
|
+
output_time_col: pl.Series(
|
|
1106
|
+
[], dtype=pl.Date if date_col else pl.Int32
|
|
1107
|
+
),
|
|
1083
1108
|
"anomaly_score": pl.Series([], dtype=pl.Float64),
|
|
1084
1109
|
"is_anomaly": pl.Series([], dtype=pl.Boolean),
|
|
1085
1110
|
}
|
|
1086
1111
|
)
|
|
1087
|
-
)
|
|
1088
1112
|
|
|
1089
1113
|
global_base_vals = (
|
|
1090
1114
|
df.filter(pl.col(year_col).is_between(baseline[0], baseline[1]))[column]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|