sciveo 0.1.30__tar.gz → 0.1.32__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.
Files changed (132) hide show
  1. {sciveo-0.1.30 → sciveo-0.1.32}/PKG-INFO +1 -1
  2. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/ml/evaluation/object_detection.py +67 -27
  3. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/logger.py +5 -1
  4. sciveo-0.1.32/sciveo/version.py +2 -0
  5. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo.egg-info/PKG-INFO +1 -1
  6. sciveo-0.1.30/sciveo/version.py +0 -2
  7. {sciveo-0.1.30 → sciveo-0.1.32}/README.md +0 -0
  8. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/__init__.py +0 -0
  9. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/api/__init__.py +0 -0
  10. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/api/base.py +0 -0
  11. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/api/upload.py +0 -0
  12. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/cli.py +0 -0
  13. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/common/__init__.py +0 -0
  14. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/common/configuration.py +0 -0
  15. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/common/model.py +0 -0
  16. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/common/optimizers.py +0 -0
  17. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/common/sampling.py +0 -0
  18. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/content/__init__.py +0 -0
  19. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/content/dataset.py +0 -0
  20. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/content/experiment.py +0 -0
  21. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/content/project.py +0 -0
  22. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/content/runner.py +0 -0
  23. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/__init__.py +0 -0
  24. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/__init__.py +0 -0
  25. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/base.py +0 -0
  26. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/encoders/__init__.py +0 -0
  27. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/encoders/base.py +0 -0
  28. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/encoders/normalizer.py +0 -0
  29. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/nlp/__init__.py +0 -0
  30. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/nlp/search.py +0 -0
  31. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/time_series/__init__.py +0 -0
  32. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/time_series/dataset.py +0 -0
  33. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/time_series/predictor.py +0 -0
  34. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/time_series/trainer.py +0 -0
  35. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/ml/time_series/window_generator.py +0 -0
  36. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/__init__.py +0 -0
  37. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/base.py +0 -0
  38. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/job_daemon.py +0 -0
  39. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/layouts/__init__.py +0 -0
  40. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/layouts/base.py +0 -0
  41. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/pipeline.py +0 -0
  42. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/postprocessors/__init__.py +0 -0
  43. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/postprocessors/base.py +0 -0
  44. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/postprocessors/default.py +0 -0
  45. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/__init__.py +0 -0
  46. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/audio/__init__.py +0 -0
  47. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/audio/audio.py +0 -0
  48. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/audio/audio_extractor_process.py +0 -0
  49. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/aws.py +0 -0
  50. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/base.py +0 -0
  51. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/file/__init__.py +0 -0
  52. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/file/archive.py +0 -0
  53. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/__init__.py +0 -0
  54. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/album.py +0 -0
  55. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/album_in_image.py +0 -0
  56. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/depth_esimation.py +0 -0
  57. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/embeddings.py +0 -0
  58. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/filters.py +0 -0
  59. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/generators.py +0 -0
  60. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/histogram.py +0 -0
  61. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/mask.py +0 -0
  62. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/resize.py +0 -0
  63. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/segmentation.py +0 -0
  64. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/image/watermark.py +0 -0
  65. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/media_info.py +0 -0
  66. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/nlp/__init__.py +0 -0
  67. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/nlp/address.py +0 -0
  68. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/qr.py +0 -0
  69. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/sci/__init__.py +0 -0
  70. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/sci/base.py +0 -0
  71. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/sci/dataset.py +0 -0
  72. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/sci/time_series/__init__.py +0 -0
  73. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/sci/time_series/predictor.py +0 -0
  74. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/sci/time_series/trainer.py +0 -0
  75. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/tpu_base.py +0 -0
  76. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/video/__init__.py +0 -0
  77. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/video/generators.py +0 -0
  78. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/video/motion_detection.py +0 -0
  79. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/video/resize.py +0 -0
  80. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/video/video_album.py +0 -0
  81. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/video/video_frames.py +0 -0
  82. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/processors/video/video_resample.py +0 -0
  83. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/queues.py +0 -0
  84. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/server.py +0 -0
  85. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/web/__init__.py +0 -0
  86. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/media/pipelines/web/server.py +0 -0
  87. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/ml/__init__.py +0 -0
  88. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/ml/evaluation/__init__.py +0 -0
  89. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/ml/images/__init__.py +0 -0
  90. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/ml/images/object_detection.py +0 -0
  91. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/ml/images/tools.py +0 -0
  92. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/ml/images/transforms.py +0 -0
  93. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/ml/nlp/__init__.py +0 -0
  94. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/monitoring/__init__.py +0 -0
  95. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/monitoring/monitor.py +0 -0
  96. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/monitoring/start.py +0 -0
  97. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/network/__init__.py +0 -0
  98. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/network/camera.py +0 -0
  99. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/network/sniffer.py +0 -0
  100. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/network/tools.py +0 -0
  101. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/__init__.py +0 -0
  102. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/array.py +0 -0
  103. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/aws/__init__.py +0 -0
  104. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/aws/priority_queue.py +0 -0
  105. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/aws/s3.py +0 -0
  106. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/common.py +0 -0
  107. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/compress.py +0 -0
  108. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/configuration.py +0 -0
  109. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/crypto.py +0 -0
  110. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/daemon.py +0 -0
  111. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/formating.py +0 -0
  112. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/hardware.py +0 -0
  113. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/http.py +0 -0
  114. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/os.py +0 -0
  115. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/random.py +0 -0
  116. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/remote.py +0 -0
  117. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/simple_counter.py +0 -0
  118. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/synchronized.py +0 -0
  119. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo/tools/timers.py +0 -0
  120. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo.egg-info/SOURCES.txt +0 -0
  121. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo.egg-info/dependency_links.txt +0 -0
  122. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo.egg-info/entry_points.txt +0 -0
  123. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo.egg-info/requires.txt +0 -0
  124. {sciveo-0.1.30 → sciveo-0.1.32}/sciveo.egg-info/top_level.txt +0 -0
  125. {sciveo-0.1.30 → sciveo-0.1.32}/setup.cfg +0 -0
  126. {sciveo-0.1.30 → sciveo-0.1.32}/setup.py +0 -0
  127. {sciveo-0.1.30 → sciveo-0.1.32}/test/test_compress.py +0 -0
  128. {sciveo-0.1.30 → sciveo-0.1.32}/test/test_configuration.py +0 -0
  129. {sciveo-0.1.30 → sciveo-0.1.32}/test/test_crypto.py +0 -0
  130. {sciveo-0.1.30 → sciveo-0.1.32}/test/test_monitoring.py +0 -0
  131. {sciveo-0.1.30 → sciveo-0.1.32}/test/test_runner.py +0 -0
  132. {sciveo-0.1.30 → sciveo-0.1.32}/test/test_sampling.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sciveo
