martibosch / pylandstats

Computing landscape metrics in the Python ecosystem
https://doi.org/10.1371/journal.pone.0225734
GNU General Public License v3.0
82 stars 16 forks source link

Error in `landscape.compute_total_adjacency_df()` #22

Closed cisluis closed 1 year ago

cisluis commented 1 year ago

Description

When running the compute_landscape_metrics_df() function errors for entropy (and other landscape-level metrics) is thrown out: "entropy cannot be computed at the landscape level"

What I Did

plsobj = pls.Landscape(data.astype(int), res=(1, 1), neighborhood_rule='8')

kws = {'total_area': {'hectares': False},
           'edge_density': {'hectares': False},
           'perimeter_area_ratio': {'hectares': False},
           'patch_density': {'hectares': False}}
df = plsobj.compute_landscape_metrics_df(metrics_kws=kws).T.squeeze()

this would throw the error for ANY data and it works if I chose not to calculate any of the diversity measures (like entropy, contagion, etc).

I figured that in the landscape.py library the function compute_total_adjacency_df() was returning a data frame of objects instead of integers (as it should because this is an array of adjacency counts), and then when entropy() uses this function to calculate counts per class, which then is passed to compute_entropy(), the calculation fails because the values in the list aren't numeric, and hence the statement

entropy = -np.sum(pcounts * np.log(pcounts))

throws an error at the numpy log command.

I fixed this problem by forcing the return of compute_total_adcacency_df() to be a data frame of integers:

def compute_total_adjacency_df(self):
        """
        Compute the total adjacency (vertical and horizontal) data frame.

        Returns
        -------
        adjacency_df: pandas.DataFrame
            Adjacency data frame with total adjacencies (vertical and horizontal).
        """
        # first `groupby` and `sum` to sum vertical and horizontal adjacencies
        # (first-level index), then `loc` to overlook the nodata row/column
        df = self._adjacency_df.groupby(level=1).sum().loc[self.classes, self.classes]
        return df.astype('int')

You should consider revising this simple error for the next update

martibosch commented 1 year ago

Hello,

sorry for the delay in my response. Thank you for reporting this bug, I believe it should be fixed by 92aa1a7. You can try it out in the v3.0.0rc.

Martí