LZGraphs 2.1.0__tar.gz → 2.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. lzgraphs-2.1.2/PKG-INFO +390 -0
  2. lzgraphs-2.1.2/README.md +341 -0
  3. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/pyproject.toml +1 -6
  4. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/__init__.py +28 -20
  5. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/exceptions/__init__.py +1 -1
  6. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/graphs/amino_acid_positional.py +154 -101
  7. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/graphs/edge_data.py +22 -8
  8. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/graphs/graph_operations.py +39 -39
  9. lzgraphs-2.1.2/src/LZGraphs/graphs/lz_graph_base.py +2201 -0
  10. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/graphs/naive.py +58 -52
  11. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/graphs/nucleotide_double_positional.py +116 -83
  12. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/metrics/__init__.py +22 -14
  13. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/metrics/diversity.py +28 -28
  14. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/metrics/entropy.py +21 -21
  15. lzgraphs-2.1.2/src/LZGraphs/metrics/pgen_distribution.py +351 -0
  16. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/metrics/saturation.py +2 -2
  17. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/mixins/gene_logic.py +26 -25
  18. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/mixins/random_walk.py +21 -24
  19. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/utilities/misc.py +18 -7
  20. lzgraphs-2.1.2/src/LZGraphs/visualization/__init__.py +18 -0
  21. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/visualization/visualize.py +11 -11
  22. lzgraphs-2.1.2/src/LZGraphs.egg-info/PKG-INFO +390 -0
  23. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs.egg-info/SOURCES.txt +6 -0
  24. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs.egg-info/requires.txt +0 -4
  25. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_aap_lzgraph.py +25 -34
  26. lzgraphs-2.1.2/tests/test_abundance.py +796 -0
  27. lzgraphs-2.1.2/tests/test_analytical_distribution.py +481 -0
  28. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_diversity_theory.py +20 -20
  29. lzgraphs-2.1.2/tests/test_flexible_input.py +213 -0
  30. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_graph_operations.py +5 -5
  31. lzgraphs-2.1.2/tests/test_lzpgen_distribution.py +262 -0
  32. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_metrics.py +32 -32
  33. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_naive_lzgraph.py +20 -22
  34. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_ndp_lzgraph.py +20 -28
  35. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_new_features.py +6 -6
  36. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_pgen_fixes.py +22 -22
  37. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_serialization.py +10 -8
  38. lzgraphs-2.1.2/tests/test_simulate.py +225 -0
  39. lzgraphs-2.1.0/PKG-INFO +0 -230
  40. lzgraphs-2.1.0/README.md +0 -177
  41. lzgraphs-2.1.0/src/LZGraphs/graphs/lz_graph_base.py +0 -1368
  42. lzgraphs-2.1.0/src/LZGraphs/visualization/__init__.py +0 -18
  43. lzgraphs-2.1.0/src/LZGraphs.egg-info/PKG-INFO +0 -230
  44. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/CHANGELOG.md +0 -0
  45. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/CONTRIBUTING.md +0 -0
  46. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/LICENSE +0 -0
  47. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/MANIFEST.in +0 -0
  48. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/requirements.txt +0 -0
  49. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/setup.cfg +0 -0
  50. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/bag_of_words/__init__.py +0 -0
  51. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/bag_of_words/bow_encoder.py +0 -0
  52. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/graphs/__init__.py +0 -0
  53. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/metrics/convenience.py +0 -0
  54. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/mixins/__init__.py +0 -0
  55. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/mixins/gene_prediction.py +0 -0
  56. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/py.typed +0 -0
  57. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/utilities/__init__.py +0 -0
  58. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/utilities/decomposition.py +0 -0
  59. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs/utilities/helpers.py +0 -0
  60. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs.egg-info/dependency_links.txt +0 -0
  61. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/src/LZGraphs.egg-info/top_level.txt +0 -0
  62. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_base_class_methods.py +0 -0
  63. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_bow_encoder.py +0 -0
  64. {lzgraphs-2.1.0 → lzgraphs-2.1.2}/tests/test_utilities.py +0 -0