3
- Version: 0.1.30
3
+ Version: 0.1.32
4
4
  Description-Content-Type: text/markdown
5
5
  Provides-Extra: mon
6
6
  Provides-Extra: net
@@ -21,6 +21,10 @@ from sciveo.ml.images.object_detection import *
21
21
 
22
22
  Object Detection Evaluation
23
23
 
24
+ Using AP and FP for object detector evaluation.
25
+ Need to define max allowed false positives (for example 0.03).
26
+ Usually max AP has relatively high FP rate, so maxing FP is on lower AP.
27
+
24
28
  """
25
29
  class EvalObjectDetection:
26
30
  def __init__(self, predictions, labels, class_names):
@@ -79,8 +83,7 @@ class EvalObjectDetection:
79
83
 
80
84
  return inter_area / union_area
81
85
 
82
- # Compute the Average Precision (AP)
83
- def compute_ap(self, class_name, iou_threshold=0.0):
86
+ def compute_ap(self, class_name, confidence_threshold=0.0):
84
87
  """
85
88
  Calculate the Average Precision based on IoU and confidence scores.
86
89
  Returns the AP for the current class.
@@ -89,7 +92,6 @@ class EvalObjectDetection:
89
92
  count_labels = 0
90
93
  true_positives = []
91
94
  false_positives = []
92
- false_negatives = []
93
95
  detected = []
94
96
 
95
97
  for i, prediction in enumerate(self.converted_predictions):
@@ -97,9 +99,11 @@ class EvalObjectDetection:
97
99
  current_labels = self.converted_labels[i].get(class_name, [])
98
100
 
99
101
  count_labels += len(current_labels)
100
- TP = 0
101
102
 
102
103
  for prediction_box in current_predictions:
104
+ if prediction_box[4] < confidence_threshold:
105
+ continue
106
+
103
107
  max_iou = 0
104
108
  gt_match = None
105
109
 
@@ -109,55 +113,91 @@ class EvalObjectDetection:
109
113
  max_iou = iou
110
114
  gt_match = label_box
111
115
 
112
- if max_iou >= iou_threshold and gt_match not in detected:
116
+ if gt_match is not None and gt_match not in detected:
113
117
  true_positives.append(1)
114
118
  false_positives.append(0)
115
119
  detected.append(gt_match)
116
- TP += 1
117
120
  else:
118
121
  true_positives.append(0)
119
122
  false_positives.append(1)
120
123
 
121
- FN = len(current_labels) - TP
122
- false_negatives.append(FN)
123
-
124
- # Convert to cumulative sums
125
124
  tp_cumsum = np.cumsum(true_positives)
126
125
  fp_cumsum = np.cumsum(false_positives)
127
126
 
128
- # Compute recall and precision
129
- recall = tp_cumsum / count_labels
130
- precision = tp_cumsum / (tp_cumsum + fp_cumsum)
127
+ recall = tp_cumsum / (count_labels + 1e-20)
128
+ precision = tp_cumsum / (tp_cumsum + fp_cumsum + 1e-20)
129
+
130
+ FP = np.sum(false_positives) / (count_labels + 1e-20)
131
131
 
132
132
  # Compute AP using the trapezoidal rule (integrating precision over recall)
133
133
  ap = np.trapz(precision, recall)
134
- return ap, np.sum(false_negatives) / count_labels
134
+ return ap, FP
135
135
 
