Dynamic Subgroups
Subscription Tier Required
This feature requires the Premier subscription tier or higher.
Sometimes the number of samples being taken varies. This can happen for a number of reasons, such as:
- Machines which have varying numbers of cavities.
- Inconsistent product sampling.
- Varying sampling rate requirements for different vendors.
In this guide, you will create an Inspection where the number of checks taken will vary based on the Machine Traceability selected by the operator. Each group of measurements will be automatically tagged with the appropriate Cavity Traceability, based on how many checks are being performed.
Warning
This guide changes the number of samples by copying Tests. While it is possible to modify the subgroup size of SPC Tests via scripting, it is not recommended. Most SPC statistics rely on a consistent subgroup size for statistical validity. In general, if you find yourself needing a varying subgroup size, you should instead use a subgroup size of 1 and take multiple measurements.
Prerequisites
This guide assumes that you have:
- At least one Process.
- At least one Part with one Characteristic. The Characteristic should have a Subgroup Size of 1.
- Machine and Cavity Traceability.
- Any Defect .
This guide will use:
- The Final Inspection Process.
- A Part named AD-50 with the Width Characteristic.
- The Scratch Defect.
The Machine Traceability will make use of Preset Values, which will restrict the operators to a dropdown list. For the purpose of this guide, the preset values will be A, B, and C.
Information
Even though the Cavity Traceability will appear to be recorded as an integer, it is set up as a Text Traceability. This is because it is generally more useful to analyze Cavities as categories. A good litmus test for whether to use Text or Integer Traceability is whether you can change the numbers to letters. If changing your cavities from 1, 2, 3 to A, B, C does not change your analysis, then you should use Text.
Create the Inspection
To begin, create an Inspection:
- Navigate to the Inspection list.
- Press the Add button.

- Fill in the Name field with Dynamic Subgroups.
- Press the Save button.

