AeroViz 0.1.9.4__tar.gz → 0.1.9.6__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 AeroViz might be problematic. Click here for more details.

Files changed (181) hide show
  1. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/__init__.py +1 -2
  2. aeroviz-0.1.9.6/AeroViz/__pycache__/__init__.cpython-312.pyc +0 -0
  3. aeroviz-0.1.9.6/AeroViz/dataProcess/Chemistry/__pycache__/__init__.cpython-312.pyc +0 -0
  4. {aeroviz-0.1.9.4/AeroViz/plot/optical → aeroviz-0.1.9.6/AeroViz/dataProcess/Optical}/PyMieScatt_update.py +4 -11
  5. aeroviz-0.1.9.6/AeroViz/dataProcess/Optical/__pycache__/PyMieScatt_update.cpython-312.pyc +0 -0
  6. aeroviz-0.1.9.6/AeroViz/dataProcess/Optical/__pycache__/__init__.cpython-312.pyc +0 -0
  7. aeroviz-0.1.9.6/AeroViz/dataProcess/Optical/__pycache__/mie_theory.cpython-312.pyc +0 -0
  8. aeroviz-0.1.9.6/AeroViz/dataProcess/SizeDistr/__pycache__/__init__.cpython-312.pyc +0 -0
  9. aeroviz-0.1.9.6/AeroViz/dataProcess/SizeDistr/prop.py +62 -0
  10. aeroviz-0.1.9.6/AeroViz/dataProcess/VOC/__pycache__/__init__.cpython-312.pyc +0 -0
  11. aeroviz-0.1.9.6/AeroViz/dataProcess/__pycache__/__init__.cpython-312.pyc +0 -0
  12. aeroviz-0.1.9.6/AeroViz/dataProcess/core/__pycache__/__init__.cpython-312.pyc +0 -0
  13. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/__init__.py +0 -1
  14. aeroviz-0.1.9.6/AeroViz/plot/__pycache__/__init__.cpython-312.pyc +0 -0
  15. aeroviz-0.1.9.6/AeroViz/plot/__pycache__/bar.cpython-312.pyc +0 -0
  16. aeroviz-0.1.9.6/AeroViz/plot/__pycache__/box.cpython-312.pyc +0 -0
  17. aeroviz-0.1.9.6/AeroViz/plot/__pycache__/pie.cpython-312.pyc +0 -0
  18. aeroviz-0.1.9.6/AeroViz/plot/__pycache__/radar.cpython-312.pyc +0 -0
  19. aeroviz-0.1.9.6/AeroViz/plot/__pycache__/regression.cpython-312.pyc +0 -0
  20. aeroviz-0.1.9.6/AeroViz/plot/__pycache__/scatter.cpython-312.pyc +0 -0
  21. aeroviz-0.1.9.6/AeroViz/plot/__pycache__/violin.cpython-312.pyc +0 -0
  22. aeroviz-0.1.9.6/AeroViz/plot/distribution/__pycache__/__init__.cpython-312.pyc +0 -0
  23. aeroviz-0.1.9.6/AeroViz/plot/distribution/__pycache__/distribution.cpython-312.pyc +0 -0
  24. aeroviz-0.1.9.4/AeroViz/plot/meteorology/meteorology.py → aeroviz-0.1.9.6/AeroViz/plot/meteorology/CBPF.py +150 -122
  25. aeroviz-0.1.9.6/AeroViz/plot/meteorology/__init__.py +3 -0
  26. aeroviz-0.1.9.6/AeroViz/plot/meteorology/__pycache__/CBPF.cpython-312.pyc +0 -0
  27. aeroviz-0.1.9.6/AeroViz/plot/meteorology/__pycache__/__init__.cpython-312.pyc +0 -0
  28. aeroviz-0.1.9.6/AeroViz/plot/meteorology/__pycache__/hysplit.cpython-312.pyc +0 -0
  29. aeroviz-0.1.9.6/AeroViz/plot/meteorology/__pycache__/wind_rose.cpython-312.pyc +0 -0
  30. aeroviz-0.1.9.6/AeroViz/plot/meteorology/wind_rose.py +77 -0
  31. aeroviz-0.1.9.6/AeroViz/plot/optical/__pycache__/__init__.cpython-312.pyc +0 -0
  32. aeroviz-0.1.9.6/AeroViz/plot/optical/__pycache__/optical.cpython-312.pyc +0 -0
  33. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/optical/optical.py +2 -3
  34. aeroviz-0.1.9.6/AeroViz/plot/templates/__pycache__/__init__.cpython-312.pyc +0 -0
  35. aeroviz-0.1.9.6/AeroViz/plot/templates/__pycache__/ammonium_rich.cpython-312.pyc +0 -0
  36. aeroviz-0.1.9.6/AeroViz/plot/templates/__pycache__/contour.cpython-312.pyc +0 -0
  37. aeroviz-0.1.9.6/AeroViz/plot/templates/__pycache__/corr_matrix.cpython-312.pyc +0 -0
  38. aeroviz-0.1.9.6/AeroViz/plot/templates/__pycache__/diurnal_pattern.cpython-312.pyc +0 -0
  39. aeroviz-0.1.9.6/AeroViz/plot/templates/__pycache__/koschmieder.cpython-312.pyc +0 -0
  40. aeroviz-0.1.9.6/AeroViz/plot/templates/__pycache__/metal_heatmap.cpython-312.pyc +0 -0
  41. aeroviz-0.1.9.6/AeroViz/plot/timeseries/__pycache__/__init__.cpython-312.pyc +0 -0
  42. aeroviz-0.1.9.6/AeroViz/plot/timeseries/__pycache__/template.cpython-312.pyc +0 -0
  43. aeroviz-0.1.9.6/AeroViz/plot/timeseries/__pycache__/timeseries.cpython-312.pyc +0 -0
  44. aeroviz-0.1.9.6/AeroViz/plot/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  45. aeroviz-0.1.9.6/AeroViz/plot/utils/__pycache__/_color.cpython-312.pyc +0 -0
  46. aeroviz-0.1.9.6/AeroViz/plot/utils/__pycache__/_unit.cpython-312.pyc +0 -0
  47. aeroviz-0.1.9.6/AeroViz/plot/utils/__pycache__/plt_utils.cpython-312.pyc +0 -0
  48. aeroviz-0.1.9.6/AeroViz/plot/utils/__pycache__/sklearn_utils.cpython-312.pyc +0 -0
  49. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/utils/plt_utils.py +1 -1
  50. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/__init__.py +4 -2
  51. aeroviz-0.1.9.6/AeroViz/rawDataReader/__pycache__/__init__.cpython-312.pyc +0 -0
  52. aeroviz-0.1.9.6/AeroViz/rawDataReader/config/__pycache__/__init__.cpython-312.pyc +0 -0
  53. aeroviz-0.1.9.6/AeroViz/rawDataReader/config/__pycache__/supported_instruments.cpython-312.pyc +0 -0
  54. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/core/__init__.py +71 -72
  55. aeroviz-0.1.9.6/AeroViz/rawDataReader/core/__pycache__/__init__.cpython-312.pyc +0 -0
  56. aeroviz-0.1.9.6/AeroViz/rawDataReader/core/__pycache__/logger.cpython-312.pyc +0 -0
  57. aeroviz-0.1.9.6/AeroViz/rawDataReader/core/__pycache__/qc.cpython-312.pyc +0 -0
  58. aeroviz-0.1.9.6/AeroViz/rawDataReader/core/logger.py +78 -0
  59. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/Aurora.py +1 -1
  60. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/EPA.py +1 -1
  61. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/Minion.py +4 -3
  62. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/NEPH.py +1 -1
  63. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/OCEC.py +1 -1
  64. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/SMPS.py +9 -7
  65. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/TEOM.py +1 -1
  66. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/AE33.cpython-312.pyc +0 -0
  67. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/AE43.cpython-312.pyc +0 -0
  68. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/APS_3321.cpython-312.pyc +0 -0
  69. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/Aurora.cpython-312.pyc +0 -0
  70. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/BC1054.cpython-312.pyc +0 -0
  71. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/EPA.cpython-312.pyc +0 -0
  72. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/GRIMM.cpython-312.pyc +0 -0
  73. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/IGAC.cpython-312.pyc +0 -0
  74. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/MA350.cpython-312.pyc +0 -0
  75. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/Minion.cpython-312.pyc +0 -0
  76. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/NEPH.cpython-312.pyc +0 -0
  77. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/OCEC.cpython-312.pyc +0 -0
  78. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/SMPS.cpython-312.pyc +0 -0
  79. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/TEOM.cpython-312.pyc +0 -0
  80. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/VOC.cpython-312.pyc +0 -0
  81. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/XRF.cpython-312.pyc +0 -0
  82. aeroviz-0.1.9.6/AeroViz/rawDataReader/script/__pycache__/__init__.cpython-312.pyc +0 -0
  83. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/tools/__init__.py +0 -1
  84. aeroviz-0.1.9.6/AeroViz/tools/__pycache__/__init__.cpython-312.pyc +0 -0
  85. aeroviz-0.1.9.6/AeroViz/tools/__pycache__/database.cpython-312.pyc +0 -0
  86. aeroviz-0.1.9.6/AeroViz/tools/__pycache__/dataclassifier.cpython-312.pyc +0 -0
  87. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz.egg-info/PKG-INFO +40 -78
  88. aeroviz-0.1.9.6/AeroViz.egg-info/SOURCES.txt +175 -0
  89. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz.egg-info/requires.txt +2 -2
  90. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/PKG-INFO +40 -78
  91. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/README.md +35 -74
  92. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/pyproject.toml +11 -4
  93. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/tests/test_RawDataReader.py +3 -0
  94. aeroviz-0.1.9.4/tests/test_aeroviz_import.py → aeroviz-0.1.9.6/tests/test_import.py +2 -2
  95. aeroviz-0.1.9.4/AeroViz/plot/hysplit/__init__.py +0 -1
  96. aeroviz-0.1.9.4/AeroViz/plot/meteorology/__init__.py +0 -1
  97. aeroviz-0.1.9.4/AeroViz/tools/datareader.py +0 -66
  98. aeroviz-0.1.9.4/AeroViz.egg-info/SOURCES.txt +0 -108
  99. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/data/DEFAULT_DATA.csv +0 -0
  100. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/data/DEFAULT_PNSD_DATA.csv +0 -0
  101. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/data/hysplit_example_data.txt +0 -0
  102. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Chemistry/__init__.py +0 -0
  103. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Chemistry/_calculate.py +0 -0
  104. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Chemistry/_isoropia.py +0 -0
  105. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Chemistry/_mass_volume.py +0 -0
  106. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Chemistry/_ocec.py +0 -0
  107. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Chemistry/_partition.py +0 -0
  108. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Chemistry/_teom.py +0 -0
  109. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Chemistry/isrpia.cnf +0 -0
  110. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Chemistry/isrpia2.exe +0 -0
  111. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Optical/Angstrom_exponent.py +0 -0
  112. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Optical/_IMPROVE.py +0 -0
  113. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Optical/__init__.py +0 -0
  114. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Optical/_absorption.py +0 -0
  115. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Optical/_extinction.py +0 -0
  116. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Optical/_mie.py +0 -0
  117. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Optical/_mie_sd.py +0 -0
  118. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Optical/_scattering.py +0 -0
  119. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/Optical/fRH.pkl +0 -0
  120. {aeroviz-0.1.9.4/AeroViz/plot/optical → aeroviz-0.1.9.6/AeroViz/dataProcess/Optical}/mie_theory.py +0 -0
  121. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/SizeDistr/__init__.py +0 -0
  122. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/SizeDistr/__merge.py +0 -0
  123. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/SizeDistr/_merge.py +0 -0
  124. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/SizeDistr/_merge_v1.py +0 -0
  125. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/SizeDistr/_merge_v2.py +0 -0
  126. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/SizeDistr/_merge_v3.py +0 -0
  127. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/SizeDistr/_merge_v4.py +0 -0
  128. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/SizeDistr/_size_distr.py +0 -0
  129. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/VOC/__init__.py +0 -0
  130. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/VOC/_potential_par.py +0 -0
  131. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/VOC/support_voc.json +0 -0
  132. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/__init__.py +0 -0
  133. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/dataProcess/core/__init__.py +0 -0
  134. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/bar.py +0 -0
  135. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/box.py +0 -0
  136. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/distribution/__init__.py +0 -0
  137. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/distribution/distribution.py +0 -0
  138. {aeroviz-0.1.9.4/AeroViz/plot/hysplit → aeroviz-0.1.9.6/AeroViz/plot/meteorology}/hysplit.py +0 -0
  139. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/optical/__init__.py +0 -0
  140. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/pie.py +0 -0
  141. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/radar.py +0 -0
  142. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/regression.py +0 -0
  143. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/scatter.py +0 -0
  144. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/templates/__init__.py +0 -0
  145. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/templates/ammonium_rich.py +0 -0
  146. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/templates/contour.py +0 -0
  147. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/templates/corr_matrix.py +0 -0
  148. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/templates/diurnal_pattern.py +0 -0
  149. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/templates/koschmieder.py +0 -0
  150. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/templates/metal_heatmap.py +0 -0
  151. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/timeseries/__init__.py +0 -0
  152. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/timeseries/template.py +0 -0
  153. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/timeseries/timeseries.py +0 -0
  154. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/utils/__init__.py +0 -0
  155. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/utils/_color.py +0 -0
  156. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/utils/_unit.py +0 -0
  157. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/utils/fRH.json +0 -0
  158. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/utils/sklearn_utils.py +0 -0
  159. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/utils/units.json +0 -0
  160. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/plot/violin.py +0 -0
  161. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/config/__init__.py +0 -0
  162. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/config/supported_instruments.py +0 -0
  163. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/core/qc.py +0 -0
  164. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/AE33.py +0 -0
  165. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/AE43.py +0 -0
  166. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/APS_3321.py +0 -0
  167. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/BC1054.py +0 -0
  168. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/GRIMM.py +0 -0
  169. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/IGAC.py +0 -0
  170. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/MA350.py +0 -0
  171. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/VOC.py +0 -0
  172. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/XRF.py +0 -0
  173. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/rawDataReader/script/__init__.py +0 -0
  174. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/tools/database.py +0 -0
  175. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/tools/dataclassifier.py +0 -0
  176. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz/tools/dataprinter.py +0 -0
  177. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz.egg-info/dependency_links.txt +0 -0
  178. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/AeroViz.egg-info/top_level.txt +0 -0
  179. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/LICENSE +0 -0
  180. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/setup.cfg +0 -0
  181. {aeroviz-0.1.9.4 → aeroviz-0.1.9.6}/setup.py +0 -0
