water-column-sonar-processing 0.0.10__tar.gz → 0.0.11__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 water-column-sonar-processing might be problematic. Click here for more details.
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/PKG-INFO +1 -1
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/pyproject.toml +1 -1
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_raw_to_zarr.py +7 -6
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/aws/dynamodb_manager.py +15 -11
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/processing/raw_to_zarr.py +23 -13
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing.egg-info/PKG-INFO +1 -1
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/.env-test +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/.github/workflows/test_action.yaml +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/.gitignore +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/.pre-commit-config.yaml +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/.python-version +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/LICENSE +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/README.md +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/open-science-data-federation/ml/autoencoder_example.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/open-science-data-federation/osdf_examples/foo.ipynb +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/open-science-data-federation/osdf_examples/sonar_ai.ipynb +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/pytest.ini +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/requirements.txt +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/requirements_dev.txt +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/setup.cfg +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/conftest.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/example_input_bucket/example_directory/foo.txt +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_create_empty_zarr_store.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_dynamodb_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_geometry_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_geometry_simplification.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_index.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_pmtile_generation.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_process.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_resample_regrid.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_resources/index/calibrated_cruises.csv +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_resources/raw_to_zarr/D20070724-T042400.bot +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_resources/raw_to_zarr/D20070724-T042400.idx +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_resources/raw_to_zarr/D20070724-T042400.raw +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_s3_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_s3fs_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_s3fs_with_moto.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_sns_sqs_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_zarr_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/__init__.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/aws/__init__.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/aws/s3_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/aws/s3fs_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/aws/sns_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/aws/sqs_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/cruise/__init__.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/cruise/create_empty_zarr_store.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/cruise/resample_regrid.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/geometry/__init__.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/geometry/geometry_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/geometry/geometry_simplification.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/geometry/pmtile_generation.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/index/__init__.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/index/index_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/model/__init__.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/model/zarr_manager.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/process.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/processing/__init__.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/processing/cruise_sampler.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/utility/__init__.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/utility/cleaner.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/utility/constants.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/utility/pipeline_status.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing/utility/timestamp.py +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing.egg-info/SOURCES.txt +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing.egg-info/dependency_links.txt +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing.egg-info/requires.txt +0 -0
- {water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/water_column_sonar_processing.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: water_column_sonar_processing
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.11
|
|
4
4
|
Summary: A processing tool for water column sonar data.
|
|
5
5
|
Author-email: Rudy Klucik <rudy.klucik@noaa.gov>
|
|
6
6
|
Project-URL: Homepage, https://github.com/CI-CMG/water-column-sonar-processing
|
|
@@ -115,17 +115,18 @@ def test_raw_to_zarr(raw_to_zarr_test_path):
|
|
|
115
115
|
# file_name = "D20070711-T182032.raw"
|
|
116
116
|
#file_name = "D20070720-T224031.raw" # 84 KB
|
|
117
117
|
raw_file_name = "D20070724-T042400.raw" # 1 MB use this for testing
|
|
118
|
-
bottom_file_name = f"{Path(raw_file_name).stem}.bot"
|
|
118
|
+
# bottom_file_name = f"{Path(raw_file_name).stem}.bot"
|
|
119
119
|
|
|
120
120
|
# TODO: move this into the raw_to_zarr function
|
|
121
|
-
s3_file_path = f"data/raw/{ship_name}/{cruise_name}/{sensor_name}/{raw_file_name}"
|
|
122
|
-
s3_bottom_file_path = f"data/raw/{ship_name}/{cruise_name}/{sensor_name}/{bottom_file_name}"
|
|
123
|
-
s3_manager.download_file(bucket_name=input_bucket_name, key=s3_file_path, file_name=raw_file_name)
|
|
124
|
-
s3_manager.download_file(bucket_name=input_bucket_name, key=s3_bottom_file_path, file_name=bottom_file_name)
|
|
121
|
+
# s3_file_path = f"data/raw/{ship_name}/{cruise_name}/{sensor_name}/{raw_file_name}"
|
|
122
|
+
# s3_bottom_file_path = f"data/raw/{ship_name}/{cruise_name}/{sensor_name}/{bottom_file_name}"
|
|
123
|
+
# s3_manager.download_file(bucket_name=input_bucket_name, key=s3_file_path, file_name=raw_file_name)
|
|
124
|
+
# s3_manager.download_file(bucket_name=input_bucket_name, key=s3_bottom_file_path, file_name=bottom_file_name)
|
|
125
125
|
|
|
126
126
|
raw_to_zarr = RawToZarr()
|
|
127
127
|
raw_to_zarr.raw_to_zarr(
|
|
128
128
|
table_name=table_name,
|
|
129
|
+
input_bucket_name=input_bucket_name,
|
|
129
130
|
output_bucket_name=output_bucket_name,
|
|
130
131
|
ship_name=ship_name,
|
|
131
132
|
cruise_name=cruise_name,
|
|
@@ -136,7 +137,7 @@ def test_raw_to_zarr(raw_to_zarr_test_path):
|
|
|
136
137
|
# TODO: test if zarr store is accessible in the s3 bucket
|
|
137
138
|
number_of_files = s3_manager.list_objects(bucket_name=output_bucket_name, prefix=f"level_1/{ship_name}/{cruise_name}/{sensor_name}/")
|
|
138
139
|
# Ensure that all the files were uploaded properly
|
|
139
|
-
assert len(number_of_files) ==
|
|
140
|
+
assert len(number_of_files) == 72
|
|
140
141
|
|
|
141
142
|
# TODO: check the dynamodb dataframe to see if info is updated there
|
|
142
143
|
# ---Verify Data is Populated in Table--- #
|
|
@@ -111,17 +111,21 @@ class DynamoDBManager:
|
|
|
111
111
|
expression_attribute_names,
|
|
112
112
|
expression_attribute_values,
|
|
113
113
|
update_expression,
|
|
114
|
-
):
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
114
|
+
): # TODO: convert to boolean
|
|
115
|
+
try:
|
|
116
|
+
response = self.__dynamodb_client.update_item(
|
|
117
|
+
TableName=table_name,
|
|
118
|
+
Key=key,
|
|
119
|
+
ExpressionAttributeNames=expression_attribute_names,
|
|
120
|
+
ExpressionAttributeValues=expression_attribute_values,
|
|
121
|
+
UpdateExpression=update_expression,
|
|
122
|
+
)
|
|
123
|
+
status_code = response["ResponseMetadata"]["HTTPStatusCode"]
|
|
124
|
+
print(f"HTTPStatusCode: {status_code}")
|
|
125
|
+
# assert status_code == 200, "Problem, unable to update dynamodb table."
|
|
126
|
+
# assert response['ConsumedCapacity']['TableName'] == table_name
|
|
127
|
+
except Exception as err:
|
|
128
|
+
print(f"Problem was encountered while updating item: {err}")
|
|
125
129
|
|
|
126
130
|
#####################################################################
|
|
127
131
|
# TODO: change to "get_cruise_as_df"
|
|
@@ -9,7 +9,7 @@ from pathlib import Path # , PurePath
|
|
|
9
9
|
|
|
10
10
|
from water_column_sonar_processing.aws import DynamoDBManager, S3Manager
|
|
11
11
|
from water_column_sonar_processing.geometry import GeometryManager
|
|
12
|
-
from water_column_sonar_processing.utility import Cleaner
|
|
12
|
+
from water_column_sonar_processing.utility import Cleaner, PipelineStatus
|
|
13
13
|
|
|
14
14
|
TEMPDIR = "/tmp"
|
|
15
15
|
|
|
@@ -53,10 +53,6 @@ class RawToZarr:
|
|
|
53
53
|
):
|
|
54
54
|
print('Writing Zarr information to DynamoDB table.')
|
|
55
55
|
dynamodb_manager = DynamoDBManager()
|
|
56
|
-
|
|
57
|
-
# The problem is that these values were never populated
|
|
58
|
-
# and so when the query looks for values that aren't there
|
|
59
|
-
# they fail
|
|
60
56
|
dynamodb_manager.update_item(
|
|
61
57
|
table_name=table_name,
|
|
62
58
|
key={
|
|
@@ -87,7 +83,8 @@ class RawToZarr:
|
|
|
87
83
|
":ma": {"N": str(np.round(max_echo_range, 4))},
|
|
88
84
|
":mi": {"N": str(np.round(min_echo_range, 4))},
|
|
89
85
|
":nd": {"N": str(num_ping_time_dropna)},
|
|
90
|
-
":ps": {"S": "PROCESSING_RESAMPLE_AND_WRITE_TO_ZARR_STORE"},
|
|
86
|
+
# ":ps": {"S": "PROCESSING_RESAMPLE_AND_WRITE_TO_ZARR_STORE"},
|
|
87
|
+
":ps": {"S": PipelineStatus.LEVEL_1_PROCESSING.name},
|
|
91
88
|
":pt": {"S": datetime.now().isoformat(timespec="seconds") + "Z"},
|
|
92
89
|
":se": {"S": sensor_name},
|
|
93
90
|
":sh": {"S": ship_name},
|
|
@@ -113,6 +110,7 @@ class RawToZarr:
|
|
|
113
110
|
"#ZP = :zp"
|
|
114
111
|
),
|
|
115
112
|
)
|
|
113
|
+
print('Done writing Zarr information to DynamoDB table.')
|
|
116
114
|
|
|
117
115
|
############################################################################
|
|
118
116
|
############################################################################
|
|
@@ -143,6 +141,7 @@ class RawToZarr:
|
|
|
143
141
|
def raw_to_zarr(
|
|
144
142
|
self,
|
|
145
143
|
table_name,
|
|
144
|
+
input_bucket_name,
|
|
146
145
|
output_bucket_name,
|
|
147
146
|
ship_name,
|
|
148
147
|
cruise_name,
|
|
@@ -157,6 +156,14 @@ class RawToZarr:
|
|
|
157
156
|
geometry_manager = GeometryManager()
|
|
158
157
|
cleaner = Cleaner()
|
|
159
158
|
cleaner.delete_local_files(file_types=["*.zarr", "*.json"]) # TODO: include bot and raw?
|
|
159
|
+
|
|
160
|
+
s3_manager = S3Manager()
|
|
161
|
+
s3_file_path = f"data/raw/{ship_name}/{cruise_name}/{sensor_name}/{raw_file_name}"
|
|
162
|
+
bottom_file_name = f"{Path(raw_file_name).stem}.bot"
|
|
163
|
+
s3_bottom_file_path = f"data/raw/{ship_name}/{cruise_name}/{sensor_name}/{bottom_file_name}"
|
|
164
|
+
s3_manager.download_file(bucket_name=input_bucket_name, key=s3_file_path, file_name=raw_file_name)
|
|
165
|
+
s3_manager.download_file(bucket_name=input_bucket_name, key=s3_bottom_file_path, file_name=bottom_file_name)
|
|
166
|
+
|
|
160
167
|
try:
|
|
161
168
|
gc.collect()
|
|
162
169
|
print('Opening raw file with echopype.')
|
|
@@ -172,7 +179,12 @@ class RawToZarr:
|
|
|
172
179
|
)
|
|
173
180
|
print('Compute volume backscattering strength (Sv) from raw data.')
|
|
174
181
|
ds_sv = ep.calibrate.compute_Sv(echodata)
|
|
175
|
-
print('Done computing volume
|
|
182
|
+
print('Done computing volume backscatter strength (Sv) from raw data.')
|
|
183
|
+
# Note: detected_seafloor_depth is located at echodata.vendor.detected_seafloor_depth
|
|
184
|
+
# but is not written out with ds_sv
|
|
185
|
+
if "detected_seafloor_depth" in list(echodata.vendor.variables):
|
|
186
|
+
ds_sv["detected_seafloor_depth"] = echodata.vendor.detected_seafloor_depth
|
|
187
|
+
#
|
|
176
188
|
frequencies = echodata.environment.frequency_nominal.values
|
|
177
189
|
#################################################################
|
|
178
190
|
# Get GPS coordinates
|
|
@@ -191,12 +203,9 @@ class RawToZarr:
|
|
|
191
203
|
# TODO: this var name is supposed to represent minimum resolution of depth measurements
|
|
192
204
|
# TODO revert this so that smaller diffs can be used
|
|
193
205
|
# The most minimum the resolution can be is as small as 0.25 meters
|
|
194
|
-
min_echo_range = np.
|
|
195
|
-
0.25,
|
|
196
|
-
np.nanmin(np.diff(ds_sv.echo_range.values))
|
|
197
|
-
)
|
|
206
|
+
min_echo_range = np.round(np.nanmin(np.diff(ds_sv.echo_range.values)), 2)
|
|
198
207
|
max_echo_range = float(np.nanmax(ds_sv.echo_range))
|
|
199
|
-
#
|
|
208
|
+
# This is the number of missing values found throughout the lat/lon
|
|
200
209
|
num_ping_time_dropna = lat[~np.isnan(lat)].shape[0] # symmetric to lon
|
|
201
210
|
#
|
|
202
211
|
start_time = np.datetime_as_string(ds_sv.ping_time.values[0], unit='ms') + "Z"
|
|
@@ -248,11 +257,12 @@ class RawToZarr:
|
|
|
248
257
|
#######################################################################
|
|
249
258
|
# TODO: verify count of objects matches, publish message, update status
|
|
250
259
|
#######################################################################
|
|
251
|
-
print('
|
|
260
|
+
print('Finished raw-to-zarr conversion.')
|
|
252
261
|
except Exception as err:
|
|
253
262
|
print(f'Exception encountered creating local Zarr store with echopype: {err}')
|
|
254
263
|
raise RuntimeError(f"Problem creating local Zarr store, {err}")
|
|
255
264
|
finally:
|
|
265
|
+
print("Finally.")
|
|
256
266
|
cleaner.delete_local_files(file_types=["*.raw", "*.bot", "*.zarr", "*.json"])
|
|
257
267
|
print('Done creating local zarr store.')
|
|
258
268
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: water_column_sonar_processing
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.11
|
|
4
4
|
Summary: A processing tool for water column sonar data.
|
|
5
5
|
Author-email: Rudy Klucik <rudy.klucik@noaa.gov>
|
|
6
6
|
Project-URL: Homepage, https://github.com/CI-CMG/water-column-sonar-processing
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/.python-version
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/requirements.txt
RENAMED
|
File without changes
|
{water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/requirements_dev.txt
RENAMED
|
File without changes
|
|
File without changes
|
{water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/conftest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_index.py
RENAMED
|
File without changes
|
|
File without changes
|
{water_column_sonar_processing-0.0.10 → water_column_sonar_processing-0.0.11}/tests/test_process.py
RENAMED
|
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
|