@@ -0,0 +1,390 @@
1
+ Metadata-Version: 2.4
2
+ Name: LZGraphs
3
+ Version: 2.1.2
4
+ Summary: An Implementation of LZ76 Based Graphs for Repertoire Representation and Analysis
5
+ Author-email: Thomas Konstantinovsky <thomaskon90@gmail.com>
6
+ Maintainer-email: Thomas Konstantinovsky <thomaskon90@gmail.com>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/MuteJester/LZGraphs
9
+ Project-URL: Documentation, https://mutejester.github.io/LZGraphs/
10
+ Project-URL: Repository, https://github.com/MuteJester/LZGraphs
11
+ Project-URL: Issues, https://github.com/MuteJester/LZGraphs/issues
12
+ Project-URL: Changelog, https://github.com/MuteJester/LZGraphs/blob/master/CHANGELOG.md
13
+ Keywords: Graph Theory,Immunology,Analytics,Biology,T-cell,Repertoire,CDR3,Bioinformatics,LZ76,Lempel-Ziv
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
18
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
19
+ Classifier: License :: OSI Approved :: MIT License
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Operating System :: OS Independent
26
+ Classifier: Typing :: Typed
27
+ Requires-Python: >=3.9
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: networkx>=3.0
31
+ Requires-Dist: numpy>=1.24
32
+ Requires-Dist: pandas>=1.5
33
+ Requires-Dist: tqdm>=4.65
34
+ Requires-Dist: scipy>=1.10
35
+ Provides-Extra: viz
36
+ Requires-Dist: matplotlib>=3.7; extra == "viz"
37
+ Requires-Dist: seaborn>=0.12; extra == "viz"
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest>=7.0; extra == "dev"
40
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
41
+ Requires-Dist: black>=23.0; extra == "dev"
42
+ Requires-Dist: isort>=5.12; extra == "dev"
43
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
44
+ Requires-Dist: pre-commit>=3.0; extra == "dev"
45
+ Requires-Dist: build>=1.0; extra == "dev"
46
+ Requires-Dist: twine>=4.0; extra == "dev"
47
+ Provides-Extra: docs
48
+ Dynamic: license-file
49
+
50
+ <p align="center">
51
+
52
+ [![PyPI version](https://img.shields.io/pypi/v/LZGraphs.svg)](https://pypi.org/project/LZGraphs/)
53
+ [![Python versions](https://img.shields.io/pypi/pyversions/LZGraphs.svg)](https://pypi.org/project/LZGraphs/)
54
+ [![CI/CD](https://github.com/MuteJester/LZGraphs/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/MuteJester/LZGraphs/actions/workflows/ci-cd.yml)
55
+ [![License](https://img.shields.io/github/license/MuteJester/LZGraphs.svg)](https://github.com/MuteJester/LZGraphs/blob/master/LICENSE)
56
+ [![Downloads](https://img.shields.io/pypi/dm/LZGraphs.svg)](https://pypi.org/project/LZGraphs/)
57
+
58
+ [![Stargazers][stars-shield]][stars-url]
59
+ [![Issues][issues-shield]][issues-url]
60
+ [![LinkedIn][linkedin-shield]][linkedin-url]
61
+
62
+ </p>
63
+
64
+
65
+ <!-- PROJECT LOGO -->
66
+ <br />
67
+ <p align="center">
68
+ <a href="https://github.com/MuteJester/LZGraphs">
69
+ <img src="https://github.com/MuteJester/LZGraphs/blob/master/misc/lzglogo2.png" alt="Logo" width="480" height="330">
70
+ </a>
71
+
72
+ <h2 align="center">LZGraphs</h2>
73
+
74
+ <p align="center">
75
+ LZ76 Graphs and Applications in Immunology
76
+ <br />
77
+ <a href="https://MuteJester.github.io/LZGraphs/"><strong>Explore the docs &raquo;</strong></a>
78
+ <br />
79
+ <br />
80
+ <a href="https://github.com/MuteJester/LZGraphs/issues">Report Bug</a>
81
+ &middot;
82
+ <a href="https://github.com/MuteJester/LZGraphs/issues">Request Feature</a>
83
+ </p>
84
+ </p>
85
+
86
+ ---
87
+
88
+ > **:dna: New to LZGraphs?** Head over to the **[full documentation and tutorials](https://MuteJester.github.io/LZGraphs/)** for comprehensive guides, API reference, and worked examples covering every feature of the library.
89
+
90
+ ---
91
+
92
+ ## Table of Contents
93
+
94
+ * [About the Project](#about-the-project)
95
+ * [Key Features](#key-features)
96
+ * [Installation](#installation)
97
+ * [Quick Start](#quick-start)
98
+ * [Graph Types](#graph-types)
99
+ * [Sequence Abundance Weighting](#sequence-abundance-weighting)
100
+ * [Core Capabilities](#core-capabilities)
101
+ * [Contributing](#contributing)
102
+ * [License](#license)
103
+ * [Contact](#contact)
104
+
105
+
106
+ <!-- ABOUT THE PROJECT -->
107
+ ## About The Project
108
+
109
+ LZGraphs :dna: is a Python library for immune receptor repertoire analysis based on the Lempel-Ziv 76 (LZ-76) compression algorithm. It builds directed graph models from TCR and BCR CDR3 sequences, capturing the sequential structure of repertoires without relying on alignment.
110
+
111
+ The methodology is presented in the research paper *"A Novel Approach to T-Cell Receptor Beta Chain (TCRB) Repertoire Encoding Using Lossless String Compression"*.
112
+
113
+ ### Background
114
+
115
+ The diversity of T-cells and B-cells is crucial for producing receptors that recognize the wide range of pathogens encountered throughout life. V(D)J recombination generates this diversity through a stochastic process, making repertoire analysis challenging. LZGraphs addresses this by decomposing sequences into LZ-76 subpatterns and encoding them as graph transitions, providing a compact, information-rich representation of an entire repertoire.
116
+
117
+
118
+ ## Key Features
119
+
120
+ - **Alignment-free analysis** -- no error-prone sequence alignment required
121
+ - **Generation probability inference** -- compute P(sequence) under the learned graph model
122
+ - **Sequence simulation** -- generate realistic synthetic sequences from the graph
123
+ - **Diversity estimation** -- LZ-based diversity indices (K-diversity family)
124
+ - **Information-theoretic metrics** -- entropy, perplexity, Jensen-Shannon divergence, mutual information, and more
125
+ - **Repertoire comparison** -- compare two repertoires via graph-level statistics
126
+ - **Analytical probability distributions** -- exact moments and scipy-like distribution objects for generation probabilities
127
+ - **Gene annotation support** -- optional V/J gene tracking on edges for gene usage analysis
128
+ - **Abundance weighting** -- weight sequences by clonal abundance for more realistic models
129
+ - **Serialization** -- save and load graphs in JSON format
130
+
131
+
132
+ ## Installation
133
+
134
+ Install from PyPI:
135
+
136
+ ```bash
137
+ pip install LZGraphs
138
+ ```
139
+
140
+ LZGraphs requires Python 3.9 or later. To verify the installation:
141
+
142
+ ```python
143
+ import LZGraphs
144
+ print(LZGraphs.__version__)
145
+ ```
146
+
147
+
148
+ ## Quick Start
149
+
150
+ Build an amino acid positional graph from CDR3 sequences and compute sequence probabilities:
151
+
152
+ ```python
153
+ import pandas as pd
154
+ from LZGraphs import AAPLZGraph
155
+
156
+ # Prepare data as a DataFrame with a 'cdr3_amino_acid' column
157
+ data = pd.DataFrame({
158
+ 'cdr3_amino_acid': [
159
+ 'CASSLAPGATNEKLFF',
160
+ 'CASSLGQAYEQYF',
161
+ 'CASSFSTCSANYGYTF',
162
+ 'CASSQEGTEAFF',
163
+ 'CASSLGQGNIQYF',
164
+ # ... your CDR3 amino acid sequences
165
+ ]
166
+ })
167
+
168
+ # Construct the graph
169
+ graph = AAPLZGraph(data, verbose=True)
170
+
171
+ # Compute the log-probability of a sequence under the model
172
+ log_prob = graph.walk_log_probability('CASSLAPGATNEKLFF')
173
+ print(f"Log P(seq): {log_prob:.4f}")
174
+
175
+ # Simulate 100 new sequences from the graph
176
+ generated = graph.simulate(100, seed=42)
177
+ print(f"Generated {len(generated)} sequences")
178
+
179
+ # Access graph properties
180
+ print(f"Nodes: {graph.num_subpatterns}, Edges: {graph.num_transitions}")
181
+ print(f"Length distribution: {graph.length_probabilities}")
182
+ ```
183
+
184
+
185
+ ## Graph Types
186
+
187
+ LZGraphs provides three graph variants, each suited to different sequence types and analysis goals:
188
+
189
+ ### AAPLZGraph -- Amino Acid Positional
190
+
191
+ Best for **CDR3 amino acid sequences**. Each LZ-76 subpattern is annotated with its position in the sequence, creating a directed acyclic graph (DAG). This enables exact analytical computations including `lzpgen_moments()` and `lzpgen_analytical_distribution()`.
192
+
193
+ ```python
194
+ from LZGraphs import AAPLZGraph
195
+
196
+ graph = AAPLZGraph(data, verbose=True) # data has 'cdr3_amino_acid' column
197
+ ```
198
+
199
+ ### NDPLZGraph -- Nucleotide Double Positional
200
+
201
+ Best for **CDR3 nucleotide sequences** where reading frame matters. Encodes both the subpattern and a double positional index derived from nucleotide positions. Also a DAG, supporting exact analytical methods.
202
+
203
+ ```python
204
+ from LZGraphs import NDPLZGraph
205
+
206
+ graph = NDPLZGraph(data, verbose=True) # data has 'cdr3_rearrangement' column
207
+ ```
208
+
209
+ ### NaiveLZGraph -- Basic Nucleotide
210
+
211
+ A simpler model for **nucleotide sequences** that uses raw LZ-76 subpatterns without positional annotation. The resulting graph may contain cycles. Use Monte Carlo methods (`lzpgen_distribution()`) rather than exact analytics for this graph type.
212
+
213
+ ```python
214
+ from LZGraphs import NaiveLZGraph
215
+ from LZGraphs import generate_kmer_dictionary
216
+
217
+ cdr3_list = ['TGTGCCAGCAGC...', 'TGTGCCAGCAGT...', ...]
218
+ dictionary = generate_kmer_dictionary(cdr3_list)
219
+ graph = NaiveLZGraph(cdr3_list, dictionary, verbose=True)
220
+ ```
221
+
222
+ ### Gene Annotation
223
+
224
+ All three graph types support optional V and J gene annotation. Include `V` and `J` columns in your DataFrame (or pass them separately for NaiveLZGraph) to track gene usage on graph edges:
225
+
226
+ ```python
227
+ data = pd.DataFrame({
228
+ 'cdr3_amino_acid': sequences,
229
+ 'V': v_genes,
230
+ 'J': j_genes,
231
+ })
232
+ graph = AAPLZGraph(data, verbose=True)
233
+
234
+ # Gene data is now available
235
+ print(graph.has_gene_data) # True
236
+ print(graph.marginal_v_genes) # V gene usage distribution
237
+ print(graph.marginal_j_genes) # J gene usage distribution
238
+ ```
239
+
240
+
241
+ ## Sequence Abundance Weighting
242
+
243
+ Immune repertoire datasets often include clonal abundance information -- the number of times each unique clonotype was observed. LZGraphs supports abundance-weighted graph construction, where each sequence contributes proportionally to its observed count rather than being treated as a single observation.
244
+
245
+ This is particularly important for:
246
+
247
+ - **More accurate probability estimates** -- highly expanded clones exert greater influence on transition probabilities, reflecting the true distribution of the repertoire
248
+ - **Better representation of clonal expansion** -- dominant clones shape the graph structure proportionally to their prevalence
249
+ - **More realistic sequence generation** -- simulated sequences reflect the abundance-weighted landscape, not just the unique sequence set
250
+
251
+ To use abundance weighting, include an `abundance` column in your DataFrame:
252
+
253
+ ```python
254
+ data = pd.DataFrame({
255
+ 'cdr3_amino_acid': ['CASSLAPGATNEKLFF', 'CASSLGQAYEQYF', 'CASSFSTCSANYGYTF'],
256
+ 'abundance': [150, 42, 7],
257
+ })
258
+
259
+ # Each sequence is weighted by its abundance during graph construction
260
+ graph = AAPLZGraph(data, verbose=True)
261
+ ```
262
+
263
+ For `NaiveLZGraph`, pass abundances as a separate parameter:
264
+
265
+ ```python
266
+ graph = NaiveLZGraph(
267
+ cdr3_list,
268
+ dictionary,
269
+ verbose=True,
270
+ abundances=[150, 42, 7, ...],
271
+ )
272
+ ```
273
+
274
+ When no abundance information is provided, every sequence is implicitly weighted as 1.
275
+
276
+
277
+ ## Core Capabilities
278
+
279
+ ### Probability Inference
280
+
281
+ Compute the probability of a sequence under the learned Markov model:
282
+
283
+ ```python
284
+ prob = graph.walk_probability('CASSLAPGATNEKLFF')
285
+ log_prob = graph.walk_log_probability('CASSLAPGATNEKLFF')
286
+ ```
287
+
288
+ ### Sequence Simulation
289
+
290
+ Generate new sequences by sampling random walks through the graph:
291
+
292
+ ```python
293
+ sequences = graph.simulate(1000, seed=42)
294
+ ```
295
+
296
+ ### Generation Probability Distributions
297
+
298
+ Characterize the distribution of generation probabilities across the repertoire:
299
+
300
+ ```python
301
+ # Monte Carlo empirical distribution (works on all graph types)
302
+ log_probs = graph.lzpgen_distribution(n=10000, seed=42)
303
+
304
+ # Exact analytical moments (DAG graphs only: AAPLZGraph, NDPLZGraph)
305
+ moments = graph.lzpgen_moments()
306
+ print(moments['mean'], moments['std'])
307
+
308
+ # Full scipy-like distribution object (DAG graphs only)
309
+ dist = graph.lzpgen_analytical_distribution()
310
+ print(dist.mean(), dist.std())
311
+ x = dist.ppf(0.05) # 5th percentile
312
+ ```
313
+
314
+ ### Diversity Metrics
315
+
316
+ ```python
317
+ from LZGraphs import lz_centrality, k_diversity
318
+
319
+ centrality = lz_centrality(graph, 'CASSLAPGATNEKLFF')
320
+ diversity = k_diversity(sequences, graph.encode_sequence, sample_size=1000)
321
+ ```
322
+
323
+ ### Information-Theoretic Analysis
324
+
325
+ ```python
326
+ from LZGraphs import (
327
+ node_entropy, edge_entropy, graph_entropy,
328
+ jensen_shannon_divergence, compare_repertoires,
329
+ )
330
+
331
+ print(f"Graph entropy: {graph_entropy(graph):.4f}")
332
+
333
+ # Compare two repertoires
334
+ jsd = jensen_shannon_divergence(graph1, graph2)
335
+ comparison = compare_repertoires(graph1, graph2)
336
+ ```
337
+
338
+ ### Visualization
339
+
340
+ ```python
341
+ from LZGraphs import plot_graph, plot_possible_paths
342
+
343
+ plot_graph(graph)
344
+ plot_possible_paths(graph, 'CASSLAPGATNEKLFF')
345
+ ```
346
+
347
+ ### Saturation Analysis
348
+
349
+ ```python
350
+ from LZGraphs import NodeEdgeSaturationProbe
351
+
352
+ probe = NodeEdgeSaturationProbe()
353
+ # Feed sequences incrementally and track node/edge saturation curves
354
+ ```
355
+
356
+ For detailed usage of every feature, see the **[documentation](https://MuteJester.github.io/LZGraphs/)**.
357
+
358
+
359
+ ## Contributing
360
+
361
+ Contributions are what make the open-source community such a powerful place to create new ideas, inspire, and make progress. Any contributions you make are **greatly appreciated**.
362
+
363
+ 1. Fork the Project
364
+ 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
365
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
366
+ 4. Push to the Branch (`git push origin feature/AmazingFeature`)
367
+ 5. Open a Pull Request
368
+
369
+
370
+ <!-- LICENSE -->
371
+ ## License
372
+
373
+ Distributed under the MIT license. See `LICENSE` for more information.
374
+
375
+
376
+ <!-- CONTACT -->
377
+ ## Contact
378
+
379
+ [Thomas Konstantinovsky]() - thomaskon90@gmail.com
380
+
381
+ Project Link: [https://github.com/MuteJester/LZGraphs](https://github.com/MuteJester/LZGraphs)
382
+
383
+
384
+ <!-- MARKDOWN LINKS & IMAGES -->
385
+ [stars-shield]: https://img.shields.io/github/stars/MuteJester/LZGraphs.svg?style=flat-square
386
+ [stars-url]: https://github.com/MuteJester/LZGraphs/stargazers
387
+ [issues-shield]: https://img.shields.io/github/issues/MuteJester/LZGraphs.svg?style=flat-square
388
+ [issues-url]: https://github.com/MuteJester/LZGraphs/issues
389
+ [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555
390
+ [linkedin-url]: https://www.linkedin.com/in/thomas-konstantinovsky-56230117b/