This example demonstrates how to create a custom experiment using loops and subexperiments for added complexity.
Experiment Description
The API allows us to build experiments with multiple elements, which can loop individually or as a group. Let's consider building an experimental sequence with the following structure:
- Open Circuit Potential (OCP) element
- Constant Potential Element (loops 4 times, increasing the voltage by 100 mV each loop)
- Galvanostatic EIS element and OCP element (loops 3 times)
- Constant Current element that loops 2 times
- C++
auto customExperiment = std::make_shared<AisExperiment>();
success &= customExperiment->appendElement(ocpElement);
int voltage = 0;
for (int i = 0; i < 4; i++) {
success &= customExperiment->appendElement(cvElement, 1);
voltage += 0.1;
}
success &= eisSubExperiment.appendElement(galvEISElement, 1);
success &= eisSubExperiment.appendElement(ocpElement2, 1);
success &= customExperiment->appendSubExperiment(eisSubExperiment, 3);
success &= customExperiment->appendElement(ccElement, 2);
if (!success) {
qDebug() << "Error building experiment";
return 0;
}
- Python
success &= customExperiment.appendElement(ocpElement)
voltage = 0
for i in range(0, 4):
success &= customExperiment.appendElement(cvElement, 1)
voltage = voltage + 0.1
success &= eisSubExperiment.appendElement(galvEISElement, 1)
success &= eisSubExperiment.appendElement(ocpElement2, 1)
success &= customExperiment.appendSubExperiment(eisSubExperiment, 3)
success &= customExperiment.appendElement(ccElement, 2)
if not success:
print("Error building experiment")
sys.exit()
Let's go over the code in more detail:
Building the Experiment
Here, we create the Open Circuit Element and add it to the experiment without specifying the number of loops, so it runs once.
- C++
success &= customExperiment->appendElement(ocpElement);
- Python
success &= customExperiment.appendElement(ocpElement)
Next, we create the Constant Potential Elements, using a for loop to increment the voltage for each element, and then adding it to the created subExperiment.
- C++
int voltage = 0;
for (int i = 0; i < 4; i++) {
success &= customExperiment->appendElement(cvElement, 1);
voltage += 0.1;
}
- Python
voltage = 0
for i in range(0, 4):
success &= customExperiment.appendElement(cvElement, 1)
voltage = voltage + 0.1
For the looped EIS and OCP elements, we create another AisExperiment (eisSubExperiment), add the elements, and use AisExperiment::appendSubExperiment with 3 passed as the loop argument. This makes the two elements loop consecutively 3 times.
- C++
success &= eisSubExperiment.appendElement(galvEISElement, 1);
success &= eisSubExperiment.appendElement(ocpElement2, 1);
success &= customExperiment->appendSubExperiment(eisSubExperiment, 3);
- Python
success &= eisSubExperiment.appendElement(galvEISElement, 1)
success &= eisSubExperiment.appendElement(ocpElement2, 1)
success &= customExperiment.appendSubExperiment(eisSubExperiment, 3)
Lastly, we create the Constant Current Element, adding it to the main experiment using AisExperiment::appendElement with the loop argument set to 2. This loops the element twice at the end.
- C++
success &= eisSubExperiment.appendElement(galvEISElement, 1);
success &= eisSubExperiment.appendElement(ocpElement2, 1);
success &= customExperiment->appendSubExperiment(eisSubExperiment, 3);
- Python
success &= eisSubExperiment.appendElement(galvEISElement, 1)
success &= eisSubExperiment.appendElement(ocpElement2, 1)
success &= customExperiment.appendSubExperiment(eisSubExperiment, 3)
Starting the Experiment
The experiment is now ready and can be started like any other experiment.
- C++
qDebug() << "New Device Connected: " << deviceName;
auto& handler = tracker->getInstrumentHandler(INSTRUMENT_NAME);
connectSignals(handler);
AisErrorCode error = handler.uploadExperimentToChannel(CHANNEL, customExperiment);
if (error) {
qDebug() << error.message();
return 0;
}
error = handler.startUploadedExperiment(CHANNEL);
if (error) {
qDebug() << error.message();
return 0;
}
});
AisErrorCode error = tracker->connectToDeviceOnComPort(COMPORT);
if (error != error.Success) {
qDebug() << error.message();
return 0;
}
- Python
def startExperiment():
handler = tracker.getInstrumentHandler(INSTRUMENT_NAME)
connectSignals(handler)
error = handler.uploadExperimentToChannel(CHANNEL, customExperiment)
if error.value() != AisErrorCode.Success:
print(error.message())
app.quit()
error = handler.startUploadedExperiment(CHANNEL)
if error.value() != AisErrorCode.Success:
print(error.message())
app.quit()
tracker.newDeviceConnected.connect(startExperiment)
error = tracker.connectToDeviceOnComPort(COMPORT)
if error.value() != AisErrorCode.Success:
print(error.message())
sys.exit()
See the full example here
Now that we have seen how create complex custom experiments, lets move on to the next example, where we will utilize manual mode operations to provide real-time control of the Squidstat.