Skip to content

Commit 0ab2b05

Browse files
committed
Review error messages and tests. Refine demo models.
1 parent 826fd29 commit 0ab2b05

10 files changed

Lines changed: 406 additions & 161 deletions

demo/dbscan-clustering-demo-v5.nlogo

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ HORIZONTAL
219219
@#$#@#$#@
220220
## WHAT IS IT?
221221

222-
This model demonstrates the use of the DBSCAN extension (https://github.com/chrfrantz/NetLogo-Extension-DBSCAN/). It highlights clustering of individuals/turtles by both variables as well as location.
222+
This model demonstrates the use of the DBSCAN extension (https://github.com/chrfrantz/NetLogo-Extension-DBSCAN/). It highlights clustering of individuals/turtles by both variables as well as location. (Clustering of patches is supported for NetLogo 6 onwards.)
223223

224224
## HOW IT WORKS
225225

@@ -237,7 +237,7 @@ Click either button and observe how the clustering works both for variable-based
237237

238238
## THINGS TO TRY
239239

240-
Try varying the maximum distance (slider 'max-distance-agents') to see how agents are clustered by variable for different wealth ranges (button 'cluster-agents-by-variable'). The same slider is also used for the maximum permissible distance between agents if performing location-based clustering (button 'cluster-agents-by-location'). You can further vary the number of members necessary to form a cluster and see how this changes the emerging clusters.
240+
Try varying the maximum distance (slider 'maximum-distance-agents') to see how agents are clustered by variable for different wealth ranges (button 'cluster-agents-by-variable'). The same slider is also used for the maximum permissible distance between agents if performing location-based clustering (button 'cluster-agents-by-location'). You can further vary the number of members necessary to form a cluster (slider 'minimum-number-of-members') and see how this changes the emerging clusters.
241241

242242
## NETLOGO FEATURES
243243

demo/dbscan-clustering-demo-v6.nlogo

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
;
55
; Author: Christopher Frantz ([email protected])
66
;
7-
; Last update: 29/05/2019
7+
; Last update: 30/05/2019
88
;
9-
; For documentation and details about supported NetLogo versions refer to
9+
; For documentation and details about the extension and supported NetLogo versions refer to
1010
; https://github.com/chrfrantz/NetLogo-Extension-DBSCAN#readme
1111
;
1212

@@ -304,7 +304,7 @@ Click either button and observe how the clustering works both for variable-based
304304

305305
## THINGS TO TRY
306306

307-
Try varying the maximum distance (slider 'max-distance-agents') to see how agents are clustered by variable for different wealth ranges (button 'cluster-agents-by-variable'). The same slider is also used for the maximum permissible distance between agents if performing location-based clustering (button 'cluster-agents-by-location'). In addition, try out the clustering of patches by different resource levels (slider 'max-distance-patches') using the button 'cluster-patches-by-variable'. You can further vary the number of members (i.e., agents or patches) necessary to form a cluster and see how this changes the emerging clusters.
307+
Try varying the maximum distance (slider 'maximum-distance-agents') to see how agents are clustered by variable for different wealth ranges (button 'cluster-agents-by-variable'). The same slider is also used for the maximum permissible distance between agents if performing location-based clustering (button 'cluster-agents-by-location'). In addition, try out the clustering of patches by different resource levels (slider 'maximum-distance-patches') using the button 'cluster-patches-by-variable'. You can further vary the number of members (i.e., agents or patches) necessary to form a cluster (slider 'minimum-number-of-members') and see how this changes the emerging clusters.
308308

309309
## NETLOGO FEATURES
310310

res/README.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
This archive contains the DBSCAN Extension for NetLogo, v0.3 (28.05.2019).
1+
This archive contains the DBSCAN Extension for NetLogo, v0.3 (30.05.2019).
22

33
Note: The new feature of this release (clustering patches - as opposed to just
44
turtles - by variable) are only supported for NetLogo versions 6 and higher.

src/main/java/org/nlogo/extensions/dbscan/DBSCANExtension.java

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
/**
2828
* NetLogo extension for clustering based on DBSCAN by agent/patch variables or coordinates.
2929
*
30+
* Website: https://github.com/chrfrantz/NetLogo-Extension-DBSCAN
31+
*
3032
* @author <a href="mailto:[email protected]>Christopher Frantz</a>
31-
* @version 0.3 (28.05.2019)
33+
* @version 0.3 (30.05.2019)
3234
*
3335
*/
3436
public class DBSCANExtension extends DefaultClassManager {
@@ -60,8 +62,8 @@ public Object report(final Argument[] args, final Context ctx)
6062

6163
AgentSet inputValues = null;
6264
String field = null;
63-
int minNumberOfElements = -1;
64-
double maxDistance = -1;
65+
int minNumberOfElements = -9999;
66+
double maxDistance = -9999;
6567

6668
try {
6769
inputValues = args[0].getAgentSet();
@@ -71,26 +73,34 @@ public Object report(final Argument[] args, final Context ctx)
7173
} catch (Exception e) {
7274
throw new ExtensionException(e.getMessage());
7375
}
74-
76+
7577
if (inputValues == null || inputValues.isEmpty()) {
7678
throw new ExtensionException(DBSCANExtensionErrors.ERROR_MISSING_INPUT_DATA);
7779
}
7880

7981
if (field == null || field.isEmpty()) {
8082
throw new ExtensionException(DBSCANExtensionErrors.ERROR_MISSING_CLUSTER_VARIABLE);
8183
}
82-
83-
if (minNumberOfElements == -1) {
84+
85+
if (minNumberOfElements == -9999) {
8486
throw new ExtensionException(DBSCANExtensionErrors.ERROR_MISSING_MINIMUM_NUMBER_OF_ELEMENTS);
8587
}
8688

87-
if (maxDistance == -1) {
89+
if (minNumberOfElements <= 1) {
90+
throw new ExtensionException(DBSCANExtensionErrors.ERROR_INVALID_MINIMUM_NUMBER_OF_ELEMENTS);
91+
}
92+
93+
if (maxDistance == -9999) {
8894
throw new ExtensionException(DBSCANExtensionErrors.ERROR_MISSING_MAXIMUM_DISTANCE_OF_ELEMENTS);
8995
}
9096

97+
if (maxDistance < 0) {
98+
throw new ExtensionException(DBSCANExtensionErrors.ERROR_NEGATIVE_MAXIMUM_DISTANCE_OF_ELEMENTS);
99+
}
100+
91101
// Convert input AgentSet to Collection
92102
Iterator<?> it = inputValues.agents().iterator();
93-
103+
94104
// Check for patches
95105
boolean patches = false;
96106
int fieldIndex = -1;
@@ -111,7 +121,7 @@ public Object report(final Argument[] args, final Context ctx)
111121
}
112122
}
113123
}
114-
124+
115125
// Add all agents/patches (including first element) to collection
116126
Collection<Agent> inputCollection = new ArrayList<>();
117127
inputCollection.add((Agent)first);
@@ -130,14 +140,15 @@ public Object report(final Argument[] args, final Context ctx)
130140
new DistanceMetricNetLogoPatchVariable(fieldIndex) :
131141
// ... treat all others as non-patch agents.
132142
new DistanceMetricNetLogoAgentVariable(field.toUpperCase())));
143+
// will at least return empty list (not be null)
133144
tmpList = clusterer.performClustering();
134145
} catch (DBSCANClusteringException e) {
135146
throw new ExtensionException(e);
136147
}
137148

