yirgacheffe 1.9.0__tar.gz → 1.9.2__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.
Potentially problematic release.
This version of yirgacheffe might be problematic. Click here for more details.
- {yirgacheffe-1.9.0/yirgacheffe.egg-info → yirgacheffe-1.9.2}/PKG-INFO +3 -1
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/pyproject.toml +4 -1
- yirgacheffe-1.9.0/tests/test_base.py → yirgacheffe-1.9.2/tests/test_pixel_coord.py +30 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/_operators.py +102 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/layers/base.py +0 -46
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2/yirgacheffe.egg-info}/PKG-INFO +3 -1
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe.egg-info/SOURCES.txt +1 -1
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe.egg-info/requires.txt +3 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/LICENSE +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/MANIFEST.in +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/README.md +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/setup.cfg +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_area.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_auto_windowing.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_constants.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_datatypes.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_group.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_h3layer.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_intersection.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_multiband.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_nodata.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_openers.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_operators.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_optimisation.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_parallel_operators.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_pickle.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_projection.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_raster.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_rescaling.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_rounding.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_save_with_window.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_sum_with_window.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_uniform_area_layer.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_union.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_vectors.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/tests/test_window.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/__init__.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/_backends/__init__.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/_backends/enumeration.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/_backends/mlx.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/_backends/numpy.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/_core.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/constants.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/layers/__init__.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/layers/area.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/layers/constant.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/layers/group.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/layers/h3layer.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/layers/rasters.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/layers/rescaled.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/layers/vectors.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/operators.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/py.typed +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/rounding.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe/window.py +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe.egg-info/dependency_links.txt +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe.egg-info/entry_points.txt +0 -0
- {yirgacheffe-1.9.0 → yirgacheffe-1.9.2}/yirgacheffe.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: yirgacheffe
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2
|
|
4
4
|
Summary: Abstraction of gdal datasets for doing basic math operations
|
|
5
5
|
Author-email: Michael Dales <mwd24@cam.ac.uk>
|
|
6
6
|
License-Expression: ISC
|
|
@@ -30,6 +30,8 @@ Requires-Dist: h3
|
|
|
30
30
|
Requires-Dist: pyproj
|
|
31
31
|
Provides-Extra: mlx
|
|
32
32
|
Requires-Dist: mlx; extra == "mlx"
|
|
33
|
+
Provides-Extra: matplotlib
|
|
34
|
+
Requires-Dist: matplotlib; extra == "matplotlib"
|
|
33
35
|
Provides-Extra: dev
|
|
34
36
|
Requires-Dist: mypy; extra == "dev"
|
|
35
37
|
Requires-Dist: pylint; extra == "dev"
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "yirgacheffe"
|
|
9
|
-
version = "1.9.
|
|
9
|
+
version = "1.9.2"
|
|
10
10
|
description = "Abstraction of gdal datasets for doing basic math operations"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
authors = [{ name = "Michael Dales", email = "mwd24@cam.ac.uk" }]
|
|
@@ -38,6 +38,9 @@ requires-python = ">=3.10"
|
|
|
38
38
|
mlx = [
|
|
39
39
|
"mlx",
|
|
40
40
|
]
|
|
41
|
+
matplotlib = [
|
|
42
|
+
"matplotlib",
|
|
43
|
+
]
|
|
41
44
|
dev = [
|
|
42
45
|
"mypy",
|
|
43
46
|
"pylint",
|
|
@@ -83,6 +83,21 @@ def test_latlng_for_pixel(
|
|
|
83
83
|
assert math.isclose(result[0], expected[0])
|
|
84
84
|
assert math.isclose(result[1], expected[1])
|
|
85
85
|
|
|
86
|
+
def test_latlng_for_pixel_on_operator() -> None:
|
|
87
|
+
layer1 = YirgacheffeLayer(
|
|
88
|
+
Area(-10, 10, 10, -10),
|
|
89
|
+
MapProjection("epsg:4326", 0.2, -0.2),
|
|
90
|
+
)
|
|
91
|
+
layer2 = YirgacheffeLayer(
|
|
92
|
+
Area(-10, 10, 10, -10),
|
|
93
|
+
MapProjection("epsg:4326", 0.2, -0.2),
|
|
94
|
+
)
|
|
95
|
+
calc = layer1 + layer2
|
|
96
|
+
result = calc.latlng_for_pixel(0, 0)
|
|
97
|
+
expected = (10.0, -10.0)
|
|
98
|
+
assert math.isclose(result[0], expected[0])
|
|
99
|
+
assert math.isclose(result[1], expected[1])
|
|
100
|
+
|
|
86
101
|
@pytest.mark.parametrize(
|
|
87
102
|
"area,projection,coord,expected",
|
|
88
103
|
[
|
|
@@ -119,6 +134,21 @@ def test_pixel_for_latlng(
|
|
|
119
134
|
result = layer.pixel_for_latlng(*coord)
|
|
120
135
|
assert result == expected
|
|
121
136
|
|
|
137
|
+
def test_pixel_for_latlng_on_operator() -> None:
|
|
138
|
+
layer1 = YirgacheffeLayer(
|
|
139
|
+
Area(-10, 10, 10, -10),
|
|
140
|
+
MapProjection("epsg:4326", 0.2, -0.2),
|
|
141
|
+
)
|
|
142
|
+
layer2 = YirgacheffeLayer(
|
|
143
|
+
Area(-10, 10, 10, -10),
|
|
144
|
+
MapProjection("epsg:4326", 0.2, -0.2),
|
|
145
|
+
)
|
|
146
|
+
calc = layer1 + layer2
|
|
147
|
+
result = calc.pixel_for_latlng(10, -10)
|
|
148
|
+
expected = (0, 0)
|
|
149
|
+
assert math.isclose(result[0], expected[0])
|
|
150
|
+
assert math.isclose(result[1], expected[1])
|
|
151
|
+
|
|
122
152
|
@pytest.mark.parametrize(
|
|
123
153
|
"area,window,projection,pixel,expected",
|
|
124
154
|
[
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import builtins
|
|
3
4
|
import logging
|
|
4
5
|
import math
|
|
5
6
|
import multiprocessing
|
|
@@ -21,6 +22,7 @@ import numpy as np
|
|
|
21
22
|
import numpy.typing as npt
|
|
22
23
|
from osgeo import gdal
|
|
23
24
|
from dill import dumps, loads # type: ignore
|
|
25
|
+
from pyproj import Transformer
|
|
24
26
|
|
|
25
27
|
from . import constants, __version__
|
|
26
28
|
from .rounding import round_up_pixels, round_down_pixels
|
|
@@ -290,6 +292,102 @@ class LayerMathMixin:
|
|
|
290
292
|
datatype=datatype
|
|
291
293
|
)
|
|
292
294
|
|
|
295
|
+
def latlng_for_pixel(self, x: int, y: int) -> tuple[float, float]:
|
|
296
|
+
"""Get geo coords for pixel. This is relative to the set view window.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
x: X axis position within raster
|
|
300
|
+
y: Y axis position within raster
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
A tuple containing the (latitude, longitude).
|
|
304
|
+
"""
|
|
305
|
+
projection = self.map_projection # type: ignore[attr-defined]
|
|
306
|
+
area = self.area # type: ignore[attr-defined]
|
|
307
|
+
if projection is None:
|
|
308
|
+
raise ValueError("Map has not projection space")
|
|
309
|
+
pixel_scale = projection.scale
|
|
310
|
+
coord_in_raster_space = (
|
|
311
|
+
(y * pixel_scale.ystep) + area.top,
|
|
312
|
+
(x * pixel_scale.xstep) + area.left,
|
|
313
|
+
)
|
|
314
|
+
transformer = Transformer.from_crs(projection.name, "EPSG:4326")
|
|
315
|
+
return transformer.transform(*coord_in_raster_space)
|
|
316
|
+
|
|
317
|
+
def pixel_for_latlng(self, lat: float, lng: float) -> tuple[int, int]:
|
|
318
|
+
"""Get pixel for geo coords. This is relative to the set view window.
|
|
319
|
+
Result is rounded down to nearest pixel.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
lat: Geospatial latitude in WGS84
|
|
323
|
+
lng: Geospatial longitude in WGS84
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
A tuple containing the x, y coordinates in pixel space.
|
|
327
|
+
"""
|
|
328
|
+
projection = self.map_projection # type: ignore[attr-defined]
|
|
329
|
+
area = self.area # type: ignore[attr-defined]
|
|
330
|
+
if projection is None:
|
|
331
|
+
raise ValueError("Map has not projection space")
|
|
332
|
+
|
|
333
|
+
transformer = Transformer.from_crs("EPSG:4326", projection.name)
|
|
334
|
+
x, y = transformer.transform(lng,lat)
|
|
335
|
+
|
|
336
|
+
pixel_scale = projection.scale
|
|
337
|
+
return (
|
|
338
|
+
round_down_pixels((x - area.left) / pixel_scale.xstep, builtins.abs(pixel_scale.xstep)),
|
|
339
|
+
round_down_pixels((y - area.top) / pixel_scale.ystep, builtins.abs(pixel_scale.ystep)),
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
@property
|
|
343
|
+
def window(self) -> Window:
|
|
344
|
+
raise NotImplementedError("Must be overridden by subclass")
|
|
345
|
+
|
|
346
|
+
@property
|
|
347
|
+
def area(self) -> Area:
|
|
348
|
+
raise NotImplementedError("Must be overridden by subclass")
|
|
349
|
+
|
|
350
|
+
def read_array(self, _x, _y, _w, _h):
|
|
351
|
+
raise NotImplementedError("Must be overridden by subclass")
|
|
352
|
+
|
|
353
|
+
def show(self, ax=None, max_pixels: int | None =1000, **kwargs):
|
|
354
|
+
"""Display data using matplotlib.
|
|
355
|
+
|
|
356
|
+
Args:
|
|
357
|
+
ax: Matplotlib axes object. If not provided, the default matplotlib context will be used.
|
|
358
|
+
max_pixels: How many pixels to downsample to. If None, raw pixels will be used.
|
|
359
|
+
**kwargs: Passed to matplotlib imshow.
|
|
360
|
+
|
|
361
|
+
Returns:
|
|
362
|
+
A matplotlib image.
|
|
363
|
+
"""
|
|
364
|
+
import matplotlib.pyplot as plt # pylint: disable=C0415
|
|
365
|
+
|
|
366
|
+
if ax is None:
|
|
367
|
+
ax = plt.gca()
|
|
368
|
+
|
|
369
|
+
window = self.window
|
|
370
|
+
|
|
371
|
+
raw_data = self.read_array(
|
|
372
|
+
0,
|
|
373
|
+
0,
|
|
374
|
+
window.xsize,
|
|
375
|
+
window.ysize
|
|
376
|
+
)
|
|
377
|
+
if max_pixels:
|
|
378
|
+
downsample = max(window.xsize, window.ysize) // max_pixels
|
|
379
|
+
data = raw_data[::downsample,::downsample]
|
|
380
|
+
else:
|
|
381
|
+
data = raw_data
|
|
382
|
+
area = self.area
|
|
383
|
+
extent = [
|
|
384
|
+
area.left,
|
|
385
|
+
area.right,
|
|
386
|
+
area.bottom,
|
|
387
|
+
area.top,
|
|
388
|
+
]
|
|
389
|
+
return ax.imshow(data, extent=extent, **kwargs)
|
|
390
|
+
|
|
293
391
|
|
|
294
392
|
class LayerOperation(LayerMathMixin):
|
|
295
393
|
|
|
@@ -334,6 +432,7 @@ class LayerOperation(LayerMathMixin):
|
|
|
334
432
|
self.kwargs = kwargs
|
|
335
433
|
self.window_op = window_op
|
|
336
434
|
self.buffer_padding = buffer_padding
|
|
435
|
+
self._forced_area = None
|
|
337
436
|
|
|
338
437
|
if lhs is None:
|
|
339
438
|
raise ValueError("LHS on operation should not be none")
|
|
@@ -401,6 +500,9 @@ class LayerOperation(LayerMathMixin):
|
|
|
401
500
|
return self._get_operation_area(self.map_projection)
|
|
402
501
|
|
|
403
502
|
def _get_operation_area(self, projection: MapProjection | None) -> Area:
|
|
503
|
+
if self._forced_area is not None:
|
|
504
|
+
return self._forced_area
|
|
505
|
+
|
|
404
506
|
lhs_area = self.lhs._get_operation_area(projection)
|
|
405
507
|
try:
|
|
406
508
|
rhs_area = self.rhs._get_operation_area(projection)
|
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
from typing import Any, Sequence
|
|
3
3
|
|
|
4
4
|
import deprecation
|
|
5
|
-
from pyproj import Transformer
|
|
6
5
|
|
|
7
6
|
from .. import __version__
|
|
8
7
|
from .._operators import LayerMathMixin
|
|
@@ -332,48 +331,3 @@ class YirgacheffeLayer(LayerMathMixin):
|
|
|
332
331
|
"""
|
|
333
332
|
res = self._read_array(x, y, width, height)
|
|
334
333
|
return backend.demote_array(res)
|
|
335
|
-
|
|
336
|
-
def latlng_for_pixel(self, x: int, y: int) -> tuple[float, float]:
|
|
337
|
-
"""Get geo coords for pixel. This is relative to the set view window.
|
|
338
|
-
|
|
339
|
-
Args:
|
|
340
|
-
x: X axis position within raster
|
|
341
|
-
y: Y axis position within raster
|
|
342
|
-
|
|
343
|
-
Returns:
|
|
344
|
-
A tuple containing the (latitude, longitude).
|
|
345
|
-
"""
|
|
346
|
-
projection = self.map_projection
|
|
347
|
-
if projection is None:
|
|
348
|
-
raise ValueError("Map has not projection space")
|
|
349
|
-
pixel_scale = projection.scale
|
|
350
|
-
coord_in_raster_space = (
|
|
351
|
-
(y * pixel_scale.ystep) + self.area.top,
|
|
352
|
-
(x * pixel_scale.xstep) + self.area.left,
|
|
353
|
-
)
|
|
354
|
-
transformer = Transformer.from_crs(projection.name, "EPSG:4326")
|
|
355
|
-
return transformer.transform(*coord_in_raster_space)
|
|
356
|
-
|
|
357
|
-
def pixel_for_latlng(self, lat: float, lng: float) -> tuple[int, int]:
|
|
358
|
-
"""Get pixel for geo coords. This is relative to the set view window.
|
|
359
|
-
Result is rounded down to nearest pixel.
|
|
360
|
-
|
|
361
|
-
Args:
|
|
362
|
-
lat: Geospatial latitude in WGS84
|
|
363
|
-
lng: Geospatial longitude in WGS84
|
|
364
|
-
|
|
365
|
-
Returns:
|
|
366
|
-
A tuple containing the x, y coordinates in pixel space.
|
|
367
|
-
"""
|
|
368
|
-
projection = self.map_projection
|
|
369
|
-
if projection is None:
|
|
370
|
-
raise ValueError("Map has not projection space")
|
|
371
|
-
|
|
372
|
-
transformer = Transformer.from_crs("EPSG:4326", projection.name)
|
|
373
|
-
x, y = transformer.transform(lng,lat)
|
|
374
|
-
|
|
375
|
-
pixel_scale = projection.scale
|
|
376
|
-
return (
|
|
377
|
-
round_down_pixels((x - self.area.left) / pixel_scale.xstep, abs(pixel_scale.xstep)),
|
|
378
|
-
round_down_pixels((y - self.area.top) / pixel_scale.ystep, abs(pixel_scale.ystep)),
|
|
379
|
-
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: yirgacheffe
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2
|
|
4
4
|
Summary: Abstraction of gdal datasets for doing basic math operations
|
|
5
5
|
Author-email: Michael Dales <mwd24@cam.ac.uk>
|
|
6
6
|
License-Expression: ISC
|
|
@@ -30,6 +30,8 @@ Requires-Dist: h3
|
|
|
30
30
|
Requires-Dist: pyproj
|
|
31
31
|
Provides-Extra: mlx
|
|
32
32
|
Requires-Dist: mlx; extra == "mlx"
|
|
33
|
+
Provides-Extra: matplotlib
|
|
34
|
+
Requires-Dist: matplotlib; extra == "matplotlib"
|
|
33
35
|
Provides-Extra: dev
|
|
34
36
|
Requires-Dist: mypy; extra == "dev"
|
|
35
37
|
Requires-Dist: pylint; extra == "dev"
|
|
@@ -4,7 +4,6 @@ README.md
|
|
|
4
4
|
pyproject.toml
|
|
5
5
|
tests/test_area.py
|
|
6
6
|
tests/test_auto_windowing.py
|
|
7
|
-
tests/test_base.py
|
|
8
7
|
tests/test_constants.py
|
|
9
8
|
tests/test_datatypes.py
|
|
10
9
|
tests/test_group.py
|
|
@@ -17,6 +16,7 @@ tests/test_operators.py
|
|
|
17
16
|
tests/test_optimisation.py
|
|
18
17
|
tests/test_parallel_operators.py
|
|
19
18
|
tests/test_pickle.py
|
|
19
|
+
tests/test_pixel_coord.py
|
|
20
20
|
tests/test_projection.py
|
|
21
21
|
tests/test_raster.py
|
|
22
22
|
tests/test_rescaling.py
|
|
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
|