136
- def threshold(self, class_name, max_false_negative):
136
+ # TODO: Use simple gradient-based threshold optimisation instead of current grid search.
137
+ def calc_thresholds(self, class_name):
137
138
  list_ap = []
138
- list_fn = []
139
+ list_FP = []
139
140
  list_thresholds = np.linspace(0.0, 1.0, 101).tolist()
140
- for i, iou_threshold in enumerate(list_thresholds):
141
- ap, FN = self.compute_ap(class_name, iou_threshold)
142
- #debug("AP", ap, "FN", FN)
143
- if FN > max_false_negative:
144
- ap = 0.0
141
+ for i, threshold in enumerate(list_thresholds):
142
+ ap, FP = self.compute_ap(class_name, threshold)
145
143
  list_ap.append(ap)
146
- list_fn.append(FN)
144
+ list_FP.append(FP)
145
+ if i % 10 == 0:
146
+ debug(class_name, "threshold", threshold, "ap", ap, "FP", FP)
147
+ return list_thresholds, list_ap, list_FP
148
+
149
+ def threshold(self, class_name, list_thresholds, list_ap, list_FP, max_fp=0.05):
147
150
  idx = list_ap.index(max(list_ap))
148
- debug("Threshold", class_name, list_thresholds[idx], "AP", list_ap[idx], "FN", list_fn[idx])
149
- return list_thresholds[idx], list_ap[idx], list_fn[idx]
151
+ if list_FP[idx] <= max_fp:
152
+ return list_thresholds[idx]
153
+
154
+ for i in range(len(list_thresholds)):
155
+ if list_FP[i] <= max_fp:
156
+ debug("Threshold", class_name, list_thresholds[i], "AP", list_ap[i], "max_fp", max_fp, "FP", list_FP[i])
157
+ idx = i
158
+ break
159
+
160
+ return list_thresholds[idx]
161
+
162
+ def thresholds(self):
163
+ """
164
+ Calculate best confidence thresholds for every class.
165
+ Predictions should be non-thresholded.
166
+ Thresholds precission is 1/100.
167
+ """
168
+
169
+ result = {}
170
+ list_thresholds = {}
171
+ list_ap = {}
172
+ list_FP = {}
173
+
174
+ for class_name in self.class_names:
175
+ list_thresholds[class_name], list_ap[class_name], list_FP[class_name] = self.calc_thresholds(class_name)
176
+ idx = list_ap[class_name].index(max(list_ap[class_name]))
177
+ debug("Threshold", class_name, list_thresholds[class_name][idx], "max AP", list_ap[class_name][idx])
150
178
 
151
- def evaluate(self, iou_thresholds={"default": 0.0}):
179
+ for max_fp in [0.01, 0.03, 0.05, 0.1]:
180
+ result[max_fp] = {"default": 0.5}
181
+ for class_name in self.class_names:
182
+ class_threshold = self.threshold(class_name, list_thresholds[class_name], list_ap[class_name], list_FP[class_name], max_fp)
183
+ result[max_fp][class_name] = class_threshold
184
+
185
+ return result
186
+
187
+ def evaluate(self, confidence_thresholds={"default": 0.0}):
152
188
  """
153
189
  Calculate metrics like mAP based on IoU.
154
190
  """
191
+
155
192
  aps = []
156
193
  class_ap = {}
194
+ class_FP = {}
195
+
157
196
  for class_name in self.class_names:
158
- ap, false_negatives = self.compute_ap(class_name, iou_thresholds.get(class_name, iou_thresholds["default"]))
197
+ ap, FP = self.compute_ap(class_name, confidence_thresholds.get(class_name, confidence_thresholds["default"]))
159
198
  aps.append(ap)
160
199
  class_ap[class_name] = ap
200
+ class_FP[class_name] = FP
161
201
 
162
202
  mAP = np.mean(aps)
163
- return {'mAP': mAP, 'AP per class': class_ap}
203
+ return {'mAP': mAP, 'AP per class': class_ap, "FP per class": class_FP}
@@ -28,7 +28,11 @@ def _sciveo_get_logger(name):
28
28
  if not logger.hasHandlers():
29
29
  with _sciveo_log_lock:
30
30
  if not logger.hasHandlers():
31
- logger.setLevel(logging.getLevelName(_sciveo_log_min_level))
31
+ log_min_level = logging.getLevelName(_sciveo_log_min_level)
32
+ if log_min_level.startswith("Level"):
33
+ log_min_level = "DEBUG"
34
+ logger.setLevel(log_min_level)
35
+
32
36
  formatter = logging.Formatter('%(asctime)s [%(thread)d] [%(levelname)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
33
37
  ch = logging.StreamHandler()
34
38
  ch.setFormatter(formatter)
@@ -0,0 +1,2 @@
1
+
2
+ __version__ = '0.1.32'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sciveo
3
- Version: 0.1.30
3
+ Version: 0.1.32
4
4
  Description-Content-Type: text/markdown
5
5
  Provides-Extra: mon
6
6
  Provides-Extra: net
@@ -1,2 +0,0 @@
1
-
2
- __version__ = '0.1.30'
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