1"""
2Distance statistics for planar point patterns
3
4"""
5__author__ = "Serge Rey sjsrey@gmail.com"
6__all__ = [
7    "DStatistic",
8    "G",
9    "F",
10    "J",
11    "K",
12    "L",
13    "Envelopes",
14    "Genv",
15    "Fenv",
16    "Jenv",
17    "Kenv",
18    "Lenv",
19]
20
21from .process import PoissonPointProcess as csr
22import numpy as np
23from matplotlib import pyplot as plt
24import warnings
25
26
27class DStatistic(object):
28    """
29    Abstract Base Class for distance statistics.
30
31    Parameters
32    ----------
33    name       : string
34                 Name of the function. ("G", "F", "J", "K" or "L")
35
36    Attributes
37    ----------
38    d          : array
39                 The distance domain sequence.
40
41    """
42
43    def __init__(self, name):
44        self.name = name
45        warnings.warn(
46            f"This class is deprecated! Please use the alternative function"
47            f" {name.lower()} in pointpats.distance_statistics.",
48            DeprecationWarning,
49            stacklevel=2,
50        )
51
52    def plot(self, qq=False):
53        """
54        Plot the distance function
55
56        Parameters
57        ----------
58        qq: Boolean
59            If False the statistic is plotted against distance. If Frue, the
60            quantile-quantile plot is generated, observed vs. CSR.
61        """
62
63        # assuming mpl
64        x = self.d
65        if qq:
66            plt.plot(self.ev, self._stat)
67            plt.plot(self.ev, self.ev)
68        else:
69            plt.plot(x, self._stat, label="{}".format(self.name))
70            plt.ylabel("{}(d)".format(self.name))
71            plt.xlabel("d")
72            plt.plot(x, self.ev, label="CSR")
73            plt.title("{} distance function".format(self.name))
74
75
76class G(DStatistic):
77    """
78    Estimates the nearest neighbor distance distribution function G for a
79    point pattern.
80
81    Parameters
82    ----------
83    pp         : :class:`.PointPattern`
84                 Point Pattern instance.
85    intervals  : int
86                 The length of distance domain sequence.
87    dmin       : float
88                 The minimum of the distance domain.
89    dmax       : float
90                 The maximum of the distance domain.
91    d          : sequence
92                 The distance domain sequence.
93                 If d is specified, intervals, dmin and dmax are ignored.
94
95    Attributes
96    ----------
97    name       : string
98                 Name of the function. ("G", "F", "J", "K" or "L")
99    d          : array
100                 The distance domain sequence.
101    G          : array
102                 The cumulative nearest neighbor distance distribution over d.
103
104    Notes
105    -----
106    In the analysis of planar point processes, the estimate of :math:`G` is
107    typically compared to the value expected from a completely spatial
108    random (CSR) process given as:
109
110    .. math::
111
112            G(d) = 1 - e^{-\lambda \pi  d^2}
113
114    where :math:`\lambda` is the intensity (points per unit area) of the point
115    process and :math:`d` is distance.
116
117    For a clustered pattern, the empirical function will be above the
118    expectation, while for a uniform pattern the empirical function falls below
119    the expectation.
120
121    """
122
123    def __init__(self, pp, intervals=10, dmin=0.0, dmax=None, d=None):
124        res = _g(pp, intervals, dmin, dmax, d)
125        self.d = res[:, 0]
126        self.G = self._stat = res[:, 1]
127        self.ev = 1 - np.exp(-pp.lambda_window * np.pi * self.d * self.d)
128        self.pp = pp
129        super(G, self).__init__(name="G")
130
131
132class F(DStatistic):
133    """
134    Estimates the empty space distribution function for a point pattern: F(d).
135
136    Parameters
137    ----------
138    pp         : :class:`.PointPattern`
139                 Point Pattern instance.
140    n          : int
141                 Number of empty space points (random points).
142    intervals  : int
143                 The length of distance domain sequence.
144    dmin       : float
145                 The minimum of the distance domain.
146    dmax       : float
147                 The maximum of the distance domain.
148    d          : sequence
149                 The distance domain sequence.
150                 If d is specified, intervals, dmin and dmax are ignored.
151
152    Attributes
153    ----------
154    d          : array
155                 The distance domain sequence.
156    G          : array
157                 The cumulative empty space nearest event distance distribution
158                 over d.
159
160    Notes
161    -----
162    In the analysis of planar point processes, the estimate of :math:`F` is
163    typically compared to the value expected from a process that displays
164    complete spatial randomness (CSR):
165
166    .. math::
167
168            F(d) = 1 - e^{-\lambda \pi  d^2}
169
170    where :math:`\lambda` is the intensity (points per unit area) of the point
171    process and :math:`d` is distance.
172
173    The expectation is identical to the expectation for the :class:`G` function
174    for a CSR process.  However, for a clustered pattern, the empirical G
175    function will be below the expectation, while for a uniform pattern the
176    empirical function falls above the expectation.
177
178    """
179
180    def __init__(self, pp, n=100, intervals=10, dmin=0.0, dmax=None, d=None):
181        res = _f(pp, n, intervals, dmin, dmax, d)
182        self.d = res[:, 0]
183        self.F = self._stat = res[:, 1]
184        self.ev = 1 - np.exp(-pp.lambda_window * np.pi * self.d * self.d)
185        super(F, self).__init__(name="F")
186
187
188class J(DStatistic):
189    """
190    Estimates the J function for a point pattern :cite:`VanLieshout1996`
191
192    Parameters
193    ----------
194    pp         : :class:`.PointPattern`
195                 Point Pattern instance.
196    n          : int
197                 Number of empty space points (random points).
198    intervals  : int
199                 The length of distance domain sequence.
200    dmin       : float
201                 The minimum of the distance domain.
202    dmax       : float
203                 The maximum of the distance domain.
204    d          : sequence
205                 The distance domain sequence.
206                 If d is specified, intervals, dmin and dmax are ignored.
207
208    Attributes
209    ----------
210    d          : array
211                 The distance domain sequence.
212    j          : array
213                 F function over d.
214
215    Notes
216    -----
217
218    The :math:`J` function is a ratio of the hazard functions defined for
219    :math:`G` and :math:`F`:
220
221    .. math::
222
223            J(d) = \\frac{1-G(d) }{1-F(d)}
224
225    where :math:`G(d)` is the nearest neighbor distance distribution function
226    (see :class:`G`)
227    and :math:`F(d)` is the empty space function (see :class:`F`).
228
229    For a CSR process the J function equals 1. Empirical values larger than 1
230    are indicative of uniformity, while values below 1 suggest clustering.
231
232
233    """
234
235    def __init__(self, pp, n=100, intervals=10, dmin=0.0, dmax=None, d=None):
236        res = _j(pp, n, intervals, dmin, dmax, d)
237        self.d = res[:, 0]
238        self.j = self._stat = res[:, 1]
239        self.ev = self.j / self.j
240        super(J, self).__init__(name="J")
241
242
243class K(DStatistic):
244    """
245    Estimates the  K function for a point pattern.
246
247    Parameters
248    ----------
249    pp         : :class:`.PointPattern`
250                 Point Pattern instance.
251    intervals  : int
252                 The length of distance domain sequence.
253    dmin       : float
254                 The minimum of the distance domain.
255    dmax       : float
256                 The maximum of the distance domain.
257    d          : sequence
258                 The distance domain sequence.
259                 If d is specified, intervals, dmin and dmax are ignored.
260
261    Attributes
262    ----------
263    d          : array
264                 The distance domain sequence.
265    k          : array
266                 K function over d.
267
268    Notes
269    -----
270
271    The :math:`K` function is estimated using
272
273    .. math::
274
275             \\hat{K}(h) = \\frac{a}{n (n-1)} \\sum_{i} \\sum_{j \\ne i} I(d_{i,j} \\le h)
276
277    where :math:`a` is the area of the window, :math:`n` the number of event points, and :math:`I(d_{i,j} \le h)` is an indicator function returning 1 when points i and j are separated by a distance of :math:`h` or less, 0 otherwise.
278
279    """
280
281    def __init__(self, pp, intervals=10, dmin=0.0, dmax=None, d=None):
282        res = _k(pp, intervals, dmin, dmax, d)
283        self.d = res[:, 0]
284        self.k = self._stat = res[:, 1]
285        self.ev = np.pi * self.d * self.d
286        super(K, self).__init__(name="K")
287
288
289class L(DStatistic):
290    """
291    Estimates the :math:`L` function for a point pattern :cite:`Sullivan2010`.
292
293    Parameters
294    ----------
295    pp         : :class:`.PointPattern`
296                 Point Pattern instance.
297    intervals  : int
298                 The length of distance domain sequence.
299    dmin       : float
300                 The minimum of the distance domain.
301    dmax       : float
302                 The maximum of the distance domain.
303    d          : sequence
304                 The distance domain sequence.
305                 If d is specified, intervals, dmin and dmax are ignored.
306
307    Attributes
308    ----------
309    d          : array
310                 The distance domain sequence.
311    l          : array
312                 L function over d.
313
314    Notes
315    -----
316
317    In the analysis of planar point processes, the :math:`L` function
318    is a scaled version of :math:`K` function. Its estimate is also
319    typically compared to the value expected from a process that displays
320    complete spatial randomness (CSR):
321
322    .. math::
323
324            L(d) = \\sqrt{\\frac{K(d)}{\\pi}}-d
325
326    where :math:`K(d)` is the estimator for the :math:`K` function
327    and :math:`d` is distance.
328
329    The expectation under the null of CSR is 0 (a horizonal line at 0).
330    For a clustered pattern, the empirical :math:`L`
331    function will be above the expectation, while for a uniform pattern the
332    empirical function falls below the expectation.
333
334    """
335
336    def __init__(self, pp, intervals=10, dmin=0.0, dmax=None, d=None):
337        res = _l(pp, intervals, dmin, dmax, d)
338        self.d = res[:, 0]
339        self.l = self._stat = res[:, 1]
340        super(L, self).__init__(name="L")
341
342    def plot(self):
343        # assuming mpl
344        x = self.d
345        plt.plot(x, self._stat, label="{}".format(self.name))
346        plt.ylabel("{}(d)".format(self.name))
347        plt.xlabel("d")
348        plt.title("{} distance function".format(self.name))
349
350
351def _g(pp, intervals=10, dmin=0.0, dmax=None, d=None):
352    """
353    Estimate the nearest neighbor distances function G.
354
355    Parameters
356    ----------
357    pp       : :class:`.PointPattern`
358               Point Pattern instance.
359    intevals : int
360               Number of intervals to evaluate F over.
361    dmin     : float
362               Lower limit of distance range.
363    dmax     : float
364               Upper limit of distance range. If dmax is None, dmax will be set
365               to maximum nearest neighor distance.
366    d        : sequence
367               The distance domain sequence. If d is specified, intervals, dmin
368               and dmax are ignored.
369
370    Returns
371    -------
372             : array
373               A 2-dimensional numpy array of 2 columns. The first column is
374               the distance domain sequence for the point pattern. The second
375               column is the cumulative nearest neighbor distance distribution.
376
377    Notes
378    -----
379    See :class:`G`.
380
381    """
382    if d is None:
383        w = pp.max_nnd / intervals
384        if dmax:
385            w = dmax / intervals
386        d = [w * i for i in range(intervals + 2)]
387    cdf = [0] * len(d)
388    for i, d_i in enumerate(d):
389        smaller = [nndi for nndi in pp.nnd if nndi <= d_i]
390        cdf[i] = len(smaller) * 1.0 / pp.n
391    return np.vstack((d, cdf)).T
392
393
394def _f(pp, n=100, intervals=10, dmin=0.0, dmax=None, d=None):
395    """
396    F empty space function.
397
398    Parameters
399    ----------
400    pp       : :class:`.PointPattern`
401               Point Pattern instance.
402    n        : int
403               Number of empty space points (random points).
404    intevals : int
405               Number of intervals to evaluate F over.
406    dmin     : float
407               Lower limit of distance range.
408    dmax     : float
409               Upper limit of distance range. If dmax is None, dmax will be set
410               to maximum nearest neighor distance.
411    d        : sequence
412               The distance domain sequence. If d is specified, intervals, dmin
413               and dmax are ignored.
414
415    Returns
416    -------
417             : array
418               A 2-dimensional numpy array of 2 columns. The first column is
419               the distance domain sequence for the point pattern. The second
420               column is corresponding F function.
421
422    Notes
423    -----
424    See :class:`.F`
425
426    """
427
428    # get a csr pattern in window of pp
429    c = csr(pp.window, n, 1, asPP=True).realizations[0]
430    # for each point in csr pattern find the closest point in pp and the
431    # associated distance
432    nnids, nnds = pp.knn_other(c, k=1)
433
434    if d is None:
435        w = pp.max_nnd / intervals
436        if dmax:
437            w = dmax / intervals
438        d = [w * i for i in range(intervals + 2)]
439    cdf = [0] * len(d)
440
441    for i, d_i in enumerate(d):
442        smaller = [nndi for nndi in nnds if nndi <= d_i]
443        cdf[i] = len(smaller) * 1.0 / n
444    return np.vstack((d, cdf)).T
445
446
447def _j(pp, n=100, intervals=10, dmin=0.0, dmax=None, d=None):
448    """
449    J function: Ratio of hazard functions for F and G.
450
451    Parameters
452    ----------
453    pp       : :class:`.PointPattern`
454               Point Pattern instance.
455    n        : int
456               Number of empty space points (random points).
457    intevals : int
458               Number of intervals to evaluate F over.
459    dmin     : float
460               Lower limit of distance range.
461    dmax     : float
462               Upper limit of distance range. If dmax is None, dmax will be set
463               to maximum nearest neighor distance.
464    d        : sequence
465               The distance domain sequence. If d is specified, intervals, dmin
466               and dmax are ignored.
467
468    Returns
469    -------
470             : array
471               A 2-dimensional numpy array of 2 columns. The first column is
472               the distance domain sequence for the point pattern. The second
473               column is corresponding J function.
474
475    Notes
476    -----
477    See :class:`.J`
478
479    """
480
481    F = _f(pp, n, intervals=intervals, dmin=dmin, dmax=dmax, d=d)
482    G = _g(pp, intervals=intervals, dmin=dmin, dmax=dmax, d=d)
483    FC = 1 - F[:, 1]
484    GC = 1 - G[:, 1]
485    last_id = len(GC) + 1
486    if np.any(FC == 0):
487        last_id = np.where(FC == 0)[0][0]
488
489    return np.vstack((F[:last_id, 0], GC[:last_id] / FC[:last_id])).T
490
491
492def _k(pp, intervals=10, dmin=0.0, dmax=None, d=None):
493    """
494    Interevent K function.
495
496    Parameters
497    ----------
498    pp       : :class:`.PointPattern`
499               Point Pattern instance.
500    n        : int
501               Number of empty space points (random points).
502    intevals : int
503               Number of intervals to evaluate F over.
504    dmin     : float
505               Lower limit of distance range.
506    dmax     : float
507               Upper limit of distance range. If dmax is None, dmax will be set to one-quarter of the minimum side of the minimum bounding rectangle.
508    d        : sequence
509               The distance domain sequence. If d is specified, intervals, dmin
510               and dmax are ignored.
511
512    Returns
513    -------
514    kcdf     : array
515               A 2-dimensional numpy array of 2 columns. The first column is
516               the distance domain sequence for the point pattern. The second
517               column is corresponding K function.
518
519    Notes
520    -----
521
522    See :class:`.K`
523    """
524
525    if d is None:
526        w = pp.rot / intervals
527        if dmax:
528            w = dmax / intervals
529        d = [w * i for i in range(intervals + 2)]
530    den = pp.lambda_window * (pp.n - 1)
531    kcdf = np.asarray([(di, len(pp.tree.query_pairs(di)) * 2 / den) for di in d])
532    return kcdf
533
534
535def _l(pp, intervals=10, dmin=0.0, dmax=None, d=None):
536    """
537    Interevent L function.
538
539    Parameters
540    ----------
541    pp       : :class:`.PointPattern`
542               Point Pattern instance.
543    n        : int
544               Number of empty space points (random points).
545    intevals : int
546               Number of intervals to evaluate F over.
547    dmin     : float
548               Lower limit of distance range.
549    dmax     : float
550               Upper limit of distance range. If dmax is None, dmax will be set
551               to length of bounding box diagonal.
552    d        : sequence
553               The distance domain sequence. If d is specified, intervals, dmin
554               and dmax are ignored.
555
556    Returns
557    -------
558    kf       : array
559               A 2-dimensional numpy array of 2 columns. The first column is
560               the distance domain sequence for the point pattern. The second
561               column is corresponding L function.
562
563    Notes
564    -----
565    See :class:`.L`
566
567    """
568
569    kf = _k(pp, intervals, dmin, dmax, d)
570    kf[:, 1] = np.sqrt(kf[:, 1] / np.pi) - kf[:, 0]
571    return kf
572
573
574class Envelopes(object):
575    """
576    Abstract base class for simulation envelopes.
577
578    Parameters
579    ----------
580    pp          : :class:`.PointPattern`
581                  Point Pattern instance.
582    intervals   : int
583                  The length of distance domain sequence. Default is 10.
584    dmin        : float
585                  The minimum of the distance domain.
586    dmax        : float
587                  The maximum of the distance domain.
588    d           : sequence
589                  The distance domain sequence.
590                  If d is specified, intervals, dmin and dmax are ignored.
591    pct         : float
592                  1-alpha, alpha is the significance level. Default is 0.05,
593                  1-alpha is the confidence level for the envelope.
594    realizations: :class:`.PointProcess`
595                  Point process instance with more than 1 realizations.
596
597    Attributes
598    ----------
599    name        : string
600                  Name of the function. ("G", "F", "J", "K" or "L")
601    observed    : array
602                  A 2-dimensional numpy array of 2 columns. The first column is
603                  the distance domain sequence for the observed point pattern.
604                  The second column is the specific function ("G", "F", "J",
605                  "K" or "L") over the distance domain sequence for the
606                  observed point pattern.
607    low         : array
608                  A 1-dimensional numpy array. Lower bound of the simulation
609                  envelope.
610    high        : array
611                  A 1-dimensional numpy array. Higher bound of the simulation
612                  envelope.
613    mean        : array
614                  A 1-dimensional numpy array. Mean values of the simulation
615                  envelope.
616
617    """
618
619    def __init__(self, *args, **kwargs):
620        # setup arguments
621        self.name = kwargs["name"]
622        warnings.warn(
623            f"This class is deprecated! Please use the alternative statistical test"
624            f" {self.name.lower()}_test in pointpats.distance_statistics.",
625            DeprecationWarning,
626            stacklevel=2,
627        )
628
629        # calculate observed function
630        self.pp = args[0]
631        self.observed = self.calc(*args, **kwargs)
632        self.d = self.observed[:, 0]  # domain to be used in all realizations
633
634        # do realizations
635        self.mapper(kwargs["realizations"])
636
637    def mapper(self, realizations):
638        reals = realizations.realizations
639        res = np.asarray([self.calc(reals[p]) for p in reals])
640
641        # When calculating the J function for all the simulations, the length
642        # of the returned interval domains might be different.
643
644        if self.name == "J":
645            res = []
646            for p in reals:
647                j = self.calc(reals[p])
648                if j.shape[0] < self.d.shape[0]:
649                    diff = self.d.shape[0] - j.shape[0]
650                    for i in range(diff):
651                        j = np.append(j, [[self.d[i + diff], np.inf]], axis=0)
652                res.append(j)
653            res = np.array(res)
654
655        res = res[:, :, -1]
656        res.sort(axis=0)
657        nres = len(res)
658        self.low = res[np.int(nres * self.pct / 2.0)]
659        self.high = res[np.int(nres * (1 - self.pct / 2.0))]
660        self.mean = res.mean(axis=0)
661
662    def calc(self, *args, **kwargs):
663        print("implement in subclass")
664
665    def plot(self):
666        # assuming mpl
667        x = self.d
668        plt.plot(x, self.observed[:, 1], label="{}".format(self.name))
669        plt.plot(x, self.mean, "g-.", label="CSR")
670        plt.plot(x, self.low, "r-.", label="LB")
671        plt.plot(x, self.high, "r-.", label="UB")
672        plt.ylabel("{}(d)".format(self.name))
673        plt.xlabel("d")
674        plt.title("{} Simulation Envelopes".format(self.name))
675        plt.legend(loc=0)
676
677
678class Genv(Envelopes):
679    """
680    Simulation envelope for G function.
681
682    Parameters
683    ----------
684    pp          : :class:`.PointPattern`
685                  Point Pattern instance.
686    intervals   : int
687                  The length of distance domain sequence. Default is 10.
688    dmin        : float
689                  The minimum of the distance domain.
690    dmax        : float
691                  Upper limit of distance range. If dmax is None, dmax will be
692                  set to maximum nearest neighbor distance.
693    d           : sequence
694                  The distance domain sequence.
695                  If d is specified, intervals, dmin and dmax are ignored.
696    pct         : float
697                  1-alpha, alpha is the significance level. Default is 0.05,
698                  which means 95% confidence level for the envelopes.
699    realizations: :class:`.PointProcess`
700                  Point process instance with more than 1 realizations.
701
702    Attributes
703    ----------
704    name        : string
705                  Name of the function. ("G", "F", "J", "K" or "L")
706    observed    : array
707                  A 2-dimensional numpy array of 2 columns. The first column is
708                  the distance domain sequence for the observed point pattern.
709                  The second column is cumulative nearest neighbor distance
710                  distribution (G function) for the observed point pattern.
711    low         : array
712                  A 1-dimensional numpy array. Lower bound of the simulation
713                  envelope.
714    high        : array
715                  A 1-dimensional numpy array. Higher bound of the simulation
716                  envelope.
717    mean        : array
718                  A 1-dimensional numpy array. Mean values of the simulation
719                  envelope.
720
721    Examples
722    --------
723    .. plot::
724
725       >>> import libpysal as ps
726       >>> from pointpats import Genv, PoissonPointProcess, Window
727       >>> from libpysal.cg import shapely_ext
728       >>> va = ps.io.open(ps.examples.get_path("vautm17n.shp"))
729       >>> polys = [shp for shp in va]
730       >>> state = shapely_ext.cascaded_union(polys)
731       >>> pp = PoissonPointProcess(Window(state.parts), 100, 1, asPP=True).realizations[0]
732       >>> csrs = PoissonPointProcess(pp.window, 100, 100, asPP=True)
733       >>> genv_bb = Genv(pp, realizations=csrs)
734       >>> genv_bb.plot()
735
736    """
737
738    def __init__(
739        self, pp, intervals=10, dmin=0.0, dmax=None, d=None, pct=0.05, realizations=None
740    ):
741        self.pp = pp
742        self.intervals = intervals
743        self.dmin = dmin
744        self.dmax = dmax
745        self.d = d
746        self.pct = pct
747        super(Genv, self).__init__(pp, realizations=realizations, name="G")
748
749    def calc(self, *args, **kwargs):
750        pp = args[0]
751        return _g(
752            pp, intervals=self.intervals, dmin=self.dmin, dmax=self.dmax, d=self.d
753        )
754
755
756class Fenv(Envelopes):
757    """
758    Simulation envelope for F function.
759
760    Parameters
761    ----------
762    pp          : :class:`.PointPattern`
763                  Point Pattern instance.
764    n           : int
765                  Number of empty space points (random points).
766    intervals   : int
767                  The length of distance domain sequence. Default is 10.
768    dmin        : float
769                  The minimum of the distance domain.
770    dmax        : float
771                  Upper limit of distance range. If dmax is None, dmax will be
772                  set to maximum nearest neighbor distance.
773    d           : sequence
774                  The distance domain sequence.
775                  If d is specified, intervals, dmin and dmax are ignored.
776    pct         : float
777                  1-alpha, alpha is the significance level. Default is 0.05,
778                  which means 95% confidence level for the envelopes.
779    realizations: :class:`.PointProcess`
780                  Point process instance with more than 1 realizations.
781
782    Attributes
783    ----------
784    name        : string
785                  Name of the function. ("G", "F", "J", "K" or "L")
786    observed    : array
787                  A 2-dimensional numpy array of 2 columns. The first column is
788                  the distance domain sequence for the observed point pattern.
789                  The second column is F function for the observed point
790                  pattern.
791    low         : array
792                  A 1-dimensional numpy array. Lower bound of the simulation
793                  envelope.
794    high        : array
795                  A 1-dimensional numpy array. Higher bound of the simulation
796                  envelope.
797    mean        : array
798                  A 1-dimensional numpy array. Mean values of the simulation
799                  envelope.
800
801    Examples
802    --------
803    .. plot::
804
805       >>> import libpysal as ps
806       >>> from libpysal.cg import shapely_ext
807       >>> from pointpats import PoissonPointProcess,Window,Fenv
808       >>> va = ps.io.open(ps.examples.get_path("vautm17n.shp"))
809       >>> polys = [shp for shp in va]
810       >>> state = shapely_ext.cascaded_union(polys)
811       >>> pp = PoissonPointProcess(Window(state.parts), 100, 1, asPP=True).realizations[0]
812       >>> csrs = PoissonPointProcess(pp.window, 100, 100, asPP=True)
813       >>> fenv = Fenv(pp, realizations=csrs)
814       >>> fenv.plot()
815
816    """
817
818    def __init__(
819        self,
820        pp,
821        n=100,
822        intervals=10,
823        dmin=0.0,
824        dmax=None,
825        d=None,
826        pct=0.05,
827        realizations=None,
828    ):
829        self.pp = pp
830        self.n = n
831        self.intervals = intervals
832        self.dmin = dmin
833        self.dmax = dmax
834        self.d = d
835        self.pct = pct
836        super(Fenv, self).__init__(pp, realizations=realizations, name="F")
837
838    def calc(self, *args, **kwargs):
839        pp = args[0]
840        return _f(
841            pp,
842            self.n,
843            intervals=self.intervals,
844            dmin=self.dmin,
845            dmax=self.dmax,
846            d=self.d,
847        )
848
849
850class Jenv(Envelopes):
851    """
852    Simulation envelope for J function.
853
854    Parameters
855    ----------
856    pp          : :class:`.PointPattern`
857                  Point Pattern instance.
858    n           : int
859                  Number of empty space points (random points).
860    intervals   : int
861                  The length of distance domain sequence. Default is 10.
862    dmin        : float
863                  The minimum of the distance domain.
864    dmax        : float
865                  Upper limit of distance range. If dmax is None, dmax will be
866                  set to maximum nearest neighbor distance.
867    d           : sequence
868                  The distance domain sequence.
869                  If d is specified, intervals, dmin and dmax are ignored.
870    pct         : float
871                  1-alpha, alpha is the significance level. Default is 0.05,
872                  which means 95% confidence level for the envelopes.
873    realizations: :class:`.PointProcess`
874                  Point process instance with more than 1 realizations.
875
876    Attributes
877    ----------
878    name        : string
879                  Name of the function. ("G", "F", "J", "K" or "L")
880    observed    : array
881                  A 2-dimensional numpy array of 2 columns. The first column is
882                  the distance domain sequence for the observed point pattern.
883                  The second column is J function for the observed point
884                  pattern.
885    low         : array
886                  A 1-dimensional numpy array. Lower bound of the simulation
887                  envelope.
888    high        : array
889                  A 1-dimensional numpy array. Higher bound of the simulation
890                  envelope.
891    mean        : array
892                  A 1-dimensional numpy array. Mean values of the simulation
893                  envelope.
894
895    Examples
896    --------
897    .. plot::
898
899       >>> import libpysal as ps
900       >>> from pointpats import Jenv, PoissonPointProcess, Window
901       >>> from libpysal.cg import shapely_ext
902       >>> va = ps.io.open(ps.examples.get_path("vautm17n.shp"))
903       >>> polys = [shp for shp in va]
904       >>> state = shapely_ext.cascaded_union(polys)
905       >>> pp = PoissonPointProcess(Window(state.parts), 100, 1, asPP=True).realizations[0]
906       >>> csrs = PoissonPointProcess(pp.window, 100, 100, asPP=True)
907       >>> jenv = Jenv(pp, realizations=csrs)
908       >>> jenv.plot()
909
910    """
911
912    def __init__(
913        self,
914        pp,
915        n=100,
916        intervals=10,
917        dmin=0.0,
918        dmax=None,
919        d=None,
920        pct=0.05,
921        realizations=None,
922    ):
923        self.pp = pp
924        self.n = n
925        self.intervals = intervals
926        self.dmin = dmin
927        self.dmax = dmax
928        self.d = d
929        self.pct = pct
930        super(Jenv, self).__init__(pp, realizations=realizations, name="J")
931
932    def calc(self, *args, **kwargs):
933        pp = args[0]
934        return _j(
935            pp,
936            self.n,
937            intervals=self.intervals,
938            dmin=self.dmin,
939            dmax=self.dmax,
940            d=self.d,
941        )
942
943
944class Kenv(Envelopes):
945    """
946    Simulation envelope for K function.
947
948    Parameters
949    ----------
950    pp          : :class:`.PointPattern`
951                  Point Pattern instance.
952    intervals   : int
953                  The length of distance domain sequence. Default is 10.
954    dmin        : float
955                  The minimum of the distance domain.
956    dmax        : float
957                  Upper limit of distance range. If dmax is None, dmax will be
958                  set to maximum nearest neighbor distance.
959    d           : sequence
960                  The distance domain sequence.
961                  If d is specified, intervals, dmin and dmax are ignored.
962    pct         : float
963                  1-alpha, alpha is the significance level. Default is 0.05,
964                  which means 95% confidence level for the envelope.
965    realizations: :class:`.PointProcess`
966                  Point process instance with more than 1 realizations.
967
968    Attributes
969    ----------
970    name        : string
971                  Name of the function. ("G", "F", "J", "K" or "L")
972    observed    : array
973                  A 2-dimensional numpy array of 2 columns. The first column is
974                  the distance domain sequence for the observed point pattern.
975                  The second column is K function for the observed point
976                  pattern.
977    low         : array
978                  A 1-dimensional numpy array. Lower bound of the simulation
979                  envelope.
980    high        : array
981                  A 1-dimensional numpy array. Higher bound of the simulation
982                  envelope.
983    mean        : array
984                  A 1-dimensional numpy array. Mean values of the simulation
985                  envelope.
986
987    Examples
988    --------
989    .. plot::
990
991       >>> import libpysal as ps
992       >>> from pointpats import Kenv, PoissonPointProcess, Window
993       >>> from libpysal.cg import shapely_ext
994       >>> va = ps.io.open(ps.examples.get_path("vautm17n.shp"))
995       >>> polys = [shp for shp in va]
996       >>> state = shapely_ext.cascaded_union(polys)
997       >>> pp = PoissonPointProcess(Window(state.parts), 100, 1, asPP=True).realizations[0]
998       >>> csrs = PoissonPointProcess(pp.window, 100, 100, asPP=True)
999       >>> kenv = Kenv(pp, realizations=csrs)
1000       >>> kenv.plot()
1001
1002    """
1003
1004    def __init__(
1005        self, pp, intervals=10, dmin=0.0, dmax=None, d=None, pct=0.05, realizations=None
1006    ):
1007        self.pp = pp
1008        self.intervals = intervals
1009        self.dmin = dmin
1010        self.dmax = dmax
1011        self.d = d
1012        self.pct = pct
1013        super(Kenv, self).__init__(pp, realizations=realizations, name="K")
1014
1015    def calc(self, *args, **kwargs):
1016        pp = args[0]
1017        return _k(
1018            pp, intervals=self.intervals, dmin=self.dmin, dmax=self.dmax, d=self.d
1019        )
1020
1021
1022class Lenv(Envelopes):
1023    """
1024    Simulation envelope for L function.
1025
1026    Parameters
1027    ----------
1028    pp          : :class:`.PointPattern`
1029                  Point Pattern instance.
1030    intervals   : int
1031                  The length of distance domain sequence. Default is 10.
1032    dmin        : float
1033                  The minimum of the distance domain.
1034    dmax        : float
1035                  Upper limit of distance range. If dmax is None, dmax will be
1036                  set to maximum nearest neighbor distance.
1037    d           : sequence
1038                  The distance domain sequence.
1039                  If d is specified, intervals, dmin and dmax are ignored.
1040    pct         : float
1041                  1-alpha, alpha is the significance level. Default is 0.05,
1042                  which means 95% confidence level for the envelopes.
1043    realizations: :class:`.PointProcess`
1044                  Point process instance with more than 1 realizations.
1045
1046    Attributes
1047    ----------
1048    name        : string
1049                  Name of the function. ("G", "F", "J", "K" or "L")
1050    observed    : array
1051                  A 2-dimensional numpy array of 2 columns. The first column is
1052                  the distance domain sequence for the observed point pattern.
1053                  The second column is L function for the observed point
1054                  pattern.
1055    low         : array
1056                  A 1-dimensional numpy array. Lower bound of the simulation
1057                  envelope.
1058    high        : array
1059                  A 1-dimensional numpy array. Higher bound of the simulation
1060                  envelope.
1061    mean        : array
1062                  A 1-dimensional numpy array. Mean values of the simulation
1063                  envelope.
1064
1065    Examples
1066    --------
1067    .. plot::
1068
1069       >>> import libpysal as ps
1070       >>> from pointpats import Lenv, PoissonPointProcess, Window
1071       >>> from libpysal.cg import shapely_ext
1072       >>> va = ps.io.open(ps.examples.get_path("vautm17n.shp"))
1073       >>> polys = [shp for shp in va]
1074       >>> state = shapely_ext.cascaded_union(polys)
1075       >>> pp = PoissonPointProcess(Window(state.parts), 100, 1, asPP=True).realizations[0]
1076       >>> csrs = PoissonPointProcess(pp.window, 100, 100, asPP=True)
1077       >>> lenv = Lenv(pp, realizations=csrs)
1078       >>> lenv.plot()
1079
1080    """
1081
1082    def __init__(
1083        self, pp, intervals=10, dmin=0.0, dmax=None, d=None, pct=0.05, realizations=None
1084    ):
1085        self.pp = pp
1086        self.intervals = intervals
1087        self.dmin = dmin
1088        self.dmax = dmax
1089        self.d = d
1090        self.pct = pct
1091        super(Lenv, self).__init__(pp, realizations=realizations, name="L")
1092
1093    def calc(self, *args, **kwargs):
1094        pp = args[0]
1095        return _l(
1096            pp, intervals=self.intervals, dmin=self.dmin, dmax=self.dmax, d=self.d
1097        )
1098