Full Code of FreyrS/dMaSIF for AI

master 0dcc26c3c218 cached
34 files
9.9 MB
2.6M tokens
118 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (10,351K chars total). Download the full file to get everything.
Repository: FreyrS/dMaSIF
Branch: master
Commit: 0dcc26c3c218
Files: 34
Total size: 9.9 MB

Directory structure:
gitextract_4r95syc5/

├── .gitignore
├── Arguments.py
├── LICENSE.md
├── README.md
├── benchmark_layers.py
├── benchmark_models.py
├── benchmark_scripts/
│   ├── DGCNN_site.sh
│   ├── Pointnet_site.sh
│   ├── dMaSIF_search.sh
│   └── dMaSIF_site.sh
├── data.py
├── data_analysis/
│   ├── analyse_atomnet.ipynb
│   ├── analyse_descriptors.py
│   ├── analyse_descriptors_para.py
│   ├── analyse_output.ipynb
│   ├── analyse_site_outputs.py
│   ├── analyse_site_outputs_graph.ipynb
│   ├── plot_search.ipynb
│   └── profiling_surface.ipynb
├── data_iteration.py
├── data_preprocessing/
│   ├── convert_pdb2npy.py
│   ├── convert_ply2npy.py
│   └── download_pdb.py
├── geometry_processing.py
├── helper.py
├── lists/
│   ├── testing.txt
│   ├── testing_ppi.txt
│   ├── training.txt
│   └── training_ppi.txt
├── main_inference.py
├── main_training.py
├── model.py
├── models/
│   └── dMaSIF_search_3layer_12A_16dim
└── requirements.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
01-benchmark_surfaces/
01-benchmark_surfaces_npy/
01-benchmark_pdbs_npy/
01-benchmark_pdbs/
01-benchmark_pdbs/
shape_index/
masif_preds/
runs/
venv/
preds/
*.log
NeurIPS_2020_benchmarks/
*.out
figures/
timings/
data_analysis/roc_curves
data_analysis/.ipynb_checkpoints/
.ipynb_checkpoints/

================================================
FILE: Arguments.py
================================================
import argparse

parser = argparse.ArgumentParser(description="Network parameters")

# Main parameters
parser.add_argument(
    "--experiment_name", type=str, help="Name of experiment", required=True
)
parser.add_argument(
    "--use_mesh", type=bool, default=False, help="Use precomputed surfaces"
)
parser.add_argument(
    "--embedding_layer",
    type=str,
    default="dMaSIF",
    choices=["dMaSIF", "DGCNN", "PointNet++"],
    help="Which convolutional embedding layer to use",
)
parser.add_argument("--profile", type=bool, default=False, help="Profile code")

# Geometric parameters
parser.add_argument(
    "--curvature_scales",
    type=list,
    default=[1.0, 2.0, 3.0, 5.0, 10.0],
    help="Scales at which we compute the geometric features (mean and Gauss curvatures)",
)
parser.add_argument(
    "--resolution",
    type=float,
    default=1.0,
    help="Resolution of the generated point cloud",
)
parser.add_argument(
    "--distance",
    type=float,
    default=1.05,
    help="Distance parameter in surface generation",
)
parser.add_argument(
    "--variance",
    type=float,
    default=0.1,
    help="Variance parameter in surface generation",
)
parser.add_argument(
    "--sup_sampling", type=int, default=20, help="Sup-sampling ratio around atoms"
)

# Hyper-parameters for the embedding
parser.add_argument(
    "--atom_dims",
    type=int,
    default=6,
    help="Number of atom types and dimension of resulting chemical features",
)
parser.add_argument(
    "--emb_dims",
    type=int,
    default=8,
    help="Number of input features (+ 3 xyz coordinates for DGCNNs)",
)
parser.add_argument(
    "--in_channels",
    type=int,
    default=16,
    help="Number of embedding dimensions",
)
parser.add_argument(
    "--orientation_units",
    type=int,
    default=16,
    help="Number of hidden units for the orientation score MLP",
)
parser.add_argument(
    "--unet_hidden_channels",
    type=int,
    default=8,
    help="Number of hidden units for TangentConv UNet",
)
parser.add_argument(
    "--post_units",
    type=int,
    default=8,
    help="Number of hidden units for the post-processing MLP",
)
parser.add_argument(
    "--n_layers", type=int, default=1, help="Number of convolutional layers"
)
parser.add_argument(
    "--radius", type=float, default=9.0, help="Radius to use for the convolution"
)
parser.add_argument(
    "--k",
    type=int,
    default=40,
    help="Number of nearset neighbours for DGCNN and PointNet++",
)
parser.add_argument(
    "--dropout",
    type=float,
    default=0.0,
    help="Amount of Dropout for the input features",
)

# Training
parser.add_argument(
    "--n_epochs", type=int, default=50, help="Number of training epochs"
)
parser.add_argument(
    "--batch_size", type=int, default=1, help="Number of proteins in a batch"
)
parser.add_argument(
    "--device", type=str, default="cuda:0", help="Which gpu/cpu to train on"
)
parser.add_argument(
    "--restart_training",
    type=str,
    default="",
    help="Which model to restart the training from",
)
parser.add_argument(
    "--n_rocauc_samples",
    type=int,
    default=100,
    help="Number of samples for the Matching ROC-AUC",
)
parser.add_argument(
    "--validation_fraction",
    type=float,
    default=0.1,
    help="Fraction of training dataset to use for validation",
)
parser.add_argument("--seed", type=int, default=42, help="Random seed")
parser.add_argument(
    "--random_rotation",
    type=bool,
    default=False,
    help="Move proteins to center and add random rotation",
)
parser.add_argument(
    "--single_protein",
    type=bool,
    default=False,
    help="Use single protein in a pair or both",
)
parser.add_argument("--site", type=bool, default=False, help="Predict interaction site")
parser.add_argument(
    "--search",
    type=bool,
    default=False,
    help="Predict matching between two partners",
)
parser.add_argument(
    "--no_chem", type=bool, default=False, help="Predict without chemical information"
)
parser.add_argument(
    "--no_geom", type=bool, default=False, help="Predict without curvature information"
)
parser.add_argument(
    "--single_pdb",
    type=str,
    default="",
    help="Which structure to do inference on",
)
parser.add_argument(
    "--pdb_list",
    type=str,
    default="",
    help="Which structures to do inference on",
)


================================================
FILE: LICENSE.md
================================================
Attribution-NonCommercial-NoDerivatives 4.0 International

=======================================================================

Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.

Using Creative Commons Public Licenses

Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.

     Considerations for licensors: Our public licenses are
     intended for use by those authorized to give the public
     permission to use material in ways otherwise restricted by
     copyright and certain other rights. Our licenses are
     irrevocable. Licensors should read and understand the terms
     and conditions of the license they choose before applying it.
     Licensors should also secure all rights necessary before
     applying our licenses so that the public can reuse the
     material as expected. Licensors should clearly mark any
     material not subject to the license. This includes other CC-
     licensed material, or material used under an exception or
     limitation to copyright. More considerations for licensors:
    wiki.creativecommons.org/Considerations_for_licensors

     Considerations for the public: By using one of our public
     licenses, a licensor grants the public permission to use the
     licensed material under specified terms and conditions. If
     the licensor's permission is not necessary for any reason--for
     example, because of any applicable exception or limitation to
     copyright--then that use is not regulated by the license. Our
     licenses grant only permissions under copyright and certain
     other rights that a licensor has authority to grant. Use of
     the licensed material may still be restricted for other
     reasons, including because others have copyright or other
     rights in the material. A licensor may make special requests,
     such as asking that all changes be marked or described.
     Although not required by our licenses, you are encouraged to
     respect those requests where reasonable. More considerations
     for the public:
    wiki.creativecommons.org/Considerations_for_licensees

=======================================================================

Creative Commons Attribution-NonCommercial-NoDerivatives 4.0
International Public License

By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NonCommercial-NoDerivatives 4.0 International Public
License ("Public License"). To the extent this Public License may be
interpreted as a contract, You are granted the Licensed Rights in
consideration of Your acceptance of these terms and conditions, and the
Licensor grants You such rights in consideration of benefits the
Licensor receives from making the Licensed Material available under
these terms and conditions.


Section 1 -- Definitions.

  a. Adapted Material means material subject to Copyright and Similar
     Rights that is derived from or based upon the Licensed Material
     and in which the Licensed Material is translated, altered,
     arranged, transformed, or otherwise modified in a manner requiring
     permission under the Copyright and Similar Rights held by the
     Licensor. For purposes of this Public License, where the Licensed
     Material is a musical work, performance, or sound recording,
     Adapted Material is always produced where the Licensed Material is
     synched in timed relation with a moving image.

  b. Copyright and Similar Rights means copyright and/or similar rights
     closely related to copyright including, without limitation,
     performance, broadcast, sound recording, and Sui Generis Database
     Rights, without regard to how the rights are labeled or
     categorized. For purposes of this Public License, the rights
     specified in Section 2(b)(1)-(2) are not Copyright and Similar
     Rights.

  c. Effective Technological Measures means those measures that, in the
     absence of proper authority, may not be circumvented under laws
     fulfilling obligations under Article 11 of the WIPO Copyright
     Treaty adopted on December 20, 1996, and/or similar international
     agreements.

  d. Exceptions and Limitations means fair use, fair dealing, and/or
     any other exception or limitation to Copyright and Similar Rights
     that applies to Your use of the Licensed Material.

  e. Licensed Material means the artistic or literary work, database,
     or other material to which the Licensor applied this Public
     License.

  f. Licensed Rights means the rights granted to You subject to the
     terms and conditions of this Public License, which are limited to
     all Copyright and Similar Rights that apply to Your use of the
     Licensed Material and that the Licensor has authority to license.

  g. Licensor means the individual(s) or entity(ies) granting rights
     under this Public License.

  h. NonCommercial means not primarily intended for or directed towards
     commercial advantage or monetary compensation. For purposes of
     this Public License, the exchange of the Licensed Material for
     other material subject to Copyright and Similar Rights by digital
     file-sharing or similar means is NonCommercial provided there is
     no payment of monetary compensation in connection with the
     exchange.

  i. Share means to provide material to the public by any means or
     process that requires permission under the Licensed Rights, such
     as reproduction, public display, public performance, distribution,
     dissemination, communication, or importation, and to make material
     available to the public including in ways that members of the
     public may access the material from a place and at a time
     individually chosen by them.

  j. Sui Generis Database Rights means rights other than copyright
     resulting from Directive 96/9/EC of the European Parliament and of
     the Council of 11 March 1996 on the legal protection of databases,
     as amended and/or succeeded, as well as other essentially
     equivalent rights anywhere in the world.

  k. You means the individual or entity exercising the Licensed Rights
     under this Public License. Your has a corresponding meaning.


Section 2 -- Scope.

  a. License grant.

       1. Subject to the terms and conditions of this Public License,
          the Licensor hereby grants You a worldwide, royalty-free,
          non-sublicensable, non-exclusive, irrevocable license to
          exercise the Licensed Rights in the Licensed Material to:

            a. reproduce and Share the Licensed Material, in whole or
               in part, for NonCommercial purposes only; and

            b. produce and reproduce, but not Share, Adapted Material
               for NonCommercial purposes only.

       2. Exceptions and Limitations. For the avoidance of doubt, where
          Exceptions and Limitations apply to Your use, this Public
          License does not apply, and You do not need to comply with
          its terms and conditions.

       3. Term. The term of this Public License is specified in Section
          6(a).

       4. Media and formats; technical modifications allowed. The
          Licensor authorizes You to exercise the Licensed Rights in
          all media and formats whether now known or hereafter created,
          and to make technical modifications necessary to do so. The
          Licensor waives and/or agrees not to assert any right or
          authority to forbid You from making technical modifications
          necessary to exercise the Licensed Rights, including
          technical modifications necessary to circumvent Effective
          Technological Measures. For purposes of this Public License,
          simply making modifications authorized by this Section 2(a)
          (4) never produces Adapted Material.

       5. Downstream recipients.

            a. Offer from the Licensor -- Licensed Material. Every
               recipient of the Licensed Material automatically
               receives an offer from the Licensor to exercise the
               Licensed Rights under the terms and conditions of this
               Public License.

            b. No downstream restrictions. You may not offer or impose
               any additional or different terms or conditions on, or
               apply any Effective Technological Measures to, the
               Licensed Material if doing so restricts exercise of the
               Licensed Rights by any recipient of the Licensed
               Material.

       6. No endorsement. Nothing in this Public License constitutes or
          may be construed as permission to assert or imply that You
          are, or that Your use of the Licensed Material is, connected
          with, or sponsored, endorsed, or granted official status by,
          the Licensor or others designated to receive attribution as
          provided in Section 3(a)(1)(A)(i).

  b. Other rights.

       1. Moral rights, such as the right of integrity, are not
          licensed under this Public License, nor are publicity,
          privacy, and/or other similar personality rights; however, to
          the extent possible, the Licensor waives and/or agrees not to
          assert any such rights held by the Licensor to the limited
          extent necessary to allow You to exercise the Licensed
          Rights, but not otherwise.

       2. Patent and trademark rights are not licensed under this
          Public License.

       3. To the extent possible, the Licensor waives any right to
          collect royalties from You for the exercise of the Licensed
          Rights, whether directly or through a collecting society
          under any voluntary or waivable statutory or compulsory
          licensing scheme. In all other cases the Licensor expressly
          reserves any right to collect such royalties, including when
          the Licensed Material is used other than for NonCommercial
          purposes.


Section 3 -- License Conditions.

Your exercise of the Licensed Rights is expressly made subject to the
following conditions.

  a. Attribution.

       1. If You Share the Licensed Material, You must:

            a. retain the following if it is supplied by the Licensor
               with the Licensed Material:

                 i. identification of the creator(s) of the Licensed
                    Material and any others designated to receive
                    attribution, in any reasonable manner requested by
                    the Licensor (including by pseudonym if
                    designated);

                ii. a copyright notice;

               iii. a notice that refers to this Public License;

                iv. a notice that refers to the disclaimer of
                    warranties;

                 v. a URI or hyperlink to the Licensed Material to the
                    extent reasonably practicable;

            b. indicate if You modified the Licensed Material and
               retain an indication of any previous modifications; and

            c. indicate the Licensed Material is licensed under this
               Public License, and include the text of, or the URI or
               hyperlink to, this Public License.

          For the avoidance of doubt, You do not have permission under
          this Public License to Share Adapted Material.

       2. You may satisfy the conditions in Section 3(a)(1) in any
          reasonable manner based on the medium, means, and context in
          which You Share the Licensed Material. For example, it may be
          reasonable to satisfy the conditions by providing a URI or
          hyperlink to a resource that includes the required
          information.

       3. If requested by the Licensor, You must remove any of the
          information required by Section 3(a)(1)(A) to the extent
          reasonably practicable.


Section 4 -- Sui Generis Database Rights.

Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:

  a. for the avoidance of doubt, Section 2(a)(1) grants You the right
     to extract, reuse, reproduce, and Share all or a substantial
     portion of the contents of the database for NonCommercial purposes
     only and provided You do not Share Adapted Material;

  b. if You include all or a substantial portion of the database
     contents in a database in which You have Sui Generis Database
     Rights, then the database in which You have Sui Generis Database
     Rights (but not its individual contents) is Adapted Material; and

  c. You must comply with the conditions in Section 3(a) if You Share
     all or a substantial portion of the contents of the database.

For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.


Section 5 -- Disclaimer of Warranties and Limitation of Liability.

  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.

  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.

  c. The disclaimer of warranties and limitation of liability provided
     above shall be interpreted in a manner that, to the extent
     possible, most closely approximates an absolute disclaimer and
     waiver of all liability.


Section 6 -- Term and Termination.

  a. This Public License applies for the term of the Copyright and
     Similar Rights licensed here. However, if You fail to comply with
     this Public License, then Your rights under this Public License
     terminate automatically.

  b. Where Your right to use the Licensed Material has terminated under
     Section 6(a), it reinstates:

       1. automatically as of the date the violation is cured, provided
          it is cured within 30 days of Your discovery of the
          violation; or

       2. upon express reinstatement by the Licensor.

     For the avoidance of doubt, this Section 6(b) does not affect any
     right the Licensor may have to seek remedies for Your violations
     of this Public License.

  c. For the avoidance of doubt, the Licensor may also offer the
     Licensed Material under separate terms or conditions or stop
     distributing the Licensed Material at any time; however, doing so
     will not terminate this Public License.

  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
     License.


Section 7 -- Other Terms and Conditions.

  a. The Licensor shall not be bound by any additional or different
     terms or conditions communicated by You unless expressly agreed.

  b. Any arrangements, understandings, or agreements regarding the
     Licensed Material not stated herein are separate from and
     independent of the terms and conditions of this Public License.


Section 8 -- Interpretation.

  a. For the avoidance of doubt, this Public License does not, and
     shall not be interpreted to, reduce, limit, restrict, or impose
     conditions on any use of the Licensed Material that could lawfully
     be made without permission under this Public License.

  b. To the extent possible, if any provision of this Public License is
     deemed unenforceable, it shall be automatically reformed to the
     minimum extent necessary to make it enforceable. If the provision
     cannot be reformed, it shall be severed from this Public License
     without affecting the enforceability of the remaining terms and
     conditions.

  c. No term or condition of this Public License will be waived and no
     failure to comply consented to unless expressly agreed to by the
     Licensor.

  d. Nothing in this Public License constitutes or may be interpreted
     as a limitation upon, or waiver of, any privileges and immunities
     that apply to the Licensor or You, including from the legal
     processes of any jurisdiction or authority.

=======================================================================

Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.

Creative Commons may be contacted at creativecommons.org.



================================================
FILE: README.md
================================================
## dMaSIF - Fast end-to-end learning on protein surfaces
![Method overview](overview.PNG)

## Abstract

Proteins’ biological functions are defined by the geometric
and chemical structure of their 3D molecular surfaces.
Recent works have shown that geometric deep learning can
be used on mesh-based representations of proteins to identify
potential functional sites, such as binding targets for
potential drugs. Unfortunately though, the use of meshes as
the underlying representation for protein structure has multiple
drawbacks including the need to pre-compute the input
features and mesh connectivities. This becomes a bottleneck
for many important tasks in protein science.

In this paper, we present a new framework for deep
learning on protein structures that addresses these limitations.
Among the key advantages of our method are the computation
and sampling of the molecular surface on-the-fly
from the underlying atomic point cloud and a novel efficient
geometric convolutional layer. As a result, we are able to
process large collections of proteins in an end-to-end fashion,
taking as the sole input the raw 3D coordinates and
chemical types of their atoms, eliminating the need for any
hand-crafted pre-computed features.

To showcase the performance of our approach, we test it
on two tasks in the field of protein structural bioinformatics:
the identification of interaction sites and the prediction
of protein-protein interactions. On both tasks, we achieve
state-of-the-art performance with much faster run times and
fewer parameters than previous models. These results will
considerably ease the deployment of deep learning methods
in protein science and open the door for end-to-end differentiable
approaches in protein modeling tasks such as function
prediction and design.

## Hardware requirements

Models have been trained on either a single NVIDIA RTX 2080 Ti or a single Tesla V100 GPU. Time and memory benchmarks were performed on a single Tesla V100.

## Software prerequisites 

Scripts have been tested using the following two sets of core dependencies:

| Dependency | First Option  | Second Option |
| ------------- | ------------- | ------------- |
| GCC | 7.5.0 | 8.4.0 |
| CMAKE | 3.10.2 | 3.16.5 |
| CUDA | 10.0.130 | 10.2.89  |
| cuDNN | 7.6.4.38  | 7.6.5.32  |
| Python | 3.6.9  | 3.7.7  |
| PyTorch | 1.4.0  | 1.6.0  |
| PyKeops | 1.4  | 1.4.1  |
| PyTorch Geometric | 1.5.0  | 1.6.1  |


## Code overview


Usage:
- In order to **train models**, run `main_training.py` with the appropriate flags. 
Available flags and their descriptions can be found in `Arguments.py`.

- The command line options needed to reproduce the **benchmarks** can be found in `benchmark_scripts/`.

- To make **inference** on the testing set using pretrained models, use `main_inference.py` with the flags that were used for training the models. 
Note that the `--experiment_name flag` should be modified to specify the training epoch to use.

Implementation:
- Our **surface generation** algorithm, **curvature** estimation method and **quasi-geodesic convolutions** are implemented in `geometry_processing.py`.

- The **definition of the neural network** along with surface and input features can be found in `model.py`. The convolutional layers are implemented in `benchmark_models.py`.

- The scripts used to **generate the figures** of the paper can be found in `data_analysis/`.


## License

<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License</a>.

## Reference