For this guide, the Process will be set directly on the Inspection. If you only have one Process created in your GS account, it will automatically be set on the Inspection. If you have created more than one Process, it will need to be set. To do this, open the Inspection Settings and select the desired Process.
Finally, open the Inspection Settings and set Auto-load first Sub-Inspection to Yes.
Traceability Test
Add a Traceability Test and select the Machine Traceability. Update the Script ID of this Test to machine.
Group Test
Add a Group Test. This will allow duplicating an entire group of Tests at once, instead of having to clone each Test individually.
Uncheck the Visible property, and set the Script ID of the Group Test to group-1.
SPC Test
Drag an SPC Test into the Group Test. Position the SPC Test all the way on the left side of the Group Test, and set the Script ID to spc-test-1. Select the Width Characteristic for the AD-50 Part. If you chose a different Characteristic for this guide, select that instead.
Pass/Fail Test
Next, add a Pass/Fail Test to the Group. Reposition the SPC and Pass/Fail Test so they each take 50% of the width of the Group Test.
Select the Scratch Defect on the Pass/Fail Test, and set the Script ID to passfail-test-1.
Scripting
Now that the Inspection has been set up, you can begin scripting. Create a new Inspection Script and give it a memorable name. If this interface is unfamiliar, review the Inspection Scripting Principles and Code Editor articles.
The tasks we will use scripting to accomplish are:
- Listening for changes to the Machine Traceability.
- Adding or deleting Tests to take the appropriate number of checks for that Machine.
- Setting the Cavity as Traceability on each set of Tests.
Listen to Machine Traceability
In the newly created Inspection Script, get a reference to the Traceability API for the Traceability Test with the Script ID machine:
const subInspection = gsApi.inspection.subInspection('subi 1');
const machineTraceability = subInspection.traceability('machine');
Information
The first Sub-Inspection will have a Script ID of subi 1 by default. This may be changed in the Sub-Inspection Settings.
Next, bind to the onOptionSelected event:
This event will fire whenever a preset option is selected on this Traceability Test.
Update Number of Tests
In order to update the number of checks required, we will need to create a mapping from the Machine to the number of cavities available on that machine. Typically, this would come from a third party system or a file uploaded to GS. For the purpose of this guide, we will create this mapping directly in code:
const machineTraceability = subInspection.traceability('machine');
const machineToCavity = {
A: 2,
B: 4,
C: 6
};
When the Machine Traceability is updated, look up the number of cavities and add or remove Tests to get the correct number of checks. We will also keep track of the current number of checks being performed, so we know how many Tests to add or remove when the Machine Traceability is updated:
let currentChecks = undefined;
machineTraceability.onOptionSelected(async () => {
const properties = await machineTraceability.getProperties();
const totalCavities = machineToCavity[properties.value];
if (totalCavities === currentChecks) {
// Already have the correct number of checks, return
return;
}
});
Next, check if it's the first time a Machine has been selected by the operator. If so, then currentChecks becomes 1 (for the existing group which was made in the UI), and that Group Test is set to visible:
if (totalCavities === currentChecks) {
// Already have the correct number of checks, return
return;
}
if (currentChecks === undefined) {
// First run, make the first set of tests visible
await subInspection.group('group-1').updateProperties({
userDefinedVisible: true
});
currentChecks = 1;
}
It is time to start adding and removing groups. If the newly selected Machine has more cavities than the previously selected Machine (or if no Machine was previously selected), then Tests should be added. This is done by iterating upward from the current number of checks until we have reached the total number of checks which must be performed, and adding a new Group Test for each iteration. Each new Group Test will have the scriptId set based on the index, and it will use the copyFrom property to copy all of the properties and Tests within group-1.
if (totalCavities > currentChecks) {
// Need to add additional checks
for (let i = currentChecks + 1; i <= totalCavities; i++) {
await subInspection.addGroupTest({
copyFrom: 'group-1',
scriptId: `group-${i}`,
});
}
}
Otherwise, if the newest Machine has fewer cavities than the previously selected Machine, any additional categories should be removed:
if (totalCavities > currentChecks) {
...
} else {
// Need to remove checks
for (let i = currentChecks; i > totalCavities; i--) {
await subInspection.removeTest(`group-${i}`);
}
}
Set Appropriate Cavity
When creating a new group, all Tests inside the group should have the Cavity Traceability set to the correct value. Begin by retrieving the ID of the Cavity Traceability:
Note that this does not use the await keyword. Instead, we are issuing a request to retrieve the Traceability's ID as soon as the script is loaded, and storing the resulting Promise for later use. This will allow us to begin fetching as soon as the script loads, but ensure that it has finished loading when the Traceability ID is actually needed:
await subInspection.addGroupTest({
copyFrom: 'group-1',
scriptId: `group-${i}`
});
const properties = await subInspection.group(groupId).getProperties();
for (let i = 0; i < properties.tests.length; i++) {
const test = properties.tests[i];
if (test.type === 'spc') {
await subInspection.spc(test.scriptId).updateProperties({
testSpecificTrace: [{
traceabilityId: await cavityPromise,
value: 1
}]
});
} else if (test.type === 'passFail') {
await subInspection.passFail(test.scriptId).updateProperties({
testSpecificTrace: [{
traceabilityId: await cavityPromise,
value: 1
}]
});
}
}
Additionally, apply the same Test Specific Traceability to the SPC and Pass/Fail Test in group-1 when it is first shown:
await subInspection.group('group-1').updateProperties({
userDefinedVisible: true
});
await subInspection.spc('spc-test-1').updateProperties({
testSpecificTrace: [{
traceabilityId: await cavityPromise,
value: 1
}]
});
await subInspection.passFail('passfail-test-1').updateProperties({
testSpecificTrace: [{
traceabilityId: await cavityPromise,
value: 1
}]
});
currentChecks = 1;
Information
await may be used on the same Promise multiple times. When the Promise is initially resolved, the value will be cached and returned on each subsequent await.
Test the Inspection
Save and Run the Inspection. Try selecting different Machines and submitting data. See that the number of measurements is updated dynamically as the Traceability value changes. Try drawing some charts in a Dashboard and check that the Cavity Traceability is set correctly.
Final Code
const subInspection = gsApi.inspection.subInspection('subi 1');
const machineTraceability = subInspection.traceability('machine');
const machineToCavity = {
A: 2,
B: 4,
C: 6
};
const cavityPromise = gsApi.entity.getTraceabilityIdByName('Cavity');
let currentChecks = undefined;
machineTraceability.onOptionSelected(async () => {
const properties = await machineTraceability.getProperties();
const totalCavities = machineToCavity[properties.value];
if (totalCavities === currentChecks) {
// Already have the correct number of checks, return
return;
}
if (currentChecks === undefined) {
// First run, make the first set of tests visible
await subInspection.group('group-1').updateProperties({
userDefinedVisible: true
});
await subInspection.spc('spc-test-1').updateProperties({
testSpecificTrace: [{
traceabilityId: await cavityPromise,
value: 1
}]
});
await subInspection.passFail('passfail-test-1').updateProperties({
testSpecificTrace: [{
traceabilityId: await cavityPromise,
value: 1
}]
});
currentChecks = 1;
}
if (totalCavities > currentChecks) {
// Need to add additional checks
for (let i = currentChecks + 1; i <= totalCavities; i++) {
const groupId = `group-${i}`;
console.log('adding ' + groupId)
await subInspection.addGroupTest({
copyFrom: 'group-1',
scriptId: groupId,
});
const properties = await subInspection.group(groupId).getProperties();
for (let i = 0; i < properties.tests.length; i++) {
const test = properties.tests[i];
if (test.type === 'spc') {
await subInspection.spc(test.scriptId).updateProperties({
testSpecificTrace: [{
traceabilityId: await cavityPromise,
value: 1
}]
});
} else if (test.type === 'passFail') {
await subInspection.passFail(test.scriptId).updateProperties({
testSpecificTrace: [{
traceabilityId: await cavityPromise,
value: 1
}]
});
}
}
}
} else {
// Need to remove checks
for (let i = currentChecks; i > totalCavities; i--) {
await subInspection.removeTest(`group-${i}`);
}
}
currentChecks = totalCavities;
});