@@ -2,13 +2,12 @@
2
2
  from AeroViz import plot
3
3
  from AeroViz.dataProcess import DataProcess
4
4
  from AeroViz.rawDataReader import RawDataReader
5
- from AeroViz.tools import DataBase, DataReader, DataClassifier
5
+ from AeroViz.tools import DataBase, DataClassifier
6
6
 
7
7
  __all__ = [
8
8
  'plot',
9
9
  'RawDataReader',
10
10
  'DataProcess',
11
11
  'DataBase',
12
- 'DataReader',
13
12
  'DataClassifier'
14
13
  ]
@@ -6,13 +6,6 @@ import numpy as np
6
6
  from scipy.special import jv, yv
7
7
 
8
8
 
9
- def coerceDType(d):
10
- if type(d) is not np.ndarray:
11
- return np.array(d)
12
- else:
13
- return d
14
-
15
-
16
9
  def MieQ(m, wavelength, diameter, nMedium=1.0, asDict=False, asCrossSection=False):
17
10
  # http://pymiescatt.readthedocs.io/en/latest/forward.html#MieQ
18
11
  nMedium = nMedium.real
@@ -271,8 +264,8 @@ def Mie_SD(m, wavelength, dp, ndp, nMedium=1.0, SMPS=True, interpolate=False, as
271
264
  nMedium = nMedium.real
272
265
  m /= nMedium
273
266
  wavelength /= nMedium
274
- dp = coerceDType(dp)
275
- ndp = coerceDType(ndp)
267
+ dp = np.array(dp)
268
+ ndp = np.array(ndp)
276
269
  _length = np.size(dp)
277
270
  Q_ext = np.zeros(_length)
278
271
  Q_sca = np.zeros(_length)
@@ -373,8 +366,8 @@ def SF_SD(m, wavelength, dp, ndp, nMedium=1.0, minAngle=0, maxAngle=180, angular
373
366
  wavelength /= nMedium
374
367
 
375
368
  _steps = int(1 + (maxAngle - minAngle) / angularResolution)
376
- ndp = coerceDType(ndp)
377
- dp = coerceDType(dp)
369
+ ndp = np.array(ndp)
370
+ dp = np.array(dp)
378
371
  SL = np.zeros(_steps)
379
372
  SR = np.zeros(_steps)
380
373
  SU = np.zeros(_steps)
@@ -0,0 +1,62 @@
1
+ import numpy as np
2
+ from numpy import exp, log
3
+ from scipy.signal import find_peaks
4
+
5
+
6
+ def geometric(dp: np.ndarray,
7
+ dist: np.ndarray
8
+ ) -> tuple[float, float]:
9
+ """ Calculate the geometric mean and standard deviation. """
10
+
11
+ _gmd = (((dist * log(dp)).sum()) / dist.sum())
12
+
13
+ logdp_mesh, gmd_mesh = np.meshgrid(log(dp), _gmd)
14
+ _gsd = ((((logdp_mesh - gmd_mesh) ** 2) * dist).sum() / dist.sum()) ** .5
15
+
16
+ return exp(_gmd), exp(_gsd)
17
+
18
+
19
+ def contribution(dp: np.ndarray,
20
+ dist: np.ndarray
21
+ ) -> tuple[float, float, float]:
22
+ """ Calculate the relative contribution of each mode. """
23
+
24
+ ultra = dist[(dp >= 11.8) & (dp < 100)].sum() / dist.sum()
25
+ accum = dist[(dp >= 100) & (dp < 1000)].sum() / dist.sum()
26
+ coars = dist[(dp >= 1000) & (dp < 2500)].sum() / dist.sum()
27
+
28
+ return ultra, accum, coars
29
+
30
+
31
+ def mode(dp: np.ndarray,
32
+ dist: np.ndarray
33
+ ) -> np.ndarray:
34
+ """ Find three peak mode in distribution. """
35
+
36
+ min_value = np.array([dist.min()])
37
+ mode, _ = find_peaks(np.concatenate([min_value, dist, min_value]), distance=len(dist) - 1)
38
+
39
+ return dp[mode - 1]
40
+
41
+
42
+ def properties(dist,
43
+ dp: np.ndarray,
44
+ dlogdp: np.ndarray,
45
+ weighting: str
46
+ ) -> dict:
47
+ """ for apply """
48
+ dist = np.array(dist)
49
+
50
+ gmd, gsd = geometric(dp, dist)
51
+ ultra, accum, coarse = contribution(dp, dist)
52
+ peak = mode(dp, dist)
53
+
54
+ return {key: round(value, 3) for key, value in
55
+ {f'total_{weighting}': (dist * dlogdp).sum(),
56
+ f'GMD_{weighting}': gmd,
57
+ f'GSD_{weighting}': gsd,
58
+ f'mode_{weighting}': peak[0],
59
+ f'ultra_{weighting}': ultra,
60
+ f'accum_{weighting}': accum,
61
+ f'coarse_{weighting}': coarse}
62
+ .items()}
@@ -3,7 +3,6 @@ from . import meteorology
3
3
  from . import optical
4
4
  from .bar import bar
5
5
  from .box import box
6
- from .hysplit import hysplit
7
6
  from .pie import pie, donuts
8
7
  from .radar import radar
9
8
  from .regression import linear_regression, multiple_linear_regression
@@ -1,85 +1,159 @@
1
1
  import math
2
- from typing import Literal
3
2
 
4
3
  import matplotlib.pyplot as plt
5
4
  import numpy as np
6
5
  import pandas as pd
7
- import windrose
8
6
  from matplotlib.pyplot import Figure, Axes
9
7
  from pandas import DataFrame, Series
10
8
  from scipy.ndimage import gaussian_filter
11
9
 
12
10
  from AeroViz.plot.utils import *
13
11
 
14
- __all__ = ['wind_rose',
15
- 'CBPF'
16
- ]
12
+ __all__ = ['CBPF']
13
+
14
+
15
+ def improve_density_estimation(df, WS, WD, val, resolution=100, bandwidth=None):
16
+ """
17
+ 改進的密度估計函數,使用KDE方法來產生更平滑的分布
18
+
19
+ Parameters:
20
+ -----------
21
+ df : DataFrame
22
+ 包含風速風向數據的DataFrame
23
+ WS : str
24
+ 風速列名
25
+ WD : str
26
+ 風向列名
27
+ val : str
28
+ 要分析的變量列名
29
+ resolution : int
30
+ 網格解析度
31
+ bandwidth : float or tuple
32
+ KDE的頻寬參數,如果為None則自動選擇
33
+ """
34
+ from scipy.stats import gaussian_kde
35
+ import numpy as np
36
+
37
+ # 轉換為笛卡爾坐標
38
+ u = df[WS] * np.sin(np.radians(df[WD]))
39
+ v = df[WS] * np.cos(np.radians(df[WD]))
40
+
41
+ # 創建網格
42
+ u_range = np.linspace(u.min(), u.max(), resolution)
43
+ v_range = np.linspace(v.min(), v.max(), resolution)
44
+ U, V = np.meshgrid(u_range, v_range)
45
+
46
+ # 準備KDE的位置
47
+ positions = np.vstack([U.ravel(), V.ravel()])
48
+ values = np.vstack([u, v])
49
+
50
+ # 使用KDE進行密度估計
51
+ kernel = gaussian_kde(values, bw_method=bandwidth)
52
+ Z = np.reshape(kernel(positions), U.shape)
53
+
54
+ # 將密度值歸一化到[0,1]區間
55
+ Z = (Z - Z.min()) / (Z.max() - Z.min())
56
+
57
+ # 應用極坐標遮罩
58
+ center_u = len(u_range) // 2
59
+ center_v = len(v_range) // 2
60
+ max_radius = min(center_u, center_v)
61
+
62
+ Y, X = np.ogrid[-center_v:resolution - center_v, -center_u:resolution - center_u]
63
+ mask = X * X + Y * Y > max_radius * max_radius
64
+ Z[mask] = np.nan
65
+
66
+ return Z, U, V
67
+
68
+
69
+ def smooth_and_clean(Z, smooth_radius=2, min_density=1):
70
+ """
71
+ 平滑並清理密度圖,去除孤立點
72
+
73
+ Parameters:
74
+ -----------
75
+ Z : ndarray
76
+ 密度估計結果
77
+ smooth_radius : int
78
+ 平滑半徑
79
+ min_density : float
80
+ 最小密度閾值
81
+ """
82
+ from scipy.ndimage import gaussian_filter
83
+
84
+ # 先進行高斯平滑
85
+ Z_smooth = gaussian_filter(Z, sigma=smooth_radius)
86
+
87
+ # 去除低於閾值的點
88
+ # Z_smooth[Z_smooth < min_density] = np.nan
89
+
90
+ # 去除孤立點
91
+ rows, cols = Z_smooth.shape
92
+ for i in range(rows):
93
+ for j in range(cols):
94
+ if not np.isnan(Z_smooth[i, j]):
95
+ # 檢查周圍點
96
+ neighborhood = Z_smooth[
97
+ max(0, i - smooth_radius):min(rows, i + smooth_radius + 1),
98
+ max(0, j - smooth_radius):min(cols, j + smooth_radius + 1)
99
+ ]
100
+ if np.count_nonzero(~np.isnan(neighborhood)) < 1: # 如果周圍有效點太少
101
+ Z_smooth[i, j] = np.nan
102
+
103
+ return Z_smooth
104
+
105
+
106
+ def is_within_circle(center_row, center_col, row, col, radius):
107
+ return np.sqrt((center_row - row) ** 2 + (center_col - col) ** 2) <= radius
108
+
109
+
110
+ def remove_lonely_point(filtered_histogram, radius=4, magic_num=13):
111
+ rows, cols = filtered_histogram.shape
112
+ data_positions = np.where(~np.isnan(filtered_histogram))
113
+
114
+ for row, col in zip(*data_positions):
115
+ valid_data_count = 0
116
+ for i in range(max(0, row - radius), min(rows, row + radius + 1)):
117
+ for j in range(max(0, col - radius), min(cols, col + radius + 1)):
118
+ if (i, j) != (row, col) and is_within_circle(row, col, i, j, radius):
119
+ if not np.isnan(filtered_histogram[i, j]):
120
+ valid_data_count += 1
121
+
122
+ if valid_data_count <= magic_num:
123
+ filtered_histogram[row, col] = np.nan
124
+
125
+ return filtered_histogram
126
+
127
+
128
+ def fill_nan_with_mean(filtered_histogram, radius=4, magic_num=13):
129
+ rows, cols = filtered_histogram.shape
130
+ nan_positions = np.where(np.isnan(filtered_histogram))
131
+
132
+ for row, col in zip(*nan_positions):
133
+ surrounding_values = []
134
+ surrounding_values_within_one = []
135
+ nan_count = 0
17
136
 
137
+ for i in range(max(0, row - radius), min(rows, row + radius + 1)):
138
+ for j in range(max(0, col - radius), min(cols, col + radius + 1)):
139
+ if (i, j) != (row, col) and is_within_circle(row, col, i, j, radius):
140
+ if np.isnan(filtered_histogram[i, j]):
141
+ nan_count += 1
142
+ else:
143
+ surrounding_values.append(filtered_histogram[i, j])
18
144
 
19
- @set_figure(figsize=(4.3, 4))
20
- def wind_rose(df: DataFrame,
21
- WS: Series | str,
22
- WD: Series | str,
23
- val: Series | str | None = None,
24
- typ: Literal['bar', 'scatter'] = 'scatter',
25
- rlabel_pos: float = 30,
26
- **kwargs
27
- ) -> tuple[Figure, Axes]:
28
- # conditional bivariate probability function (cbpf) python
29
- # https://davidcarslaw.github.io/openair/reference/polarPlot.html
30
- # https://github.com/davidcarslaw/openair/blob/master/R/polarPlot.R
31
- windrose.WindroseAxes._info = 'WindroseAxes'
32
-
33
- df = df.dropna(subset=[WS, WD] + ([val] if val is not None else []))
34
-
35
- radius = df[WS].to_numpy()
36
- theta = df[WD].to_numpy()
37
- radian = np.radians(theta)
38
- values = df[val].to_numpy() if val is not None else None
39
-
40
- # In this case, the windrose is a simple frequency diagram,
41
- # the function automatically calculates the radians of the given wind direction.
42
- if typ == 'bar':
43
- fig, ax = plt.subplots(figsize=(5.5, 4), subplot_kw={'projection': 'windrose'})
44
- fig.subplots_adjust(left=0)
45
-
46
- ax.bar(theta, radius, bins=[0, 1, 2, 3], normed=True, colors=['#0F1035', '#365486', '#7FC7D9', '#DCF2F1'])
47
- ax.set(
48
- ylim=(0, 30),
49
- yticks=[0, 15, 30],
50
- yticklabels=['', '15 %', '30 %'],
51
- rlabel_position=rlabel_pos
52
- )
53
- ax.set_thetagrids(angles=[0, 45, 90, 135, 180, 225, 270, 315],
54
- labels=["E", "NE", "N", "NW", "W", "SW", "S", "SE"])
55
-
56
- ax.legend(units='m/s', bbox_to_anchor=[1.1, 0.5], loc='center left', ncol=1)
57
-
58
- # In this case, the windrose is a scatter plot,
59
- # in contrary, this function does not calculate the radians, so user have to input the radian.
60
- else:
61
- fig, ax = plt.subplots(figsize=(5, 4), subplot_kw={'projection': 'windrose'})
62
- fig.subplots_adjust(left=0)
63
-
64
- scatter = ax.scatter(radian, radius, s=15, c=values, vmax=np.quantile(values, 0.90), edgecolors='none',
65
- cmap='jet', alpha=0.8)
66
- ax.set(
67
- ylim=(0, 7),
68
- yticks=[1, 3, 5, 7],
69
- yticklabels=['1 m/s', '3 m/s', '5 m/s', '7 m/s'],
70
- rlabel_position=rlabel_pos,
71
- theta_direction=-1,
72
- theta_zero_location='N',
73
- title=kwargs.get('title', None)
74
- )
75
- ax.set_thetagrids(angles=[0, 45, 90, 135, 180, 225, 270, 315],
76
- labels=["N", "NE", "E", "SE", "S", "SW", "W", "NW"])
77
-
78
- plt.colorbar(scatter, ax=ax, label=Unit(val), pad=0.1, fraction=0.04)
145
+ for i in range(max(0, row - 2), min(rows, row + 2 + 1)):
146
+ for j in range(max(0, col - 2), min(cols, col + 2 + 1)):
147
+ if (i, j) != (row, col) and is_within_circle(row, col, i, j, 2):
148
+ if np.isnan(filtered_histogram[i, j]):
149
+ pass
150
+ else:
151
+ surrounding_values_within_one.append(filtered_histogram[i, j])
79
152
 
80
- plt.show()
153
+ if nan_count < magic_num and surrounding_values_within_one:
154
+ filtered_histogram[row, col] = np.mean(surrounding_values)
81
155
 
82
- return fig, ax
156
+ return filtered_histogram
83
157
 
84
158
 
85
159
  # TODO: fix the bug of the CBPF function
@@ -90,7 +164,7 @@ def CBPF(df: DataFrame,
90
164
  val: Series | str | None = None,
91
165
  percentile: list | float | int | None = None,
92
166
  max_ws: float | None = 5,
93
- resolution: int = 100,
167
+ resolution: int = 50,
94
168
  sigma: float | tuple = 2,
95
169
  rlabel_pos: float = 30,
96
170
  bottom_text: str | bool | None = None,
@@ -157,64 +231,18 @@ def CBPF(df: DataFrame,
157
231
  histogram_filled = np.nan_to_num(histogram, nan=0) # 將 NaN 替換為 0
158
232
 
159
233
  filtered_histogram = gaussian_filter(histogram_filled, sigma=sigma)
160
- filtered_histogram[np.isnan(histogram)] = np.nan
161
-
162
- def is_within_circle(center_row, center_col, row, col, radius):
163
- return np.sqrt((center_row - row) ** 2 + (center_col - col) ** 2) <= radius
164
-
165
- def remove_lonely_point(filtered_histogram, radius=4, magic_num=13):
166
- rows, cols = filtered_histogram.shape
167
- data_positions = np.where(~np.isnan(filtered_histogram))
168
-
169
- for row, col in zip(*data_positions):
170
- valid_data_count = 0
171
- for i in range(max(0, row - radius), min(rows, row + radius + 1)):
172
- for j in range(max(0, col - radius), min(cols, col + radius + 1)):
173
- if (i, j) != (row, col) and is_within_circle(row, col, i, j, radius):
174
- if not np.isnan(filtered_histogram[i, j]):
175
- valid_data_count += 1
176
-
177
- if valid_data_count <= magic_num:
178
- filtered_histogram[row, col] = np.nan
179
-
180
- return filtered_histogram
181
-
182
- def fill_nan_with_mean(filtered_histogram, radius=4, magic_num=13):
183
- rows, cols = filtered_histogram.shape
184
- nan_positions = np.where(np.isnan(filtered_histogram))
185
-
186
- for row, col in zip(*nan_positions):
187
- surrounding_values = []
188
- surrounding_values_within_one = []
189
- nan_count = 0
190
-
191
- for i in range(max(0, row - radius), min(rows, row + radius + 1)):
192
- for j in range(max(0, col - radius), min(cols, col + radius + 1)):
193
- if (i, j) != (row, col) and is_within_circle(row, col, i, j, radius):
194
- if np.isnan(filtered_histogram[i, j]):
195
- nan_count += 1
196
- else:
197
- surrounding_values.append(filtered_histogram[i, j])
198
-
199
- for i in range(max(0, row - 2), min(rows, row + 2 + 1)):
200
- for j in range(max(0, col - 2), min(cols, col + 2 + 1)):
201
- if (i, j) != (row, col) and is_within_circle(row, col, i, j, 2):
202
- if np.isnan(filtered_histogram[i, j]):
203
- pass
204
- else:
205
- surrounding_values_within_one.append(filtered_histogram[i, j])
206
-
207
- if nan_count < magic_num and surrounding_values_within_one:
208
- filtered_histogram[row, col] = np.mean(surrounding_values)
209
-
210
- return filtered_histogram
234
+ # filtered_histogram[np.isnan(histogram)] = np.nan
235
+ # breakpoint()
236
+ # filtered_histogram = smooth_and_clean(filtered_histogram)
211
237
 
212
238
  # Apply the function to your data
213
- fil_radius, magic_num = 3, 13
214
- filtered_histogram = remove_lonely_point(filtered_histogram, fil_radius, magic_num)
215
- filtered_histogram = fill_nan_with_mean(filtered_histogram, fil_radius, magic_num)
239
+ # fil_radius, magic_num = 3, 13
240
+ # filtered_histogram = remove_lonely_point(filtered_histogram, fil_radius, magic_num)
241
+ # filtered_histogram = fill_nan_with_mean(filtered_histogram, fil_radius, magic_num)
242
+
216
243
  if np.all(np.isnan(filtered_histogram)):
217
244
  raise ValueError("All values in the filtered histogram are NaN. Please decrease the resolution.")
245
+
218
246
  # plot
219
247
  fig, ax = plt.subplots()
220
248
  fig.subplots_adjust(left=0)
@@ -0,0 +1,3 @@
1
+ from .CBPF import CBPF
2
+ from .hysplit import hysplit
3
+ from .wind_rose import wind_rose
@@ -0,0 +1,77 @@
1
+ from typing import Literal
2
+
3
+ import matplotlib.pyplot as plt
4
+ import numpy as np
5
+ import windrose
6
+ from matplotlib.pyplot import Figure, Axes
7
+ from pandas import DataFrame, Series
8
+
9
+ from AeroViz.plot.utils import *
10
+
11
+ __all__ = ['wind_rose']
12
+
13
+
14
+ @set_figure(figsize=(4.3, 4))
15
+ def wind_rose(df: DataFrame,
16
+ WS: Series | str,
17
+ WD: Series | str,
18
+ val: Series | str | None = None,
19
+ typ: Literal['bar', 'scatter'] = 'scatter',
20
+ rlabel_pos: float = 30,
21
+ **kwargs
22
+ ) -> tuple[Figure, Axes]:
23
+ # conditional bivariate probability function (cbpf) python
24
+ # https://davidcarslaw.github.io/openair/reference/polarPlot.html
25
+ # https://github.com/davidcarslaw/openair/blob/master/R/polarPlot.R
26
+ windrose.WindroseAxes._info = 'WindroseAxes'
27
+
28
+ df = df.dropna(subset=[WS, WD] + ([val] if val is not None else []))
29
+
30
+ radius = df[WS].to_numpy()
31
+ theta = df[WD].to_numpy()
32
+ radian = np.radians(theta)
33
+ values = df[val].to_numpy() if val is not None else None
34
+
35
+ # In this case, the windrose is a simple frequency diagram,
36
+ # the function automatically calculates the radians of the given wind direction.
37
+ if typ == 'bar':
38
+ fig, ax = plt.subplots(figsize=(5.5, 4), subplot_kw={'projection': 'windrose'})
39
+ fig.subplots_adjust(left=0)
40
+
41
+ ax.bar(theta, radius, bins=[0, 1, 2, 3], normed=True, colors=['#0F1035', '#365486', '#7FC7D9', '#DCF2F1'])
42
+ ax.set(
43
+ ylim=(0, 30),
44
+ yticks=[0, 15, 30],
45
+ yticklabels=['', '15 %', '30 %'],
46
+ rlabel_position=rlabel_pos
47
+ )
48
+ ax.set_thetagrids(angles=[0, 45, 90, 135, 180, 225, 270, 315],
49
+ labels=["E", "NE", "N", "NW", "W", "SW", "S", "SE"])
50
+
51
+ ax.legend(units='m/s', bbox_to_anchor=[1.1, 0.5], loc='center left', ncol=1)
52
+
53
+ # In this case, the windrose is a scatter plot,
54
+ # in contrary, this function does not calculate the radians, so user have to input the radian.
55
+ else:
56
+ fig, ax = plt.subplots(figsize=(5, 4), subplot_kw={'projection': 'windrose'})
57
+ fig.subplots_adjust(left=0)
58
+
59
+ scatter = ax.scatter(radian, radius, s=15, c=values, vmax=np.quantile(values, 0.90), edgecolors='none',
60
+ cmap='jet', alpha=0.8)
61
+ ax.set(
62
+ ylim=(0, 7),
63
+ yticks=[1, 3, 5, 7],
64
+ yticklabels=['1 m/s', '3 m/s', '5 m/s', '7 m/s'],
65
+ rlabel_position=rlabel_pos,
66
+ theta_direction=-1,
67
+ theta_zero_location='N',
68
+ title=kwargs.get('title', None)
69
+ )
70
+ ax.set_thetagrids(angles=[0, 45, 90, 135, 180, 225, 270, 315],
71
+ labels=["N", "NE", "E", "SE", "S", "SW", "W", "NW"])
72
+
73
+ plt.colorbar(scatter, ax=ax, label=Unit(val), pad=0.1, fraction=0.04)
74
+
75
+ plt.show()
76
+
77
+ return fig, ax
@@ -3,11 +3,10 @@ from typing import Literal
3
3
 
4
4
  import matplotlib.pyplot as plt
5
5
  import numpy as np
6
- # from PyMieScatt import ScatteringFunction
7
6
  from matplotlib.pyplot import Figure, Axes
8
7
 
9
- from AeroViz.plot.optical.PyMieScatt_update import ScatteringFunction
10
- from AeroViz.plot.optical.mie_theory import Mie_Q, Mie_MEE, Mie_PESD
8
+ from AeroViz.dataProcess.Optical.PyMieScatt_update import ScatteringFunction
9
+ from AeroViz.dataProcess.Optical.mie_theory import Mie_Q, Mie_MEE, Mie_PESD
11
10
  from AeroViz.plot.utils import *
12
11
 
13
12
  __all__ = ['Q_plot',
@@ -50,7 +50,7 @@ def set_figure(func=None,
50
50
  plt.rcParams['legend.labelspacing'] = 0.7
51
51
 
52
52
  plt.rcParams['figure.figsize'] = figsize or (4, 4)
53
- plt.rcParams['figure.dpi'] = 200
53
+ plt.rcParams['figure.dpi'] = 300
54
54
  plt.rcParams['figure.autolayout'] = autolayout
55
55
 
56
56
  if not autolayout: