1
1
"""
2
- Creating Classification Diagrams
3
- ==================================
2
+ Creating Plot Templates/Classifier Models
3
+ ==========================================
4
4
5
- * Create JSON files
6
- * Add util.classification
7
- * Add plot.templates file
5
+ :mod:`pyrolite` provides a system for creating and using plot templates/classifier models
6
+ based on a series of polygons in variable space (e.g., the TAS diagram). A variety of
7
+ `diagram templates <../examples/plotting/templates.html>`__/ `classifiers <../examples/util/TAS.html>`__
8
+ are available, but you can also create your own.
8
9
10
+ In this tutorial, we'll go through the process of creating a diagram template from scratch,
11
+ as a demonstration of how you might create your own for your use - or to later contribute
12
+ to the collection in pyrolite.
9
13
"""
10
14
11
15
#######################################################################################
12
- # First let's pull in a simple dataset to use throughout these examples:
16
+ # The basis for most diagrams and classifiers is the class
17
+ # :class:`~pyrolite.util.classification.PolygonClassifier`; the docstring-based help
18
+ # text is a good place to start to understand what we'll need to put it together:
13
19
#
14
- from pyrolite .util .synthetic import normal_frame
20
+ from pyrolite .util .classification import PolygonClassifier
21
+
22
+ help (PolygonClassifier )
23
+ #######################################################################################
24
+ # The key things you'll need to construct a classifer are:
25
+ #
26
+ # 1. a name
27
+ # 2. a specification of what the axes correspond to,
28
+ # 3. and a dictionary of fields (dictionaries containing a 'name' and coordinates defining the polygon).
29
+ #
30
+ # We can also optionally specify the x and y limits, which are specific to plotting.
31
+ # Here we'll put together a simple classifier model with just two fields,
32
+ # and add this to a :mod:`matplotlib` axis. You can optionally specify names/labels for each field, \
33
+ # here we opt to just use some basic IDs (A and B), so these are what will be added to the plot:
34
+ #
35
+
36
+ clf = PolygonClassifier (
37
+ name = "DemoClassifier" ,
38
+ axes = {"x" : "SiO2" , "y" : "MgO" },
39
+ fields = {
40
+ "A" : {
41
+ "poly" : [[0 , 75 ], [0 , 100 ], [50 , 100 ], [50 , 75 ]],
42
+ },
43
+ "B" : {
44
+ "poly" : [[0 , 25 ], [0 , 75 ], [25 , 75 ], [25 , 25 ]],
45
+ },
46
+ },
47
+ xlim = (0 , 100 ),
48
+ ylim = (0 , 100 ),
49
+ )
50
+ ax = clf .add_to_axes (add_labels = True )
51
+ ax .figure
52
+ #######################################################################################
53
+ # While we're individually passing each of these arguments to
54
+ # :class:`~pyrolite.util.classification.PolygonClassifier`, we can also pass a dictionary
55
+ # of keyword arguments:
56
+ #
57
+ cfg = dict (
58
+ name = "DemoClassifier" ,
59
+ axes = {"x" : "SiO2" , "y" : "MgO" },
60
+ fields = {
61
+ "A" : {
62
+ "poly" : [[0 , 75 ], [0 , 100 ], [50 , 100 ], [50 , 75 ]],
63
+ },
64
+ "B" : {
65
+ "poly" : [[0 , 25 ], [0 , 75 ], [25 , 75 ], [25 , 25 ]],
66
+ },
67
+ },
68
+ xlim = (0 , 100 ),
69
+ ylim = (0 , 100 ),
70
+ )
71
+
72
+ clf = PolygonClassifier (** cfg )
73
+ #######################################################################################
74
+ # Each of the built-in models are saved as JSON files, and loaded in a manner as above;
75
+ # we can replicate that here - saving our configuration to JSON then loading it up again.
76
+ # We'll use a temporary directory here, but you can save it wherever you like (note the
77
+ # :mod:`pyrolite` templates live under `/data/models` in the repository); once you've
78
+ # got a template working how you'd like, consider
79
+ # `submitting it <../../dev/contributing.html>`__!
80
+ #
81
+ import json
82
+
83
+ from pyrolite .util .general import temp_path
84
+
85
+ tmp = temp_path ()
86
+ with open (tmp / "demo_classifier.json" , "w" ) as f :
87
+ f .write (json .dumps (cfg ))
88
+
89
+
90
+ with open (tmp / "demo_classifier.json" , "r" ) as f :
91
+ clf = PolygonClassifier (** json .load (f ))
92
+
93
+ clf .add_to_axes (add_labels = True ).figure
94
+ #######################################################################################
95
+ # Ternary Templates
96
+ # ~~~~~~~~~~~~~~~~~
97
+ #
98
+ # While it's slightly more work, you can also generate ternary templates using a very
99
+ # simliar pattern to the bivariate ones above. The principal differences are that you'll
100
+ # need to specify three axes (t, l, r), specify a 'ternary' transform, and have coordinates
101
+ # for polygons in the ternary space - each with three values. For example,
102
+ # here are two fields from the UDSA soil texture triangle:
103
+ #
104
+ cfg = {
105
+ "axes" : {"t" : "Clay" , "l" : "Sand" , "r" : "Silt" },
106
+ "transform" : "ternary" ,
107
+ "fields" : {
108
+ "sand" : {"name" : "Sand" , "poly" : [[0 , 100 , 0 ], [10 , 90 , 0 ], [0 , 85 , 15 ]]},
109
+ "loamy-sand" : {
110
+ "name" : "Loamy Sand" ,
111
+ "poly" : [[10 , 90 , 0 ], [0 , 85 , 15 ], [0 , 70 , 30 ], [15 , 85 , 0 ]],
112
+ },
113
+ },
114
+ }
115
+ PolygonClassifier (** cfg ).add_to_axes (add_labels = True ).figure
0 commit comments