138149
// Convert generated lists of clusters to nested LogoList
139150
LogoListBuilder list = new LogoListBuilder();
140-
151+
141152
for (ArrayList<Agent> intList: tmpList) {
142153
LogoListBuilder internalBuilder = new LogoListBuilder();
143154
for (Agent agent: intList) {
@@ -170,8 +181,8 @@ public Object report(final Argument[] args, final Context ctx)
170181
throws ExtensionException, LogoException {
171182

172183
AgentSet inputValues = null;
173-
int minNumberOfElements = -1;
174-
double maxDistance = -1;
184+
int minNumberOfElements = -9999;
185+
double maxDistance = -9999;
175186

176187
try {
177188
inputValues = args[0].getAgentSet();
@@ -180,29 +191,37 @@ public Object report(final Argument[] args, final Context ctx)
180191
} catch (Exception e) {
181192
throw new ExtensionException(e.getMessage());
182193
}
183-
194+
184195
if (inputValues == null || inputValues.isEmpty()) {
185196
throw new ExtensionException(DBSCANExtensionErrors.ERROR_MISSING_INPUT_DATA);
186197
}
187198

188-
if (minNumberOfElements == -1) {
199+
if (minNumberOfElements == -9999) {
189200
throw new ExtensionException(DBSCANExtensionErrors.ERROR_MISSING_MINIMUM_NUMBER_OF_ELEMENTS);
190201
}
191202

192-
if (maxDistance == -1) {
203+
if (minNumberOfElements <= 1) {
204+
throw new ExtensionException(DBSCANExtensionErrors.ERROR_INVALID_MINIMUM_NUMBER_OF_ELEMENTS);
205+
}
206+
207+
if (maxDistance == -9999) {
193208
throw new ExtensionException(DBSCANExtensionErrors.ERROR_MISSING_MAXIMUM_DISTANCE_OF_ELEMENTS);
194209
}
195210

211+
if (maxDistance < 0) {
212+
throw new ExtensionException(DBSCANExtensionErrors.ERROR_NEGATIVE_MAXIMUM_DISTANCE_OF_ELEMENTS);
213+
}
214+
196215
// Convert input AgentSet to Collection
197216
Iterator<?> it = inputValues.agents().iterator();
198-
217+
199218
// Check for patches
200219
boolean patches = false;
201220
Object first = it.hasNext() ? it.next() : null;
202221
if (first.getClass().equals(Patch.class)) {
203222
patches = true;
204223
}
205-
224+
206225
// Add all agents/patches (including first element) to collection
207226
Collection<org.nlogo.api.Agent> inputCollection = new ArrayList<>();
208227
inputCollection.add((org.nlogo.api.Agent)first);
@@ -220,7 +239,8 @@ public Object report(final Argument[] args, final Context ctx)
220239
// For patches, use patch-specific coordinate fields
221240
new DistanceMetricNetLogoPatchLocation() :
222241
// ... treat all others as non-patch agents.
223-
new DistanceMetricNetLogoAgentLocation()));
242+
new DistanceMetricNetLogoAgentLocation()));
243+
// will at least return empty list (not be null)
224244
tmpList = clusterer.performClustering();
225245
} catch (DBSCANClusteringException e) {
226246
throw new ExtensionException(e);

src/main/java/org/nlogo/extensions/dbscan/DBSCANExtensionErrors.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@
33
/**
44
* Error messages for DBSCAN extension.
55
*
6+
* Website: https://github.com/chrfrantz/NetLogo-Extension-DBSCAN
7+
*
68
* @author <a href="mailto:[email protected]>Christopher Frantz</a>
7-
* @version 0.3 (28.05.2019)
9+
* @version 0.3 (30.05.2019)
810
*
911
*/
1012
public final class DBSCANExtensionErrors {
1113

1214
public static final String ERROR_MISSING_INPUT_DATA = "Clustering input data (e.g., turtles, patches) has not been provided (or is empty).";
1315
public static final String ERROR_MISSING_CLUSTER_VARIABLE = "Cluster variable has not been specified.";
16+
public static final String ERROR_INVALID_MINIMUM_NUMBER_OF_ELEMENTS = "Minimum number of cluster elements cannot be smaller than 2.";
1417
public static final String ERROR_MISSING_MINIMUM_NUMBER_OF_ELEMENTS = "Minimum number of cluster elements has not been specified.";
18+
public static final String ERROR_NEGATIVE_MAXIMUM_DISTANCE_OF_ELEMENTS = "Maximum distance of cluster variable values cannot be negative.";
1519
public static final String ERROR_MISSING_MAXIMUM_DISTANCE_OF_ELEMENTS = "Maximum distance of cluster variable values has not been specified.";
1620
public static final String ERROR_CLUSTER_PATCHES_NOT_SUPPORTED_IN_NETLOGO_5 = "Clustering of patches by variables is not supported for NetLogo 5 version of the DBSCAN extension. " +
1721
"Upgrade to NetLogo 6 or higher to use this feature.";

src/main/java/org/nlogo/extensions/dbscan/metrics/DistanceMetricNetLogoAgentLocation.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
/**
99
* Distance metric implementation for agent locations.
10+
*
11+
* Website: https://github.com/chrfrantz/NetLogo-Extension-DBSCAN
1012
*
1113
* @author <a href="mailto:[email protected]>Christopher Frantz</a>
12-
* @version 0.3 (28.05.2019)
14+
* @version 0.3 (30.05.2019)
1315
*
1416
*/
1517
public class DistanceMetricNetLogoAgentLocation implements DistanceMetric<Agent>{

src/main/java/org/nlogo/extensions/dbscan/metrics/DistanceMetricNetLogoAgentVariable.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
/**
99
* Distance metric implementation for agent variables.
10+
*
11+
* Website: https://github.com/chrfrantz/NetLogo-Extension-DBSCAN
1012
*
1113
* @author <a href="mailto:[email protected]>Christopher Frantz</a>
12-
* @version 0.3 (28.05.2019)
14+
* @version 0.3 (30.05.2019)
1315
*
1416
*/
1517
public class DistanceMetricNetLogoAgentVariable implements DistanceMetric<Agent>{

src/main/java/org/nlogo/extensions/dbscan/metrics/DistanceMetricNetLogoPatchLocation.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@
77

88
/**
99
* Distance metric implementation for patch locations.
10+
*
11+
* While clustering patches by location does not really make sense,
12+
* perhaps future NetLogo features (e.g., sparse patch matrices) may warrant
13+
* the use.
14+
*
15+
* Website: https://github.com/chrfrantz/NetLogo-Extension-DBSCAN
1016
*
1117
* @author <a href="mailto:[email protected]>Christopher Frantz</a>
12-
* @version 0.3 (28.05.2019)
18+
* @version 0.3 (30.05.2019)
1319
*
1420
*/
1521
public class DistanceMetricNetLogoPatchLocation implements DistanceMetric<Agent>{

src/main/java/org/nlogo/extensions/dbscan/metrics/DistanceMetricNetLogoPatchVariable.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
/**
99
* Distance metric implementation for patch variables.
10+
*
11+
* Website: https://github.com/chrfrantz/NetLogo-Extension-DBSCAN
1012
*
1113
* @author <a href="mailto:[email protected]>Christopher Frantz</a>
12-
* @version 0.3 (28.05.2019)
14+
* @version 0.3 (30.05.2019)
1315
*
1416
*/
1517
public class DistanceMetricNetLogoPatchVariable implements DistanceMetric<Agent>{

0 commit comments

Comments
 (0)