Repository: martinfleis/momepy
Pull request #104 (2019-11-05 11:33:35)

BUG: fix FractalDimension formula
Fractal Dimension taken from Hermosilla et al (2014) is not correct. This PR fixes it based on FRAGSTATS.

codecov[bot]: # [Codecov](https://codecov.io/gh/martinfleis/momepy/pull/104?src=pr&el=h1) Report
> Merging [#104](https://codecov.io/gh/martinfleis/momepy/pull/104?src=pr&el=desc) into [master](https://codecov.io/gh/martinfleis/momepy/commit/be76468fe35e914c1c8ffad52d8b3c9213aa52b5?src=pr&el=desc) will **decrease** coverage by `0.36%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/martinfleis/momepy/pull/104/graphs/tree.svg?width=650&token=i04999UxkK&height=150&src=pr)](https://codecov.io/gh/martinfleis/momepy/pull/104?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #104      +/-   ##
==========================================
- Coverage   93.23%   92.86%   -0.37%     
==========================================
  Files           9        9              
  Lines        2439     2439              
==========================================
- Hits         2274     2265       -9     
- Misses        165      174       +9
```


| [Impacted Files](https://codecov.io/gh/martinfleis/momepy/pull/104?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [momepy/shape.py](https://codecov.io/gh/martinfleis/momepy/pull/104/diff?src=pr&el=tree#diff-bW9tZXB5L3NoYXBlLnB5) | `95.24% <ø> (ø)` | :arrow_up: |
| [momepy/diversity.py](https://codecov.io/gh/martinfleis/momepy/pull/104/diff?src=pr&el=tree#diff-bW9tZXB5L2RpdmVyc2l0eS5weQ==) | `84.28% <0%> (-6.43%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/martinfleis/momepy/pull/104?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/martinfleis/momepy/pull/104?src=pr&el=footer). Last update [be76468...866e611](https://codecov.io/gh/martinfleis/momepy/pull/104?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/momepy/shape.py b/momepy/shape.py
index a6ce0ce..3f28419 100644
--- a/momepy/shape.py
+++ b/momepy/shape.py
@@ -106,7 +106,7 @@ class FractalDimension:
     Calculates fractal dimension of each object in given geoDataFrame.
 
     .. math::
-        {log({{perimeter} \\over {4}})} \\over log(area)
+        {2log({{perimeter} \\over {4}})} \\over log(area)
 
     Parameters
     ----------
@@ -131,17 +131,15 @@ class FractalDimension:
         Series containing used area values
 
     References
-    ---------
-    Hermosilla, T. et al. (2014) ‘Using street based metrics to characterize urban
-    typologies’, Computers, Environment and Urban Systems, 44, pp. 68–79.
-    doi: 10.1016/j.compenvurbsys.2013.12.002.
+    ----------
+    McGarigal, K., & Marks, B. (1995). FRAGSTATS: spatial pattern analysis program for quantifying landscape structure.
 
     Examples
     --------
     >>> buildings_df['fractal'] = momepy.FractalDimension(buildings_df, 'area', 'peri').fd
     100%|██████████| 144/144 [00:00<00:00, 3928.09it/s]
     >>> buildings_df.fractal[0]
-    0.5363389283519454
+    1.0726778567038908
     """
 
     def __init__(self, gdf, areas=None, perimeters=None):
@@ -164,7 +162,8 @@ class FractalDimension:
             areas = "mm_a"
 
         self.fd = gdf.apply(
-            lambda row: math.log(row[perimeters] / 4) / math.log(row[areas]), axis=1
+            lambda row: (2 * math.log(row[perimeters] / 4)) / math.log(row[areas]),
+            axis=1,
         )
 
 


Test patch:
diff --git a/tests/test_shape.py b/tests/test_shape.py
index 0fd17da..547d9f8 100644
--- a/tests/test_shape.py
+++ b/tests/test_shape.py
@@ -36,8 +36,10 @@ class TestShape:
 
     def test_FractalDimension(self):
         self.df_buildings["fd"] = mm.FractalDimension(self.df_buildings).fd
-        check = math.log(self.df_buildings.geometry[0].length / 4) / math.log(
-            self.df_buildings.geometry[0].area
+        check = (
+            2
+            * math.log(self.df_buildings.geometry[0].length / 4)
+            / math.log(self.df_buildings.geometry[0].area)
         )
         assert self.df_buildings["fd"][0] == check