Sverrisson, F., Feydy, J., Correia, B. E., & Bronstein, M. M. (2020). Fast end-to-end learning on protein surfaces. [bioRxiv](https://www.biorxiv.org/content/10.1101/2020.12.28.424589v1).

================================================
FILE: benchmark_layers.py
================================================
import torch
from typing import Optional
from pykeops.torch import LazyTensor
from torch_geometric.nn import EdgeConv, Reshape

from torch_cluster import knn

from math import ceil
from torch_geometric.nn.inits import reset

from torch.nn import ELU, Conv1d
from torch.nn import Sequential as S, Linear as L, BatchNorm1d as BN


def ranges_slices(batch):
    """Helper function for the diagonal ranges function."""
    Ns = batch.bincount()
    indices = Ns.cumsum(0)
    ranges = torch.cat((0 * indices[:1], indices))
    ranges = (
        torch.stack((ranges[:-1], ranges[1:])).t().int().contiguous().to(batch.device)
    )
    slices = (1 + torch.arange(len(Ns))).int().to(batch.device)

    return ranges, slices


def diagonal_ranges(batch_x=None, batch_y=None):
    """Encodes the block-diagonal structure associated to a batch vector."""

    if batch_x is None and batch_y is None:
        return None

    ranges_x, slices_x = ranges_slices(batch_x)
    ranges_y, slices_y = ranges_slices(batch_y)

    return ranges_x, slices_x, ranges_y, ranges_y, slices_y, ranges_x


@torch.jit.ignore
def keops_knn(
    x: torch.Tensor,
    y: torch.Tensor,
    k: int,
    batch_x: Optional[torch.Tensor] = None,
    batch_y: Optional[torch.Tensor] = None,
    cosine: bool = False,
) -> torch.Tensor:
    r"""Straightforward modification of PyTorch_geometric's knn method."""

    x = x.view(-1, 1) if x.dim() == 1 else x
    y = y.view(-1, 1) if y.dim() == 1 else y

    y_i = LazyTensor(y[:, None, :])
    x_j = LazyTensor(x[None, :, :])

    if cosine:
        D_ij = -(y_i | x_j)
    else:
        D_ij = ((y_i - x_j) ** 2).sum(-1)

    D_ij.ranges = diagonal_ranges(batch_y, batch_x)
    idy = D_ij.argKmin(k, dim=1)  # (N, K)

    rows = torch.arange(k * len(y), device=idy.device) // k

    return torch.stack([rows, idy.view(-1)], dim=0)


knns = {"torch": knn, "keops": keops_knn}


@torch.jit.ignore
def knn_graph(
    x: torch.Tensor,
    k: int,
    batch: Optional[torch.Tensor] = None,
    loop: bool = False,
    flow: str = "source_to_target",
    cosine: bool = False,
    target: Optional[torch.Tensor] = None,
    batch_target: Optional[torch.Tensor] = None,
    backend: str = "torch",
) -> torch.Tensor:
    r"""Straightforward modification of PyTorch_geometric's knn_graph method to allow for source/targets."""

    assert flow in ["source_to_target", "target_to_source"]
    if target is None:
        target = x
    if batch_target is None:
        batch_target = batch

    row, col = knns[backend](
        x, target, k if loop else k + 1, batch, batch_target, cosine=cosine
    )
    row, col = (col, row) if flow == "source_to_target" else (row, col)
    if not loop:
        mask = row != col
        row, col = row[mask], col[mask]
    return torch.stack([row, col], dim=0)


class MyDynamicEdgeConv(EdgeConv):
    r"""Straightforward modification of PyTorch_geometric's DynamicEdgeConv layer."""

    def __init__(self, nn, k, aggr="max", **kwargs):
        super(MyDynamicEdgeConv, self).__init__(nn=nn, aggr=aggr, **kwargs)
        self.k = k

    def forward(self, x, batch=None):
        """"""
        edge_index = knn_graph(
            x, self.k, batch, loop=False, flow=self.flow, backend="keops"
        )
        return super(MyDynamicEdgeConv, self).forward(x, edge_index)

    def __repr__(self):
        return "{}(nn={}, k={})".format(self.__class__.__name__, self.nn, self.k)


class MyXConv(torch.nn.Module):
    def __init__(
        self,
        in_channels=None,
        out_channels=None,
        dim=None,
        kernel_size=None,
        hidden_channels=None,
        dilation=1,
        bias=True,
        backend="torch",
    ):
        super(MyXConv, self).__init__()

        self.in_channels = in_channels
        if hidden_channels is None:
            hidden_channels = in_channels // 4
        if hidden_channels == 0:
            hidden_channels = 1

        self.hidden_channels = hidden_channels
        self.out_channels = out_channels
        self.dim = dim
        self.kernel_size = kernel_size
        self.dilation = dilation
        self.backend = backend

        C_in, C_delta, C_out = in_channels, hidden_channels, out_channels
        D, K = dim, kernel_size

        self.mlp1 = S(
            L(dim, C_delta),
            ELU(),
            BN(C_delta),
            L(C_delta, C_delta),
            ELU(),
            BN(C_delta),
            Reshape(-1, K, C_delta),
        )

        self.mlp2 = S(
            L(D * K, K ** 2),
            ELU(),
            BN(K ** 2),
            Reshape(-1, K, K),
            Conv1d(K, K ** 2, K, groups=K),
            ELU(),
            BN(K ** 2),
            Reshape(-1, K, K),
            Conv1d(K, K ** 2, K, groups=K),
            BN(K ** 2),
            Reshape(-1, K, K),
        )

        C_in = C_in + C_delta
        depth_multiplier = int(ceil(C_out / C_in))
        self.conv = S(
            Conv1d(C_in, C_in * depth_multiplier, K, groups=C_in),
            Reshape(-1, C_in * depth_multiplier),
            L(C_in * depth_multiplier, C_out, bias=bias),
        )

        self.reset_parameters()

    def reset_parameters(self):
        reset(self.mlp1)
        reset(self.mlp2)
        reset(self.conv)

    def forward(self, x, source, batch_source, target, batch_target):
        """"""
        # Load data shapes:
        # pos = pos.unsqueeze(-1) if pos.dim() == 1 else pos
        (Nin, _), (N, D), K = source.size(), target.size(), self.kernel_size

        # Compute K-nn:
        row, col = knn_graph(
            source,
            K * self.dilation,
            batch_source,
            loop=True,
            flow="target_to_source",
            target=target,
            batch_target=batch_target,
            backend=self.backend,
        )
        # row is a vector of size N*K*dilation that indexes "target"
        # col is a vector of size N*K*dilation that indexes "source"

        # If needed, sup-sample the K-NN graph:
        if self.dilation > 1:
            dil = self.dilation
            index = torch.randint(
                K * dil,
                (N, K),
                dtype=torch.long,
                layout=torch.strided,
                device=row.device,
            )
            arange = torch.arange(N, dtype=torch.long, device=row.device)
            arange = arange * (K * dil)
            index = (index + arange.view(-1, 1)).view(-1)  # (N*K,)
            row, col = row[index], col[index]

        # assert row.max() < N
        # assert col.max() < Nin

        # Line 1: local difference vector:
        pos = source[col] - target[row]  # (N * K, D)

        # Line 2: compute F_delta
        x_star = self.mlp1(pos.view(N * K, D))

        # Line 3: concatenate the features and reshape:
        if x is not None:
            x = x.unsqueeze(-1) if x.dim() == 1 else x
            x = x[col].view(N, K, self.in_channels)
            x_star = torch.cat([x_star, x], dim=-1)
        x_star = x_star.transpose(1, 2).contiguous()
        x_star = x_star.view(N, self.in_channels + self.hidden_channels, K, 1)

        # Line 4: Compute the transformation matrix:
        transform_matrix = self.mlp2(pos.view(N, K * D))
        transform_matrix = transform_matrix.view(N, 1, K, K)

        # Line 5: Apply it to the neighborhood:
        x_transformed = torch.matmul(transform_matrix, x_star)
        x_transformed = x_transformed.view(N, -1, K)  # (N, I+H, K)

        # Line 6: Apply the convolution filter:
        out = self.conv(x_transformed)  # (N, Cout)

        return out

    def __repr__(self):
        return "{}({}, {})".format(
            self.__class__.__name__, self.in_channels, self.out_channels
        )


================================================
FILE: benchmark_models.py
================================================
import torch
import torch.nn.functional as F
import torch.nn as nn
from torch.nn import (
    Sequential as Seq,
    Dropout,
    Linear as Lin,
    LeakyReLU,
    ReLU,
    BatchNorm1d as BN,
)
import torch_geometric.transforms as T
from torch_geometric.data import DataLoader
from torch_geometric.nn import (
    DynamicEdgeConv,
    PointConv,
    XConv,
    fps,
    radius,
    global_max_pool,
    knn_interpolate,
)
from pykeops.torch import LazyTensor

from benchmark_layers import MyDynamicEdgeConv, MyXConv
from geometry_processing import dMaSIFConv, mesh_normals_areas, tangent_vectors
from helper import diagonal_ranges

DEConv = {"torch": DynamicEdgeConv, "keops": MyDynamicEdgeConv}

# Dynamic Graph CNNs ===========================================================
# Adapted from the PyTorch_geometric gallery to get a close fit to
# the original paper.


def MLP(channels, batch_norm=True):
    """Multi-layer perceptron, with ReLU non-linearities and batch normalization."""
    return Seq(
        *[
            Seq(
                Lin(channels[i - 1], channels[i]),
                BN(channels[i]) if batch_norm else nn.Identity(),
                LeakyReLU(negative_slope=0.2),
            )
            for i in range(1, len(channels))
        ]
    )


class DGCNN_seg(torch.nn.Module):
    def __init__(
        self, in_channels, out_channels, n_layers, k=40, aggr="max", backend="keops"
    ):
        super(DGCNN_seg, self).__init__()

        self.name = "DGCNN_seg_" + backend
        self.I, self.O = (
            in_channels + 3,
            out_channels,
        )  # Add coordinates to input channels
        self.n_layers = n_layers

        self.transform_1 = DEConv[backend](MLP([2 * 3, 64, 128]), k, aggr)
        self.transform_2 = MLP([128, 1024])
        self.transform_3 = MLP([1024, 512, 256], batch_norm=False)
        self.transform_4 = Lin(256, 3 * 3)

        self.conv_layers = nn.ModuleList(
            [DEConv[backend](MLP([2 * self.I, self.O, self.O]), k, aggr)]
            + [
                DEConv[backend](MLP([2 * self.O, self.O, self.O]), k, aggr)
                for i in range(n_layers - 1)
            ]
        )

        self.linear_layers = nn.ModuleList(
            [
                nn.Sequential(
                    nn.Linear(self.O, self.O), nn.ReLU(), nn.Linear(self.O, self.O)
                )
                for i in range(n_layers)
            ]
        )

        self.linear_transform = nn.ModuleList(
            [nn.Linear(self.I, self.O)]
            + [nn.Linear(self.O, self.O) for i in range(n_layers - 1)]
        )

    def forward(self, positions, features, batch_indices):
        # Lab: (B,), Pos: (N, 3), Batch: (N,)
        pos, feat, batch = positions, features, batch_indices

        # TransformNet:
        x = pos  # Don't use the normals!

        x = self.transform_1(x, batch)  # (N, 3) -> (N, 128)
        x = self.transform_2(x)  # (N, 128) -> (N, 1024)
        x = global_max_pool(x, batch)  # (B, 1024)

        x = self.transform_3(x)  # (B, 256)
        x = self.transform_4(x)  # (B, 3*3)
        x = x[batch]  # (N, 3*3)
        x = x.view(-1, 3, 3)  # (N, 3, 3)

        # Apply the transform:
        x0 = torch.einsum("ni,nij->nj", pos, x)  # (N, 3)

        # Add features to coordinates
        x = torch.cat([x0, feat], dim=-1).contiguous()

        for i in range(self.n_layers):
            x_i = self.conv_layers[i](x, batch)
            x_i = self.linear_layers[i](x_i)
            x = self.linear_transform[i](x)
            x = x + x_i

        return x


# Reference PointNet models, from the PyTorch_geometric gallery =========================


class SAModule(torch.nn.Module):
    """Set abstraction module."""

    def __init__(self, ratio, r, nn, max_num_neighbors=64):
        super(SAModule, self).__init__()
        self.ratio = ratio
        self.r = r
        self.conv = PointConv(nn)
        self.max_num_neighbors = max_num_neighbors

    def forward(self, x, pos, batch):
        # Subsample with Farthest Point Sampling:
        # idx = fps(pos, batch, ratio=self.ratio)  # Extract self.ratio indices TURN OFF FOR NOW
        idx = torch.arange(0, len(pos), device=pos.device)

        # For each "cluster", get the list of (up to 64) neighbors in a ball of radius r:
        row, col = radius(
            pos,
            pos[idx],
            self.r,
            batch,
            batch[idx],
            max_num_neighbors=self.max_num_neighbors,
        )

        # Applies the PointNet++ Conv:
        edge_index = torch.stack([col, row], dim=0)
        x = self.conv(x, (pos, pos[idx]), edge_index)

        # Return the features and sub-sampled point clouds:
        pos, batch = pos[idx], batch[idx]
        return x, pos, batch


class GlobalSAModule(torch.nn.Module):
    def __init__(self, nn):
        super(GlobalSAModule, self).__init__()
        self.nn = nn

    def forward(self, x, pos, batch):
        x = self.nn(torch.cat([x, pos], dim=1))
        x = global_max_pool(x, batch)
        pos = pos.new_zeros((x.size(0), 3))
        batch = torch.arange(x.size(0), device=batch.device)
        return x, pos, batch


class FPModule(torch.nn.Module):
    def __init__(self, k, nn):
        super(FPModule, self).__init__()
        self.k = k
        self.nn = nn

    def forward(self, x, pos, batch, x_skip, pos_skip, batch_skip):
        x = knn_interpolate(x, pos, pos_skip, batch, batch_skip, k=self.k)
        if x_skip is not None:
            x = torch.cat([x, x_skip], dim=1)
        x = self.nn(x)
        return x, pos_skip, batch_skip


class PointNet2_seg(torch.nn.Module):
    def __init__(self, args, in_channels, out_channels):
        super(PointNet2_seg, self).__init__()

        self.name = "PointNet2"
        self.I, self.O = in_channels, out_channels
        self.radius = args.radius
        self.k = 10000  # We don't restrict the number of points in a patch
        self.n_layers = args.n_layers

        # self.sa1_module = SAModule(1.0, self.radius, MLP([self.I+3, self.O, self.O]),self.k)
        self.layers = nn.ModuleList(
            [SAModule(1.0, self.radius, MLP([self.I + 3, self.O, self.O]), self.k)]
            + [
                SAModule(1.0, self.radius, MLP([self.O + 3, self.O, self.O]), self.k)
                for i in range(self.n_layers - 1)
            ]
        )

        self.linear_layers = nn.ModuleList(
            [
                nn.Sequential(
                    nn.Linear(self.O, self.O), nn.ReLU(), nn.Linear(self.O, self.O)
                )
                for i in range(self.n_layers)
            ]
        )

        self.linear_transform = nn.ModuleList(
            [nn.Linear(self.I, self.O)]
            + [nn.Linear(self.O, self.O) for i in range(self.n_layers - 1)]
        )

    def forward(self, positions, features, batch_indices):
        x = (features, positions, batch_indices)
        for i, layer in enumerate(self.layers):
            x_i, pos, b_ind = layer(*x)
            x_i = self.linear_layers[i](x_i)
            x = self.linear_transform[i](x[0])
            x = x + x_i
            x = (x, pos, b_ind)

        return x[0]


## TangentConv benchmark segmentation


class dMaSIFConv_seg(torch.nn.Module):
    def __init__(self, args, in_channels, out_channels, n_layers, radius=9.0):
        super(dMaSIFConv_seg, self).__init__()

        self.name = "dMaSIFConv_seg_keops"
        self.radius = radius
        self.I, self.O = in_channels, out_channels

        self.layers = nn.ModuleList(
            [dMaSIFConv(self.I, self.O, radius, self.O)]
            + [dMaSIFConv(self.O, self.O, radius, self.O) for i in range(n_layers - 1)]
        )

        self.linear_layers = nn.ModuleList(
            [
                nn.Sequential(
                    nn.Linear(self.O, self.O), nn.ReLU(), nn.Linear(self.O, self.O)
                )
                for i in range(n_layers)
            ]
        )

        self.linear_transform = nn.ModuleList(
            [nn.Linear(self.I, self.O)]
            + [nn.Linear(self.O, self.O) for i in range(n_layers - 1)]
        )

    def forward(self, features):
        # Lab: (B,), Pos: (N, 3), Batch: (N,)
        points, nuv, ranges = self.points, self.nuv, self.ranges
        x = features
        for i, layer in enumerate(self.layers):
            x_i = layer(points, nuv, x, ranges)
            x_i = self.linear_layers[i](x_i)
            x = self.linear_transform[i](x)
            x = x + x_i

        return x

    def load_mesh(self, xyz, triangles=None, normals=None, weights=None, batch=None):
        """Loads the geometry of a triangle mesh.

        Input arguments:
        - xyz, a point cloud encoded as an (N, 3) Tensor.
        - triangles, a connectivity matrix encoded as an (N, 3) integer tensor.
        - weights, importance weights for the orientation estimation, encoded as an (N, 1) Tensor.
        - radius, the scale used to estimate the local normals.
        - a batch vector, following PyTorch_Geometric's conventions.

        The routine updates the model attributes:
        - points, i.e. the point cloud itself,
        - nuv, a local oriented basis in R^3 for every point,
        - ranges, custom KeOps syntax to implement batch processing.
        """

        # 1. Save the vertices for later use in the convolutions ---------------
        self.points = xyz
        self.batch = batch
        self.ranges = diagonal_ranges(
            batch
        )  # KeOps support for heterogeneous batch processing
        self.triangles = triangles
        self.normals = normals
        self.weights = weights

        # 2. Estimate the normals and tangent frame ----------------------------
        # Normalize the scale:
        points = xyz / self.radius

        # Normals and local areas:
        if normals is None:
            normals, areas = mesh_normals_areas(points, triangles, 0.5, batch)
        tangent_bases = tangent_vectors(normals)  # Tangent basis (N, 2, 3)

        # 3. Steer the tangent bases according to the gradient of "weights" ----

        # 3.a) Encoding as KeOps LazyTensors:
        # Orientation scores:
        weights_j = LazyTensor(weights.view(1, -1, 1))  # (1, N, 1)
        # Vertices:
        x_i = LazyTensor(points[:, None, :])  # (N, 1, 3)
        x_j = LazyTensor(points[None, :, :])  # (1, N, 3)
        # Normals:
        n_i = LazyTensor(normals[:, None, :])  # (N, 1, 3)
        n_j = LazyTensor(normals[None, :, :])  # (1, N, 3)
        # Tangent basis:
        uv_i = LazyTensor(tangent_bases.view(-1, 1, 6))  # (N, 1, 6)

        # 3.b) Pseudo-geodesic window:
        # Pseudo-geodesic squared distance:
        rho2_ij = ((x_j - x_i) ** 2).sum(-1) * ((2 - (n_i | n_j)) ** 2)  # (N, N, 1)
        # Gaussian window:
        window_ij = (-rho2_ij).exp()  # (N, N, 1)

        # 3.c) Coordinates in the (u, v) basis - not oriented yet:
        X_ij = uv_i.matvecmult(x_j - x_i)  # (N, N, 2)

        # 3.d) Local average in the tangent plane:
        orientation_weight_ij = window_ij * weights_j  # (N, N, 1)
        orientation_vector_ij = orientation_weight_ij * X_ij  # (N, N, 2)

        # Support for heterogeneous batch processing:
        orientation_vector_ij.ranges = self.ranges  # Block-diagonal sparsity mask

        orientation_vector_i = orientation_vector_ij.sum(dim=1)  # (N, 2)
        orientation_vector_i = (
            orientation_vector_i + 1e-5
        )  # Just in case someone's alone...

        # 3.e) Normalize stuff:
        orientation_vector_i = F.normalize(orientation_vector_i, p=2, dim=-1)  #  (N, 2)
        ex_i, ey_i = (
            orientation_vector_i[:, 0][:, None],
            orientation_vector_i[:, 1][:, None],
        )  # (N,1)

        # 3.f) Re-orient the (u,v) basis:
        uv_i = tangent_bases  # (N, 2, 3)
        u_i, v_i = uv_i[:, 0, :], uv_i[:, 1, :]  # (N, 3)
        tangent_bases = torch.cat(
            (ex_i * u_i + ey_i * v_i, -ey_i * u_i + ex_i * v_i), dim=1
        ).contiguous()  # (N, 6)

        # 4. Store the local 3D frame as an attribute --------------------------
        self.nuv = torch.cat(
            (normals.view(-1, 1, 3), tangent_bases.view(-1, 2, 3)), dim=1
        )


================================================
FILE: benchmark_scripts/DGCNN_site.sh
================================================
# Load environment
python -W ignore -u main_training.py --experiment_name DGCNN_site_1layer_k200 --batch_size 64 --embedding_layer DGCNN --site True --single_protein True --device cuda:0 --n_layers 1 --random_rotation True --k 200
python -W ignore -u main_training.py --experiment_name DGCNN_site_1layer_k100 --batch_size 64 --embedding_layer DGCNN --site True --single_protein True --device cuda:0 --n_layers 1 --random_rotation True --k 100

python -W ignore -u main_training.py --experiment_name DGCNN_site_3layer_k200 --batch_size 64 --embedding_layer DGCNN --site True --single_protein True --device cuda:0 --n_layers 3 --random_rotation True --k 200
python -W ignore -u main_training.py --experiment_name DGCNN_site_3layer_k100 --batch_size 64 --embedding_layer DGCNN --site True --single_protein True --device cuda:0 --n_layers 3 --random_rotation True --k 100

================================================
FILE: benchmark_scripts/Pointnet_site.sh
================================================
# Load environment
python -W ignore -u main_training.py --experiment_name PointNet_site_3layer_15A --batch_size 64 --embedding_layer PointNet++ --site True --single_protein True --device cuda:0 --random_rotation True --radius 15.0 --n_layers 3
python -W ignore -u main_training.py --experiment_name PointNet_site_3layer_5A --batch_size 64 --embedding_layer PointNet++ --site True --single_protein True --device cuda:0 --random_rotation True --radius 5.0 --n_layers 3
python -W ignore -u main_training.py --experiment_name PointNet_site_3layer_9A --batch_size 64 --embedding_layer PointNet++ --site True --single_protein True --device cuda:0 --random_rotation True --radius 9.0 --n_layers 3

python -W ignore -u main_training.py --experiment_name PointNet_site_1layer_15A --batch_size 64 --embedding_layer PointNet++ --site True --single_protein True --device cuda:0 --random_rotation True --radius 15.0 --n_layers 1
python -W ignore -u main_training.py --experiment_name PointNet_site_1layer_5A --batch_size 64 --embedding_layer PointNet++ --site True --single_protein True --device cuda:0 --random_rotation True --radius 5.0 --n_layers 1
python -W ignore -u main_training.py --experiment_name PointNet_site_1layer_9A --batch_size 64 --embedding_layer PointNet++ --site True --single_protein True --device cuda:0 --random_rotation True --radius 9.0 --n_layers 1

================================================
FILE: benchmark_scripts/dMaSIF_search.sh
================================================
# Load environment
python -W ignore -u main_training.py --experiment_name dMaSIF_search_1layer_12A --batch_size 64 --embedding_layer dMaSIF --search True --device cuda:0 --random_rotation True --radius 12.0 --n_layers 1
python -W ignore -u main_training.py --experiment_name dMaSIF_search_3layer_12A --batch_size 64 --embedding_layer dMaSIF --search True --device cuda:0 --random_rotation True --radius 12.0 --n_layers 3


================================================
FILE: benchmark_scripts/dMaSIF_site.sh
================================================
# Load environment
python -W ignore -u main_training.py --experiment_name dMaSIF_site_1layer_15A --batch_size 64 --embedding_layer dMaSIF --site True --single_protein True --random_rotation True --radius 15.0 --n_layers 1
python -W ignore -u main_training.py --experiment_name dMaSIF_site_1layer_5A --batch_size 64 --embedding_layer dMaSIF --site True --single_protein True --random_rotation True --radius 5.0 --n_layers 1
python -W ignore -u main_training.py --experiment_name dMaSIF_site_1layer_9A --batch_size 64 --embedding_layer dMaSIF --site True --single_protein True --random_rotation True --radius 9.0 --n_layers 1

python -W ignore -u main_training.py --experiment_name dMaSIF_site_3layer_15A --batch_size 64 --embedding_layer dMaSIF --site True --single_protein True --random_rotation True --radius 15.0 --n_layers 3
python -W ignore -u main_training.py --experiment_name dMaSIF_site_3layer_5A --batch_size 64 --embedding_layer dMaSIF --site True --single_protein True --random_rotation True --radius 5.0 --n_layers 3
python -W ignore -u main_training.py --experiment_name dMaSIF_site_3layer_9A --batch_size 64 --embedding_layer dMaSIF --site True --single_protein True --random_rotation True --radius 9.0 --n_layers 3


================================================
FILE: data.py
================================================
import torch
from torch_geometric.data import InMemoryDataset, Data, DataLoader
from torch_geometric.transforms import Compose
import numpy as np
from scipy.spatial.transform import Rotation
import math
import urllib.request
import tarfile
from pathlib import Path
import requests
from data_preprocessing.convert_pdb2npy import convert_pdbs
from data_preprocessing.convert_ply2npy import convert_plys

tensor = torch.FloatTensor
inttensor = torch.LongTensor


def numpy(x):
    return x.detach().cpu().numpy()


def iface_valid_filter(protein_pair):
    labels1 = protein_pair.y_p1.reshape(-1)
    labels2 = protein_pair.y_p2.reshape(-1)
    valid1 = (
        (torch.sum(labels1) < 0.75 * len(labels1))
        and (torch.sum(labels1) > 30)
        and (torch.sum(labels1) > 0.01 * labels2.shape[0])
    )
    valid2 = (
        (torch.sum(labels2) < 0.75 * len(labels2))
        and (torch.sum(labels2) > 30)
        and (torch.sum(labels2) > 0.01 * labels1.shape[0])
    )

    return valid1 and valid2


class RandomRotationPairAtoms(object):
    r"""Randomly rotate a protein"""

    def __call__(self, data):
        R1 = tensor(Rotation.random().as_matrix())
        R2 = tensor(Rotation.random().as_matrix())

        data.atom_coords_p1 = torch.matmul(R1, data.atom_coords_p1.T).T
        data.xyz_p1 = torch.matmul(R1, data.xyz_p1.T).T
        data.normals_p1 = torch.matmul(R1, data.normals_p1.T).T

        data.atom_coords_p2 = torch.matmul(R2, data.atom_coords_p2.T).T
        data.xyz_p2 = torch.matmul(R2, data.xyz_p2.T).T
        data.normals_p2 = torch.matmul(R2, data.normals_p2.T).T

        data.rand_rot1 = R1
        data.rand_rot2 = R2
        return data

    def __repr__(self):
        return "{}()".format(self.__class__.__name__)


class CenterPairAtoms(object):
    r"""Centers a protein"""

    def __call__(self, data):
        atom_center1 = data.atom_coords_p1.mean(dim=-2, keepdim=True)
        atom_center2 = data.atom_coords_p2.mean(dim=-2, keepdim=True)

        data.atom_coords_p1 = data.atom_coords_p1 - atom_center1
        data.atom_coords_p2 = data.atom_coords_p2 - atom_center2

        data.xyz_p1 = data.xyz_p1 - atom_center1
        data.xyz_p2 = data.xyz_p2 - atom_center2

        data.atom_center1 = atom_center1
        data.atom_center2 = atom_center2
        return data

    def __repr__(self):
        return "{}()".format(self.__class__.__name__)


class NormalizeChemFeatures(object):
    r"""Centers a protein"""

    def __call__(self, data):
        pb_upper = 3.0
        pb_lower = -3.0

        chem_p1 = data.chemical_features_p1
        chem_p2 = data.chemical_features_p2

        pb_p1 = chem_p1[:, 0]
        pb_p2 = chem_p2[:, 0]
        hb_p1 = chem_p1[:, 1]
        hb_p2 = chem_p2[:, 1]
        hp_p1 = chem_p1[:, 2]
        hp_p2 = chem_p2[:, 2]

        # Normalize PB
        pb_p1 = torch.clamp(pb_p1, pb_lower, pb_upper)
        pb_p1 = (pb_p1 - pb_lower) / (pb_upper - pb_lower)
        pb_p1 = 2 * pb_p1 - 1

        pb_p2 = torch.clamp(pb_p2, pb_lower, pb_upper)
        pb_p2 = (pb_p2 - pb_lower) / (pb_upper - pb_lower)
        pb_p2 = 2 * pb_p2 - 1

        # Normalize HP
        hp_p1 = hp_p1 / 4.5
        hp_p2 = hp_p2 / 4.5

        data.chemical_features_p1 = torch.stack([pb_p1, hb_p1, hp_p1]).T
        data.chemical_features_p2 = torch.stack([pb_p2, hb_p2, hp_p2]).T

        return data

    def __repr__(self):
        return "{}()".format(self.__class__.__name__)


def load_protein_npy(pdb_id, data_dir, center=False, single_pdb=False):
    """Loads a protein surface mesh and its features"""

    # Load the data, and read the connectivity information:
    triangles = (
        None
        if single_pdb
        else inttensor(np.load(data_dir / (pdb_id + "_triangles.npy"))).T
    )
    # Normalize the point cloud, as specified by the user:
    points = None if single_pdb else tensor(np.load(data_dir / (pdb_id + "_xyz.npy")))
    center_location = None if single_pdb else torch.mean(points, axis=0, keepdims=True)

    atom_coords = tensor(np.load(data_dir / (pdb_id + "_atomxyz.npy")))
    atom_types = tensor(np.load(data_dir / (pdb_id + "_atomtypes.npy")))

    if center:
        points = points - center_location
        atom_coords = atom_coords - center_location

    # Interface labels
    iface_labels = (
        None
        if single_pdb
        else tensor(np.load(data_dir / (pdb_id + "_iface_labels.npy")).reshape((-1, 1)))
    )

    # Features
    chemical_features = (
        None if single_pdb else tensor(np.load(data_dir / (pdb_id + "_features.npy")))
    )

    # Normals
    normals = (
        None if single_pdb else tensor(np.load(data_dir / (pdb_id + "_normals.npy")))
    )

    protein_data = Data(
        xyz=points,
        face=triangles,
        chemical_features=chemical_features,
        y=iface_labels,
        normals=normals,
        center_location=center_location,
        num_nodes=None if single_pdb else points.shape[0],
        atom_coords=atom_coords,
        atom_types=atom_types,
    )
    return protein_data


class PairData(Data):
    def __init__(
        self,
        xyz_p1=None,
        xyz_p2=None,
        face_p1=None,
        face_p2=None,
        chemical_features_p1=None,
        chemical_features_p2=None,
        y_p1=None,
        y_p2=None,
        normals_p1=None,
        normals_p2=None,
        center_location_p1=None,
        center_location_p2=None,
        atom_coords_p1=None,
        atom_coords_p2=None,
        atom_types_p1=None,
        atom_types_p2=None,
        atom_center1=None,
        atom_center2=None,
        rand_rot1=None,
        rand_rot2=None,
    ):
        super().__init__()
        self.xyz_p1 = xyz_p1
        self.xyz_p2 = xyz_p2
        self.face_p1 = face_p1
        self.face_p2 = face_p2

        self.chemical_features_p1 = chemical_features_p1
        self.chemical_features_p2 = chemical_features_p2
        self.y_p1 = y_p1
        self.y_p2 = y_p2
        self.normals_p1 = normals_p1
        self.normals_p2 = normals_p2
        self.center_location_p1 = center_location_p1
        self.center_location_p2 = center_location_p2
        self.atom_coords_p1 = atom_coords_p1
        self.atom_coords_p2 = atom_coords_p2
        self.atom_types_p1 = atom_types_p1
        self.atom_types_p2 = atom_types_p2
        self.atom_center1 = atom_center1
        self.atom_center2 = atom_center2
        self.rand_rot1 = rand_rot1
        self.rand_rot2 = rand_rot2

    def __inc__(self, key, value):
        if key == "face_p1":
            return self.xyz_p1.size(0)
        if key == "face_p2":
            return self.xyz_p2.size(0)
        else:
            return super(PairData, self).__inc__(key, value)

    def __cat_dim__(self, key, value):
        if ("index" in key) or ("face" in key):
            return 1
        else:
            return 0


def load_protein_pair(pdb_id, data_dir,single_pdb=False):
    """Loads a protein surface mesh and its features"""
    pspl = pdb_id.split("_")
    p1_id = pspl[0] + "_" + pspl[1]
    p2_id = pspl[0] + "_" + pspl[2]

    p1 = load_protein_npy(p1_id, data_dir, center=False,single_pdb=single_pdb)
    p2 = load_protein_npy(p2_id, data_dir, center=False,single_pdb=single_pdb)
    # pdist = ((p1['xyz'][:,None,:]-p2['xyz'][None,:,:])**2).sum(-1).sqrt()
    # pdist = pdist<2.0
    # y_p1 = (pdist.sum(1)>0).to(torch.float).reshape(-1,1)
    # y_p2 = (pdist.sum(0)>0).to(torch.float).reshape(-1,1)
    y_p1 = p1["y"]
    y_p2 = p2["y"]

    protein_pair_data = PairData(
        xyz_p1=p1["xyz"],
        xyz_p2=p2["xyz"],
        face_p1=p1["face"],
        face_p2=p2["face"],
        chemical_features_p1=p1["chemical_features"],
        chemical_features_p2=p2["chemical_features"],
        y_p1=y_p1,
        y_p2=y_p2,
        normals_p1=p1["normals"],
        normals_p2=p2["normals"],
        center_location_p1=p1["center_location"],
        center_location_p2=p2["center_location"],
        atom_coords_p1=p1["atom_coords"],
        atom_coords_p2=p2["atom_coords"],
        atom_types_p1=p1["atom_types"],
        atom_types_p2=p2["atom_types"],
    )
    return protein_pair_data


class ProteinPairsSurfaces(InMemoryDataset):
    url = ""

    def __init__(self, root, ppi=False, train=True, transform=None, pre_transform=None):
        self.ppi = ppi
        super(ProteinPairsSurfaces, self).__init__(root, transform, pre_transform)
        path = self.processed_paths[0] if train else self.processed_paths[1]
        self.data, self.slices = torch.load(path)

    @property
    def raw_file_names(self):
        return "masif_site_masif_search_pdbs_and_ply_files.tar.gz"

    @property
    def processed_file_names(self):
        if not self.ppi:
            file_names = [
                "training_pairs_data.pt",
                "testing_pairs_data.pt",
                "training_pairs_data_ids.npy",
                "testing_pairs_data_ids.npy",
            ]
        else:
            file_names = [
                "training_pairs_data_ppi.pt",
                "testing_pairs_data_ppi.pt",
                "training_pairs_data_ids_ppi.npy",
                "testing_pairs_data_ids_ppi.npy",
            ]
        return file_names

    def download(self):
        url = 'https://zenodo.org/record/2625420/files/masif_site_masif_search_pdbs_and_ply_files.tar.gz'
        target_path = self.raw_paths[0]
        response = requests.get(url, stream=True)
        if response.status_code == 200:
            with open(target_path, 'wb') as f:
                f.write(response.raw.read())
                
        #raise RuntimeError(
        #    "Dataset not found. Please download {} from {} and move it to {}".format(
        #        self.raw_file_names, self.url, self.raw_dir
        #    )
        #)

    def process(self):
        pdb_dir = Path(self.root) / "raw" / "01-benchmark_pdbs"
        surf_dir = Path(self.root) / "raw" / "01-benchmark_surfaces"
        protein_dir = Path(self.root) / "raw" / "01-benchmark_surfaces_npy"
        lists_dir = Path('./lists')

        # Untar surface files
        if not (pdb_dir.exists() and surf_dir.exists()):
            tar = tarfile.open(self.raw_paths[0])
            tar.extractall(self.raw_dir)
            tar.close()

        if not protein_dir.exists():
            protein_dir.mkdir(parents=False, exist_ok=False)
            convert_plys(surf_dir,protein_dir)
            convert_pdbs(pdb_dir,protein_dir)

        with open(lists_dir / "training.txt") as f_tr, open(
            lists_dir / "testing.txt"
        ) as f_ts:
            training_list = sorted(f_tr.read().splitlines())
            testing_list = sorted(f_ts.read().splitlines())

        with open(lists_dir / "training_ppi.txt") as f_tr, open(
            lists_dir / "testing_ppi.txt"
        ) as f_ts:
            training_pairs_list = sorted(f_tr.read().splitlines())
            testing_pairs_list = sorted(f_ts.read().splitlines())
            pairs_list = sorted(training_pairs_list + testing_pairs_list)

        if not self.ppi:
            training_pairs_list = []
            for p in pairs_list:
                pspl = p.split("_")
                p1 = pspl[0] + "_" + pspl[1]
                p2 = pspl[0] + "_" + pspl[2]

                if p1 in training_list:
                    training_pairs_list.append(p)
                if p2 in training_list:
                    training_pairs_list.append(pspl[0] + "_" + pspl[2] + "_" + pspl[1])

            testing_pairs_list = []
            for p in pairs_list:
                pspl = p.split("_")
                p1 = pspl[0] + "_" + pspl[1]
                p2 = pspl[0] + "_" + pspl[2]
                if p1 in testing_list:
                    testing_pairs_list.append(p)
                if p2 in testing_list:
                    testing_pairs_list.append(pspl[0] + "_" + pspl[2] + "_" + pspl[1])

        # # Read data into huge `Data` list.
        training_pairs_data = []
        training_pairs_data_ids = []
        for p in training_pairs_list:
            try:
                protein_pair = load_protein_pair(p, protein_dir)
            except FileNotFoundError:
                continue
            training_pairs_data.append(protein_pair)
            training_pairs_data_ids.append(p)

        testing_pairs_data = []
        testing_pairs_data_ids = []
        for p in testing_pairs_list:
            try:
                protein_pair = load_protein_pair(p, protein_dir)
            except FileNotFoundError:
                continue
            testing_pairs_data.append(protein_pair)
            testing_pairs_data_ids.append(p)

        if self.pre_filter is not None:
            training_pairs_data = [
                data for data in training_pairs_data if self.pre_filter(data)
            ]
            testing_pairs_data = [
                data for data in testing_pairs_data if self.pre_filter(data)
            ]

        if self.pre_transform is not None:
            training_pairs_data = [
                self.pre_transform(data) for data in training_pairs_data
            ]
            testing_pairs_data = [
                self.pre_transform(data) for data in testing_pairs_data
            ]

        training_pairs_data, training_pairs_slices = self.collate(training_pairs_data)
        torch.save(
            (training_pairs_data, training_pairs_slices), self.processed_paths[0]
        )
        np.save(self.processed_paths[2], training_pairs_data_ids)
        testing_pairs_data, testing_pairs_slices = self.collate(testing_pairs_data)
        torch.save((testing_pairs_data, testing_pairs_slices), self.processed_paths[1])
        np.save(self.processed_paths[3], testing_pairs_data_ids)


================================================
FILE: data_analysis/analyse_atomnet.ipynb
================================================
{
 "metadata": {
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7-final"
  },
  "orig_nbformat": 2,
  "kernelspec": {
   "name": "python37764bitvenvvenv0f8ab664edda4e43b2faa48ba983dc72",
   "display_name": "Python 3.7.7 64-bit ('venv': venv)"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2,
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from sklearn.metrics import mean_squared_error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "0.8289113443652403\n0.16479157\n"
     ]
    },
    {
     "output_type": "display_data",
     "data": {
      "text/plain": "<Figure size 432x288 with 1 Axes>",
      "image/svg+xml": "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n  \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<!-- Created with matplotlib (https://matplotlib.org/) -->\n<svg height=\"265.995469pt\" version=\"1.1\" viewBox=\"0 0 291.115 265.995469\" width=\"291.115pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <metadata>\n  <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n   <cc:Work>\n    <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n    <dc:date>2020-11-14T13:07:27.340743</dc:date>\n    <dc:format>image/svg+xml</dc:format>\n    <dc:creator>\n     <cc:Agent>\n      <dc:title>Matplotlib v3.3.2, https://matplotlib.org/</dc:title>\n     </cc:Agent>\n    </dc:creator>\n   </cc:Work>\n  </rdf:RDF>\n </metadata>\n <defs>\n  <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n </defs>\n <g id=\"figure_1\">\n  <g id=\"patch_1\">\n   <path d=\"M 0 265.995469 \nL 291.115 265.995469 \nL 291.115 0 \nL 0 0 \nz\n\" style=\"fill:none;\"/>\n  </g>\n  <g id=\"axes_1\">\n   <g id=\"patch_2\">\n    <path d=\"M 58.523438 228.439219 \nL 275.963437 228.439219 \nL 275.963437 10.999219 \nL 58.523438 10.999219 \nz\n\" style=\"fill:#ffffff;\"/>\n   </g>\n   <g id=\"PathCollection_1\">\n    <defs>\n     <path d=\"M 0 0.5 \nC 0.132602 0.5 0.25979 0.447317 0.353553 0.353553 \nC 0.447317 0.25979 0.5 0.132602 0.5 0 \nC 0.5 -0.132602 0.447317 -0.25979 0.353553 -0.353553 \nC 0.25979 -0.447317 0.132602 -0.5 0 -0.5 \nC -0.132602 -0.5 -0.25979 -0.447317 -0.353553 -0.353553 \nC -0.447317 -0.25979 -0.5 -0.132602 -0.5 0 \nC -0.5 0.132602 -0.447317 0.25979 -0.353553 0.353553 \nC -0.25979 0.447317 -0.132602 0.5 0 0.5 \nz\n\" id=\"md91571ca24\" style=\"stroke:#1f77b4;\"/>\n    </defs>\n    <g clip-path=\"url(#pd4d130ab8b)\">\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.44337\" xlink:href=\"#md91571ca24\" y=\"141.958379\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"107.303932\" xlink:href=\"#md91571ca24\" y=\"178.342521\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.657162\" xlink:href=\"#md91571ca24\" y=\"130.957431\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.423558\" xlink:href=\"#md91571ca24\" y=\"114.606713\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.494109\" xlink:href=\"#md91571ca24\" y=\"119.909365\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.367901\" xlink:href=\"#md91571ca24\" y=\"110.805951\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.129329\" xlink:href=\"#md91571ca24\" y=\"131.612228\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.38702\" xlink:href=\"#md91571ca24\" y=\"123.178228\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.902128\" xlink:href=\"#md91571ca24\" y=\"110.54833\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.655569\" xlink:href=\"#md91571ca24\" y=\"136.423971\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.597653\" xlink:href=\"#md91571ca24\" y=\"123.584656\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.395447\" xlink:href=\"#md91571ca24\" y=\"118.201671\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"188.009746\" xlink:href=\"#md91571ca24\" y=\"117.390967\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.078004\" xlink:href=\"#md91571ca24\" y=\"107.804066\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.298591\" xlink:href=\"#md91571ca24\" y=\"106.29894\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.562025\" xlink:href=\"#md91571ca24\" y=\"117.380821\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"190.7346\" xlink:href=\"#md91571ca24\" y=\"106.306597\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.26989\" xlink:href=\"#md91571ca24\" y=\"120.364077\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.104558\" xlink:href=\"#md91571ca24\" y=\"132.155897\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.009398\" xlink:href=\"#md91571ca24\" y=\"161.289315\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"205.666523\" xlink:href=\"#md91571ca24\" y=\"104.64813\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"188.232277\" xlink:href=\"#md91571ca24\" y=\"109.426978\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"123.021212\" xlink:href=\"#md91571ca24\" y=\"160.22085\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"83.895062\" xlink:href=\"#md91571ca24\" y=\"178.447397\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"93.953104\" xlink:href=\"#md91571ca24\" y=\"191.884114\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.698916\" xlink:href=\"#md91571ca24\" y=\"110.457895\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"214.519977\" xlink:href=\"#md91571ca24\" y=\"91.059322\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.9402\" xlink:href=\"#md91571ca24\" y=\"113.47294\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.089478\" xlink:href=\"#md91571ca24\" y=\"121.283049\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"120.151733\" xlink:href=\"#md91571ca24\" y=\"190.888331\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.4432\" xlink:href=\"#md91571ca24\" y=\"117.596665\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"138.969784\" xlink:href=\"#md91571ca24\" y=\"139.014562\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.590742\" xlink:href=\"#md91571ca24\" y=\"120.358431\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.904334\" xlink:href=\"#md91571ca24\" y=\"134.695783\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"88.249657\" xlink:href=\"#md91571ca24\" y=\"196.827172\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"129.799182\" xlink:href=\"#md91571ca24\" y=\"151.183951\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.250104\" xlink:href=\"#md91571ca24\" y=\"124.908076\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"258.943692\" xlink:href=\"#md91571ca24\" y=\"104.225806\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.796806\" xlink:href=\"#md91571ca24\" y=\"141.838171\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.424203\" xlink:href=\"#md91571ca24\" y=\"128.209055\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"136.791142\" xlink:href=\"#md91571ca24\" y=\"148.285447\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.941048\" xlink:href=\"#md91571ca24\" y=\"122.689174\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.576434\" xlink:href=\"#md91571ca24\" y=\"122.534155\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"141.288821\" xlink:href=\"#md91571ca24\" y=\"142.938811\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.90113\" xlink:href=\"#md91571ca24\" y=\"116.019838\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"120.41737\" xlink:href=\"#md91571ca24\" y=\"185.061515\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.799828\" xlink:href=\"#md91571ca24\" y=\"119.393388\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.016256\" xlink:href=\"#md91571ca24\" y=\"134.781357\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.667894\" xlink:href=\"#md91571ca24\" y=\"158.196375\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"137.492755\" xlink:href=\"#md91571ca24\" y=\"137.519772\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.873518\" xlink:href=\"#md91571ca24\" y=\"110.311423\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"251.427509\" xlink:href=\"#md91571ca24\" y=\"44.70772\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.543828\" xlink:href=\"#md91571ca24\" y=\"119.508292\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"138.186138\" xlink:href=\"#md91571ca24\" y=\"133.410112\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.333793\" xlink:href=\"#md91571ca24\" y=\"124.233556\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"200.58707\" xlink:href=\"#md91571ca24\" y=\"81.228635\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.013598\" xlink:href=\"#md91571ca24\" y=\"132.311667\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"242.765066\" xlink:href=\"#md91571ca24\" y=\"35.582064\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.403852\" xlink:href=\"#md91571ca24\" y=\"106.425392\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"202.831843\" xlink:href=\"#md91571ca24\" y=\"94.013752\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"134.782806\" xlink:href=\"#md91571ca24\" y=\"107.677892\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.60811\" xlink:href=\"#md91571ca24\" y=\"148.529272\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.128702\" xlink:href=\"#md91571ca24\" y=\"118.747259\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.352709\" xlink:href=\"#md91571ca24\" y=\"132.523015\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"130.240589\" xlink:href=\"#md91571ca24\" y=\"134.890589\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.334061\" xlink:href=\"#md91571ca24\" y=\"143.803468\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.060889\" xlink:href=\"#md91571ca24\" y=\"123.620693\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.375657\" xlink:href=\"#md91571ca24\" y=\"124.603939\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"196.312382\" xlink:href=\"#md91571ca24\" y=\"107.636504\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"58.523438\" xlink:href=\"#md91571ca24\" y=\"141.355289\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.409606\" xlink:href=\"#md91571ca24\" y=\"130.036401\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.50022\" xlink:href=\"#md91571ca24\" y=\"158.236287\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.398005\" xlink:href=\"#md91571ca24\" y=\"121.790344\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.798784\" xlink:href=\"#md91571ca24\" y=\"129.497451\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.934461\" xlink:href=\"#md91571ca24\" y=\"118.560854\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.243738\" xlink:href=\"#md91571ca24\" y=\"123.888507\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"120.195222\" xlink:href=\"#md91571ca24\" y=\"155.435835\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.027224\" xlink:href=\"#md91571ca24\" y=\"140.30153\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"83.525774\" xlink:href=\"#md91571ca24\" y=\"180.856515\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.57594\" xlink:href=\"#md91571ca24\" y=\"142.643155\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.987824\" xlink:href=\"#md91571ca24\" y=\"118.87857\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"125.78089\" xlink:href=\"#md91571ca24\" y=\"152.482418\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"89.49741\" xlink:href=\"#md91571ca24\" y=\"198.763908\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"137.143691\" xlink:href=\"#md91571ca24\" y=\"140.928758\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.425616\" xlink:href=\"#md91571ca24\" y=\"109.018072\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.986515\" xlink:href=\"#md91571ca24\" y=\"114.844115\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"194.192949\" xlink:href=\"#md91571ca24\" y=\"117.314784\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.409169\" xlink:href=\"#md91571ca24\" y=\"149.074673\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"141.703328\" xlink:href=\"#md91571ca24\" y=\"131.329195\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"142.410883\" xlink:href=\"#md91571ca24\" y=\"110.999936\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.08034\" xlink:href=\"#md91571ca24\" y=\"124.416759\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.633142\" xlink:href=\"#md91571ca24\" y=\"127.936912\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.528724\" xlink:href=\"#md91571ca24\" y=\"111.654101\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"203.518591\" xlink:href=\"#md91571ca24\" y=\"74.731576\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"112.481897\" xlink:href=\"#md91571ca24\" y=\"140.66266\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.966493\" xlink:href=\"#md91571ca24\" y=\"172.311733\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.522181\" xlink:href=\"#md91571ca24\" y=\"137.297587\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.754956\" xlink:href=\"#md91571ca24\" y=\"140.791731\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.068155\" xlink:href=\"#md91571ca24\" y=\"121.453552\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.706089\" xlink:href=\"#md91571ca24\" y=\"131.47516\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.662928\" xlink:href=\"#md91571ca24\" y=\"104.247749\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.206212\" xlink:href=\"#md91571ca24\" y=\"116.6499\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.158433\" xlink:href=\"#md91571ca24\" y=\"108.139366\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.093599\" xlink:href=\"#md91571ca24\" y=\"119.917509\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"123.699989\" xlink:href=\"#md91571ca24\" y=\"153.641933\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.573539\" xlink:href=\"#md91571ca24\" y=\"129.158621\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.420359\" xlink:href=\"#md91571ca24\" y=\"113.103246\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.589407\" xlink:href=\"#md91571ca24\" y=\"123.331529\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"91.556201\" xlink:href=\"#md91571ca24\" y=\"170.662528\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"232.283004\" xlink:href=\"#md91571ca24\" y=\"96.357205\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.342496\" xlink:href=\"#md91571ca24\" y=\"121.24441\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"231.957204\" xlink:href=\"#md91571ca24\" y=\"35.667675\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.919886\" xlink:href=\"#md91571ca24\" y=\"109.114987\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.874553\" xlink:href=\"#md91571ca24\" y=\"116.524784\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.145522\" xlink:href=\"#md91571ca24\" y=\"131.526574\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.561457\" xlink:href=\"#md91571ca24\" y=\"108.175219\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.352455\" xlink:href=\"#md91571ca24\" y=\"120.66145\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"137.510148\" xlink:href=\"#md91571ca24\" y=\"151.318885\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.203979\" xlink:href=\"#md91571ca24\" y=\"132.74544\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"133.717309\" xlink:href=\"#md91571ca24\" y=\"158.713672\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"101.801968\" xlink:href=\"#md91571ca24\" y=\"148.002758\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.022046\" xlink:href=\"#md91571ca24\" y=\"116.70029\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"189.986472\" xlink:href=\"#md91571ca24\" y=\"108.850181\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"138.873313\" xlink:href=\"#md91571ca24\" y=\"161.566561\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.023201\" xlink:href=\"#md91571ca24\" y=\"130.83218\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.458131\" xlink:href=\"#md91571ca24\" y=\"119.98918\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.767932\" xlink:href=\"#md91571ca24\" y=\"122.735227\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.252315\" xlink:href=\"#md91571ca24\" y=\"121.485627\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.621446\" xlink:href=\"#md91571ca24\" y=\"110.360005\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"202.405548\" xlink:href=\"#md91571ca24\" y=\"105.642878\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.322837\" xlink:href=\"#md91571ca24\" y=\"103.539709\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.02043\" xlink:href=\"#md91571ca24\" y=\"124.847774\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.238986\" xlink:href=\"#md91571ca24\" y=\"119.059676\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"107.235073\" xlink:href=\"#md91571ca24\" y=\"148.707708\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.776605\" xlink:href=\"#md91571ca24\" y=\"117.781957\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.682407\" xlink:href=\"#md91571ca24\" y=\"143.860585\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.975505\" xlink:href=\"#md91571ca24\" y=\"124.475104\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.915711\" xlink:href=\"#md91571ca24\" y=\"122.448405\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.374417\" xlink:href=\"#md91571ca24\" y=\"131.431687\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.463973\" xlink:href=\"#md91571ca24\" y=\"105.763628\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.814017\" xlink:href=\"#md91571ca24\" y=\"102.762333\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.986827\" xlink:href=\"#md91571ca24\" y=\"100.85861\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"126.176631\" xlink:href=\"#md91571ca24\" y=\"133.825805\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.319265\" xlink:href=\"#md91571ca24\" y=\"120.316072\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"130.791433\" xlink:href=\"#md91571ca24\" y=\"131.636488\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"105.915934\" xlink:href=\"#md91571ca24\" y=\"174.659827\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.947909\" xlink:href=\"#md91571ca24\" y=\"122.675579\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.952256\" xlink:href=\"#md91571ca24\" y=\"111.605909\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.849856\" xlink:href=\"#md91571ca24\" y=\"121.489075\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"85.88754\" xlink:href=\"#md91571ca24\" y=\"195.230504\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"104.670735\" xlink:href=\"#md91571ca24\" y=\"147.71593\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.275422\" xlink:href=\"#md91571ca24\" y=\"113.039288\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"125.392764\" xlink:href=\"#md91571ca24\" y=\"186.933967\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.550022\" xlink:href=\"#md91571ca24\" y=\"123.163544\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.647036\" xlink:href=\"#md91571ca24\" y=\"100.594188\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.996937\" xlink:href=\"#md91571ca24\" y=\"107.704582\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.840555\" xlink:href=\"#md91571ca24\" y=\"122.441493\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.611669\" xlink:href=\"#md91571ca24\" y=\"123.864427\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.625542\" xlink:href=\"#md91571ca24\" y=\"120.557091\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.41283\" xlink:href=\"#md91571ca24\" y=\"117.014701\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.521646\" xlink:href=\"#md91571ca24\" y=\"123.529214\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.750485\" xlink:href=\"#md91571ca24\" y=\"136.972006\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.988602\" xlink:href=\"#md91571ca24\" y=\"128.943388\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.404316\" xlink:href=\"#md91571ca24\" y=\"118.642072\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"130.799041\" xlink:href=\"#md91571ca24\" y=\"169.898374\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.493733\" xlink:href=\"#md91571ca24\" y=\"143.715556\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.403062\" xlink:href=\"#md91571ca24\" y=\"123.545172\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.993126\" xlink:href=\"#md91571ca24\" y=\"140.794934\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"213.897371\" xlink:href=\"#md91571ca24\" y=\"123.77323\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"226.595499\" xlink:href=\"#md91571ca24\" y=\"71.685819\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.077831\" xlink:href=\"#md91571ca24\" y=\"123.182096\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.764285\" xlink:href=\"#md91571ca24\" y=\"144.445047\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.600408\" xlink:href=\"#md91571ca24\" y=\"125.253597\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.205347\" xlink:href=\"#md91571ca24\" y=\"146.437625\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.134293\" xlink:href=\"#md91571ca24\" y=\"108.855427\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.404113\" xlink:href=\"#md91571ca24\" y=\"119.178317\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.241521\" xlink:href=\"#md91571ca24\" y=\"125.258523\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.866999\" xlink:href=\"#md91571ca24\" y=\"142.572874\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.990507\" xlink:href=\"#md91571ca24\" y=\"119.822893\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.620665\" xlink:href=\"#md91571ca24\" y=\"118.304075\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.063549\" xlink:href=\"#md91571ca24\" y=\"150.210182\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"106.368577\" xlink:href=\"#md91571ca24\" y=\"182.768425\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.983817\" xlink:href=\"#md91571ca24\" y=\"134.2012\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.441067\" xlink:href=\"#md91571ca24\" y=\"71.375916\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"118.24515\" xlink:href=\"#md91571ca24\" y=\"162.695817\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.694425\" xlink:href=\"#md91571ca24\" y=\"125.557725\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.437509\" xlink:href=\"#md91571ca24\" y=\"131.794233\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.500149\" xlink:href=\"#md91571ca24\" y=\"131.155063\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.334204\" xlink:href=\"#md91571ca24\" y=\"89.678255\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.407971\" xlink:href=\"#md91571ca24\" y=\"117.675961\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"194.0153\" xlink:href=\"#md91571ca24\" y=\"109.773613\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.37422\" xlink:href=\"#md91571ca24\" y=\"130.453044\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.983403\" xlink:href=\"#md91571ca24\" y=\"125.618334\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.888367\" xlink:href=\"#md91571ca24\" y=\"113.248582\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.165362\" xlink:href=\"#md91571ca24\" y=\"133.74124\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"251.695323\" xlink:href=\"#md91571ca24\" y=\"42.11621\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"135.661329\" xlink:href=\"#md91571ca24\" y=\"131.336399\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.810821\" xlink:href=\"#md91571ca24\" y=\"116.864002\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"197.258273\" xlink:href=\"#md91571ca24\" y=\"109.840147\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"221.990112\" xlink:href=\"#md91571ca24\" y=\"110.286186\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"271.512449\" xlink:href=\"#md91571ca24\" y=\"37.670308\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.383523\" xlink:href=\"#md91571ca24\" y=\"120.596766\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.837494\" xlink:href=\"#md91571ca24\" y=\"131.672453\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.245165\" xlink:href=\"#md91571ca24\" y=\"116.230969\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.418142\" xlink:href=\"#md91571ca24\" y=\"117.949575\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.981667\" xlink:href=\"#md91571ca24\" y=\"114.146466\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"117.76678\" xlink:href=\"#md91571ca24\" y=\"163.087799\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.229217\" xlink:href=\"#md91571ca24\" y=\"127.160026\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"116.3237\" xlink:href=\"#md91571ca24\" y=\"123.318523\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"93.659213\" xlink:href=\"#md91571ca24\" y=\"197.498146\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.598269\" xlink:href=\"#md91571ca24\" y=\"116.743393\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"264.183997\" xlink:href=\"#md91571ca24\" y=\"44.784958\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"129.469034\" xlink:href=\"#md91571ca24\" y=\"142.644167\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"129.163168\" xlink:href=\"#md91571ca24\" y=\"131.224925\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"183.926886\" xlink:href=\"#md91571ca24\" y=\"101.547671\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.697051\" xlink:href=\"#md91571ca24\" y=\"131.443765\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.770544\" xlink:href=\"#md91571ca24\" y=\"159.0022\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.477785\" xlink:href=\"#md91571ca24\" y=\"128.438103\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.428274\" xlink:href=\"#md91571ca24\" y=\"117.659549\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.612875\" xlink:href=\"#md91571ca24\" y=\"121.554336\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.963881\" xlink:href=\"#md91571ca24\" y=\"153.864363\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"189.869659\" xlink:href=\"#md91571ca24\" y=\"105.171752\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.550765\" xlink:href=\"#md91571ca24\" y=\"121.892798\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.599405\" xlink:href=\"#md91571ca24\" y=\"112.561638\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"131.776763\" xlink:href=\"#md91571ca24\" y=\"155.453695\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.756726\" xlink:href=\"#md91571ca24\" y=\"153.328287\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"109.408019\" xlink:href=\"#md91571ca24\" y=\"200.381208\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"128.647479\" xlink:href=\"#md91571ca24\" y=\"155.158184\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.483278\" xlink:href=\"#md91571ca24\" y=\"117.480683\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.127992\" xlink:href=\"#md91571ca24\" y=\"118.270865\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.963069\" xlink:href=\"#md91571ca24\" y=\"121.128892\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"127.244266\" xlink:href=\"#md91571ca24\" y=\"153.404054\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.774159\" xlink:href=\"#md91571ca24\" y=\"110.568728\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.724087\" xlink:href=\"#md91571ca24\" y=\"111.586232\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"190.052285\" xlink:href=\"#md91571ca24\" y=\"113.83051\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.808888\" xlink:href=\"#md91571ca24\" y=\"121.075606\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"194.145112\" xlink:href=\"#md91571ca24\" y=\"99.517832\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.446408\" xlink:href=\"#md91571ca24\" y=\"111.929345\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"199.045711\" xlink:href=\"#md91571ca24\" y=\"114.949366\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.418891\" xlink:href=\"#md91571ca24\" y=\"88.064156\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"136.054717\" xlink:href=\"#md91571ca24\" y=\"144.340768\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.982341\" xlink:href=\"#md91571ca24\" y=\"113.455548\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.586369\" xlink:href=\"#md91571ca24\" y=\"146.89088\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.713357\" xlink:href=\"#md91571ca24\" y=\"105.191687\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.548737\" xlink:href=\"#md91571ca24\" y=\"112.675056\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.162075\" xlink:href=\"#md91571ca24\" y=\"130.322441\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.109625\" xlink:href=\"#md91571ca24\" y=\"107.212973\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"219.274292\" xlink:href=\"#md91571ca24\" y=\"66.136952\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.297047\" xlink:href=\"#md91571ca24\" y=\"117.749462\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.626727\" xlink:href=\"#md91571ca24\" y=\"110.939887\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.590528\" xlink:href=\"#md91571ca24\" y=\"128.426829\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"193.902195\" xlink:href=\"#md91571ca24\" y=\"128.1055\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.628343\" xlink:href=\"#md91571ca24\" y=\"133.012773\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.941785\" xlink:href=\"#md91571ca24\" y=\"126.160492\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"92.813\" xlink:href=\"#md91571ca24\" y=\"185.166993\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"205.08307\" xlink:href=\"#md91571ca24\" y=\"81.368831\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.923959\" xlink:href=\"#md91571ca24\" y=\"164.806968\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"227.183306\" xlink:href=\"#md91571ca24\" y=\"43.518846\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.266419\" xlink:href=\"#md91571ca24\" y=\"129.252178\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.913306\" xlink:href=\"#md91571ca24\" y=\"115.353266\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"205.731766\" xlink:href=\"#md91571ca24\" y=\"116.166346\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.560666\" xlink:href=\"#md91571ca24\" y=\"129.525401\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.367098\" xlink:href=\"#md91571ca24\" y=\"113.512445\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"74.705859\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.273125\" xlink:href=\"#md91571ca24\" y=\"117.394235\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.500229\" xlink:href=\"#md91571ca24\" y=\"126.574292\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.555326\" xlink:href=\"#md91571ca24\" y=\"108.661252\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"200.711412\" xlink:href=\"#md91571ca24\" y=\"110.942513\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"138.327361\" xlink:href=\"#md91571ca24\" y=\"128.238485\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"90.119641\" xlink:href=\"#md91571ca24\" y=\"181.757213\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.719225\" xlink:href=\"#md91571ca24\" y=\"115.295146\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"142.912044\" xlink:href=\"#md91571ca24\" y=\"134.253793\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.1866\" xlink:href=\"#md91571ca24\" y=\"127.75802\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"86.547823\" xlink:href=\"#md91571ca24\" y=\"181.92391\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"108.982567\" xlink:href=\"#md91571ca24\" y=\"179.205731\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.527185\" xlink:href=\"#md91571ca24\" y=\"109.451718\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.679282\" xlink:href=\"#md91571ca24\" y=\"120.2754\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.511863\" xlink:href=\"#md91571ca24\" y=\"123.903457\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"135.823069\" xlink:href=\"#md91571ca24\" y=\"149.848673\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.771773\" xlink:href=\"#md91571ca24\" y=\"123.769322\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.70654\" xlink:href=\"#md91571ca24\" y=\"92.435746\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.807538\" xlink:href=\"#md91571ca24\" y=\"118.407271\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.930872\" xlink:href=\"#md91571ca24\" y=\"124.576262\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"130.064093\" xlink:href=\"#md91571ca24\" y=\"174.950776\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.35618\" xlink:href=\"#md91571ca24\" y=\"141.779672\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.098111\" xlink:href=\"#md91571ca24\" y=\"120.434555\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.099499\" xlink:href=\"#md91571ca24\" y=\"107.863702\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.26629\" xlink:href=\"#md91571ca24\" y=\"104.766834\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.591672\" xlink:href=\"#md91571ca24\" y=\"119.417008\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.567754\" xlink:href=\"#md91571ca24\" y=\"124.506965\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"91.464869\" xlink:href=\"#md91571ca24\" y=\"191.333678\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"111.129424\" xlink:href=\"#md91571ca24\" y=\"173.306719\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"90.889024\" xlink:href=\"#md91571ca24\" y=\"195.293434\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.881937\" xlink:href=\"#md91571ca24\" y=\"129.529989\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.039685\" xlink:href=\"#md91571ca24\" y=\"119.470834\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"137.642824\" xlink:href=\"#md91571ca24\" y=\"156.508671\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.223559\" xlink:href=\"#md91571ca24\" y=\"112.654729\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.284457\" xlink:href=\"#md91571ca24\" y=\"168.744111\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.470723\" xlink:href=\"#md91571ca24\" y=\"103.066636\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"105.269053\" xlink:href=\"#md91571ca24\" y=\"167.869259\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"247.208797\" xlink:href=\"#md91571ca24\" y=\"63.632351\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.464369\" xlink:href=\"#md91571ca24\" y=\"110.760512\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.544577\" xlink:href=\"#md91571ca24\" y=\"125.142254\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.62495\" xlink:href=\"#md91571ca24\" y=\"98.513255\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.334905\" xlink:href=\"#md91571ca24\" y=\"128.790176\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.500363\" xlink:href=\"#md91571ca24\" y=\"132.725758\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.8295\" xlink:href=\"#md91571ca24\" y=\"147.180655\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"208.668302\" xlink:href=\"#md91571ca24\" y=\"91.8313\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.942897\" xlink:href=\"#md91571ca24\" y=\"118.816246\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.693675\" xlink:href=\"#md91571ca24\" y=\"118.51564\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"193.998659\" xlink:href=\"#md91571ca24\" y=\"106.040513\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"207.16252\" xlink:href=\"#md91571ca24\" y=\"98.861931\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.595922\" xlink:href=\"#md91571ca24\" y=\"128.728425\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.660949\" xlink:href=\"#md91571ca24\" y=\"107.837153\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.750925\" xlink:href=\"#md91571ca24\" y=\"149.14346\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.193066\" xlink:href=\"#md91571ca24\" y=\"119.825942\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"216.46425\" xlink:href=\"#md91571ca24\" y=\"99.240557\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"41.066894\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.52893\" xlink:href=\"#md91571ca24\" y=\"156.090613\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"127.419666\" xlink:href=\"#md91571ca24\" y=\"172.972932\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"128.139391\" xlink:href=\"#md91571ca24\" y=\"145.734298\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.303202\" xlink:href=\"#md91571ca24\" y=\"119.162385\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.657983\" xlink:href=\"#md91571ca24\" y=\"131.919134\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.838567\" xlink:href=\"#md91571ca24\" y=\"122.740426\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.985306\" xlink:href=\"#md91571ca24\" y=\"170.943973\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.991507\" xlink:href=\"#md91571ca24\" y=\"109.644816\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"124.89881\" xlink:href=\"#md91571ca24\" y=\"165.129193\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"262.072276\" xlink:href=\"#md91571ca24\" y=\"38.192775\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"142.802269\" xlink:href=\"#md91571ca24\" y=\"117.168134\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"58.523438\" xlink:href=\"#md91571ca24\" y=\"159.569264\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"243.129643\" xlink:href=\"#md91571ca24\" y=\"39.317359\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.88125\" xlink:href=\"#md91571ca24\" y=\"93.511619\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"135.228988\" xlink:href=\"#md91571ca24\" y=\"133.940936\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.145806\" xlink:href=\"#md91571ca24\" y=\"122.209195\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.835704\" xlink:href=\"#md91571ca24\" y=\"154.170356\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"205.739024\" xlink:href=\"#md91571ca24\" y=\"89.942353\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.483766\" xlink:href=\"#md91571ca24\" y=\"118.752818\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.91415\" xlink:href=\"#md91571ca24\" y=\"112.278822\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.841797\" xlink:href=\"#md91571ca24\" y=\"112.45525\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.814397\" xlink:href=\"#md91571ca24\" y=\"121.735111\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"119.727\" xlink:href=\"#md91571ca24\" y=\"146.311353\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.732616\" xlink:href=\"#md91571ca24\" y=\"122.661256\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.277663\" xlink:href=\"#md91571ca24\" y=\"105.637919\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.141616\" xlink:href=\"#md91571ca24\" y=\"114.468331\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"207.965963\" xlink:href=\"#md91571ca24\" y=\"91.589776\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.766504\" xlink:href=\"#md91571ca24\" y=\"138.58211\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.462753\" xlink:href=\"#md91571ca24\" y=\"123.155062\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.271847\" xlink:href=\"#md91571ca24\" y=\"111.557936\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.625177\" xlink:href=\"#md91571ca24\" y=\"103.154305\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"38.951887\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.035266\" xlink:href=\"#md91571ca24\" y=\"119.747009\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.109593\" xlink:href=\"#md91571ca24\" y=\"161.763479\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"183.734449\" xlink:href=\"#md91571ca24\" y=\"105.233706\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.654865\" xlink:href=\"#md91571ca24\" y=\"134.50821\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"214.951223\" xlink:href=\"#md91571ca24\" y=\"79.010998\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.802187\" xlink:href=\"#md91571ca24\" y=\"102.823548\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.956107\" xlink:href=\"#md91571ca24\" y=\"144.643562\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.447759\" xlink:href=\"#md91571ca24\" y=\"142.060506\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.871528\" xlink:href=\"#md91571ca24\" y=\"122.043741\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"116.973848\" xlink:href=\"#md91571ca24\" y=\"150.341847\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"193.288726\" xlink:href=\"#md91571ca24\" y=\"108.679443\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.579691\" xlink:href=\"#md91571ca24\" y=\"119.412278\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.422425\" xlink:href=\"#md91571ca24\" y=\"116.839451\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"36.098732\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"114.726606\" xlink:href=\"#md91571ca24\" y=\"151.485741\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.566334\" xlink:href=\"#md91571ca24\" y=\"127.591478\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"95.146138\" xlink:href=\"#md91571ca24\" y=\"183.798689\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.190861\" xlink:href=\"#md91571ca24\" y=\"99.848614\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"129.404167\" xlink:href=\"#md91571ca24\" y=\"142.19282\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.543077\" xlink:href=\"#md91571ca24\" y=\"124.377851\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.366162\" xlink:href=\"#md91571ca24\" y=\"134.746993\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"136.658006\" xlink:href=\"#md91571ca24\" y=\"149.81219\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.976649\" xlink:href=\"#md91571ca24\" y=\"124.777589\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.943846\" xlink:href=\"#md91571ca24\" y=\"122.623063\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"37.982739\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"190.915553\" xlink:href=\"#md91571ca24\" y=\"118.184214\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"121.739769\" xlink:href=\"#md91571ca24\" y=\"178.671949\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.505618\" xlink:href=\"#md91571ca24\" y=\"123.691563\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"227.403284\" xlink:href=\"#md91571ca24\" y=\"100.016417\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.200966\" xlink:href=\"#md91571ca24\" y=\"128.21838\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.805991\" xlink:href=\"#md91571ca24\" y=\"119.572464\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"136.576245\" xlink:href=\"#md91571ca24\" y=\"158.291019\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"265.932204\" xlink:href=\"#md91571ca24\" y=\"38.148029\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"193.356055\" xlink:href=\"#md91571ca24\" y=\"120.951723\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.966628\" xlink:href=\"#md91571ca24\" y=\"151.362611\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"105.592312\" xlink:href=\"#md91571ca24\" y=\"181.235607\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.403062\" xlink:href=\"#md91571ca24\" y=\"148.85096\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"135.69373\" xlink:href=\"#md91571ca24\" y=\"144.143711\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"198.257341\" xlink:href=\"#md91571ca24\" y=\"93.608472\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.057549\" xlink:href=\"#md91571ca24\" y=\"117.217342\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.965695\" xlink:href=\"#md91571ca24\" y=\"108.989355\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.996996\" xlink:href=\"#md91571ca24\" y=\"124.377666\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.484714\" xlink:href=\"#md91571ca24\" y=\"117.108729\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.212796\" xlink:href=\"#md91571ca24\" y=\"128.722209\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"107.932331\" xlink:href=\"#md91571ca24\" y=\"180.836154\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"102.007819\" xlink:href=\"#md91571ca24\" y=\"176.991201\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.55718\" xlink:href=\"#md91571ca24\" y=\"117.48239\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"215.813739\" xlink:href=\"#md91571ca24\" y=\"67.283464\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.557591\" xlink:href=\"#md91571ca24\" y=\"100.064526\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"115.077406\" xlink:href=\"#md91571ca24\" y=\"176.477968\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.420535\" xlink:href=\"#md91571ca24\" y=\"142.582429\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"114.546851\" xlink:href=\"#md91571ca24\" y=\"161.131113\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.798031\" xlink:href=\"#md91571ca24\" y=\"118.551719\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.317876\" xlink:href=\"#md91571ca24\" y=\"99.259387\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"110.158195\" xlink:href=\"#md91571ca24\" y=\"165.614714\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.557179\" xlink:href=\"#md91571ca24\" y=\"130.305924\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"190.762905\" xlink:href=\"#md91571ca24\" y=\"97.600979\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.699279\" xlink:href=\"#md91571ca24\" y=\"105.129051\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.965581\" xlink:href=\"#md91571ca24\" y=\"110.831643\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.33125\" xlink:href=\"#md91571ca24\" y=\"128.401635\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.770297\" xlink:href=\"#md91571ca24\" y=\"121.998367\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"120.282556\" xlink:href=\"#md91571ca24\" y=\"177.281275\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.112164\" xlink:href=\"#md91571ca24\" y=\"104.613446\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.594948\" xlink:href=\"#md91571ca24\" y=\"128.733261\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.854043\" xlink:href=\"#md91571ca24\" y=\"129.766649\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.21286\" xlink:href=\"#md91571ca24\" y=\"136.364897\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.562562\" xlink:href=\"#md91571ca24\" y=\"146.789491\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"73.721769\" xlink:href=\"#md91571ca24\" y=\"203.123201\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.504332\" xlink:href=\"#md91571ca24\" y=\"132.397556\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.569835\" xlink:href=\"#md91571ca24\" y=\"110.27647\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"128.788813\" xlink:href=\"#md91571ca24\" y=\"169.961916\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.619914\" xlink:href=\"#md91571ca24\" y=\"119.50922\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.892873\" xlink:href=\"#md91571ca24\" y=\"149.22284\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.109665\" xlink:href=\"#md91571ca24\" y=\"122.654576\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.534808\" xlink:href=\"#md91571ca24\" y=\"120.979179\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.460701\" xlink:href=\"#md91571ca24\" y=\"121.945535\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.447373\" xlink:href=\"#md91571ca24\" y=\"100.833947\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"188.84585\" xlink:href=\"#md91571ca24\" y=\"116.256612\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"196.915807\" xlink:href=\"#md91571ca24\" y=\"102.881882\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"124.645854\" xlink:href=\"#md91571ca24\" y=\"162.705359\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.226051\" xlink:href=\"#md91571ca24\" y=\"127.687854\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"112.852268\" xlink:href=\"#md91571ca24\" y=\"175.446856\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.837514\" xlink:href=\"#md91571ca24\" y=\"127.730686\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"123.450293\" xlink:href=\"#md91571ca24\" y=\"169.647233\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.970305\" xlink:href=\"#md91571ca24\" y=\"124.345504\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.711919\" xlink:href=\"#md91571ca24\" y=\"129.556673\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"225.973242\" xlink:href=\"#md91571ca24\" y=\"93.039302\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.572465\" xlink:href=\"#md91571ca24\" y=\"114.526847\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.15709\" xlink:href=\"#md91571ca24\" y=\"119.613605\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.506123\" xlink:href=\"#md91571ca24\" y=\"113.826239\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"203.379318\" xlink:href=\"#md91571ca24\" y=\"101.564468\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.654486\" xlink:href=\"#md91571ca24\" y=\"97.010875\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.651434\" xlink:href=\"#md91571ca24\" y=\"115.656128\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.258265\" xlink:href=\"#md91571ca24\" y=\"145.815955\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.261114\" xlink:href=\"#md91571ca24\" y=\"119.304689\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.7935\" xlink:href=\"#md91571ca24\" y=\"131.365889\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"190.511084\" xlink:href=\"#md91571ca24\" y=\"110.807075\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"227.04704\" xlink:href=\"#md91571ca24\" y=\"99.812217\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.441984\" xlink:href=\"#md91571ca24\" y=\"114.674693\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.402778\" xlink:href=\"#md91571ca24\" y=\"133.278381\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.803511\" xlink:href=\"#md91571ca24\" y=\"135.680351\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.686215\" xlink:href=\"#md91571ca24\" y=\"125.278846\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.225139\" xlink:href=\"#md91571ca24\" y=\"125.797565\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.787159\" xlink:href=\"#md91571ca24\" y=\"118.836572\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.657013\" xlink:href=\"#md91571ca24\" y=\"119.099957\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"191.44872\" xlink:href=\"#md91571ca24\" y=\"100.385138\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"209.122384\" xlink:href=\"#md91571ca24\" y=\"93.452257\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.352937\" xlink:href=\"#md91571ca24\" y=\"109.200803\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.118463\" xlink:href=\"#md91571ca24\" y=\"121.157298\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.656224\" xlink:href=\"#md91571ca24\" y=\"119.680098\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"123.318019\" xlink:href=\"#md91571ca24\" y=\"154.000487\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.514197\" xlink:href=\"#md91571ca24\" y=\"112.369666\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"106.507371\" xlink:href=\"#md91571ca24\" y=\"192.798272\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.237817\" xlink:href=\"#md91571ca24\" y=\"113.712604\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.847727\" xlink:href=\"#md91571ca24\" y=\"127.379405\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"127.517148\" xlink:href=\"#md91571ca24\" y=\"159.485984\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"99.330401\" xlink:href=\"#md91571ca24\" y=\"182.449456\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"126.054867\" xlink:href=\"#md91571ca24\" y=\"114.234759\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"198.093171\" xlink:href=\"#md91571ca24\" y=\"114.769267\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.868497\" xlink:href=\"#md91571ca24\" y=\"126.665438\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.662006\" xlink:href=\"#md91571ca24\" y=\"132.069568\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.473089\" xlink:href=\"#md91571ca24\" y=\"134.303955\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.083292\" xlink:href=\"#md91571ca24\" y=\"105.620308\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.843603\" xlink:href=\"#md91571ca24\" y=\"122.756011\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.943576\" xlink:href=\"#md91571ca24\" y=\"108.29494\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.883682\" xlink:href=\"#md91571ca24\" y=\"124.934456\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.936372\" xlink:href=\"#md91571ca24\" y=\"103.569463\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.095269\" xlink:href=\"#md91571ca24\" y=\"118.088665\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.2446\" xlink:href=\"#md91571ca24\" y=\"108.426835\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.589576\" xlink:href=\"#md91571ca24\" y=\"111.576975\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"141.161368\" xlink:href=\"#md91571ca24\" y=\"135.617632\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.182422\" xlink:href=\"#md91571ca24\" y=\"103.966843\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.825842\" xlink:href=\"#md91571ca24\" y=\"128.274694\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.210137\" xlink:href=\"#md91571ca24\" y=\"109.826068\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.444887\" xlink:href=\"#md91571ca24\" y=\"118.578564\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.337572\" xlink:href=\"#md91571ca24\" y=\"90.699777\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.759086\" xlink:href=\"#md91571ca24\" y=\"97.716172\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.209403\" xlink:href=\"#md91571ca24\" y=\"110.809821\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.934548\" xlink:href=\"#md91571ca24\" y=\"119.085286\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.337724\" xlink:href=\"#md91571ca24\" y=\"118.504631\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.343642\" xlink:href=\"#md91571ca24\" y=\"113.270586\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"116.812082\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.917891\" xlink:href=\"#md91571ca24\" y=\"113.251351\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.431803\" xlink:href=\"#md91571ca24\" y=\"128.822493\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"104.331158\" xlink:href=\"#md91571ca24\" y=\"186.361012\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.732625\" xlink:href=\"#md91571ca24\" y=\"117.879492\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"183.233256\" xlink:href=\"#md91571ca24\" y=\"98.761269\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"198.205811\" xlink:href=\"#md91571ca24\" y=\"105.220073\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.899211\" xlink:href=\"#md91571ca24\" y=\"98.868636\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.883396\" xlink:href=\"#md91571ca24\" y=\"98.434222\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.193312\" xlink:href=\"#md91571ca24\" y=\"106.297793\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.940904\" xlink:href=\"#md91571ca24\" y=\"106.187559\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.985645\" xlink:href=\"#md91571ca24\" y=\"124.835518\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"184.082683\" xlink:href=\"#md91571ca24\" y=\"111.759999\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.377953\" xlink:href=\"#md91571ca24\" y=\"192.881303\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"137.096943\" xlink:href=\"#md91571ca24\" y=\"129.06155\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.601474\" xlink:href=\"#md91571ca24\" y=\"122.119809\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.844478\" xlink:href=\"#md91571ca24\" y=\"122.965965\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.08594\" xlink:href=\"#md91571ca24\" y=\"109.256947\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"190.842923\" xlink:href=\"#md91571ca24\" y=\"120.515292\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.116721\" xlink:href=\"#md91571ca24\" y=\"112.060082\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.579765\" xlink:href=\"#md91571ca24\" y=\"124.824543\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"234.639314\" xlink:href=\"#md91571ca24\" y=\"119.837513\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.323213\" xlink:href=\"#md91571ca24\" y=\"118.65618\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"108.068597\" xlink:href=\"#md91571ca24\" y=\"181.49595\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.865019\" xlink:href=\"#md91571ca24\" y=\"186.104305\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.555529\" xlink:href=\"#md91571ca24\" y=\"135.381996\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"137.519246\" xlink:href=\"#md91571ca24\" y=\"160.415749\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.165392\" xlink:href=\"#md91571ca24\" y=\"121.223959\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.687711\" xlink:href=\"#md91571ca24\" y=\"103.07279\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.455379\" xlink:href=\"#md91571ca24\" y=\"106.72948\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.726898\" xlink:href=\"#md91571ca24\" y=\"133.79499\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.317663\" xlink:href=\"#md91571ca24\" y=\"118.669127\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"210.248348\" xlink:href=\"#md91571ca24\" y=\"108.041602\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.681801\" xlink:href=\"#md91571ca24\" y=\"119.770948\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"103.282011\" xlink:href=\"#md91571ca24\" y=\"193.473335\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.304776\" xlink:href=\"#md91571ca24\" y=\"105.519774\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.598617\" xlink:href=\"#md91571ca24\" y=\"117.107928\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.580507\" xlink:href=\"#md91571ca24\" y=\"124.086664\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"256.942147\" xlink:href=\"#md91571ca24\" y=\"31.796762\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"118.413661\" xlink:href=\"#md91571ca24\" y=\"100.389597\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.370076\" xlink:href=\"#md91571ca24\" y=\"119.292281\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.803282\" xlink:href=\"#md91571ca24\" y=\"111.720173\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.95857\" xlink:href=\"#md91571ca24\" y=\"136.647431\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.234875\" xlink:href=\"#md91571ca24\" y=\"140.484577\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.175578\" xlink:href=\"#md91571ca24\" y=\"118.155006\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"183.295259\" xlink:href=\"#md91571ca24\" y=\"106.449993\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.255732\" xlink:href=\"#md91571ca24\" y=\"117.778161\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.316322\" xlink:href=\"#md91571ca24\" y=\"115.34127\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"90.401958\" xlink:href=\"#md91571ca24\" y=\"190.332789\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.315818\" xlink:href=\"#md91571ca24\" y=\"157.33472\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.244953\" xlink:href=\"#md91571ca24\" y=\"166.484058\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"202.966735\" xlink:href=\"#md91571ca24\" y=\"113.969625\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.4949\" xlink:href=\"#md91571ca24\" y=\"116.45705\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.161954\" xlink:href=\"#md91571ca24\" y=\"127.914367\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.749703\" xlink:href=\"#md91571ca24\" y=\"122.030733\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.619922\" xlink:href=\"#md91571ca24\" y=\"94.86105\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"195.536544\" xlink:href=\"#md91571ca24\" y=\"118.100127\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.419493\" xlink:href=\"#md91571ca24\" y=\"140.680861\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.120727\" xlink:href=\"#md91571ca24\" y=\"129.565111\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"138.830803\" xlink:href=\"#md91571ca24\" y=\"143.318567\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"188.214586\" xlink:href=\"#md91571ca24\" y=\"106.722238\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.319921\" xlink:href=\"#md91571ca24\" y=\"113.0884\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.28341\" xlink:href=\"#md91571ca24\" y=\"118.977118\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.754501\" xlink:href=\"#md91571ca24\" y=\"129.583279\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.315186\" xlink:href=\"#md91571ca24\" y=\"113.367321\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"95.657116\" xlink:href=\"#md91571ca24\" y=\"195.449419\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"95.247605\" xlink:href=\"#md91571ca24\" y=\"174.714792\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.18812\" xlink:href=\"#md91571ca24\" y=\"143.189923\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"119.285237\" xlink:href=\"#md91571ca24\" y=\"179.212976\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.084777\" xlink:href=\"#md91571ca24\" y=\"115.590751\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.453983\" xlink:href=\"#md91571ca24\" y=\"124.472516\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"183.075644\" xlink:href=\"#md91571ca24\" y=\"144.546195\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.088375\" xlink:href=\"#md91571ca24\" y=\"123.834092\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"120.939229\" xlink:href=\"#md91571ca24\" y=\"152.074395\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.775808\" xlink:href=\"#md91571ca24\" y=\"105.593963\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"30.297564\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.189855\" xlink:href=\"#md91571ca24\" y=\"96.305558\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"141.918886\" xlink:href=\"#md91571ca24\" y=\"144.049459\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"104.272447\" xlink:href=\"#md91571ca24\" y=\"170.706392\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.95164\" xlink:href=\"#md91571ca24\" y=\"112.460859\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.958966\" xlink:href=\"#md91571ca24\" y=\"174.971895\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"23.790726\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"107.932331\" xlink:href=\"#md91571ca24\" y=\"182.263668\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.846575\" xlink:href=\"#md91571ca24\" y=\"106.895791\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.31502\" xlink:href=\"#md91571ca24\" y=\"122.67509\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"184.861696\" xlink:href=\"#md91571ca24\" y=\"115.35837\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"104.311951\" xlink:href=\"#md91571ca24\" y=\"199.65322\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.769581\" xlink:href=\"#md91571ca24\" y=\"141.025947\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.928378\" xlink:href=\"#md91571ca24\" y=\"127.868723\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.062908\" xlink:href=\"#md91571ca24\" y=\"121.903181\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.199001\" xlink:href=\"#md91571ca24\" y=\"105.465335\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.037727\" xlink:href=\"#md91571ca24\" y=\"124.755124\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.277015\" xlink:href=\"#md91571ca24\" y=\"116.991946\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"228.949658\" xlink:href=\"#md91571ca24\" y=\"108.937654\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.151457\" xlink:href=\"#md91571ca24\" y=\"145.533392\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"222.692464\" xlink:href=\"#md91571ca24\" y=\"86.028917\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"109.060122\" xlink:href=\"#md91571ca24\" y=\"193.47896\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.731607\" xlink:href=\"#md91571ca24\" y=\"124.378582\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.222202\" xlink:href=\"#md91571ca24\" y=\"139.069908\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.433941\" xlink:href=\"#md91571ca24\" y=\"119.704484\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.940595\" xlink:href=\"#md91571ca24\" y=\"118.798962\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"206.278256\" xlink:href=\"#md91571ca24\" y=\"84.494872\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"138.433579\" xlink:href=\"#md91571ca24\" y=\"144.215288\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.752183\" xlink:href=\"#md91571ca24\" y=\"141.180079\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.515371\" xlink:href=\"#md91571ca24\" y=\"97.882762\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.366145\" xlink:href=\"#md91571ca24\" y=\"125.56943\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.872618\" xlink:href=\"#md91571ca24\" y=\"115.302387\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.220015\" xlink:href=\"#md91571ca24\" y=\"127.382177\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.102396\" xlink:href=\"#md91571ca24\" y=\"118.959642\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.405548\" xlink:href=\"#md91571ca24\" y=\"107.605419\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"209.595686\" xlink:href=\"#md91571ca24\" y=\"100.285691\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"140.953923\" xlink:href=\"#md91571ca24\" y=\"133.526509\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.116687\" xlink:href=\"#md91571ca24\" y=\"111.009809\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.690306\" xlink:href=\"#md91571ca24\" y=\"118.981022\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"119.906023\" xlink:href=\"#md91571ca24\" y=\"164.830511\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.561657\" xlink:href=\"#md91571ca24\" y=\"123.445707\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.968199\" xlink:href=\"#md91571ca24\" y=\"115.527647\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.634765\" xlink:href=\"#md91571ca24\" y=\"124.128825\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"135.659223\" xlink:href=\"#md91571ca24\" y=\"164.390358\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.2316\" xlink:href=\"#md91571ca24\" y=\"101.544284\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.123842\" xlink:href=\"#md91571ca24\" y=\"148.791533\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"188.096555\" xlink:href=\"#md91571ca24\" y=\"93.722382\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.676702\" xlink:href=\"#md91571ca24\" y=\"119.072549\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.951317\" xlink:href=\"#md91571ca24\" y=\"116.593741\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.261682\" xlink:href=\"#md91571ca24\" y=\"117.700874\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"141.809655\" xlink:href=\"#md91571ca24\" y=\"125.712468\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.940641\" xlink:href=\"#md91571ca24\" y=\"164.370017\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"128.048428\" xlink:href=\"#md91571ca24\" y=\"143.608871\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.951634\" xlink:href=\"#md91571ca24\" y=\"139.300283\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.705055\" xlink:href=\"#md91571ca24\" y=\"148.672077\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.797795\" xlink:href=\"#md91571ca24\" y=\"106.174276\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.559522\" xlink:href=\"#md91571ca24\" y=\"161.76426\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.652688\" xlink:href=\"#md91571ca24\" y=\"143.425704\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"114.526555\" xlink:href=\"#md91571ca24\" y=\"191.722452\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"205.269701\" xlink:href=\"#md91571ca24\" y=\"112.76156\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.350934\" xlink:href=\"#md91571ca24\" y=\"150.305532\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.6697\" xlink:href=\"#md91571ca24\" y=\"117.667792\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.788503\" xlink:href=\"#md91571ca24\" y=\"119.429088\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"190.499044\" xlink:href=\"#md91571ca24\" y=\"116.367325\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.906779\" xlink:href=\"#md91571ca24\" y=\"125.533395\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.313238\" xlink:href=\"#md91571ca24\" y=\"115.891026\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"137.130025\" xlink:href=\"#md91571ca24\" y=\"157.975591\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.267002\" xlink:href=\"#md91571ca24\" y=\"131.310862\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"129.815849\" xlink:href=\"#md91571ca24\" y=\"146.929498\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.539409\" xlink:href=\"#md91571ca24\" y=\"128.473755\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.314538\" xlink:href=\"#md91571ca24\" y=\"127.875579\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.455683\" xlink:href=\"#md91571ca24\" y=\"139.998952\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"98.365691\" xlink:href=\"#md91571ca24\" y=\"196.250575\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.196903\" xlink:href=\"#md91571ca24\" y=\"152.081925\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.817206\" xlink:href=\"#md91571ca24\" y=\"133.101178\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.489243\" xlink:href=\"#md91571ca24\" y=\"124.243834\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.949175\" xlink:href=\"#md91571ca24\" y=\"134.44719\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"190.597038\" xlink:href=\"#md91571ca24\" y=\"107.451175\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.074005\" xlink:href=\"#md91571ca24\" y=\"130.85239\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.320976\" xlink:href=\"#md91571ca24\" y=\"113.6\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.029282\" xlink:href=\"#md91571ca24\" y=\"135.269781\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"117.340233\" xlink:href=\"#md91571ca24\" y=\"182.41478\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.545438\" xlink:href=\"#md91571ca24\" y=\"129.078708\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.181214\" xlink:href=\"#md91571ca24\" y=\"113.66887\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.257532\" xlink:href=\"#md91571ca24\" y=\"123.64138\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"117.281885\" xlink:href=\"#md91571ca24\" y=\"164.144116\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.182223\" xlink:href=\"#md91571ca24\" y=\"100.747306\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.198931\" xlink:href=\"#md91571ca24\" y=\"139.550406\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.649008\" xlink:href=\"#md91571ca24\" y=\"122.680781\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"123.048759\" xlink:href=\"#md91571ca24\" y=\"147.666188\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.893671\" xlink:href=\"#md91571ca24\" y=\"125.073286\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"109.089115\" xlink:href=\"#md91571ca24\" y=\"171.390139\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.941698\" xlink:href=\"#md91571ca24\" y=\"127.886227\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.729486\" xlink:href=\"#md91571ca24\" y=\"127.104408\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.237866\" xlink:href=\"#md91571ca24\" y=\"98.091347\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.227197\" xlink:href=\"#md91571ca24\" y=\"114.418999\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.866984\" xlink:href=\"#md91571ca24\" y=\"133.146674\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.250415\" xlink:href=\"#md91571ca24\" y=\"109.33348\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.108411\" xlink:href=\"#md91571ca24\" y=\"129.021248\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"48.312405\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.422135\" xlink:href=\"#md91571ca24\" y=\"142.240236\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"116.459604\" xlink:href=\"#md91571ca24\" y=\"164.715043\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.468008\" xlink:href=\"#md91571ca24\" y=\"133.511957\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.32512\" xlink:href=\"#md91571ca24\" y=\"118.122\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.460685\" xlink:href=\"#md91571ca24\" y=\"115.510363\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.877518\" xlink:href=\"#md91571ca24\" y=\"143.71055\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"119.422579\" xlink:href=\"#md91571ca24\" y=\"143.883092\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.825805\" xlink:href=\"#md91571ca24\" y=\"121.579383\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.301542\" xlink:href=\"#md91571ca24\" y=\"133.172575\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.843579\" xlink:href=\"#md91571ca24\" y=\"111.702089\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.84997\" xlink:href=\"#md91571ca24\" y=\"103.824423\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.88716\" xlink:href=\"#md91571ca24\" y=\"96.61356\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"134.679045\" xlink:href=\"#md91571ca24\" y=\"142.610083\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.2044\" xlink:href=\"#md91571ca24\" y=\"140.333962\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"124.435299\" xlink:href=\"#md91571ca24\" y=\"103.276425\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.081263\" xlink:href=\"#md91571ca24\" y=\"102.000864\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"177.387699\" xlink:href=\"#md91571ca24\" y=\"53.970581\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"106.213467\" xlink:href=\"#md91571ca24\" y=\"185.785115\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.071762\" xlink:href=\"#md91571ca24\" y=\"123.669099\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.369515\" xlink:href=\"#md91571ca24\" y=\"118.943205\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.676625\" xlink:href=\"#md91571ca24\" y=\"132.473595\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"201.804832\" xlink:href=\"#md91571ca24\" y=\"115.649704\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.254132\" xlink:href=\"#md91571ca24\" y=\"121.255723\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"109.349309\" xlink:href=\"#md91571ca24\" y=\"151.032965\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.684545\" xlink:href=\"#md91571ca24\" y=\"182.360515\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.279328\" xlink:href=\"#md91571ca24\" y=\"111.229525\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"121.870598\" xlink:href=\"#md91571ca24\" y=\"147.358796\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"124.621573\" xlink:href=\"#md91571ca24\" y=\"167.872075\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"198.678309\" xlink:href=\"#md91571ca24\" y=\"118.813671\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.771681\" xlink:href=\"#md91571ca24\" y=\"105.191776\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.071581\" xlink:href=\"#md91571ca24\" y=\"126.604887\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"123.54307\" xlink:href=\"#md91571ca24\" y=\"168.902721\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.460803\" xlink:href=\"#md91571ca24\" y=\"129.94599\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"128.234702\" xlink:href=\"#md91571ca24\" y=\"163.264595\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.599917\" xlink:href=\"#md91571ca24\" y=\"115.678651\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.935607\" xlink:href=\"#md91571ca24\" y=\"123.056538\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.662212\" xlink:href=\"#md91571ca24\" y=\"121.453424\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.966043\" xlink:href=\"#md91571ca24\" y=\"111.984665\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.892332\" xlink:href=\"#md91571ca24\" y=\"139.722664\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.460447\" xlink:href=\"#md91571ca24\" y=\"106.076917\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"142.907553\" xlink:href=\"#md91571ca24\" y=\"178.571655\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.313887\" xlink:href=\"#md91571ca24\" y=\"120.944821\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.012327\" xlink:href=\"#md91571ca24\" y=\"130.153411\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"193.474708\" xlink:href=\"#md91571ca24\" y=\"102.194878\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"125.202505\" xlink:href=\"#md91571ca24\" y=\"163.641514\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.266518\" xlink:href=\"#md91571ca24\" y=\"121.526995\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.494595\" xlink:href=\"#md91571ca24\" y=\"129.899549\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.935451\" xlink:href=\"#md91571ca24\" y=\"124.090352\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.297682\" xlink:href=\"#md91571ca24\" y=\"122.008435\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.130561\" xlink:href=\"#md91571ca24\" y=\"109.050658\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"119.759615\" xlink:href=\"#md91571ca24\" y=\"161.689348\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.29672\" xlink:href=\"#md91571ca24\" y=\"123.046381\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.881345\" xlink:href=\"#md91571ca24\" y=\"177.85944\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"141.488288\" xlink:href=\"#md91571ca24\" y=\"156.494567\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.242067\" xlink:href=\"#md91571ca24\" y=\"117.331328\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.743399\" xlink:href=\"#md91571ca24\" y=\"155.314798\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"121.76151\" xlink:href=\"#md91571ca24\" y=\"187.726426\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.164351\" xlink:href=\"#md91571ca24\" y=\"135.463225\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.780496\" xlink:href=\"#md91571ca24\" y=\"119.651473\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.426586\" xlink:href=\"#md91571ca24\" y=\"125.287233\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"183.699158\" xlink:href=\"#md91571ca24\" y=\"116.562194\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"123.152767\" xlink:href=\"#md91571ca24\" y=\"145.110622\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"191.632058\" xlink:href=\"#md91571ca24\" y=\"100.477336\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.263078\" xlink:href=\"#md91571ca24\" y=\"123.488673\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.738624\" xlink:href=\"#md91571ca24\" y=\"127.797432\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.502131\" xlink:href=\"#md91571ca24\" y=\"116.309445\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.127379\" xlink:href=\"#md91571ca24\" y=\"134.809219\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.348723\" xlink:href=\"#md91571ca24\" y=\"121.773026\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.051528\" xlink:href=\"#md91571ca24\" y=\"138.248633\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.374205\" xlink:href=\"#md91571ca24\" y=\"115.464633\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"124.948455\" xlink:href=\"#md91571ca24\" y=\"148.512184\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.035163\" xlink:href=\"#md91571ca24\" y=\"111.958073\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"237.878464\" xlink:href=\"#md91571ca24\" y=\"56.278769\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.693951\" xlink:href=\"#md91571ca24\" y=\"106.937135\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.862648\" xlink:href=\"#md91571ca24\" y=\"160.911648\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.082471\" xlink:href=\"#md91571ca24\" y=\"120.489826\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.935489\" xlink:href=\"#md91571ca24\" y=\"130.832054\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.612435\" xlink:href=\"#md91571ca24\" y=\"124.326091\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.21049\" xlink:href=\"#md91571ca24\" y=\"103.986904\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"266.858124\" xlink:href=\"#md91571ca24\" y=\"76.49343\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.777892\" xlink:href=\"#md91571ca24\" y=\"120.603194\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.243534\" xlink:href=\"#md91571ca24\" y=\"130.735076\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.201803\" xlink:href=\"#md91571ca24\" y=\"113.000066\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.685066\" xlink:href=\"#md91571ca24\" y=\"119.640827\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.115907\" xlink:href=\"#md91571ca24\" y=\"127.74136\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.26738\" xlink:href=\"#md91571ca24\" y=\"117.866952\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.420668\" xlink:href=\"#md91571ca24\" y=\"126.974823\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"142.635675\" xlink:href=\"#md91571ca24\" y=\"102.778427\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.257949\" xlink:href=\"#md91571ca24\" y=\"165.545327\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.173033\" xlink:href=\"#md91571ca24\" y=\"132.734378\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"134.299071\" xlink:href=\"#md91571ca24\" y=\"120.096816\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.157241\" xlink:href=\"#md91571ca24\" y=\"117.37069\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"207.633282\" xlink:href=\"#md91571ca24\" y=\"101.825055\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.304746\" xlink:href=\"#md91571ca24\" y=\"149.495638\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.153367\" xlink:href=\"#md91571ca24\" y=\"103.478224\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.848406\" xlink:href=\"#md91571ca24\" y=\"121.270912\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"191.133172\" xlink:href=\"#md91571ca24\" y=\"123.963667\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.830975\" xlink:href=\"#md91571ca24\" y=\"92.627659\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.72606\" xlink:href=\"#md91571ca24\" y=\"95.514729\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.255368\" xlink:href=\"#md91571ca24\" y=\"151.438177\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"121.983302\" xlink:href=\"#md91571ca24\" y=\"166.740124\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"130.752655\" xlink:href=\"#md91571ca24\" y=\"135.204864\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"107.088659\" xlink:href=\"#md91571ca24\" y=\"196.267073\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"132.408247\" xlink:href=\"#md91571ca24\" y=\"144.387514\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"94.650375\" xlink:href=\"#md91571ca24\" y=\"142.670691\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.292428\" xlink:href=\"#md91571ca24\" y=\"112.311391\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.123159\" xlink:href=\"#md91571ca24\" y=\"150.773734\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.46938\" xlink:href=\"#md91571ca24\" y=\"129.669195\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.822415\" xlink:href=\"#md91571ca24\" y=\"141.195422\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"120.316985\" xlink:href=\"#md91571ca24\" y=\"169.019222\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"140.588957\" xlink:href=\"#md91571ca24\" y=\"132.866853\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"184.237275\" xlink:href=\"#md91571ca24\" y=\"86.122612\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.870455\" xlink:href=\"#md91571ca24\" y=\"134.613947\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.031312\" xlink:href=\"#md91571ca24\" y=\"123.428259\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"131.889363\" xlink:href=\"#md91571ca24\" y=\"144.828423\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"200.412778\" xlink:href=\"#md91571ca24\" y=\"109.538194\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.842846\" xlink:href=\"#md91571ca24\" y=\"108.879778\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.41512\" xlink:href=\"#md91571ca24\" y=\"110.504543\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"208.704903\" xlink:href=\"#md91571ca24\" y=\"122.619645\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.99966\" xlink:href=\"#md91571ca24\" y=\"105.63024\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.545603\" xlink:href=\"#md91571ca24\" y=\"136.101421\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.451627\" xlink:href=\"#md91571ca24\" y=\"106.416986\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.15668\" xlink:href=\"#md91571ca24\" y=\"157.312451\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"207.083876\" xlink:href=\"#md91571ca24\" y=\"89.454626\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.285151\" xlink:href=\"#md91571ca24\" y=\"121.279669\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.266243\" xlink:href=\"#md91571ca24\" y=\"112.301797\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"91.094498\" xlink:href=\"#md91571ca24\" y=\"201.936505\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.319249\" xlink:href=\"#md91571ca24\" y=\"175.459868\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.608567\" xlink:href=\"#md91571ca24\" y=\"88.588117\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.875002\" xlink:href=\"#md91571ca24\" y=\"138.38456\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.347958\" xlink:href=\"#md91571ca24\" y=\"138.841025\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.522371\" xlink:href=\"#md91571ca24\" y=\"134.643554\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"193.25473\" xlink:href=\"#md91571ca24\" y=\"112.968903\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.766328\" xlink:href=\"#md91571ca24\" y=\"127.315312\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.243643\" xlink:href=\"#md91571ca24\" y=\"126.767556\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.052555\" xlink:href=\"#md91571ca24\" y=\"164.399842\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"120.125637\" xlink:href=\"#md91571ca24\" y=\"133.767487\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.271294\" xlink:href=\"#md91571ca24\" y=\"119.988157\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"141.69003\" xlink:href=\"#md91571ca24\" y=\"142.534469\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"198.636952\" xlink:href=\"#md91571ca24\" y=\"89.362101\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.201282\" xlink:href=\"#md91571ca24\" y=\"124.812033\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.451168\" xlink:href=\"#md91571ca24\" y=\"126.38138\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.135059\" xlink:href=\"#md91571ca24\" y=\"112.807329\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"80.913235\" xlink:href=\"#md91571ca24\" y=\"199.469649\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.811657\" xlink:href=\"#md91571ca24\" y=\"115.983496\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.494364\" xlink:href=\"#md91571ca24\" y=\"121.188744\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.204476\" xlink:href=\"#md91571ca24\" y=\"113.199696\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.854824\" xlink:href=\"#md91571ca24\" y=\"123.906271\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"238.590212\" xlink:href=\"#md91571ca24\" y=\"105.021137\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.36794\" xlink:href=\"#md91571ca24\" y=\"110.140369\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.50557\" xlink:href=\"#md91571ca24\" y=\"112.030769\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.009226\" xlink:href=\"#md91571ca24\" y=\"149.061223\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.516103\" xlink:href=\"#md91571ca24\" y=\"110.650205\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"135.087979\" xlink:href=\"#md91571ca24\" y=\"156.373912\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.987603\" xlink:href=\"#md91571ca24\" y=\"112.587356\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.31663\" xlink:href=\"#md91571ca24\" y=\"141.248384\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.089304\" xlink:href=\"#md91571ca24\" y=\"131.869723\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.167815\" xlink:href=\"#md91571ca24\" y=\"143.807574\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.01302\" xlink:href=\"#md91571ca24\" y=\"115.435999\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.776035\" xlink:href=\"#md91571ca24\" y=\"117.935565\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"183.128367\" xlink:href=\"#md91571ca24\" y=\"103.074556\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"137.515261\" xlink:href=\"#md91571ca24\" y=\"148.716155\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"131.808944\" xlink:href=\"#md91571ca24\" y=\"140.200742\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.007198\" xlink:href=\"#md91571ca24\" y=\"126.097517\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"126.739437\" xlink:href=\"#md91571ca24\" y=\"119.198876\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.131334\" xlink:href=\"#md91571ca24\" y=\"152.554647\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"200.066086\" xlink:href=\"#md91571ca24\" y=\"100.102855\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"202.907662\" xlink:href=\"#md91571ca24\" y=\"104.462071\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"133.261549\" xlink:href=\"#md91571ca24\" y=\"135.860252\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"198.441509\" xlink:href=\"#md91571ca24\" y=\"124.696326\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.248954\" xlink:href=\"#md91571ca24\" y=\"93.794166\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.203191\" xlink:href=\"#md91571ca24\" y=\"128.916333\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.54123\" xlink:href=\"#md91571ca24\" y=\"110.392884\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.01667\" xlink:href=\"#md91571ca24\" y=\"113.581774\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.028992\" xlink:href=\"#md91571ca24\" y=\"124.154692\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.256199\" xlink:href=\"#md91571ca24\" y=\"139.909014\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.120048\" xlink:href=\"#md91571ca24\" y=\"118.726554\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.994301\" xlink:href=\"#md91571ca24\" y=\"106.009281\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.280732\" xlink:href=\"#md91571ca24\" y=\"118.208857\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.104993\" xlink:href=\"#md91571ca24\" y=\"125.763544\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.057732\" xlink:href=\"#md91571ca24\" y=\"134.739874\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.484413\" xlink:href=\"#md91571ca24\" y=\"104.149177\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.480135\" xlink:href=\"#md91571ca24\" y=\"126.056286\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"132.930611\" xlink:href=\"#md91571ca24\" y=\"165.520019\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.621666\" xlink:href=\"#md91571ca24\" y=\"119.888041\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.885592\" xlink:href=\"#md91571ca24\" y=\"121.67892\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.133243\" xlink:href=\"#md91571ca24\" y=\"154.037074\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"230.87725\" xlink:href=\"#md91571ca24\" y=\"101.020015\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.926293\" xlink:href=\"#md91571ca24\" y=\"131.628887\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"118.498098\" xlink:href=\"#md91571ca24\" y=\"160.136637\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.879587\" xlink:href=\"#md91571ca24\" y=\"121.306689\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.606035\" xlink:href=\"#md91571ca24\" y=\"111.950903\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.438796\" xlink:href=\"#md91571ca24\" y=\"142.108061\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.079716\" xlink:href=\"#md91571ca24\" y=\"144.987918\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.860481\" xlink:href=\"#md91571ca24\" y=\"141.493022\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.141067\" xlink:href=\"#md91571ca24\" y=\"116.403091\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.805984\" xlink:href=\"#md91571ca24\" y=\"137.04231\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.475292\" xlink:href=\"#md91571ca24\" y=\"127.624317\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.595973\" xlink:href=\"#md91571ca24\" y=\"103.828768\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"108.217539\" xlink:href=\"#md91571ca24\" y=\"201.975762\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.872664\" xlink:href=\"#md91571ca24\" y=\"124.637422\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"108.265739\" xlink:href=\"#md91571ca24\" y=\"180.141352\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.267143\" xlink:href=\"#md91571ca24\" y=\"104.096488\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.300919\" xlink:href=\"#md91571ca24\" y=\"133.817352\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.647511\" xlink:href=\"#md91571ca24\" y=\"122.642771\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.094607\" xlink:href=\"#md91571ca24\" y=\"116.27015\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"107.335452\" xlink:href=\"#md91571ca24\" y=\"177.950293\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"129.965886\" xlink:href=\"#md91571ca24\" y=\"156.730839\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"85.288853\" xlink:href=\"#md91571ca24\" y=\"201.040058\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.949526\" xlink:href=\"#md91571ca24\" y=\"122.115075\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.627831\" xlink:href=\"#md91571ca24\" y=\"116.553275\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"133.276596\" xlink:href=\"#md91571ca24\" y=\"156.209729\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.443056\" xlink:href=\"#md91571ca24\" y=\"138.4469\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.847028\" xlink:href=\"#md91571ca24\" y=\"118.219875\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"132.757712\" xlink:href=\"#md91571ca24\" y=\"163.490499\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"128.75982\" xlink:href=\"#md91571ca24\" y=\"171.388578\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.320577\" xlink:href=\"#md91571ca24\" y=\"116.128605\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.111613\" xlink:href=\"#md91571ca24\" y=\"134.517031\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.014243\" xlink:href=\"#md91571ca24\" y=\"148.281054\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.176101\" xlink:href=\"#md91571ca24\" y=\"164.059206\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"142.66634\" xlink:href=\"#md91571ca24\" y=\"131.57376\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.370051\" xlink:href=\"#md91571ca24\" y=\"122.224673\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.4103\" xlink:href=\"#md91571ca24\" y=\"125.826682\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.570642\" xlink:href=\"#md91571ca24\" y=\"133.235388\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.083082\" xlink:href=\"#md91571ca24\" y=\"118.965722\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.394965\" xlink:href=\"#md91571ca24\" y=\"142.667566\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.063405\" xlink:href=\"#md91571ca24\" y=\"124.71728\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"142.519355\" xlink:href=\"#md91571ca24\" y=\"126.598465\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.835472\" xlink:href=\"#md91571ca24\" y=\"115.172717\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.982337\" xlink:href=\"#md91571ca24\" y=\"116.750558\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.491478\" xlink:href=\"#md91571ca24\" y=\"100.087795\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"136.035723\" xlink:href=\"#md91571ca24\" y=\"143.883962\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.130982\" xlink:href=\"#md91571ca24\" y=\"121.225988\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.380186\" xlink:href=\"#md91571ca24\" y=\"126.757192\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.907555\" xlink:href=\"#md91571ca24\" y=\"123.050188\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"197.927265\" xlink:href=\"#md91571ca24\" y=\"94.045809\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.574667\" xlink:href=\"#md91571ca24\" y=\"107.36036\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"200.313488\" xlink:href=\"#md91571ca24\" y=\"106.073212\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.967054\" xlink:href=\"#md91571ca24\" y=\"140.375725\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"117.266663\" xlink:href=\"#md91571ca24\" y=\"157.705898\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.801643\" xlink:href=\"#md91571ca24\" y=\"135.764139\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.492631\" xlink:href=\"#md91571ca24\" y=\"131.269993\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.122573\" xlink:href=\"#md91571ca24\" y=\"124.932195\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.540038\" xlink:href=\"#md91571ca24\" y=\"113.852009\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"202.93484\" xlink:href=\"#md91571ca24\" y=\"93.606467\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.012989\" xlink:href=\"#md91571ca24\" y=\"132.288568\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.020067\" xlink:href=\"#md91571ca24\" y=\"128.532342\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.351478\" xlink:href=\"#md91571ca24\" y=\"110.129718\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.917566\" xlink:href=\"#md91571ca24\" y=\"118.66789\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"122.274309\" xlink:href=\"#md91571ca24\" y=\"125.937234\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.844809\" xlink:href=\"#md91571ca24\" y=\"121.889119\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"104.844676\" xlink:href=\"#md91571ca24\" y=\"190.751242\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.292205\" xlink:href=\"#md91571ca24\" y=\"86.560943\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.18621\" xlink:href=\"#md91571ca24\" y=\"134.515014\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.229345\" xlink:href=\"#md91571ca24\" y=\"117.170921\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"204.179236\" xlink:href=\"#md91571ca24\" y=\"114.114539\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.553281\" xlink:href=\"#md91571ca24\" y=\"122.270716\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"131.578637\" xlink:href=\"#md91571ca24\" y=\"156.38661\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.843128\" xlink:href=\"#md91571ca24\" y=\"123.665119\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.432616\" xlink:href=\"#md91571ca24\" y=\"108.570603\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"131.786587\" xlink:href=\"#md91571ca24\" y=\"156.631118\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.091694\" xlink:href=\"#md91571ca24\" y=\"119.485969\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"207.086779\" xlink:href=\"#md91571ca24\" y=\"109.435182\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"136.668549\" xlink:href=\"#md91571ca24\" y=\"151.586156\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"189.543031\" xlink:href=\"#md91571ca24\" y=\"97.595526\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.088294\" xlink:href=\"#md91571ca24\" y=\"133.478205\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.875033\" xlink:href=\"#md91571ca24\" y=\"119.291902\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"193.01447\" xlink:href=\"#md91571ca24\" y=\"95.58629\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"141.175423\" xlink:href=\"#md91571ca24\" y=\"149.49462\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"202.394817\" xlink:href=\"#md91571ca24\" y=\"108.986188\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"116.741182\" xlink:href=\"#md91571ca24\" y=\"187.57672\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.129923\" xlink:href=\"#md91571ca24\" y=\"101.178258\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.32085\" xlink:href=\"#md91571ca24\" y=\"119.862409\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"89.361507\" xlink:href=\"#md91571ca24\" y=\"171.748913\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"219.234426\" xlink:href=\"#md91571ca24\" y=\"36.807098\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.785854\" xlink:href=\"#md91571ca24\" y=\"118.323067\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.56355\" xlink:href=\"#md91571ca24\" y=\"113.651838\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.232658\" xlink:href=\"#md91571ca24\" y=\"116.671694\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.763247\" xlink:href=\"#md91571ca24\" y=\"119.338679\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.760509\" xlink:href=\"#md91571ca24\" y=\"126.399144\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.137442\" xlink:href=\"#md91571ca24\" y=\"155.501156\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.285089\" xlink:href=\"#md91571ca24\" y=\"111.784237\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.255922\" xlink:href=\"#md91571ca24\" y=\"128.761939\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.84263\" xlink:href=\"#md91571ca24\" y=\"122.585248\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.409937\" xlink:href=\"#md91571ca24\" y=\"111.940446\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"151.228469\" xlink:href=\"#md91571ca24\" y=\"129.185913\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"184.240865\" xlink:href=\"#md91571ca24\" y=\"102.835302\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.679431\" xlink:href=\"#md91571ca24\" y=\"155.056892\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.459855\" xlink:href=\"#md91571ca24\" y=\"124.200618\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.695537\" xlink:href=\"#md91571ca24\" y=\"116.326045\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.478715\" xlink:href=\"#md91571ca24\" y=\"129.985771\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.354887\" xlink:href=\"#md91571ca24\" y=\"122.295469\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"194.543283\" xlink:href=\"#md91571ca24\" y=\"100.606794\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"146.537641\" xlink:href=\"#md91571ca24\" y=\"153.607799\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"247.143217\" xlink:href=\"#md91571ca24\" y=\"40.619215\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"93.032252\" xlink:href=\"#md91571ca24\" y=\"200.285015\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.682611\" xlink:href=\"#md91571ca24\" y=\"113.960805\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"249.011749\" xlink:href=\"#md91571ca24\" y=\"108.290251\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"125.266646\" xlink:href=\"#md91571ca24\" y=\"150.997992\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.085699\" xlink:href=\"#md91571ca24\" y=\"122.912265\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.970378\" xlink:href=\"#md91571ca24\" y=\"110.875524\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.083547\" xlink:href=\"#md91571ca24\" y=\"130.403065\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.051498\" xlink:href=\"#md91571ca24\" y=\"149.314451\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"97.083528\" xlink:href=\"#md91571ca24\" y=\"184.834305\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.137812\" xlink:href=\"#md91571ca24\" y=\"130.466213\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.951681\" xlink:href=\"#md91571ca24\" y=\"103.34274\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"112.441668\" xlink:href=\"#md91571ca24\" y=\"170.468396\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.454214\" xlink:href=\"#md91571ca24\" y=\"116.019668\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"107.741709\" xlink:href=\"#md91571ca24\" y=\"190.865067\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.681579\" xlink:href=\"#md91571ca24\" y=\"148.923363\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.077379\" xlink:href=\"#md91571ca24\" y=\"116.063635\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"191.795282\" xlink:href=\"#md91571ca24\" y=\"106.45361\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"214.120964\" xlink:href=\"#md91571ca24\" y=\"80.470093\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"153.073199\" xlink:href=\"#md91571ca24\" y=\"128.085714\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.410356\" xlink:href=\"#md91571ca24\" y=\"122.526144\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"134.118124\" xlink:href=\"#md91571ca24\" y=\"146.451826\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.634444\" xlink:href=\"#md91571ca24\" y=\"113.841737\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.673607\" xlink:href=\"#md91571ca24\" y=\"130.375545\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"164.455175\" xlink:href=\"#md91571ca24\" y=\"122.310722\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.37376\" xlink:href=\"#md91571ca24\" y=\"114.880524\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.289673\" xlink:href=\"#md91571ca24\" y=\"110.229169\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.437638\" xlink:href=\"#md91571ca24\" y=\"117.748157\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"148.367032\" xlink:href=\"#md91571ca24\" y=\"123.80924\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.189477\" xlink:href=\"#md91571ca24\" y=\"144.077689\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.459374\" xlink:href=\"#md91571ca24\" y=\"86.525869\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"185.600881\" xlink:href=\"#md91571ca24\" y=\"109.670549\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.390477\" xlink:href=\"#md91571ca24\" y=\"108.09236\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"199.106185\" xlink:href=\"#md91571ca24\" y=\"99.621106\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"132.569948\" xlink:href=\"#md91571ca24\" y=\"141.178091\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.978922\" xlink:href=\"#md91571ca24\" y=\"168.113311\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.242922\" xlink:href=\"#md91571ca24\" y=\"109.434283\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.518968\" xlink:href=\"#md91571ca24\" y=\"109.465345\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"200.070428\" xlink:href=\"#md91571ca24\" y=\"83.698058\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"184.238908\" xlink:href=\"#md91571ca24\" y=\"101.69773\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"136.255228\" xlink:href=\"#md91571ca24\" y=\"140.000323\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.64348\" xlink:href=\"#md91571ca24\" y=\"123.547826\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.755519\" xlink:href=\"#md91571ca24\" y=\"120.383155\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.402549\" xlink:href=\"#md91571ca24\" y=\"108.85288\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.807944\" xlink:href=\"#md91571ca24\" y=\"122.42786\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.736288\" xlink:href=\"#md91571ca24\" y=\"124.896868\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.429182\" xlink:href=\"#md91571ca24\" y=\"119.233914\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"243.935976\" xlink:href=\"#md91571ca24\" y=\"45.365028\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"134.045279\" xlink:href=\"#md91571ca24\" y=\"136.65802\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"141.62911\" xlink:href=\"#md91571ca24\" y=\"136.821781\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.165907\" xlink:href=\"#md91571ca24\" y=\"109.370985\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"186.927771\" xlink:href=\"#md91571ca24\" y=\"118.788736\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"120.241607\" xlink:href=\"#md91571ca24\" y=\"170.831263\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.60901\" xlink:href=\"#md91571ca24\" y=\"118.949881\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"121.981487\" xlink:href=\"#md91571ca24\" y=\"164.960883\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"166.67995\" xlink:href=\"#md91571ca24\" y=\"112.793997\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"131.478757\" xlink:href=\"#md91571ca24\" y=\"143.564909\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.216324\" xlink:href=\"#md91571ca24\" y=\"115.266818\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"126.818081\" xlink:href=\"#md91571ca24\" y=\"170.339097\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"77.786446\" xlink:href=\"#md91571ca24\" y=\"190.129258\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.744243\" xlink:href=\"#md91571ca24\" y=\"112.626381\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.975551\" xlink:href=\"#md91571ca24\" y=\"109.156444\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.200099\" xlink:href=\"#md91571ca24\" y=\"128.200436\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"211.833862\" xlink:href=\"#md91571ca24\" y=\"73.795732\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.214373\" xlink:href=\"#md91571ca24\" y=\"121.014199\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.944019\" xlink:href=\"#md91571ca24\" y=\"133.84534\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.804329\" xlink:href=\"#md91571ca24\" y=\"120.858932\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.025638\" xlink:href=\"#md91571ca24\" y=\"115.490646\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"126.306371\" xlink:href=\"#md91571ca24\" y=\"121.51953\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.58779\" xlink:href=\"#md91571ca24\" y=\"122.381657\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"139.257499\" xlink:href=\"#md91571ca24\" y=\"117.726256\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.448405\" xlink:href=\"#md91571ca24\" y=\"121.645442\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.434107\" xlink:href=\"#md91571ca24\" y=\"122.299466\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.333303\" xlink:href=\"#md91571ca24\" y=\"107.525049\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"223.741235\" xlink:href=\"#md91571ca24\" y=\"106.49522\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"140.658321\" xlink:href=\"#md91571ca24\" y=\"156.654259\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"132.770212\" xlink:href=\"#md91571ca24\" y=\"139.264613\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"192.536243\" xlink:href=\"#md91571ca24\" y=\"95.855938\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.210956\" xlink:href=\"#md91571ca24\" y=\"111.78176\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.569\" xlink:href=\"#md91571ca24\" y=\"98.35011\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"191.156047\" xlink:href=\"#md91571ca24\" y=\"95.996358\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.382979\" xlink:href=\"#md91571ca24\" y=\"112.269354\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.47478\" xlink:href=\"#md91571ca24\" y=\"127.006353\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.324378\" xlink:href=\"#md91571ca24\" y=\"99.014532\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"136.687899\" xlink:href=\"#md91571ca24\" y=\"148.133062\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"218.420834\" xlink:href=\"#md91571ca24\" y=\"114.008647\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"101.276125\" xlink:href=\"#md91571ca24\" y=\"189.48747\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"168.210428\" xlink:href=\"#md91571ca24\" y=\"102.230814\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.958042\" xlink:href=\"#md91571ca24\" y=\"119.114154\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.731671\" xlink:href=\"#md91571ca24\" y=\"126.356841\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"215.195488\" xlink:href=\"#md91571ca24\" y=\"77.469192\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.29886\" xlink:href=\"#md91571ca24\" y=\"117.377107\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.929025\" xlink:href=\"#md91571ca24\" y=\"119.126449\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.656262\" xlink:href=\"#md91571ca24\" y=\"134.805467\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.935875\" xlink:href=\"#md91571ca24\" y=\"113.76779\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.657335\" xlink:href=\"#md91571ca24\" y=\"112.1933\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.617122\" xlink:href=\"#md91571ca24\" y=\"122.276291\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"127.243903\" xlink:href=\"#md91571ca24\" y=\"168.56388\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"136.53888\" xlink:href=\"#md91571ca24\" y=\"147.599652\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"73.384007\" xlink:href=\"#md91571ca24\" y=\"187.089855\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"198.764988\" xlink:href=\"#md91571ca24\" y=\"111.866166\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.839734\" xlink:href=\"#md91571ca24\" y=\"119.488907\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.322373\" xlink:href=\"#md91571ca24\" y=\"121.5659\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.372926\" xlink:href=\"#md91571ca24\" y=\"114.429804\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.563355\" xlink:href=\"#md91571ca24\" y=\"119.897952\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"114.325791\" xlink:href=\"#md91571ca24\" y=\"185.306622\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"173.325484\" xlink:href=\"#md91571ca24\" y=\"131.887183\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"181.321229\" xlink:href=\"#md91571ca24\" y=\"107.019197\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"189.759068\" xlink:href=\"#md91571ca24\" y=\"108.446829\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"182.533522\" xlink:href=\"#md91571ca24\" y=\"104.824195\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"189.401619\" xlink:href=\"#md91571ca24\" y=\"93.863164\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"137.047545\" xlink:href=\"#md91571ca24\" y=\"138.643716\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.598853\" xlink:href=\"#md91571ca24\" y=\"142.406697\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"154.729652\" xlink:href=\"#md91571ca24\" y=\"113.609176\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"150.246295\" xlink:href=\"#md91571ca24\" y=\"128.56412\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"197.472237\" xlink:href=\"#md91571ca24\" y=\"108.096036\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"201.30303\" xlink:href=\"#md91571ca24\" y=\"114.873479\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"87.847028\" xlink:href=\"#md91571ca24\" y=\"198.81411\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"180.698584\" xlink:href=\"#md91571ca24\" y=\"125.0968\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.053763\" xlink:href=\"#md91571ca24\" y=\"142.187659\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"129.633567\" xlink:href=\"#md91571ca24\" y=\"145.273546\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"129.174768\" xlink:href=\"#md91571ca24\" y=\"145.905742\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.940428\" xlink:href=\"#md91571ca24\" y=\"120.123645\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"85.87992\" xlink:href=\"#md91571ca24\" y=\"163.575668\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"187.698566\" xlink:href=\"#md91571ca24\" y=\"107.3528\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"248.006447\" xlink:href=\"#md91571ca24\" y=\"68.566178\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"169.844985\" xlink:href=\"#md91571ca24\" y=\"119.270323\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.690385\" xlink:href=\"#md91571ca24\" y=\"129.91456\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.336144\" xlink:href=\"#md91571ca24\" y=\"102.997218\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.009707\" xlink:href=\"#md91571ca24\" y=\"125.57131\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.035501\" xlink:href=\"#md91571ca24\" y=\"118.31449\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"189.326682\" xlink:href=\"#md91571ca24\" y=\"104.975014\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"131.97822\" xlink:href=\"#md91571ca24\" y=\"135.400851\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"152.208978\" xlink:href=\"#md91571ca24\" y=\"130.761556\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"144.037081\" xlink:href=\"#md91571ca24\" y=\"133.298304\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"191.566569\" xlink:href=\"#md91571ca24\" y=\"107.202377\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.206806\" xlink:href=\"#md91571ca24\" y=\"119.760595\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.336871\" xlink:href=\"#md91571ca24\" y=\"124.912833\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"110.88661\" xlink:href=\"#md91571ca24\" y=\"167.741842\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"109.44716\" xlink:href=\"#md91571ca24\" y=\"181.920748\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"147.197794\" xlink:href=\"#md91571ca24\" y=\"143.085109\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"161.937935\" xlink:href=\"#md91571ca24\" y=\"115.499841\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"170.941477\" xlink:href=\"#md91571ca24\" y=\"118.987681\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"176.46362\" xlink:href=\"#md91571ca24\" y=\"119.010264\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.0214\" xlink:href=\"#md91571ca24\" y=\"119.952803\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.277489\" xlink:href=\"#md91571ca24\" y=\"114.460773\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.900079\" xlink:href=\"#md91571ca24\" y=\"129.7627\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"133.991422\" xlink:href=\"#md91571ca24\" y=\"141.950361\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"172.486853\" xlink:href=\"#md91571ca24\" y=\"120.022597\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"158.007891\" xlink:href=\"#md91571ca24\" y=\"121.822319\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"157.024738\" xlink:href=\"#md91571ca24\" y=\"124.437891\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"149.239911\" xlink:href=\"#md91571ca24\" y=\"130.680412\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"179.642374\" xlink:href=\"#md91571ca24\" y=\"113.388783\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.123861\" xlink:href=\"#md91571ca24\" y=\"112.673391\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"103.072182\" xlink:href=\"#md91571ca24\" y=\"166.940051\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"167.361261\" xlink:href=\"#md91571ca24\" y=\"117.365572\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.142683\" xlink:href=\"#md91571ca24\" y=\"105.901444\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.490679\" xlink:href=\"#md91571ca24\" y=\"98.923277\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"225.028116\" xlink:href=\"#md91571ca24\" y=\"97.355914\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"138.415492\" xlink:href=\"#md91571ca24\" y=\"142.056089\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.417488\" xlink:href=\"#md91571ca24\" y=\"118.566788\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"155.979285\" xlink:href=\"#md91571ca24\" y=\"119.968953\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"162.330455\" xlink:href=\"#md91571ca24\" y=\"121.532894\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"165.326609\" xlink:href=\"#md91571ca24\" y=\"123.488734\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.083315\" xlink:href=\"#md91571ca24\" y=\"141.838919\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"174.800887\" xlink:href=\"#md91571ca24\" y=\"130.056284\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"199.809936\" xlink:href=\"#md91571ca24\" y=\"82.787351\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"160.289413\" xlink:href=\"#md91571ca24\" y=\"115.509716\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"159.993883\" xlink:href=\"#md91571ca24\" y=\"125.764295\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"196.307198\" xlink:href=\"#md91571ca24\" y=\"96.843604\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"114.366014\" xlink:href=\"#md91571ca24\" y=\"153.542339\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.986316\" xlink:href=\"#md91571ca24\" y=\"100.570547\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"163.638648\" xlink:href=\"#md91571ca24\" y=\"124.459025\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"145.471567\" xlink:href=\"#md91571ca24\" y=\"145.686725\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"171.750856\" xlink:href=\"#md91571ca24\" y=\"110.22612\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"102.930848\" xlink:href=\"#md91571ca24\" y=\"197.608977\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"103.906432\" xlink:href=\"#md91571ca24\" y=\"167.625943\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"156.478961\" xlink:href=\"#md91571ca24\" y=\"125.642675\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.087624\" xlink:href=\"#md91571ca24\" y=\"128.567053\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"143.856931\" xlink:href=\"#md91571ca24\" y=\"131.346582\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"275.963437\" xlink:href=\"#md91571ca24\" y=\"91.444525\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"178.214043\" xlink:href=\"#md91571ca24\" y=\"103.797094\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"258.254404\" xlink:href=\"#md91571ca24\" y=\"44.64354\"/>\n     <use style=\"fill:#1f77b4;stroke:#1f77b4;\" x=\"175.919113\" xlink:href=\"#md91571ca24\" y=\"111.984809\"/>\n     <use style=\"fill:#1f77b4;stro
Download .txt
gitextract_4r95syc5/

├── .gitignore
├── Arguments.py
├── LICENSE.md
├── README.md
├── benchmark_layers.py
├── benchmark_models.py
├── benchmark_scripts/
│   ├── DGCNN_site.sh
│   ├── Pointnet_site.sh
│   ├── dMaSIF_search.sh
│   └── dMaSIF_site.sh
├── data.py
├── data_analysis/
│   ├── analyse_atomnet.ipynb
│   ├── analyse_descriptors.py
│   ├── analyse_descriptors_para.py
│   ├── analyse_output.ipynb
│   ├── analyse_site_outputs.py
│   ├── analyse_site_outputs_graph.ipynb
│   ├── plot_search.ipynb
│   └── profiling_surface.ipynb
├── data_iteration.py
├── data_preprocessing/
│   ├── convert_pdb2npy.py
│   ├── convert_ply2npy.py
│   └── download_pdb.py
├── geometry_processing.py
├── helper.py
├── lists/
│   ├── testing.txt
│   ├── testing_ppi.txt
│   ├── training.txt
│   └── training_ppi.txt
├── main_inference.py
├── main_training.py
├── model.py
├── models/
│   └── dMaSIF_search_3layer_12A_16dim
└── requirements.txt
Download .txt
SYMBOL INDEX (118 symbols across 11 files)

FILE: benchmark_layers.py
  function ranges_slices (line 15) | def ranges_slices(batch):
  function diagonal_ranges (line 28) | def diagonal_ranges(batch_x=None, batch_y=None):
  function keops_knn (line 41) | def keops_knn(
  function knn_graph (line 74) | def knn_graph(
  class MyDynamicEdgeConv (line 103) | class MyDynamicEdgeConv(EdgeConv):
    method __init__ (line 106) | def __init__(self, nn, k, aggr="max", **kwargs):
    method forward (line 110) | def forward(self, x, batch=None):
    method __repr__ (line 117) | def __repr__(self):
  class MyXConv (line 121) | class MyXConv(torch.nn.Module):
    method __init__ (line 122) | def __init__(
    method reset_parameters (line 185) | def reset_parameters(self):
    method forward (line 190) | def forward(self, x, source, batch_source, target, batch_target):
    method __repr__ (line 255) | def __repr__(self):

FILE: benchmark_models.py
  function MLP (line 36) | def MLP(channels, batch_norm=True):
  class DGCNN_seg (line 50) | class DGCNN_seg(torch.nn.Module):
    method __init__ (line 51) | def __init__(
    method forward (line 90) | def forward(self, positions, features, batch_indices):
  class SAModule (line 124) | class SAModule(torch.nn.Module):
    method __init__ (line 127) | def __init__(self, ratio, r, nn, max_num_neighbors=64):
    method forward (line 134) | def forward(self, x, pos, batch):
  class GlobalSAModule (line 158) | class GlobalSAModule(torch.nn.Module):
    method __init__ (line 159) | def __init__(self, nn):
    method forward (line 163) | def forward(self, x, pos, batch):
  class FPModule (line 171) | class FPModule(torch.nn.Module):
    method __init__ (line 172) | def __init__(self, k, nn):
    method forward (line 177) | def forward(self, x, pos, batch, x_skip, pos_skip, batch_skip):
  class PointNet2_seg (line 185) | class PointNet2_seg(torch.nn.Module):
    method __init__ (line 186) | def __init__(self, args, in_channels, out_channels):
    method forward (line 218) | def forward(self, positions, features, batch_indices):
  class dMaSIFConv_seg (line 233) | class dMaSIFConv_seg(torch.nn.Module):
    method __init__ (line 234) | def __init__(self, args, in_channels, out_channels, n_layers, radius=9...
    method forward (line 260) | def forward(self, features):
    method load_mesh (line 272) | def load_mesh(self, xyz, triangles=None, normals=None, weights=None, b...

FILE: data.py
  function numpy (line 18) | def numpy(x):
  function iface_valid_filter (line 22) | def iface_valid_filter(protein_pair):
  class RandomRotationPairAtoms (line 39) | class RandomRotationPairAtoms(object):
    method __call__ (line 42) | def __call__(self, data):
    method __repr__ (line 58) | def __repr__(self):
  class CenterPairAtoms (line 62) | class CenterPairAtoms(object):
    method __call__ (line 65) | def __call__(self, data):
    method __repr__ (line 79) | def __repr__(self):
  class NormalizeChemFeatures (line 83) | class NormalizeChemFeatures(object):
    method __call__ (line 86) | def __call__(self, data):
    method __repr__ (line 118) | def __repr__(self):
  function load_protein_npy (line 122) | def load_protein_npy(pdb_id, data_dir, center=False, single_pdb=False):
  class PairData (line 173) | class PairData(Data):
    method __init__ (line 174) | def __init__(
    method __inc__ (line 220) | def __inc__(self, key, value):
    method __cat_dim__ (line 228) | def __cat_dim__(self, key, value):
  function load_protein_pair (line 235) | def load_protein_pair(pdb_id, data_dir,single_pdb=False):
  class ProteinPairsSurfaces (line 271) | class ProteinPairsSurfaces(InMemoryDataset):
    method __init__ (line 274) | def __init__(self, root, ppi=False, train=True, transform=None, pre_tr...
    method raw_file_names (line 281) | def raw_file_names(self):
    method processed_file_names (line 285) | def processed_file_names(self):
    method download (line 302) | def download(self):
    method process (line 316) | def process(self):

FILE: data_analysis/analyse_descriptors_para.py
  function analyse_pdb (line 29) | def analyse_pdb(pdb_id,D):

FILE: data_iteration.py
  function process_single (line 16) | def process_single(protein_pair, chain_idx=1):
  function save_protein_batch_single (line 76) | def save_protein_batch_single(protein_pair_id, P, save_path, pdb_idx):
  function project_iface_labels (line 101) | def project_iface_labels(P, threshold=2.0):
  function process (line 123) | def process(args, protein_pair, net):
  function generate_matchinglabels (line 140) | def generate_matchinglabels(args, P1, P2):
  function compute_loss (line 157) | def compute_loss(args, P1, P2, n_points_sample=16):
  function extract_single (line 218) | def extract_single(P_batch, number):
  function iterate (line 244) | def iterate(
  function iterate_surface_precompute (line 423) | def iterate_surface_precompute(dataset, net, args):

FILE: data_preprocessing/convert_pdb2npy.py
  function load_structure_np (line 9) | def load_structure_np(fname, center):
  function convert_pdbs (line 34) | def convert_pdbs(pdb_dir, npy_dir):

FILE: data_preprocessing/convert_ply2npy.py
  function load_surface_np (line 7) | def load_surface_np(fname, center):
  function convert_plys (line 42) | def convert_plys(ply_dir, npy_dir):

FILE: data_preprocessing/download_pdb.py
  class NotDisordered (line 28) | class NotDisordered(Select):
    method accept_atom (line 29) | def accept_atom(self, atom):
  function find_modified_amino_acids (line 33) | def find_modified_amino_acids(path):
  function extractPDB (line 48) | def extractPDB(
  function protonate (line 86) | def protonate(in_pdb_file, out_pdb_file):
  function get_single (line 108) | def get_single(pdb_id: str,chains: list):

FILE: geometry_processing.py
  function save_vtk (line 21) | def save_vtk(
  function subsample (line 87) | def subsample(x, batch=None, scale=1.0):
  function soft_distances (line 136) | def soft_distances(x, y, batch_x, batch_y, smoothness=0.01, atomtypes=No...
  function atoms_to_points_normals (line 201) | def atoms_to_points_normals(
  function mesh_normals_areas (line 328) | def mesh_normals_areas(vertices, triangles=None, scale=[1.0], batch=None...
  function tangent_vectors (line 418) | def tangent_vectors(normals):
  function curvatures (line 444) | def curvatures(
  class ContiguousBackward (line 557) | class ContiguousBackward(torch.autograd.Function):
    method forward (line 563) | def forward(ctx, input):
    method backward (line 567) | def backward(ctx, grad_output):
  class dMaSIFConv (line 570) | class dMaSIFConv(nn.Module):
    method __init__ (line 571) | def __init__(
    method forward (line 700) | def forward(self, points, nuv, features, ranges=None):

FILE: helper.py
  function ranges_slices (line 15) | def ranges_slices(batch):
  function diagonal_ranges (line 28) | def diagonal_ranges(batch_x=None, batch_y=None):
  function soft_dimension (line 42) | def soft_dimension(features):

FILE: model.py
  function knn_atoms (line 19) | def knn_atoms(x, y, x_batch, y_batch, k):
  function get_atom_features (line 37) | def get_atom_features(x, y, x_batch, y_batch, y_atomtype, k=16):
  class Atom_embedding (line 53) | class Atom_embedding(nn.Module):
    method __init__ (line 54) | def __init__(self, args):
    method forward (line 65) | def forward(self, x, y, y_atomtypes, x_batch, y_batch):
  class AtomNet (line 84) | class AtomNet(nn.Module):
    method __init__ (line 85) | def __init__(self, args):
    method forward (line 99) | def forward(self, xyz, atom_xyz, atomtypes, batch, atom_batch):
  class Atom_embedding_MP (line 104) | class Atom_embedding_MP(nn.Module):
    method __init__ (line 105) | def __init__(self, args):
    method forward (line 125) | def forward(self, x, y, y_atomtypes, x_batch, y_batch):
  class Atom_Atom_embedding_MP (line 145) | class Atom_Atom_embedding_MP(nn.Module):
    method __init__ (line 146) | def __init__(self, args):
    method forward (line 168) | def forward(self, x, y, y_atomtypes, x_batch, y_batch):
  class AtomNet_MP (line 191) | class AtomNet_MP(nn.Module):
    method __init__ (line 192) | def __init__(self, args):
    method forward (line 205) | def forward(self, xyz, atom_xyz, atomtypes, batch, atom_batch):
  function combine_pair (line 215) | def combine_pair(P1, P2):
  function split_pair (line 235) | def split_pair(P1P2):
  function project_iface_labels (line 270) | def project_iface_labels(P, threshold=2.0):
  class dMaSIF (line 289) | class dMaSIF(nn.Module):
    method __init__ (line 290) | def __init__(self, args):
    method features (line 358) | def features(self, P, i=1):
    method embed (line 394) | def embed(self, P):
    method preprocess_surface (line 446) | def preprocess_surface(self, P):
    method forward (line 458) | def forward(self, P1, P2=None):
Copy disabled (too large) Download .json
Condensed preview — 34 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (11,386K chars).
[
  {
    "path": ".gitignore",
    "chars": 289,
    "preview": "01-benchmark_surfaces/\n01-benchmark_surfaces_npy/\n01-benchmark_pdbs_npy/\n01-benchmark_pdbs/\n01-benchmark_pdbs/\nshape_ind"
  },
  {
    "path": "Arguments.py",
    "chars": 4337,
    "preview": "import argparse\n\nparser = argparse.ArgumentParser(description=\"Network parameters\")\n\n# Main parameters\nparser.add_argume"
  },
  {
    "path": "LICENSE.md",
    "chars": 19123,
    "preview": "Attribution-NonCommercial-NoDerivatives 4.0 International\n\n============================================================="
  },
  {
    "path": "README.md",
    "chars": 4014,
    "preview": "## dMaSIF - Fast end-to-end learning on protein surfaces\n![Method overview](overview.PNG)\n\n## Abstract\n\nProteins’ biolog"
  },
  {
    "path": "benchmark_layers.py",
    "chars": 7716,
    "preview": "import torch\nfrom typing import Optional\nfrom pykeops.torch import LazyTensor\nfrom torch_geometric.nn import EdgeConv, R"
  },
  {
    "path": "benchmark_models.py",
    "chars": 12233,
    "preview": "import torch\nimport torch.nn.functional as F\nimport torch.nn as nn\nfrom torch.nn import (\n    Sequential as Seq,\n    Dro"
  },
  {
    "path": "benchmark_scripts/DGCNN_site.sh",
    "chars": 867,
    "preview": "# Load environment\npython -W ignore -u main_training.py --experiment_name DGCNN_site_1layer_k200 --batch_size 64 --embed"
  },
  {
    "path": "benchmark_scripts/Pointnet_site.sh",
    "chars": 1361,
    "preview": "# Load environment\npython -W ignore -u main_training.py --experiment_name PointNet_site_3layer_15A --batch_size 64 --emb"
  },
  {
    "path": "benchmark_scripts/dMaSIF_search.sh",
    "chars": 421,
    "preview": "# Load environment\npython -W ignore -u main_training.py --experiment_name dMaSIF_search_1layer_12A --batch_size 64 --emb"
  },
  {
    "path": "benchmark_scripts/dMaSIF_site.sh",
    "chars": 1230,
    "preview": "# Load environment\npython -W ignore -u main_training.py --experiment_name dMaSIF_site_1layer_15A --batch_size 64 --embed"
  },
  {
    "path": "data.py",
    "chars": 13710,
    "preview": "import torch\nfrom torch_geometric.data import InMemoryDataset, Data, DataLoader\nfrom torch_geometric.transforms import C"
  },
  {
    "path": "data_analysis/analyse_atomnet.ipynb",
    "chars": 3639398,
    "preview": "{\n \"metadata\": {\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_ext"
  },
  {
    "path": "data_analysis/analyse_descriptors.py",
    "chars": 2820,
    "preview": "import numpy as np\nfrom pathlib import Path\nfrom sklearn.metrics import roc_auc_score, roc_curve\nfrom scipy.spatial.dist"
  },
  {
    "path": "data_analysis/analyse_descriptors_para.py",
    "chars": 3303,
    "preview": "import numpy as np\nfrom pathlib import Path\nfrom sklearn.metrics import roc_auc_score, roc_curve\nfrom scipy.spatial.dist"
  },
  {
    "path": "data_analysis/analyse_output.ipynb",
    "chars": 5880572,
    "preview": "{\n \"metadata\": {\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_ext"
  },
  {
    "path": "data_analysis/analyse_site_outputs.py",
    "chars": 3631,
    "preview": "import numpy as np\nimport pandas as pd\nfrom pathlib import Path\nfrom tqdm import tqdm\nfrom scipy.spatial.distance import"
  },
  {
    "path": "data_analysis/analyse_site_outputs_graph.ipynb",
    "chars": 85500,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n "
  },
  {
    "path": "data_analysis/plot_search.ipynb",
    "chars": 163055,
    "preview": "{\n \"metadata\": {\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_ext"
  },
  {
    "path": "data_analysis/profiling_surface.ipynb",
    "chars": 336892,
    "preview": "{\n \"metadata\": {\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_ext"
  },
  {
    "path": "data_iteration.py",
    "chars": 16950,
    "preview": "import torch\nimport numpy as np\nfrom helper import *\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch."
  },
  {
    "path": "data_preprocessing/convert_pdb2npy.py",
    "chars": 1180,
    "preview": "import numpy as np\nfrom pathlib import Path\nfrom tqdm import tqdm\nfrom Bio.PDB import *\n\nele2num = {\"C\": 0, \"H\": 1, \"O\":"
  },
  {
    "path": "data_preprocessing/convert_ply2npy.py",
    "chars": 1691,
    "preview": "import numpy as np\nfrom pathlib import Path\nfrom tqdm import tqdm\nfrom plyfile import PlyData, PlyElement\n\n\ndef load_sur"
  },
  {
    "path": "data_preprocessing/download_pdb.py",
    "chars": 5075,
    "preview": "import Bio\nfrom Bio.PDB import * \nfrom Bio.SeqUtils import IUPACData\nimport sys\nimport importlib\nimport os\nimport numpy "
  },
  {
    "path": "geometry_processing.py",
    "chars": 33557,
    "preview": "import numpy as np\nfrom math import pi\nimport torch\nfrom pykeops.torch import LazyTensor\nfrom plyfile import PlyData, Pl"
  },
  {
    "path": "helper.py",
    "chars": 2131,
    "preview": "import colorsys\n\nimport numpy as np\nimport torch\nfrom pykeops.torch import LazyTensor\nfrom plyfile import PlyData, PlyEl"
  },
  {
    "path": "lists/testing.txt",
    "chars": 2519,
    "preview": "1A99_D\n1AUI_A\n1BO6_A\n1BOU_B\n1BPL_B\n1C7N_D\n1CS0_B\n1DM5_F\n1DOS_B\n1EFV_A\n1EHI_A\n1EV7_A\n1EWY_A\n1EZ1_B\n1F06_A\n1F6M_A\n1FFV_C\n1"
  },
  {
    "path": "lists/testing_ppi.txt",
    "chars": 8647,
    "preview": "1A2K_C_AB\n1A2W_A_B\n1A79_C_B\n1A99_C_D\n1ACB_E_I\n1AGQ_C_D\n1AHS_C_B\n1AK4_A_D\n1AN1_E_I\n1ARZ_A_C\n1ATN_A_D\n1AVX_A_B\n1AY7_A_B\n1B"
  },
  {
    "path": "lists/training.txt",
    "chars": 21055,
    "preview": "1A0G_B\n1A0H_D\n1A22_A\n1A2K_AB\n1A6J_B\n1A79_C\n1AA7_A\n1ACB_I\n1AIH_D\n1ARZ_C\n1AVA_C\n1AVO_K\n1AVO_L\n1AY7_A\n1AZS_AB\n1B0N_A\n1B27_A"
  },
  {
    "path": "lists/training_ppi.txt",
    "chars": 45070,
    "preview": "1A0G_A_B\n1A0H_E_D\n1A14_HL_N\n1A1U_A_C\n1A22_A_B\n1A2A_C_D\n1A2X_A_B\n1A2Y_BA_C\n1A3R_H_P\n1A6D_A_B\n1A6J_A_B\n1A73_A_B\n1AA7_A_B\n1"
  },
  {
    "path": "main_inference.py",
    "chars": 2922,
    "preview": "# Standard imports:\nimport numpy as np\nimport torch\nfrom torch.utils.tensorboard import SummaryWriter\nfrom torch.utils.d"
  },
  {
    "path": "main_training.py",
    "chars": 5366,
    "preview": "# Standard imports:\nimport numpy as np\nimport torch\nfrom torch.utils.tensorboard import SummaryWriter\nfrom torch.utils.d"
  },
  {
    "path": "model.py",
    "chars": 16540,
    "preview": "import math\nimport time\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.autograd.profile"
  },
  {
    "path": "requirements.txt",
    "chars": 2181,
    "preview": "absl-py==0.11.0\nappdirs==1.4.4\nargon2-cffi==20.1.0\nase==3.20.1\nasync-generator==1.10\nattrs==20.3.0\nbackcall==0.2.0\nbiopy"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the FreyrS/dMaSIF GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 34 files (9.9 MB), approximately 2.6M tokens, and a symbol index with 118 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!