%%HTML
<video width="1280" height="720" controls>
<source src="img/Simplified Figure.mp4" type="video/mp4">
</video>
ChronoSeq V4 Workflow |
---|
![]() |
Our device design addresses several challenges not present in the original Dropseq system (See Figure Below). First, extended cell viability. We maintain cell suspension viability for experiments lasting 2 hours or longer, compared to typical 30-minute Drop-seq runs. Second, cross-contamination prevention. We implemented a washing system to remove unused cells or beads between samples. Third, sample isolation. We designed a system to prevent mixing wash fluid with droplets. To address these challenges, our device operates in two main phases during each injection cycle. 1. Flushing phase that clears fluid lines of residual beads or cells from previous injections. 2. Injection phase that precisely introduces cells and time-tagged beads into the microfluidic chip. This integrated system enables controlled, sequential introduction of cells and time-tagged beads, capturing gene expression dynamics across multiple time points in a single experiment.
ChronoSeq vs Dropseq comparison |
---|
![]() |
The ChronoSeq device is controlled via serial connections to a computer, which coordinates the actions of its various components, while the Dropseq device works by setting flow rates manually on syringe pumps. Some key features distinguish the ChronoSeq device:
The primary function of the microfluidic chip is to co-encapsulate cells with time-tagged beads using a flow-focusing junction at the center of the chip. While we initially considered using the Dropseq microfluidic chip for this purpose, several limitations made it unsuitable for our application:
ChronoSeq vs Dropseq chip comparison |
---|
![]() |
This notebook has several sections. The first part of the Notebook explains what needs to be done before you start an experiment and operate the device. The second part is used to Control Device Operation. Press Shift+Enter
to Execute a Cell.
Each Section Begins with a Markdown Cell Header and Tells you whether you need to execute the cells in the section or if the Code in the Section is Optional. The Code in some optional sections might be in Raw NBConvert
Format and you will need to Convert that Cell to Code
Format before you can execute.
Please go through the Device Assembly and Setup Notebook before going through this notebook.
You should receive your beads suspended in Ethanol. Store these beads in a new box at -20°C before you start your experiments or for long term storage. Label the box with the Date you received the beads, the bead type and the batch number.
Execute cells are specified with :Execute while optional cells are specified with :Optional in the header. Also execute all the cells with %%HTML
Magic at start of the Cell to make the video playable.
Main Menu
The switch to Turn on the Device is behind the Water Bath next to the Computer
SWITCH LOCATION | ZOOMED IN VIEW |
---|---|
![]() |
![]() |
Click on Checkboxes if Task has been Completed
Do you have enough 3.33X Lysis Buffer Stock?
Have you read the Protocols, ordered Reagents, ordered remaining items and prepared solutions for Library Preparation?
Do you have enough Microfluidic Chips? Have these chips recently produced droplets without jetting? Test your chips in a dummy run if you haven't done so in the last two weeks. You can use 1X Lysis buffer instead of beads for the Dummy run. Make sure the chips you are using are between 1-3 months from aquapel treatment. If its less than 1 month after Aquapel treatment then delamination might be an issue. If its more than 3 months then chips might have unreliable droplet formation and Jetting. During Normal Device Operation The Droplet Formation Junction will stretch out initially and then come closer to the mouth of the Center Junction in the Microfluidic Chip. Please see the following notebooks for more details:
Have you prepared your tubes for Bead Timepoints/Injection Filtering the beads is important to avoid blockage in the Microfluidic Chips during operation. Prepare 50ml Falcon Tubes with 1ml of Beads in each tube if you plan to do a Single-Cell run. The following protocols should help:
Do you have Cells in culture?. You should have Cells in Culture and ready to Harvest for this experiment. There are slightly different protocols depending on whether you are culturing Adherent or Suspension cells. Read this protocol for more details.
Have you prepared enough Lysis buffer and Distilled Water tubes for Priming the Bead Time-Point Reservoirs? For more details see the priming section in this notebook.
Distilled Water: | Lysis Buffer: |
---|---|
![]() |
![]() |
You should store your Oil below your Bench Protected from heat,light and moisture in a sealed container with Desiccant Beads. Avoid using oil that is cloudy. You can check if the oil is cloudy or not, by comparing the transparency of the Oil against a Dark Background. Cloudy oil might have more jetting during droplet formation.
![]() |
![]() |
![]() |
![]() |
If you did the cleanup correctly last time then the reservoirs should be empty and dry.
![]() |
![]() |
✶ Important Notes:
- If any container is empty you need to prime the container with Distilled water. If the container has Lysis buffer in it then you need to prime the container with Distilled water and Check the inside of the reservoir cap for salt crystalls and clean thoroughly if necessary. Even a little bit of Lysis buffer splashed under the cap can create dry crystals that can dislodge and block the Microfluidic Chip during an injection.
- Moreover, you need to make sure the tubing inside the reservoir is not completely touching the bottom of the 50ml Falcon Tube. There should be a slight gap to allow beads to be sucked up easily during injection. Nor should the tubing inside the reservoir be too far away from the bottom of the 50ml tube. If its too far away then all the beads inside the reservoir will not be used and there is a high chance of bubbles being introduced into the microfluidic chip ruining the injection. You don't need to check all the containers only the ones you plan to use for your experiment. A good test is to shake your reservoir back and forth. Because of this shaking, your tubing should also move. The movement of the tubing is a good indicator it is not touching the bottom of the 50ml tube.
![]() |
![]() |
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/YrAKv27Uwf4?si=FPxGCGToSI2_xRXT" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
Empty out the 2L GL45 Bottle with the Sucked up Water after you are done.
You need to connect the correct Pressure Source to the Pressure Controller. There are two sources to choose from:
Choose the appropriate source depending on your experiment. For example, if want to maintain your cells in Culture conditions for a few hours to study the temporal response to a pertubation, then you should choose 5%CO2. However, if you just want to profile the cells for Quality Control or other experiments then you should connect to the House Air.
![]() |
![]() |
Push the tubing in all the way and then try to pull it out. If you cannot pull it out then the tubing is securely connected. Since the connectors are push-connect you can press the outer ring concentric to the inlet and pull the tubing out if necessary.
The video below shows how to connect and disconnect the Pneumatic Tubing using the Push Connect:
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/HRj4VNQaSBs?si=5bF_OtHEwsG67wSq" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
Next turn on the air supply.
House Air
For house air there is a valve you need to open in the middle of the bench. Open it perpendicular to the close position for maximum air flow. You can monitor the air pressure with the pressure gauge on the first filter.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Rotate the Valve on Top of the Cylinder to Close Completely. The Valve should have clear markings for which direction to turn for closing or opening it. |
---|
![]() |
Turn the House Air Valve Off to the Close Position |
---|
![]() |
⚠ WARNING: If you try to Disconnect the Pneumatic Tubing while the Pressure is still on you can Injure Yourself. BE CAREFUL. Pay attention to leaks and always change the tubing or any fitting when there is no Air pressure. Execute the Cell Below to see a video of what happens when you have disconnected tubing while the System is pressurized. Don't try this. This is only intended as a warning to help you avoid injury.
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/BGRQahoE-Q8?si=9jTpWmVCqRvhUAt8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
# coding : utf8
%matplotlib inline
import os
import sys
#Adding required directories to sys.path. Make sure you are in the Directory with the Git Repo when you start Jupyter Notebook
sys.path.append(os.getcwd());
sys.path.append(os.getcwd()+"\\DLL64");
import time
import Elveflow64
from ctypes import *
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import ivPID.PID as PID_controller
import serial
import threading
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers import SchedulerNotRunningError
from datetime import datetime,timedelta
import seaborn as sns
import pygame
pygame 1.9.5 Hello from the pygame community. https://www.pygame.org/contribute.html
%%javascript
IPython.OutputArea.prototype._should_scroll = function(lines) {
return false;
}
You meed to use the NI MAX software installed to Check and Specify the COM Ports being used for the different Devices Connected to the Computer. See the Device Assembly and Setup Notebook for more details.
vortexRelayCOM="COM9"
mainPlotterRobotCOM="COM4"
smallDropletCollectionRobotCOM="COM10"
magneticStirrerCOM="COM6"
OB1_pressureControllerCOM="01C35786" #Elveflow Value in NI MAX
firstController="Valve_Controller1" #Elveflow Value in NI MAX
secondController="Valve_Controller2" #Elveflow Value in NI MAX
DIY_thirdControllerCOM="COM8"
Cell_Channel_BFS_COM="ASRL3::INSTR" #Bronkhorst Flow Sensor Format
arduinoSensirionFlowMeterCOM="COM5"
arduinoVortexServo2COM="COM7"
Oil_Channel_BFS_COM="ASRL11::INSTR" #Bronkhorst Flow Sensor Format
vortexRelay=serial.Serial(vortexRelayCOM,timeout=1,write_timeout=0)
time.sleep(5)
print(vortexRelay.name)
print(vortexRelay.get_settings())
print(vortexRelay.is_open)
if not vortexRelay.is_open:
vortexRelay.open()
time.sleep(5)
#Initializing Collection Tube Robot
plotter=serial.Serial(mainPlotterRobotCOM,timeout=1,write_timeout=1)
time.sleep(5)
print(plotter.name)
print(plotter.get_settings())
print(plotter.is_open)
if not plotter.is_open:
plotter.open()
time.sleep(5)
droplet_collector=serial.Serial(smallDropletCollectionRobotCOM,timeout=1,write_timeout=1)
time.sleep(5)
print(droplet_collector.name)
print(droplet_collector.get_settings())
print(droplet_collector.is_open)
if not droplet_collector.is_open:
droplet_collector.open()
time.sleep(5)
#Initializing magnetic stirrer
ser = serial.Serial(magneticStirrerCOM, timeout=1, write_timeout=0) #Opening COM6 with default options 9600,8,N,1
#Need a few seconds for the serial connection to open. time.sleep is necessary so commands immediately following get executed
time.sleep(5)
print(ser.name)
print(ser.get_settings())
print(ser.is_open)
if not ser.is_open:
ser.open()
time.sleep(5)
#Initializing Pressure Controller
pressureController=c_int32()
error=Elveflow64.OB1_Initialization(OB1_pressureControllerCOM.encode('ascii'),2,2,2,0,byref(pressureController))
if(error==0):
print("Pressure Controller Connection Started")
print('Pressure Controller ID: %d' % pressureController.value)
else:
print("error %d :" % error)
#Defining Channel Bindings according to current configuration
cell_channel=1
oil_channel=2
bead_channel=3
#Initializing Valve Controllers
valve_controller1=c_int32()
error=Elveflow64.MUX_Initialization(firstController.encode("ascii"),byref(valve_controller1))
if(error==0):
print("Valve Controller 1 Connection Started")
print('Valve Controller ID: %d' % valve_controller1.value)
else:
print("error %d :" % error)
valve_controller2=c_int32()
error=Elveflow64.MUX_Initialization(secondController.encode("ascii"),byref(valve_controller2))
if(error==0):
print("Valve Controller 2 Connection Started")
print('Valve Controller ID: %d' % valve_controller2.value)
else:
print("error %d :" % error)
#valve_controller3=c_int32()
#valve_controller3.value=4629#Assigning some number for third valve controller
#Third valve controller using relay board
#thirdController=serial.Serial(DIY_thirdControllerCOM, timeout=1, write_timeout=0)
#time.sleep(5.0)
#print(thirdController.is_open)
#print(thirdController.get_settings())
#Initializing Flow Meters
cellChannelFlowMeter=c_int32()
beadChannelFlowMeter=c_int32()
oilChannelFlowMeter=c_int32()
error=Elveflow64.BFS_Initialization(Cell_Channel_BFS_COM.encode('ascii'),byref(cellChannelFlowMeter))
error=Elveflow64.BFS_Set_Filter(cellChannelFlowMeter,float(0.1))
print('Cell Channel Flow Meter ID: %d' % cellChannelFlowMeter.value)
print("error %d :" % error) #Error 1073481728 is harmless and is just a warning
#Use this code if processing data from the sensor using an Arduino UNO R3
arduino_Bead_Flow_meter = serial.Serial(arduinoSensirionFlowMeterCOM, timeout=1, write_timeout=1) #Opening COM6 with default options 9600,8,N,1
#Need a few seconds for the serial connection to open. time.sleep is necessary so commands immediately following get executed
time.sleep(5)
print(arduino_Bead_Flow_meter.name)
print(arduino_Bead_Flow_meter.get_settings())
print(arduino_Bead_Flow_meter.is_open)
#Initializing Vortexes
#arduino_Vortex_Servo= serial.Serial("COM12", timeout=1, write_timeout=1)
#arduino_Vortex_Servo.write("A0\n".encode())
#time.sleep(5)
#print(arduino_Vortex_Servo.name)
#print(arduino_Vortex_Servo.get_settings())
#print(arduino_Vortex_Servo.is_open)
arduino_Vortex_Servo2=serial.Serial(arduinoVortexServo2COM, timeout=1, write_timeout=0)
arduino_Vortex_Servo2.write("A0|B0\n".encode())
time.sleep(5)
print(arduino_Vortex_Servo2.name)
print(arduino_Vortex_Servo2.get_settings())
print(arduino_Vortex_Servo2.is_open)
error=Elveflow64.BFS_Initialization(Oil_Channel_BFS_COM.encode('ascii'),byref(oilChannelFlowMeter))
error=Elveflow64.BFS_Set_Filter(oilChannelFlowMeter,float(0.1))
print('Oil Channel Flow Meter ID: %d' % oilChannelFlowMeter.value)
print("error %d :" % error)
#Density measurement is required so that correct flow measurement is returned.
#Defining Return Variables
cellChannelFlowDensity=c_double(-1)
oilChannelFlowDensity=c_double(-1)
cellChannelFlowRate=c_double(-1)
oilChannelFlowRate=c_double(-1)
#Getting Density and Flow values for Cell Channel
error=Elveflow64.BFS_Get_Density(cellChannelFlowMeter,byref(cellChannelFlowDensity))
print("Cell Channel Density:")
print(cellChannelFlowDensity.value)
error=Elveflow64.BFS_Get_Flow(cellChannelFlowMeter.value,byref(cellChannelFlowRate))
print("Cell Channel Flow rate:")
print(cellChannelFlowRate.value)
#Getting Density and Flow values for Oil Channel
error=Elveflow64.BFS_Get_Density(oilChannelFlowMeter,byref(oilChannelFlowDensity))
print("Oil Channel Density:")
print(oilChannelFlowDensity.value)
error=Elveflow64.BFS_Get_Flow(oilChannelFlowMeter.value,byref(oilChannelFlowRate))
print("Oil Channel Flow rate:")
print(oilChannelFlowRate.value)
COM9 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 0, 'inter_byte_timeout': None} True COM4 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 1, 'inter_byte_timeout': None} True COM10 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 1, 'inter_byte_timeout': None} True COM6 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 0, 'inter_byte_timeout': None} True Pressure Controller Connection Started Pressure Controller ID: 0 Valve Controller 1 Connection Started Valve Controller ID: 0 Valve Controller 2 Connection Started Valve Controller ID: 1 Cell Channel Flow Meter ID: 0 error 0 : COM5 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 1, 'inter_byte_timeout': None} True COM7 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 0, 'inter_byte_timeout': None} True Oil Channel Flow Meter ID: 1 error 0 : Cell Channel Density: 6.092843532562256 Cell Channel Flow rate: -369.641563306904 Oil Channel Density: 8.488499641418457 Oil Channel Flow rate: -66.20482099745226
You need to turn the pressure on and Plug all Three Channels of the OB1 with Luer Plugs for the Calibration. Make sure you do this when you are setting up the instrument for the first time.
#Make sure you Calibrate with the plugs in place if you are generating the file for the first time.
#See OB1 user manual for details about calibration and the plug type to use.
calibrationVector=(c_double*1000)()
currentWorkingDirectory=os.getcwd()
calibrationFilePath=currentWorkingDirectory + "\\OB1_CalibrationFile.txt"
fileExists=os.path.isfile(calibrationFilePath)
if(fileExists):
error=Elveflow64.Elveflow_Calibration_Load(calibrationFilePath.encode('ascii'), byref(calibrationVector), 1000)
if(error==0):
print("Calibration File Load Successful!")
else:
print("error %d :" % error)
else:
Elveflow64.OB1_Calib(pressureController.value, calibrationVector, 1000)
error=Elveflow64.Elveflow_Calibration_Save(calibrationFilePath.encode('ascii'), byref(calibrationVector), 1000)
if(error==0):
print('Calibration saved in %s' % calibrationFilePath)
else:
print("error %d :" % error)
Calibration File Load Successful!
global cell_channel_density
cell_channel_density=0
#Sets stirrer speed in rpm units
def set_stirrer_speed(rpm):
buffer=ser.read(ser.inWaiting())
byteString="s "+str(rpm)
ser.write(byteString.encode())
def stop_stirrer():
set_stirrer_speed(0)
#Closes serial connection to stirrer. You need to restart the kernel once this function has been executed.
def shutdown_stirrer():
stop_stirrer()
ser.close()
if not ser.is_open:
print("Magnetic Stirrer Connection Closed!")
#Shuts down the system. You should restart the Kernel if you want to restart the Device.
def shutdown_device():
stop_vent() #Stops venting if not already stopped.
#Shutting Down OB1
error=Elveflow64.OB1_Destructor(pressureController.value)
if(error==0):
print("Pressure Controller Connection Closed!")
else:
print("error %d :" % error)
#Shutting Down MUX Wire
error=Elveflow64.MUX_Destructor(valve_controller1.value)
if(error==0):
print("Valve Controller 1 Connection Closed!")
else:
print("error %d :" % error)
error=Elveflow64.MUX_Destructor(valve_controller2.value)
if(error==0):
print("Valve Controller 2 Connection Closed!")
else:
print("error %d :" % error)
#thirdController.close()
#if not thirdController.isOpen():
# print("Valve Controller 3 Connection Closed!")
#else:
# print("error! Count not close Valve Controller 3 connection.")
#Shutting Down Flow Meters
error=Elveflow64.BFS_Destructor(cellChannelFlowMeter.value)
if(error==0):
print("Cell Channel Flow meter Connection Closed!")
else:
print("error %d :" % error)
arduino_Bead_Flow_meter.close()
if not arduino_Bead_Flow_meter.isOpen():
print("Bead Channel Flow meter Connection Closed!")
else:
print("error! Could not close Bead Channel Flow meter connection.")
#arduino_Vortex_Servo.close()
#if not arduino_Vortex_Servo.isOpen():
# print("Bead Channel Vortex Connection Closed!")
#else:
# print("error! Count not close Bead Channel Vortex connection.")
stop_both_vortices()
arduino_Vortex_Servo2.close()
if not arduino_Vortex_Servo2.isOpen():
print("Bead Channel Vortex Connection Closed!")
else:
print("error! Count not close Bead Channel Vortex 2 connection.")
error=Elveflow64.BFS_Destructor(oilChannelFlowMeter.value)
if(error==0):
print("Oil Channel Flow meter Connection Closed!")
else:
print("error %d :" % error)
#Shutting Down Magnetic Stirrer
shutdown_stirrer()
#Shutting Down plotter
plotter.write("H\n".encode())
time.sleep(1.0)
plotter.write("D\n".encode())
plotter.close()
if not plotter.isOpen():
print("Connection to the Robot closed successfully!")
else:
print("error! Could not close connection to the Robot.")
#Shutting Down Droplet_Collector
droplet_collector.write("H\n".encode())
time.sleep(1.0)
droplet_collector.close()
if not droplet_collector.isOpen():
print("Connection to the Droplet Collector closed successfully!")
else:
print("error! Could not close connection to the Droplet Collector.")
#Shutting Down Vortex Relay
vortexRelay.write("A0|B0\n".encode())
vortexRelay.close()
if not vortexRelay.isOpen():
print("Connection to the Vortex Relay closed successfully!")
else:
print("error! Could not close connection to the Vortex Relay.")
def get_time_elapsed(initiation_time):
return (time.time()-initiation_time)
def set_oil_channel_pressure(oil_channel_pressure):
Elveflow64.OB1_Set_Press(pressureController.value,c_int32(oil_channel),c_double(oil_channel_pressure),byref(calibrationVector),len(calibrationVector))
def get_oil_channel_pressure():
getOilChannelPressure=c_double()
Elveflow64.OB1_Get_Press(pressureController.value,c_int32(oil_channel),1,byref(calibrationVector),byref(getOilChannelPressure),len(calibrationVector))
return getOilChannelPressure.value
def set_cell_channel_pressure(cell_channel_pressure):
Elveflow64.OB1_Set_Press(pressureController.value,c_int32(cell_channel),c_double(cell_channel_pressure),byref(calibrationVector),len(calibrationVector))
def get_cell_channel_pressure():
getCellChannelPressure=c_double()
Elveflow64.OB1_Get_Press(pressureController.value,c_int32(cell_channel),1,byref(calibrationVector),byref(getCellChannelPressure),len(calibrationVector))
return getCellChannelPressure.value
def set_bead_channel_pressure(bead_channel_pressure):
Elveflow64.OB1_Set_Press(pressureController.value,c_int32(bead_channel),c_double(bead_channel_pressure),byref(calibrationVector),len(calibrationVector))
def get_bead_channel_pressure():
getBeadChannelPressure=c_double()
Elveflow64.OB1_Get_Press(pressureController.value,c_int32(bead_channel),1,byref(calibrationVector),byref(getBeadChannelPressure),len(calibrationVector))
return getBeadChannelPressure.value
#Stops all pressure regulators to stop flow
def stop_pressure():
set_flow_rates(0.0,0.0,0.0)
set_oil_channel_pressure(0.0)
set_bead_channel_pressure(0.0)
set_cell_channel_pressure(0.0)
def get_cell_channel_flowrate():
cellChannelFlow=c_double()
Elveflow64.BFS_Get_Flow(cellChannelFlowMeter.value,byref(cellChannelFlow))
#massFlowRate=cell_channel_density*cellChannelFlow.value
#adjustedFlowRate=massFlowRate/1003.5 #Airbubbles inside the cell channel cause a lot of problems.
#This is a quick and easy fix for that problem.
return cellChannelFlow.value
#Use this code if using the Elveflow analog flow meter and OB1 to collect data
def get_bead_channel_flowrate():
beadChannelFlow=c_double()
error=Elveflow64.OB1_Get_Sens_Data(pressureController.value, 3, 1, byref(beadChannelFlow))
return beadChannelFlow.value*scalingFactor
#Using an Arduino to get data from flow meter because the software and hardware for the company that sold it does not work.
#See older code or use the ESI SDK Manual if you want to use their API and hardware.
digitalEvagreenDropletOilScalingFactor=3.17886487
digitalDistilledWaterScalingFactor=0.9197808172314549 # This is the correct scaling factor in the 70ul range which we are interested in
analogDistilledWaterScalingFactor=1.0072439810048586
lysisBufferScalingFactor=1.068302009661219
lysisBufferFicollScalingFactor=0.9215405000604387
scalingFactor60ul=0.8728679338516443
lysisBufferScalingFactor55ul=47.30912429940319/55.00098949211909
scalingFactor55ulFicoll=(45.12911217481021/54.998555598755836)*(56.734000373435556/54.999752771488176)*(54.74053725139174/54.99842052428598)*(55.09634046962294/54.99954728967373)
scalingFactor=analogDistilledWaterScalingFactor
beadChannelScalingFactor=1.0
def set_bead_channel_scaling_factor(newScaling):
global beadChannelScalingFactor
beadChannelScalingFactor=newScaling
def reset_bead_channel_scaling_factor():
global beadChannelScalingFactor
beadChannelScalingFactor=1.0
def get_bead_channel_flowrate():
#Empty the buffer if its more than 11 bytes so new values can be brought in during sampling.
#The arduino has been programmed to send a maximum of 10 bytes of data in a line.
if arduino_Bead_Flow_meter.inWaiting()>11:
buffer=arduino_Bead_Flow_meter.read(arduino_Bead_Flow_meter.inWaiting())
while True:
try:
beadChannelFlow=float((arduino_Bead_Flow_meter.readline()).decode("utf-8"))
break
except ValueError:
pass
#Assign Correct Scaling factor to the fluid being used
return beadChannelFlow*beadChannelScalingFactor
def stop_bead_vortex():
stop_both_vortices()
def start_bead_vortex():
vortexRelay.write("A1|B0\n".encode())
#arduino_Vortex_Servo2.write("A75|B0|W5000|A65|B0\n".encode())
#Use this method to stop the Bead Channel Vortex
def stop_bead_vortex2():
stop_both_vortices()
def start_bead_vortex2():
vortexRelay.write("A0|B1\n".encode())
#arduino_Vortex_Servo2.write("B75|A0|W5000|B65|A0\n".encode())
def start_both_vortices():
vortexRelay.write("A1|B1\n".encode())
#arduino_Vortex_Servo2.write("A75|B75|W5000|A65|B65\n".encode())
def stop_both_vortices():
#arduino_Vortex_Servo2.write("A0|B0\n".encode())
vortexRelay.write("A0|B0\n".encode())
#Use this when using the miniCoriflow flow meter
def get_oil_channel_flowrate():
oilChannelFlow=c_double()
Elveflow64.BFS_Get_Flow(oilChannelFlowMeter.value,byref(oilChannelFlow))
return oilChannelFlow.value
def safely_set_cell_channel_pressure(newCellChannelPressure):
if pidforCellChannel.getTargetValue()==0.0 and pidforCellChannel.getFlushValue() is False:
set_cell_channel_pressure(0.0)
else:
if newCellChannelPressure>2000.00 :
set_cell_channel_pressure(2000.0)
elif newCellChannelPressure<0.0:
set_cell_channel_pressure(0.0)
else:
set_cell_channel_pressure(newCellChannelPressure)
def safely_set_oil_channel_pressure(newOilChannelPressure):
if pidforOilChannel.getTargetValue()==0.0 and pidforOilChannel.getFlushValue() is False:
set_oil_channel_pressure(0.0)
else:
if newOilChannelPressure>2000.00:
set_oil_channel_pressure(2000.0)
elif newOilChannelPressure<0.0:
set_oil_channel_pressure(0.0)
else:
set_oil_channel_pressure(newOilChannelPressure)
def safely_set_bead_channel_pressure(newBeadChannelPressure):
if pidforBeadChannel.getTargetValue()==0.0 and pidforBeadChannel.getFlushValue() is False:
set_bead_channel_pressure(0.0)
else:
if newBeadChannelPressure>2000.00:
set_bead_channel_pressure(2000.0)
elif newBeadChannelPressure<0.0:
set_bead_channel_pressure(0.0)
else:
set_bead_channel_pressure(newBeadChannelPressure)
#Only using the I to control the flow rate seems to be good enough, no need to use any other option
def initialize_pid_controllers():
"""Change PID values here for global effect on flow regulation. Might not need to mess with these parameters if you
execute the code with the same containers, tubing and liquids as me.
"""
global pidforCellChannel,pidforBeadChannel,pidforOilChannel
pidforCellChannel=PID_controller.PID(0.0,0.75,0.0) #Initial Kp, Ki, and Kd values
pidforOilChannel=PID_controller.PID(0.0,1.0,0.0)
pidforBeadChannel=PID_controller.PID(0.0,0.1,0.0)
def clear_PID_controllers():
"""You get a software induced pressure spike if you don't clear PID controllers"""
pidforCellChannel.clear()
pidforBeadChannel.clear()
pidforOilChannel.clear()
def set_flow_rates(cell_flow,bead_flow,oil_flow):
#clear_PID_controllers() #Clear PID controller before any flow rate change to prevent software induced pressure spike.
pidforCellChannel.setTargetValue(cell_flow)
pidforBeadChannel.setTargetValue(bead_flow)
pidforOilChannel.setTargetValue(oil_flow)
#Function to set pressure instead of Flow rates. You can just flush at a certain pressure if necessary
def set_flush_pressures(cell_pressure,bead_pressure,oil_pressure):
pidforCellChannel.start_flush_at_pressure(cell_pressure)
pidforBeadChannel.start_flush_at_pressure(bead_pressure)
pidforOilChannel.start_flush_at_pressure(oil_pressure)
#Stops flushing. You need to use this function before you can start using PID control for Flow rates again
def stop_flushing_all_channels():
pidforCellChannel.stop_flush()
pidforBeadChannel.stop_flush()
pidforOilChannel.stop_flush()
#Updates Cell Channel Density and helps monitor flow through
def get_cell_channel_density():
global cell_channel_density
cellChannelDensity=c_double(-1)
Elveflow64.BFS_Get_Density(cellChannelFlowMeter,byref(cellChannelDensity))
cell_channel_density=cellChannelDensity.value
return cellChannelDensity.value
def get_oil_channel_density():
oilChannelDensity=c_double(-1)
Elveflow64.BFS_Get_Density(oilChannelFlowMeter,byref(oilChannelDensity))
#oil_channel_density=cellChannelDensity.value
return oilChannelDensity.value
def setNewPIDKis(CellKi,BeadKi,OilKi):
global pidforCellChannel,pidforBeadChannel,pidforOilChannel
pidforCellChannel.setKi(CellKi)
pidforOilChannel.setKi(OilKi)
pidforBeadChannel.setKi(BeadKi)
#Generates a Sin wave pressure pulse to flush the device
def sin_pressure_wave(max_cell_pressure,max_bead_pressure,max_oil_pressure,duration):
start_time=time.time()
while(get_time_elapsed(start_time)<duration):
cell_pressure=max_cell_pressure*np.sin(np.pi*get_time_elapsed(start_time)/duration)
bead_pressure=max_bead_pressure*np.sin(np.pi*get_time_elapsed(start_time)/duration)
oil_pressure=max_oil_pressure*np.sin(np.pi*get_time_elapsed(start_time)/duration)
set_flush_pressures(cell_pressure,bead_pressure,oil_pressure)
set_flush_pressures(0.0,0.0,0.0)
stop_flushing_all_channels()
global total_waste_collections
total_waste_collections=0
global store_chip_values
store_chip_values=False
#Function for recording flow data from the pressure controller and flow sensors and then using that data to apply PID control
def record_flow_data(sampling_duration):
global store_chip_values
global record_data
print("Schedule %s Started at %s"%(current_count,datetime.now()))
initialize_pid_controllers()
start_time=time.time()
while (get_time_elapsed(start_time)<sampling_duration):
#Getting Pressure and Flow values for each channel
#Cell Channel
cellChannelPressure=get_cell_channel_pressure()
cellChannelFlowrate=get_cell_channel_flowrate()
if record_data is True:
cellChannelPressureMeasurements.append((cellChannelPressure, get_time_elapsed(start_time),current_count))
cellChannelFlowMeasurements.append((cellChannelFlowrate, get_time_elapsed(start_time),current_count))
#Oil Channel
oilChannelPressure=get_oil_channel_pressure()
oilChannelFlowrate=get_oil_channel_flowrate()
if record_data is True:
oilChannelPressureMeasurements.append((oilChannelPressure, get_time_elapsed(start_time),current_count))
oilChannelFlowMeasurements.append((oilChannelFlowrate, get_time_elapsed(start_time),current_count))
#Bead Channel
beadChannelPressure=get_bead_channel_pressure()
beadChannelFlowrate=get_bead_channel_flowrate()
if record_data is True:
beadChannelPressureMeasurements.append((beadChannelPressure, get_time_elapsed(start_time),current_count))
beadChannelFlowMeasurements.append((beadChannelFlowrate, get_time_elapsed(start_time),current_count))
#Add function to compute whether there is backflow or not
#Applying PID update function for all channels
safely_set_cell_channel_pressure(pidforCellChannel.update(cellChannelFlowrate))
safely_set_oil_channel_pressure(pidforOilChannel.update(oilChannelFlowrate))
safely_set_bead_channel_pressure(pidforBeadChannel.update(beadChannelFlowrate))
start_vent()
print("Schedule %s Completed at %s "%(current_count,datetime.now()))
if store_chip_values is True:
store_chip_calibration_for_latest_run()
store_chip_values=False
waste_tube2.goToCoordinates()
bad_collection_tube.goHome()
def plot_channel_data(channel_measurements,type_of_measurement,channel_name,save_plots=False):
assert type_of_measurement in ("Pressure","Flow")
if type_of_measurement is "Pressure":
ylabel="Pressure (mBar)"
else:
ylabel="Flow (ul/min)"
channel_measurement_df=pd.DataFrame(channel_measurements,columns=[type_of_measurement,"Time","Sample"])
print(channel_measurement_df.shape) #Rows and columns
sub_plots=sns.relplot(x="Time",y=type_of_measurement,col="Sample",col_wrap=2,data=channel_measurement_df,kind="line")
sub_plots.set_xlabels("Time (Seconds)")
sub_plots.set_ylabels(ylabel)
plt.subplots_adjust(top=0.9)
sub_plots.fig.suptitle("%s Channel Plot of %s vs Time"%(channel_name,type_of_measurement))
if save_plots is True:
sub_plots.savefig(channel_name+type_of_measurement+".png",dpi=600)
def plot_flow_data(save_plots=False):
"""Pass the variable save_plots a True value to save the plots to the current working directory.
By default this is set to False.
"""
plot_channel_data(cellChannelPressureMeasurements,"Pressure","Cell",save_plots)
plot_channel_data(cellChannelFlowMeasurements,"Flow","Cell",save_plots)
plot_channel_data(oilChannelPressureMeasurements,"Pressure","Oil",save_plots)
plot_channel_data(oilChannelFlowMeasurements,"Flow","Oil",save_plots)
plot_channel_data(beadChannelPressureMeasurements,"Pressure","Bead",save_plots)
plot_channel_data(beadChannelFlowMeasurements,"Flow","Bead",save_plots)
def get_latest_pressure_measurements():
newCellPressure=cellChannelPressureMeasurements.copy()
newOilPressure=oilChannelPressureMeasurements.copy()
newBeadPressure=beadChannelPressureMeasurements.copy()
lastCellPressure,timestamp,count=newCellPressure[-1]
lastBeadPressure,timestamp,count=newBeadPressure[-1]
lastOilPressure,timestamp,count=newOilPressure[-1]
return (lastCellPressure,lastBeadPressure,lastOilPressure)
def get_average_pressure_measurments(begin,end,minuscount):
newCellPressure=cellChannelPressureMeasurements.copy()
newOilPressure=oilChannelPressureMeasurements.copy()
newBeadPressure=beadChannelPressureMeasurements.copy()
cell_pressure_df=pd.DataFrame(newCellPressure,columns=["Pressure","Time","Sample"])
oil_pressure_df=pd.DataFrame(newOilPressure,columns=["Pressure","Time","Sample"])
bead_pressure_df=pd.DataFrame(newBeadPressure,columns=["Pressure","Time","Sample"])
targetCellPressures=cell_pressure_df[(cell_pressure_df.Time>begin) & (cell_pressure_df.Time<end) & (cell_pressure_df.Sample==cell_pressure_df.Sample.max()+minuscount)]
targetBeadPressures=bead_pressure_df[(bead_pressure_df.Time>begin) & (bead_pressure_df.Time<end) & (bead_pressure_df.Sample==bead_pressure_df.Sample.max()+minuscount)]
targetOilPressures=oil_pressure_df[(oil_pressure_df.Time>begin) & (oil_pressure_df.Time<end) & (oil_pressure_df.Sample==oil_pressure_df.Sample.max()+minuscount)]
return (targetCellPressures.Pressure.mean(),targetBeadPressures.Pressure.mean(),targetOilPressures.Pressure.mean())
def get_average_flow_measurments(begin,end,minuscount):
newCellFlow=cellChannelFlowMeasurements.copy()
newOilFlow=oilChannelFlowMeasurements.copy()
newBeadFlow=beadChannelFlowMeasurements.copy()
cell_flow_df=pd.DataFrame(newCellFlow,columns=["Flow","Time","Sample"])
oil_flow_df=pd.DataFrame(newOilFlow,columns=["Flow","Time","Sample"])
bead_flow_df=pd.DataFrame(newBeadFlow,columns=["Flow","Time","Sample"])
targetCellFlows=cell_flow_df[(cell_flow_df.Time>begin) & (cell_flow_df.Time<end) & (cell_flow_df.Sample==cell_flow_df.Sample.max()+minuscount)]
targetBeadFlows=bead_flow_df[(bead_flow_df.Time>begin) & (bead_flow_df.Time<end) & (bead_flow_df.Sample==bead_flow_df.Sample.max()+minuscount)]
targetOilFlows=oil_flow_df[(oil_flow_df.Time>begin) & (oil_flow_df.Time<end) & (oil_flow_df.Sample==oil_flow_df.Sample.max()+minuscount)]
return (targetCellFlows.Flow.mean(),targetBeadFlows.Flow.mean(),targetOilFlows.Flow.mean())
def get_average_pressure_measurments_for_previous_run(begin,end):
return get_average_pressure_measurments(begin,end,-1)
def get_average_pressure_measurments_for_latest_run(begin,end):
return get_average_pressure_measurments(begin,end,0)
def get_average_flow_measurments_for_previous_run(begin,end):
return get_average_flow_measurments(begin,end,-1)
def get_average_flow_measurments_for_latest_run(begin,end):
return get_average_flow_measurments(begin,end,0)
def store_chip_calibration_for_latest_run():
currentWorkingDirectory=os.getcwd()
calibrationFilePath=currentWorkingDirectory + "\\Chip_CalibrationFile.txt"
calibrationFile=open(calibrationFilePath,"w")
cellPress,beadPress,oilPress=get_average_pressure_measurments_for_latest_run(200,205)
cellFlow,beadFlow,oilFlow=get_average_flow_measurments_for_latest_run(200,205)
calibrationFile.write(str(cellPress)+'\n')
calibrationFile.write(str(beadPress)+'\n')
calibrationFile.write(str(oilPress)+'\n')
calibrationFile.write(str(cellFlow)+'\n')
calibrationFile.write(str(beadFlow)+'\n')
calibrationFile.write(str(oilFlow)+'\n')
calibrationFile.close()
def get_chip_stored_pressure_calibration_values(override=False):
currentWorkingDirectory=os.getcwd()
calibrationFilePath=currentWorkingDirectory + "\\Chip_CalibrationFile.txt"
fileExists=os.path.isfile(calibrationFilePath)
if fileExists:
calibrationFile=open(calibrationFilePath,"r")
cellPress=float(calibrationFile.readline())
beadPress=float(calibrationFile.readline())
oilPress=float(calibrationFile.readline())
calibrationFile.close()
#Ficoll Pressures
bestStoredCellPress=276.39
bestStoredBeadPress=464.95
bestStoredOilPress=862.19
#Non Ficoll Lysis buffer Pressures
#bestStoredCellPress=326.65
#bestStoredBeadPress=287.90
#bestStoredOilPress=947.87
if override is True:
return(cellPress,beadPress,oilPress)
else:
if not (0.7*bestStoredCellPress<=cellPress<=1.3*bestStoredCellPress):
print("WARNING! Something is wrong. Stored pressure values are not in range of expected values.")
print("Using best known stored values for this run...")
return(bestStoredCellPress,bestStoredBeadPress,bestStoredOilPress)
elif not (0.7*bestStoredBeadPress<=beadPress<=1.3*bestStoredBeadPress):
print("WARNING! Something is wrong. Stored pressure values are not in range of expected values.")
print("Using best known stored values for this run...")
return(bestStoredCellPress,bestStoredBeadPress,bestStoredOilPress)
elif not (0.7*bestStoredOilPress<=oilPress<=1.3*bestStoredOilPress):
print("WARNING! Something is wrong. Stored pressure values are not in range of expected values.")
print("Using best known stored values for this run...")
return(bestStoredCellPress,bestStoredBeadPress,bestStoredOilPress)
else:
return(cellPress,beadPress,oilPress)
else:
return None
def get_chip_stored_flow_calibration_values():
currentWorkingDirectory=os.getcwd()
calibrationFilePath=currentWorkingDirectory + "\\Chip_CalibrationFile.txt"
fileExists=os.path.isfile(calibrationFilePath)
if fileExists:
calibrationFile=open(calibrationFilePath,"r")
calibrationFile.readline()
calibrationFile.readline()
calibrationFile.readline()
cellFlow=float(calibrationFile.readline())
beadFlow=float(calibrationFile.readline())
oilFlow=float(calibrationFile.readline())
calibrationFile.close()
return(cellFlow,beadFlow,oilFlow)
else:
return None
#Creating a ctypes vector to store the valve state for every MUX valve.
#Zero based indexing used. So first valve state is at index 0
valveController1_state=(c_int32*16)(0)
valveController2_state=(c_int32*16)(0)
#valveController3_state=(c_int32*8)(0)
safety_time=5.0
def convertStateVectorToString(state_vector):
finalString=""
for i in range(0,len(state_vector)):
finalString+=str(state_vector[i])
return finalString
#def set_third_controller(state_vector):
# stringVector=""
# for digit in state_vector:
# stringVector+=str(digit)
# stringVector+="\n"
# thirdController.write(stringVector.encode())
#Initializing PID controllers for flow rate control
initialize_pid_controllers()
#Defining function to print out all valve states
def print_array(int_array):
for i in range(0,len(int_array)):
print(int_array[i], end= " ")
print("")
#Defining functions to set valves to a specific state
#WARNING! Only use the safe alternatives of these functions defined below
def set_valves(Instr_ID,state_vector):
assert Instr_ID in (valve_controller1,valve_controller2)#,valve_controller3)
if Instr_ID in (valve_controller1,valve_controller2):
error=Elveflow64.MUX_Wire_Set_all_valves(Instr_ID.value, state_vector,len(state_vector))
if(error==0):
if Instr_ID is valve_controller1:
print("Valve Controller 1 State successfully changed!")
print_array(state_vector)
else:
print("Valve Controller 2 State successfully changed!")
print_array(state_vector)
else:
print("error %d :" % error)
# else:
# assert len(state_vector) is 8
# #set_third_controller(state_vector)
# print("Valve Controller 3 State successfully changed!")
# print_array(state_vector)
#Use safe alternative defined below
def close_all_valves(Instr_ID,state_vector):
for i in range(0,len(state_vector)):
state_vector[i]=0
set_valves(Instr_ID,state_vector)
def reset_state_vector(state_vector):
for i in range(0,len(state_vector)):
state_vector[i]=0
def reset_all_state_vectors():
reset_state_vector(valveController1_state)
reset_state_vector(valveController2_state)
#reset_state_vector(valveController3_state)
class valve2_2:
def __init__(self,valve_index,valve_controller_id,type_of_valve):
"""
NC is a Normally Closed Valve: you need to turn it on to open it
NO is a Normally Open Valve: you need to turn it on to close it
2_2 valve means there are two bidirectional ports in the valve.
A 3_2 valve can be converted to a 2_2 NO or 2_2 NC Valve by blocking the corresponding port on the valve
"""
assert type_of_valve in ("NC","NO")
assert type(valve_controller_id) is c_int32
assert valve_controller_id in (valve_controller1,valve_controller2)#,valve_controller3)
self.type=type_of_valve
self.index=valve_index
self.controller=valve_controller_id
if self.controller is valve_controller1:
self.state_vector=valveController1_state
elif self.controller is valve_controller2:
self.state_vector=valveController2_state
else:
self.state_vector=valveController3_state
def OPEN(self):
if self.type is "NC":
(self.state_vector)[self.index]=1
else:
(self.state_vector)[self.index]=0
def CLOSE(self):
if self.type is "NO":
(self.state_vector)[self.index]=1
else:
(self.state_vector)[self.index]=0
class valve3_2:
def __init__(self,valve_index,valve_controller_id,NC_Port,NO_Port,flip=False):
"""
A 3_2 valve means there are 3 bidirectional ports on the valve.
A 3_2 valve can be converted to a 2_2 NO or 2_2 NC Valve by blocking the corresponding port on the valve
Look for the Ports marked NO and NC on the valve if you want to do this.
"""
assert type(valve_controller_id) is c_int32
assert valve_controller_id in (valve_controller1,valve_controller2)#,valve_controller3)
assert type(NC_Port) is str and type(NO_Port) is str
self.NC_Port=NC_Port
self.NO_Port=NO_Port
self.index=valve_index
self.controller=valve_controller_id
self.flip=flip
if self.controller is valve_controller1:
self.state_vector=valveController1_state
elif self.controller is valve_controller2:
self.state_vector=valveController2_state
else:
self.state_vector=valveController3_state
def ON(self):
if self.flip is False:
(self.state_vector)[self.index]=1
else:
(self.state_vector)[self.index]=0
def OFF(self):
if self.flip is False:
(self.state_vector)[self.index]=0
else:
(self.state_vector)[self.index]=1
class time_point_valve(valve2_2):
all_time_point_valves={}
def __init__(self,valve_index,valve_controller_id,type_of_valve,time_point):
"""
A time point valve is essentially a 2_2 valve but the length of the tubing from the reservoir all the way to the valve
matters. This is because the length determines the amount of time it will take at 2000mbar to reach the manifold when using
a chip which is ~105um in height. These values need to be empirically determined depending on the length of tubing used.
"""
super().__init__(valve_index,valve_controller_id,type_of_valve)
self.time_point=time_point
time_point_valve.all_time_point_valves[time_point]=self
def get_time_point(self):
return self.time_point
def update_valve_states():
set_valves(valve_controller1,valveController1_state)
set_valves(valve_controller2,valveController2_state)
#set_valves(valve_controller3,valveController3_state)
def reset_valve_states():
close_all_valves(valve_controller1,valveController1_state)
close_all_valves(valve_controller2,valveController2_state)
#close_all_valves(valve_controller3,valveController3_state)
reset_valve_states()
#Instantiating Valve Objects
#waste_valve= valve3_2(0,valve_controller1,"Waste Tube","Sample Tube")#Zero based indexing used. First valve has index 0
cell_bypass_valve= valve3_2(9,valve_controller2,"Waste Tube","Chip",True)
bead_bypass_valve= valve3_2(15,valve_controller1,"Waste Tube","Chip",True)
bead_water_flush_valve= valve2_2(3,valve_controller1,"NC")
bead_ipa_flush_valve=valve2_2(4,valve_controller1,"NC")
bead_lysis_buffer_flush_valve= valve2_2(14,valve_controller1,"NC")
cell_ipa_flush_valve=valve2_2(0,valve_controller2,"NC")
cell_aceticAcidSDS_flush_valve=valve2_2(1,valve_controller2,"NC")
cell_air_flush_valve=valve2_2(3,valve_controller2,"NC")
cell_media_flush_valve=valve2_2(2,valve_controller2,"NC")
cell_sample_flush_valve1=valve2_2(8,valve_controller2,"NC")
cell_sample_flush_valve2=valve2_2(10,valve_controller2,"NC")
cell_sample_flush_valve3=valve2_2(11,valve_controller2,"NC")
cell_gas_vent_valve=valve2_2(7,valve_controller2,"NC")
oil_bypass_valve=valve3_2(4,valve_controller2,"Chip","Waste Tube",True)
bead_time_points_valve_list=[] #List of all Valves for the time points. Each index corresponds to the respective time point
bead_time_points_valve_list.append(time_point_valve(0,valve_controller1,"NC",1)) #First Time point added
bead_time_points_valve_list.append(time_point_valve(1,valve_controller1,"NC",2)) #Second Time point added
bead_time_points_valve_list.append(time_point_valve(2,valve_controller1,"NC",3)) #Third Time point added
bead_time_points_valve_list.append(time_point_valve(3,valve_controller1,"NC",4)) #Fourth Time point added
bead_time_points_valve_list.append(time_point_valve(4,valve_controller1,"NC",5)) #Fifth Time point added
bead_time_points_valve_list.append(time_point_valve(5,valve_controller1,"NC",6)) #Sixth Time point added
bead_time_points_valve_list.append(time_point_valve(6,valve_controller1,"NC",7)) #Seventh Time point added
bead_time_points_valve_list.append(time_point_valve(7,valve_controller1,"NC",8)) #Eighth Time point added
bead_time_points_valve_list.append(time_point_valve(8,valve_controller1,"NC",9)) #Ninth Time point added
bead_time_points_valve_list.append(time_point_valve(9,valve_controller1,"NC",10)) #Tenth Time point added
bead_time_points_valve_list.append(time_point_valve(10,valve_controller1,"NC",11)) #Eleventh Time point added
bead_time_points_valve_list.append(time_point_valve(11,valve_controller1,"NC",12)) #Twelveth Time point added
bead_time_points_valve_list.append(time_point_valve(12,valve_controller1,"NC",13)) #Thirteenth Time point added
bead_time_points_valve_list.append(time_point_valve(13,valve_controller1,"NC",14)) #Fourteenth Time point added
bead_time_points_valve_list.append(time_point_valve(14,valve_controller2,"NC",15)) #Fifteenth Time point added
bead_time_points_valve_list.append(time_point_valve(15,valve_controller2,"NC",16)) #Sixteenth Time point added
reset_valve_states()
#Defining Function for Flushing the Cell culture media with 5%C02 air mix.
def switch_bypass_off():
bead_bypass_valve.ON()
update_valve_states()
def start_vent():
stop_pressure()
reset_all_state_vectors()
bead_bypass_valve.OFF()
cell_gas_vent_valve.OPEN()
update_valve_states()
set_cell_channel_pressure(20.0)
set_stirrer_speed(100)
bypass_off_thread=threading.Timer(safety_time,switch_bypass_off)
bypass_off_thread.start()
#Slow Gas Flow through the Vent Valve
def stop_vent():
reset_valve_states()
stop_pressure()
stop_stirrer()
#Use if One of the injections fails
def failed_chip_injection_flush(duration):
stop_vent()
waste_tube1.goToCoordinates()
bad_collection_tube.goToCoordinates()
time.sleep(2.5)
print("Priming Tubing that Connects to Chip:")
oil_bypass_valve.OFF()
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.OFF()
update_valve_states()
set_cell_channel_pressure(2000.0)
set_bead_channel_pressure(2000.0)
set_oil_channel_pressure(1000.0)
time.sleep(duration)
stop_pressure()
waste_tube1.goHome()
start_vent()
def dry_cell_channel(duration):
stop_pressure()
reset_all_state_vectors()
cell_gas_vent_valve.OPEN()
update_valve_states()
set_cell_channel_pressure(2000.0)
time.sleep(duration)
reset_valve_states()
stop_pressure()
stop_stirrer()
Valve Controller 1 State successfully changed! 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 error -50405 : Valve Controller 1 State successfully changed! 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 error -50405 :
#I've defined the coordinate space pretty much completely in negative coordinates. with 0<=X<=-10000 and 0<=Y<=-8000
class robot_action():
all_time_points={}
in_tube=False
previous_yoffset=0
previous_xoffset=0
previous_y=0
previous_x=0
def __init__(self,xpos,ypos,final_xoffset,final_yoffset,timepoint=None):
self.xpos=xpos
self.ypos=ypos
self.xoffset=final_xoffset
self.yoffset=final_yoffset
self.timepoint=timepoint
if (self.timepoint is not None):
robot_action.all_time_points[self.timepoint]=self
def goToCoordinates(self):
if robot_action.in_tube is True:
plotter.write(("Y"+str(robot_action.previous_yoffset*-1)+"|X"+str(robot_action.previous_xoffset*-1)+"\n").encode())
plotter.write(("G"+str(self.xpos)+","+str(self.ypos)+"|Y"+str(self.yoffset)+"|X"+str(self.xoffset)+"\n").encode())
robot_action.in_tube=True
robot_action.previous_yoffset=self.yoffset
robot_action.previous_xoffset=self.xoffset
robot_action.previous_y=self.ypos
robot_action.previous_x=self.xpos
def goToCoordinatesFast(self):
if robot_action.in_tube is True:
plotter.write(("Y"+str(robot_action.previous_yoffset*-1)+"|X"+str(robot_action.previous_xoffset*-1)+"\n").encode())
plotter.write(("G"+str(self.xpos)+","+str(self.ypos)+"|Y"+str(self.yoffset)+"|X"+str(self.xoffset)+"\n").encode())
robot_action.in_tube=True
robot_action.previous_yoffset=self.yoffset
robot_action.previous_xoffset=self.xoffset
robot_action.previous_y=self.ypos
robot_action.previous_x=self.xpos
def goToCoordinatesSmoothly(self):
assert robot_action.previous_x==self.xpos , "Please only change the Y coordinate for this movement. Changing the X coordinate is not currently supported. "
assert self.yoffset==0 and self.xoffset==0 and robot_action.previous_xoffset==0 and robot_action.previous_yoffset==0 , "No X and Y offsets are supported for this movement both for Previous and Current Position. Please remove all offsets for starting and ending postion."
assert abs(self.ypos-robot_action.previous_y)>1000,"The final Y positions have to differ by more than 1000 steps."
if robot_action.in_tube is True:
plotter.write(("Y"+str(robot_action.previous_yoffset*-1)+"|X"+str(robot_action.previous_xoffset*-1)+"\n").encode())
plotter.write(("S"+str(self.xpos)+","+str(self.ypos)+"|Y"+str(self.yoffset)+"|X"+str(self.xoffset)+"\n").encode())
robot_action.in_tube=True
robot_action.previous_yoffset=self.yoffset
robot_action.previous_xoffset=self.xoffset
robot_action.previous_y=self.ypos
robot_action.previous_x=self.xpos
def goToCoordinatesKeepTubeUp(self):
if robot_action.in_tube is True:
plotter.write(("Y"+str(robot_action.previous_yoffset*-1)+"|X"+str(robot_action.previous_xoffset*-1)+"\n").encode())
plotter.write(("U"+str(self.xpos)+","+str(self.ypos)+"|Y"+str(self.yoffset)+"|X"+str(self.xoffset)+"\n").encode())
robot_action.in_tube=True
robot_action.previous_yoffset=self.yoffset
robot_action.previous_xoffset=self.xoffset
robot_action.previous_y=self.ypos
robot_action.previous_x=self.xpos
def getCoordinatesFromPosition():
buffer=plotter.read(plotter.inWaiting())
plotter.write("C\n".encode())
time.sleep(7.0)
buffer=plotter.read(plotter.inWaiting()).decode()
lines=buffer.split("\n")
print(lines[2])
def goHome(self):
robot_action.robotGoHome()
def robotGoHome():
if robot_action.in_tube is True:
plotter.write(("Y"+str(robot_action.previous_yoffset*-1)+"|X"+str(robot_action.previous_xoffset*-1)+"\n").encode())
plotter.write("H\n".encode())
robot_action.in_tube=False
droplet_collection.droplet_collector_go_home()
def enableRobot():
plotter.write("E\n".encode())
def disableRobot():
plotter.write("D\n".encode())
def tubeUp():
plotter.write("T1\n".encode())
def tubeDown():
plotter.write("T0\n".encode())
def manuallyMove():
plotter.write("D|T1\n".encode())
class droplet_collection():
in_tube=False
current_time_delay_from_home=1000
at_home=True
def __init__(self,servo_angle1,servo_angle2,time_taken_from_home=1000):
self.servo_angle1=servo_angle1
self.servo_angle2=servo_angle2
self.time_taken_from_home=time_taken_from_home
def goToCoordinates(self):
if droplet_collection.in_tube==False and droplet_collection.at_home==True:
droplet_collector.write(("A"+str(self.servo_angle1)+"|W"+str(self.time_taken_from_home)+"|B"+str(self.servo_angle2)+"\n").encode())
droplet_collection.in_tube=True
droplet_collection.current_time_delay_from_home=self.time_taken_from_home
droplet_collection.at_home=False
elif droplet_collection.in_tube==False and droplet_collection.at_home==False:
time_diff=abs(droplet_collection.current_time_delay_from_home-self.time_taken_from_home)
droplet_collector.write(("A"+str(self.servo_angle1)+"|W"+str(time_diff)+"|B"+str(self.servo_angle2)+"\n").encode())
droplet_collection.in_tube=True
droplet_collection.current_time_delay_from_home=self.time_taken_from_home
droplet_collection.at_home=False
else:
time_diff=abs(droplet_collection.current_time_delay_from_home-self.time_taken_from_home)
droplet_collector.write(("B0|W500|A"+str(self.servo_angle1)+"|W"+str(time_diff)+"|B"+str(self.servo_angle2)+"\n").encode())
droplet_collection.in_tube=True
droplet_collection.current_time_delay_from_home=self.time_taken_from_home
droplet_collection.at_home=False
def goToCoordinatesFast(self):
self.goToCoordinates()
def goToCoordinatesSlowly(self):
if droplet_collection.in_tube==False and droplet_collection.at_home==True:
droplet_collector.write(("X"+str(self.servo_angle1)+"|Y"+str(self.servo_angle2)+"\n").encode())
droplet_collection.in_tube=True
droplet_collection.current_time_delay_from_home=self.time_taken_from_home
droplet_collection.at_home=False
elif droplet_collection.in_tube==False and droplet_collection.at_home==False:
droplet_collector.write(("X"+str(self.servo_angle1)+"|Y"+str(self.servo_angle2)+"\n").encode())
droplet_collection.in_tube=True
droplet_collection.current_time_delay_from_home=self.time_taken_from_home
droplet_collection.at_home=False
else:
#time_diff=abs(droplet_collection.current_time_delay_from_home-self.time_taken_from_home)
droplet_collector.write(("Y0|X"+str(self.servo_angle1)+"|Y"+str(self.servo_angle2)+"\n").encode())
droplet_collection.in_tube=True
droplet_collection.current_time_delay_from_home=self.time_taken_from_home
droplet_collection.at_home=False
def goToCoordinatesKeepTubeUp(self):
if droplet_collection.in_tube==False:
droplet_collector.write(("A"+str(self.servo_angle1)+"\n").encode())
droplet_collection.in_tube=False
droplet_collection.at_home=False
droplet_collection.current_time_delay_from_home=self.time_taken_from_home
else:
droplet_collector.write(("B0|W500|A"+str(self.servo_angle1)+"\n").encode())
droplet_collection.in_tube=False
droplet_collection.at_home=False
droplet_collection.current_time_delay_from_home=self.time_taken_from_home
def goHome(self):
droplet_collection.droplet_collector_go_home()
def droplet_collector_go_home():
if droplet_collection.in_tube==False:
droplet_collector.write(("H\n").encode())
droplet_collection.in_tube=False
droplet_collection.at_home=True
else:
droplet_collector.write(("B0|W500|H\n").encode())
droplet_collection.in_tube=False
droplet_collection.at_home=True
robot_action.robotGoHome()
#Defining Various Tube Positions for the Robot:
#These need to be Calibrated.
good_collection_tube=droplet_collection(180,180,1000)
bad_collection_tube=droplet_collection(60,180,350)
waste_tube1=robot_action(-4706,-3616,1000,0)
waste_tube2=robot_action(-4738,-832,1000,0)
bead_time_point_collection_tubes=[]
bead_time_point_collection_tubes.append(robot_action(-7437,-9188,0,500,1))
bead_time_point_collection_tubes.append(robot_action(-5282,-9251,0,500,2))
bead_time_point_collection_tubes.append(robot_action(-2928,-9118,0,500,3))
bead_time_point_collection_tubes.append(robot_action(-727,-9245,0,500,4))
bead_time_point_collection_tubes.append(robot_action(-7433,-11267,0,500,5))
bead_time_point_collection_tubes.append(robot_action(-5232,-11292,0,500,6))
bead_time_point_collection_tubes.append(robot_action(-2939,-11261,0,500,7))
bead_time_point_collection_tubes.append(robot_action(-731,-11296,0,500,8))
bead_time_point_collection_tubes.append(robot_action(-7453,-13410,0,500,9))
bead_time_point_collection_tubes.append(robot_action(-5168,-13342,0,500,10))
bead_time_point_collection_tubes.append(robot_action(-2884,-13375,0,500,11))
bead_time_point_collection_tubes.append(robot_action(-733,-13405,0,500,12))
bead_time_point_collection_tubes.append(robot_action(-7485,-15491,0,500,13))
bead_time_point_collection_tubes.append(robot_action(-5186,-15485,0,500,14))
bead_time_point_collection_tubes.append(robot_action(-3019,-15484,0,500,15))
bead_time_point_collection_tubes.append(robot_action(-744,-15516,0,500,16))
def test_robot():
waste_tube1.goToCoordinates()
time.sleep(5.0)
good_collection_tube.goToCoordinates()
for tube in bead_time_point_collection_tubes:
tube.goToCoordinates()
time.sleep(5.0)
waste_tube1.goToCoordinates()
time.sleep(10.0)
waste_tube2.goToCoordinates()
time.sleep(10.0)
bad_collection_tube.goToCoordinates()
time.sleep(10.0)
good_collection_tube.goToCoordinates()
time.sleep(10.0)
robot_action.robotGoHome()
test_robot()
def test_vortices():
time.sleep(10.0)
start_bead_vortex()
time.sleep(10.0)
stop_bead_vortex()
start_bead_vortex2()
time.sleep(10.0)
stop_bead_vortex2()
time.sleep(10.0)
start_both_vortices()
time.sleep(10.0)
stop_both_vortices()
test_vortices()
def make_some_noise():
print("Noise Noise")
pygame.mixer.init()
pygame.mixer.music.set_volume(1.0)
soundlist=[os.getcwd()+"\\Fire_pager-jason-1283464858.mp3"]
for sound in soundlist:
pygame.mixer.music.load(sound)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
continue
def collection_tube_message():
print("Change the Collection Tube before you start Collecting Samples")
pygame.mixer.init()
pygame.mixer.music.set_volume(1.0)
soundlist=[os.getcwd()+"\\ChangeTheCollectionTube.mp3"]
for sound in soundlist:
pygame.mixer.music.load(sound)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
continue
def change_collection_tube_warning():
warningThread=threading.Thread(target=collection_tube_message)
warningThread.start()
#Function executes a specific schedule
current_count=0
def start_schedule(schedule,duration,var=False):
"""
This function is executes a single schedule. Its called through the execute_schedules function defined below. The basic idea behind
this function is that is divided code execution between two parallely running threads. The first threads controls the pressure control
and flow measurements, however it needs instructions from the schedule to change anything. This thread executes with any schedule.
I've defined a lot of functions that provide different methods of flow control above. You can also control valves, and the stirrer
through these methods. In addition the record_data parameter has been set to False. You can set this to True anytime in a given schedule
and see the pressure and flow rate data for that schedule. This is very useful for troubleshooting. You can then use the plot_flow_data()
function to plot the data collected for that schedule. A dataset is created everytime you run the execute_schedules function.
Feel free to modify the code if you want to output the data to a image file or store the data in a table using pandas.
"""
stop_vent()
global record_data,current_count
record_data=False
current_count+=1
recordingAndPressureControlThread=threading.Thread(target=record_flow_data,args=[duration])
recordingAndPressureControlThread.start()
if var is False:
schedulingThread=threading.Thread(target=schedule)
else:
schedulingThread=threading.Thread(target=schedule,args=[var])
schedulingThread.start()
def scheduler_shutdown():
""" Shuts down the scheduler. Called from the execute_schedules function defined below.
"""
scheduler.remove_all_jobs()
scheduler.shutdown()
make_some_noise()
print("Scheduler has been Shutdown! \nIf not complete, current schedule will continue executing till it finishes.")
#Stops all running processes after current scheduler stops executing.
def emergency_stop():
try:
scheduler.remove_all_jobs()
scheduler.shutdown()
shutdown_scheduler_thread.cancel()
print("Emergency Scheduler shutdown successful!")
except SchedulerNotRunningError:
print("Scheduler has already stopped!")
#Function creates a timeline for execution of various schedules in the scheduleList
def execute_schedules(scheduleList,gap_between_iterations,fixed_interval=False):
"""
You can execute a list of schedules with this function. An example would be scheduleList=[(schedule1,2,70.0),
(schedule2,3,60)]
execute_schedules(scheduleList,15.0). This will execute the functions schedule1, and schedule2 2 times and 3 times respectively.
The gap between the end of one iteration and the start of the next will be 15.0 seconds. If you want to execute all iterations
at regular intervals {for example every 60seconds}, then set the fixed_interval input parameter to True. If you do this then
the gap between the start of each iteration will be the input varaible gap_between_iterations. Make sure the execution time of
each iteration is less then the gap+2*safety_time. Otherwise the function will throw an assertion error.
I have not included a condition to check this but its also important that you check if the execution duration for a schedule is the
same duration you provide in the scheduleList. Please check this manually for now. I might include updated check conditions for
this in future implementations.
"""
initialize_pid_controllers()
#Initializing lists for storing pressure and flow measurement values
global cellChannelPressureMeasurements,oilChannelPressureMeasurements,beadChannelPressureMeasurements
global cellChannelFlowMeasurements,oilChannelFlowMeasurements,beadChannelFlowMeasurements
cellChannelPressureMeasurements=[]
oilChannelPressureMeasurements=[]
beadChannelPressureMeasurements=[]
cellChannelFlowMeasurements=[]
oilChannelFlowMeasurements=[]
beadChannelFlowMeasurements=[]
if(gap_between_iterations<2*safety_time):
gap_between_iterations=2*safety_time
global scheduler,current_count
current_count=0
scheduler=BackgroundScheduler()
scheduler.start()
#First iteration will execute after 5 seconds
current_time=datetime.now()+timedelta(seconds=5)
end_time=current_time
execution_time=current_time
firstExec=True
for execution_information in scheduleList:
assert type(execution_information) is tuple
extra_var=0
if len(execution_information) is 3:
schedule,numberofIterations,duration=execution_information
elif len(execution_information) is 4:
schedule,numberofIterations,duration,var=execution_information
extra_var=1
if fixed_interval is True:
if gap_between_iterations+2*safety_time<duration:
scheduler.remove_all_jobs()
scheduler.shutdown()
assert gap_between_iterations+2*safety_time<duration,"Execution duration for a schedule is longer than gap between iterations"
for i in range(0,numberofIterations):
if fixed_interval is False and firstExec is False:
end_time+=timedelta(seconds=duration)
if firstExec is True:
execution_time=end_time
firstExec=False
end_time+=timedelta(seconds=duration)
else:
execution_time=end_time-timedelta(seconds=duration)
if extra_var is 1:
scheduler.add_job(start_schedule,"date",run_date=execution_time,misfire_grace_time=15,args=[schedule,duration,var])
else:
scheduler.add_job(start_schedule,"date",run_date=execution_time,misfire_grace_time=15,args=[schedule,duration])
end_time+=timedelta(seconds=gap_between_iterations)
shutdown_time=end_time-timedelta(seconds=gap_between_iterations-1)
global shutdown_scheduler_thread
shutdown_scheduler_thread=threading.Timer((shutdown_time-datetime.now()).total_seconds(),scheduler_shutdown)
shutdown_scheduler_thread.start()
#This function makes it easy to write a schedule with complex timing for each channel.
#I can think about the timing for each channel independent of the others and then merge the schedules for the channels easily
def getMergedExecutionSchedule(execution_list):
exec_df=pd.DataFrame(execution_list,columns=["Exec_Text","TimeStamps"])
exec_df=exec_df.sort_values(by="TimeStamps")
exec_text=""
for i in range(0,len(exec_df.index)-1):
text,time=exec_df.iloc[i]
time=time.to_pydatetime()
nextText,nextTime=exec_df.iloc[i+1]
nextTime=nextTime.to_pydatetime()
diff=nextTime-time
sec_delay=diff.total_seconds()
exec_text+=text
exec_text+=("time.sleep(%f)\n"%sec_delay)
text,time=exec_df.iloc[len(exec_df.index)-1]
exec_text+=text
return exec_text
Schedules are small lego blogs of machine operation for completing several machine tasks.
def cell_clean():
cell_media_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(20.0)
def prime_outlet_tubing():
waste_tube1.goToCoordinates()
bad_collection_tube.goToCoordinates()
time.sleep(2.5)
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(60.0)
def cell_bypass_flush():
set_flush_pressures(2000.0,0.0,0.0)
cell_media_flush_valve.OPEN()
cell_bypass_valve.ON()
update_valve_states()
time.sleep(60.0)
def bead_bypass_flush():
waste_tube1.goToCoordinates()
time.sleep(2.5)
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(60.0)
def chip_test():
global record_data
record_data=True
print("Testing Chip:")
oil_bypass_valve.OFF()
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
print(get_cell_channel_density())
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
time.sleep(5.0)
set_flush_pressures(300.0,300.0,0.0)
time.sleep(60.0)
stop_flushing_all_channels()
time.sleep(5.0)
record_data=False
def cell_channel_flush():
global record_data
record_data=True
print("Cell Channel Flush:")
oil_bypass_valve.ON()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
print(get_cell_channel_density())
#set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
for i in range(0,6):
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(2000.0,0.0,0.0)
record_data=False
def cell_and_oil_channel_flush():
print("Cell Channel Flush:")
oil_bypass_valve.ON()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
set_bead_channel_scaling_factor(digitalDistilledWaterScalingFactor)
set_flush_pressures(2000.0,0.0,1000.0)
time.sleep(20.0)
def bead_priming():
set_flush_pressures(0.0,2000.0,0.0)
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
time.sleep(5.0)
bead_lysis_buffer_flush_valve.CLOSE()
for time_point in bead_time_points_valve_list:
time_point.OPEN()
update_valve_states()
time.sleep(5.0)
time_point.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
time.sleep(5.0)
bead_lysis_buffer_flush_valve.CLOSE()
stop_flushing_all_channels()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
#Pressures are going to be off because no chip is connected. Have to rely on flow control to get the correct injection timing.
def bead_injection_only_priming():
setNewPIDKis(0.75,0.1,1.5)
outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
set_flow_rates(0.0,875.0,0.0)
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
time.sleep(60.0)
bead_lysis_buffer_flush_valve.CLOSE()
for time_point in bead_time_points_valve_list:
time_point.OPEN()
update_valve_states()
time.sleep(time_point.get_time_to_manifold())
time_point.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
time.sleep(60.0)
bead_lysis_buffer_flush_valve.CLOSE()
set_flow_rates(0.0,0.0,0.0)
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
def tubing_clean():
set_flush_pressures(0.0,2000.0,0.0)
#outlet_bypass_valve.ON()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.OFF()
bead_air_flush_valve.CLOSE()
update_valve_states()
time.sleep(20.0)
bead_air_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
time.sleep(20.0)
bead_lysis_buffer_flush_valve.OPEN()
bead_air_flush_valve.CLOSE()
update_valve_states()
time.sleep(20.0)
def prime_the_cell_channel():
cell_sample_flush_valve1.OPEN()
cell_sample_flush_valve2.OPEN()
cell_sample_flush_valve3.OPEN()
cell_media_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(60.0) #You can change this time by specifying a different flush period
def prime_the_chip_tubing():
#Make sure the chip is not connected when you run this protocol. This is necessary everytime you change the liquid or chip.
#Run this to make sure there is no backflow and everything ramps up smoothly when priming the chip. Make sure you take all
#the tubing and but in a 50ml bottle cap or something to collect the run-off and prevent it from getting into the microscope.
waste_tube1.goToCoordinates()
time.sleep(2.5)
print("Priming Tubing that Connects to Chip:")
oil_bypass_valve.OFF()
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.OFF()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
set_bead_channel_scaling_factor(scalingFactor60ul)
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(60.0) #You can change this time by specifying a different flush period for the chip.
def prime_the_chip():
global total_waste_collections
total_waste_collections+=1
waste_tube=waste_tube1
if total_waste_collections>8:
waste_tube=waste_tube2
robot_action.enableRobot()
waste_tube.goToCoordinates()
setNewPIDKis(1.0,1.0,1.0)
oil_val=200.0
bead_val=55.0
cell_val=15.0
global record_data
global store_chip_values
store_chip_values=True
record_data=True
storedCellPress,storedBeadPress,storedOilPress=get_chip_stored_pressure_calibration_values(False)
print("Testing Chip:")
set_bead_channel_scaling_factor(scalingFactor60ul)
#outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(2.5)
for i in range(0,4):
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(2000.0,2000.0,0.0)
print(get_cell_channel_density())
print(get_oil_channel_density())
set_stirrer_speed(300)
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(10.0)
cell_media_flush_valve.OPEN()
cell_bypass_valve.ON()
update_valve_states()
time.sleep(16.75)
bead_bypass_valve.ON()
update_valve_states()
time.sleep(2.25)
set_flush_pressures(2000.0,2000.0,1000.0)
bead_bypass_valve.OFF()
cell_bypass_valve.OFF()
oil_bypass_valve.OFF()
update_valve_states()
#Controlling the Rocket engine for Soft landing
time.sleep(20.0)
set_flush_pressures(2.5*storedCellPress,0.0,storedOilPress)
bead_bypass_valve.ON()
cell_bypass_valve.OFF()
update_valve_states()
time.sleep(2.0)
set_flush_pressures(0.0,0.0,2000.00)
time.sleep(6.0)
set_stirrer_speed(0)
bead_bypass_valve.ON()
cell_bypass_valve.ON()
oil_bypass_valve.ON()
bead_lysis_buffer_flush_valve.OPEN()
cell_media_flush_valve.OPEN()
update_valve_states()
stop_flushing_all_channels()
time.sleep(7.5)
for i in range(0,3):
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
bad_collection_tube.goToCoordinates()
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
time.sleep(5.0)
bead_lysis_buffer_flush_valve.OPEN()
cell_bypass_valve.ON()
bead_bypass_valve.OFF()
oil_bypass_valve.ON()
update_valve_states()
set_flush_pressures(2.5*storedCellPress,storedBeadPress,storedOilPress) #Empirically Determined. Can be obtained before each run as part of a "Calibration run"
time.sleep(1.0)
oil_bypass_valve.OFF()
update_valve_states()
time.sleep(1.0)
cell_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(2.5*storedCellPress,storedBeadPress,storedOilPress) #Leave it like this, I don't think it can get much better than this
time.sleep(3.0)
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress)
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(5.0)
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
pidforOilChannel.restart_flow(oil_val,1.0,oilPress)
pidforCellChannel.restart_flow(cell_val,1.0,cellPress)
pidforBeadChannel.restart_flow(bead_val,0.3,beadPress)
#Add another 7-8 seconds.
time.sleep(18.0) #Empirically determine this to get the best time for when the droplets start emerging from the tubing.
good_collection_tube.goToCoordinatesFast()
time.sleep(45.0)
#Cleaning out any cells trapped in the Cell Channel
#before flushing again this should reduce cellular debris getting to the chip
oil_bypass_valve.OFF()
cell_bypass_valve.OFF()
bead_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,0.0,2000.0) #Oil starts emerging about 9-10 seconds from here.
#This oil is harmless so no problems collecting it I think.
time.sleep(5.0)
cell_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,0.0,1000.0)
time.sleep(8.0)
stop_flushing_all_channels()
time.sleep(2.0)
waste_tube.goToCoordinates()
time.sleep(2.0)
bead_bypass_valve.ON()
cell_bypass_valve.ON()
oil_bypass_valve.ON()
update_valve_states()
#Cleaning out any remaining Cells or Beads stuck in the tubing.
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(20.0)
#Cleaning out remaining Cells and Beads through the Chip and injection loops/tubing.
cell_media_flush_valve.OPEN()
cell_bypass_valve.OFF()
oil_bypass_valve.OFF()
bead_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(20.0)
oil_bypass_valve.ON()
update_valve_states()
stop_flushing_all_channels()
time.sleep(1.5)
#Cleaning the tubing going into the chip through the bypass valves
for i in range(0,5):
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(18.5)
stop_flushing_all_channels()
time.sleep(1.5)
#Latest 9/27/22
def get_sample_from_multiple_cell_tubes_ficoll(time_and_cell_tuple):
time_point_number,cell_sample_flush_valve_number=time_and_cell_tuple
print("Time point is : "+str(time_point_number))
print("Cell Sample valve number is: "+str(cell_sample_flush_valve_number))
cell_sample_flush_valve=cell_sample_flush_valve1
if(cell_sample_flush_valve_number is 2):
cell_sample_flush_valve=cell_sample_flush_valve2
if(cell_sample_flush_valve_number is 3):
cell_sample_flush_valve=cell_sample_flush_valve3
global total_waste_collections
total_waste_collections+=1
waste_tube=waste_tube1
if total_waste_collections>8:
waste_tube=waste_tube2
time_point=time_point_valve.all_time_point_valves[time_point_number]
bead_tube=robot_action.all_time_points[time_point_number]
robot_action.enableRobot()
waste_tube.goToCoordinates()
bad_collection_tube.goToCoordinatesKeepTubeUp()
setNewPIDKis(1.0,1.0,1.0)
oil_val=200.0
bead_val=55.0
cell_val=55.0
global record_data
global store_chip_values
store_chip_values=True
record_data=True
storedCellPress,storedBeadPress,storedOilPress=get_chip_stored_pressure_calibration_values(False)
print("Testing Chip:")
set_bead_channel_scaling_factor(scalingFactor55ulFicoll)
#outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(2.5)
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(12.5)
print(get_cell_channel_density())
print(get_oil_channel_density())
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.OPEN()
oil_bypass_valve.OFF()
update_valve_states()
#Mini-Priming to make chip change successfully
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(10.0)
set_flush_pressures(storedCellPress,0.0,storedOilPress)
bead_bypass_valve.ON()
cell_bypass_valve.OFF()
update_valve_states()
time.sleep(2.0)
set_flush_pressures(0.0,0.0,2000.00)
time.sleep(4.0)
oil_bypass_valve.ON()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
stop_flushing_all_channels()
time.sleep(2.5)
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
stop_flushing_all_channels()
time.sleep(2.5)
bead_lysis_buffer_flush_valve.OPEN()
cell_bypass_valve.ON()
bead_bypass_valve.OFF()
oil_bypass_valve.ON()
update_valve_states()
bead_tube.goToCoordinates()
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress)
time.sleep(1.0)
oil_bypass_valve.OFF()
update_valve_states()
time.sleep(1.0)
cell_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress)
time.sleep(3.0)
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress)
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(5.0)
#Start stirring things up
set_stirrer_speed(100)
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
pidforOilChannel.restart_flow(oil_val,1.0,oilPress)
pidforCellChannel.restart_flow(cell_val,1.0,cellPress)
pidforBeadChannel.restart_flow(bead_val,1.0,beadPress)
time.sleep(11.0)
print(get_cell_channel_density())
print(get_oil_channel_density())
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.OPEN()
oil_bypass_valve.ON()
update_valve_states()
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(5.0)
if time_point_number<9:
start_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
start_bead_vortex2()
cell_media_flush_valve.CLOSE()
cell_sample_flush_valve.OPEN()
cell_bypass_valve.ON()
update_valve_states()
time.sleep(16.75)
time_point.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
bead_bypass_valve.ON()
update_valve_states()
time.sleep(7.0) #Doubled this time.
set_flush_pressures(2000.0,2000.0,1000.0)
bead_bypass_valve.OFF()
cell_bypass_valve.OFF()
oil_bypass_valve.OFF()
update_valve_states()
#Controlling the Rocket engine for Soft landing
time.sleep(35.0)#Increased this
set_flush_pressures(storedCellPress,0.0,storedOilPress)
bead_bypass_valve.ON()
cell_bypass_valve.OFF()
update_valve_states()
time.sleep(2.0)
set_flush_pressures(0.0,0.0,2000.00)
time.sleep(4.0)
#Let it keep stirring not much harm here.
#set_stirrer_speed(0)
if time_point_number<9:
stop_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
stop_bead_vortex2()
bead_bypass_valve.ON()
cell_bypass_valve.ON()
oil_bypass_valve.ON()
time_point.CLOSE()
cell_sample_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
cell_media_flush_valve.OPEN()
update_valve_states()
stop_flushing_all_channels()
time.sleep(5.0)
bead_bypass_valve.OFF()
update_valve_states()
#bead_tube.goToCoordinates()
time.sleep(2.5)
bead_bypass_valve.ON()
update_valve_states()
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(7.5)
set_flush_pressures(storedCellPress,1.5*storedBeadPress,storedOilPress)
bead_bypass_valve.ON()
cell_bypass_valve.ON()
oil_bypass_valve.ON()
update_valve_states()
time.sleep(15.0)
#set_flush_pressures(2000.0,2000.0,0.0)
#time.sleep(2.5)
#stop_flushing_all_channels()
#bad_collection_tube.goToCoordinatesKeepTubeUp()
#bad_collection_tube.goToCoordinates()
#bead_bypass_valve.OFF()
#bead_lysis_buffer_flush_valve.OPEN()
#update_valve_states()
#bead_lysis_buffer_flush_valve.OPEN()
cell_bypass_valve.ON()
bead_bypass_valve.OFF()
oil_bypass_valve.ON()
update_valve_states()#Droplets start emerging 22 seconds from here. Approox. To this add some additional stabilization time. In this case 13-14 seconds.
set_flush_pressures(storedCellPress,1.5*storedBeadPress,storedOilPress) #Empirically Determined. Can be obtained before each run as part of a "Calibration run"
time.sleep(1.0)
oil_bypass_valve.OFF()
update_valve_states()
time.sleep(1.0)
cell_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress) #Leave it like this, I don't think it can get much better than this
time.sleep(3.0)
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress)
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(5.0)
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
pidforOilChannel.restart_flow(oil_val,1.0,oilPress)
pidforCellChannel.restart_flow(cell_val,1.0,cellPress)
pidforBeadChannel.restart_flow(bead_val,1.0,beadPress)
time.sleep(24.0) #Empirically determine this to get the best time for when the droplets start emerging from the tubing.
good_collection_tube.goToCoordinatesSlowly()
#good_collection_tube.goToCoordinates()
time.sleep(50.0)
#Cleaning out any cells trapped in the Cell Channel
#before flushing again this should reduce cellular debris getting to the chip
oil_bypass_valve.OFF()
cell_bypass_valve.OFF()
bead_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,0.0,2000.0) #Oil starts emerging about 9-10 seconds from here.
#This oil is harmless so no problems collecting it I think.
time.sleep(5.0)
cell_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,0.0,1000.0)
time.sleep(12.0)#Increasing this for now. More oil should help flow more beads down where they belong.
stop_flushing_all_channels()
time.sleep(2.0)
bad_collection_tube.goToCoordinates()
time.sleep(2.0)
bead_bypass_valve.ON()
cell_bypass_valve.ON()
oil_bypass_valve.ON()
update_valve_states()
#Cleaning out any remaining Cells or Beads stuck in the tubing.
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(20.0)
#Cleaning out remaining Cells and Beads through the Chip and injection loops/tubing.
cell_media_flush_valve.OPEN()
cell_bypass_valve.OFF()
oil_bypass_valve.OFF()
bead_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(20.0)
oil_bypass_valve.ON()
update_valve_states()
stop_flushing_all_channels()
time.sleep(1.5)
#Cleaning the tubing going into the chip through the bypass valves
for i in range(0,5):
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(18.5)
stop_flushing_all_channels()
time.sleep(1.5)
def get_sample_cells_only(time_and_cell_tuple):
time_point_number,cell_sample_flush_valve_number=time_and_cell_tuple
print("Time point is : "+str(time_point_number))
print("Cell Sample valve number is: "+str(cell_sample_flush_valve_number))
cell_sample_flush_valve=cell_sample_flush_valve1
if(cell_sample_flush_valve_number is 2):
cell_sample_flush_valve=cell_sample_flush_valve2
if(cell_sample_flush_valve_number is 3):
cell_sample_flush_valve=cell_sample_flush_valve3
global total_waste_collections
total_waste_collections+=1
waste_tube=waste_tube1
if total_waste_collections>8:
waste_tube=waste_tube1
time_point=time_point_valve.all_time_point_valves[time_point_number]
bead_tube=robot_action.all_time_points[time_point_number]
robot_action.enableRobot()
waste_tube.goToCoordinates()
good_collection_tube.goToCoordinates()
print(get_cell_channel_density())
global record_data
record_data=True
set_bead_channel_scaling_factor(scalingFactor55ulFicoll)
set_stirrer_speed(100)
time.sleep(3.0)
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(15.0)
cell_media_flush_valve.CLOSE()
cell_sample_flush_valve.OPEN()
update_valve_states()
time.sleep(20.0)
cell_bypass_valve.ON()
update_valve_states()
bead_tube.goToCoordinates()
#stop_flushing_all_channels()
time.sleep(5.0)
set_flush_pressures(2000.0,0.0,0.0)
cell_bypass_valve.OFF()
cell_sample_flush_valve.OPEN()
update_valve_states()
print(get_cell_channel_density())
time.sleep(5.0)
cell_bypass_valve.ON()
cell_sample_flush_valve.CLOSE()
cell_media_flush_valve.OPEN()
update_valve_states()
waste_tube.goToCoordinates()
time.sleep(5.0)
cell_bypass_valve.OFF()
update_valve_states()
time.sleep(10.0)
def get_sample_from_multiple_cell_tubes(time_and_cell_tuple):
time_point_number,cell_sample_flush_valve_number=time_and_cell_tuple
print("Time point is : "+str(time_point_number))
print("Cell Sample valve number is: "+str(cell_sample_flush_valve_number))
cell_sample_flush_valve=cell_sample_flush_valve1
if(cell_sample_flush_valve_number is 2):
cell_sample_flush_valve=cell_sample_flush_valve2
if(cell_sample_flush_valve_number is 3):
cell_sample_flush_valve=cell_sample_flush_valve3
global total_waste_collections
total_waste_collections+=1
waste_tube=waste_tube1
if total_waste_collections>8:
waste_tube=waste_tube2
time_point=time_point_valve.all_time_point_valves[time_point_number]
bead_tube=robot_action.all_time_points[time_point_number]
robot_action.enableRobot()
waste_tube.goToCoordinates()
setNewPIDKis(1.0,1.0,1.0)
oil_val=200.0
bead_val=55.0
cell_val=55.0
global record_data
global store_chip_values
store_chip_values=True
record_data=True
storedCellPress,storedBeadPress,storedOilPress=get_chip_stored_pressure_calibration_values(False)
print("Testing Chip:")
set_bead_channel_scaling_factor(scalingFactor60ul)
#outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(2.5)
for i in range(0,4):
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
print(get_cell_channel_density())
print(get_oil_channel_density())
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.OPEN()
oil_bypass_valve.OFF()
update_valve_states()
#Mini-Priming to make chip change successfully
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(10.0)
set_flush_pressures(storedCellPress,0.0,storedOilPress)
bead_bypass_valve.ON()
cell_bypass_valve.OFF()
update_valve_states()
time.sleep(2.0)
set_flush_pressures(0.0,0.0,2000.00)
time.sleep(4.0)
oil_bypass_valve.ON()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
stop_flushing_all_channels()
time.sleep(2.5)
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
stop_flushing_all_channels()
time.sleep(2.5)
bead_lysis_buffer_flush_valve.OPEN()
cell_bypass_valve.ON()
bead_bypass_valve.OFF()
oil_bypass_valve.ON()
update_valve_states()
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress)
time.sleep(1.0)
oil_bypass_valve.OFF()
update_valve_states()
time.sleep(1.0)
cell_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress)
time.sleep(3.0)
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress)
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(5.0)
#Start stirring things up
set_stirrer_speed(300)
if time_point_number<9:
start_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
start_bead_vortex2()
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
pidforOilChannel.restart_flow(oil_val,1.0,oilPress)
pidforCellChannel.restart_flow(cell_val,1.0,cellPress)
pidforBeadChannel.restart_flow(bead_val,1.0,beadPress)
time.sleep(11.0)
print(get_cell_channel_density())
print(get_oil_channel_density())
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.OPEN()
oil_bypass_valve.ON()
update_valve_states()
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(5.0)
cell_media_flush_valve.CLOSE()
cell_sample_flush_valve.OPEN()
cell_bypass_valve.ON()
update_valve_states()
time.sleep(16.75)
time_point.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
bead_bypass_valve.ON()
update_valve_states()
time.sleep(2.25)
set_flush_pressures(2000.0,2000.0,1000.0)
bead_bypass_valve.OFF()
cell_bypass_valve.OFF()
oil_bypass_valve.OFF()
update_valve_states()
#Controlling the Rocket engine for Soft landing
time.sleep(20.0)
set_flush_pressures(storedCellPress,0.0,storedOilPress)
bead_bypass_valve.ON()
cell_bypass_valve.OFF()
update_valve_states()
time.sleep(2.0)
set_flush_pressures(0.0,0.0,2000.00)
time.sleep(4.0)
set_stirrer_speed(0)
if time_point_number<9:
stop_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
stop_bead_vortex2()
bead_bypass_valve.ON()
cell_bypass_valve.ON()
oil_bypass_valve.ON()
time_point.CLOSE()
cell_sample_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
cell_media_flush_valve.OPEN()
update_valve_states()
stop_flushing_all_channels()
time.sleep(5.0)
bead_bypass_valve.OFF()
update_valve_states()
bead_tube.goToCoordinates()
time.sleep(2.5)
bead_bypass_valve.ON()
update_valve_states()
for i in range(0,3):
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
bad_collection_tube.goToCoordinatesKeepTubeUp()
#bad_collection_tube.goToCoordinates()
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
time.sleep(5.0)
bead_lysis_buffer_flush_valve.OPEN()
cell_bypass_valve.ON()
bead_bypass_valve.OFF()
oil_bypass_valve.ON()
update_valve_states()#Droplets start emerging 22 seconds from here. Approox. To this add some additional stabilization time. In this case 13-14 seconds.
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress) #Empirically Determined. Can be obtained before each run as part of a "Calibration run"
time.sleep(1.0)
oil_bypass_valve.OFF()
update_valve_states()
time.sleep(1.0)
cell_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress) #Leave it like this, I don't think it can get much better than this
time.sleep(3.0)
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress)
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(5.0)
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
pidforOilChannel.restart_flow(oil_val,1.0,oilPress)
pidforCellChannel.restart_flow(cell_val,1.0,cellPress)
pidforBeadChannel.restart_flow(bead_val,1.0,beadPress)
time.sleep(24.0) #Empirically determine this to get the best time for when the droplets start emerging from the tubing.
good_collection_tube.goToCoordinatesSmoothly()
#good_collection_tube.goToCoordinates()
time.sleep(50.0)
#Cleaning out any cells trapped in the Cell Channel
#before flushing again this should reduce cellular debris getting to the chip
oil_bypass_valve.OFF()
cell_bypass_valve.OFF()
bead_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,0.0,2000.0) #Oil starts emerging about 9-10 seconds from here.
#This oil is harmless so no problems collecting it I think.
time.sleep(5.0)
cell_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,0.0,1000.0)
time.sleep(12.0)#Increasing this for now. More oil should help flow more beads down where they belong.
stop_flushing_all_channels()
time.sleep(2.0)
waste_tube.goToCoordinates()
time.sleep(2.0)
bead_bypass_valve.ON()
cell_bypass_valve.ON()
oil_bypass_valve.ON()
update_valve_states()
#Cleaning out any remaining Cells or Beads stuck in the tubing.
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(20.0)
#Cleaning out remaining Cells and Beads through the Chip and injection loops/tubing.
cell_media_flush_valve.OPEN()
cell_bypass_valve.OFF()
oil_bypass_valve.OFF()
bead_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(20.0)
oil_bypass_valve.ON()
update_valve_states()
stop_flushing_all_channels()
time.sleep(1.5)
#Cleaning the tubing going into the chip through the bypass valves
for i in range(0,5):
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(18.5)
stop_flushing_all_channels()
time.sleep(1.5)
def get_sample(time_point_number):
global total_waste_collections
total_waste_collections+=1
waste_tube=waste_tube1
if total_waste_collections>8:
waste_tube=waste_tube2
time_point=time_point_valve.all_time_point_valves[time_point_number]
bead_tube=robot_action.all_time_points[time_point_number]
robot_action.enableRobot()
waste_tube.goToCoordinates()
setNewPIDKis(1.0,1.0,1.0)
oil_val=200.0
bead_val=55.0
cell_val=15.0
global record_data
global store_chip_values
store_chip_values=True
record_data=True
storedCellPress,storedBeadPress,storedOilPress=get_chip_stored_pressure_calibration_values(False)
print("Testing Chip:")
set_bead_channel_scaling_factor(scalingFactor55ulFicoll)
#outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(2.5)
for i in range(0,4):
set_flush_pressures(2000.0,2000.0,1000.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(2000.0,2000.0,0.0)
print(get_cell_channel_density())
print(get_oil_channel_density())
if time_point_number<9:
start_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
start_bead_vortex2()
set_stirrer_speed(300)
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(10.0)
cell_media_flush_valve.CLOSE()
cell_sample_flush_valve1.OPEN()
cell_bypass_valve.ON()
update_valve_states()
time.sleep(16.75)
time_point.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
bead_bypass_valve.ON()
update_valve_states()
time.sleep(2.25)
bead_bypass_valve.OFF()
cell_bypass_valve.OFF()
update_valve_states()
#Controlling the Rocket engine for Soft landing
time.sleep(18.0) #-2 seconds here
set_flush_pressures(2000.0,2000.0,storedOilPress)
oil_bypass_valve.OFF()
update_valve_states()
time.sleep(2.00) #Add 2 seconds here.
set_flush_pressures(2.5*storedCellPress,0.0,storedOilPress)
bead_bypass_valve.ON()
cell_bypass_valve.OFF()
update_valve_states()
time.sleep(2.0)
set_flush_pressures(0.0,0.0,2000.00)
time.sleep(6.0)
set_stirrer_speed(0)
if time_point_number<9:
stop_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
stop_bead_vortex2()
bead_bypass_valve.ON()
cell_bypass_valve.ON()
oil_bypass_valve.ON()
time_point.CLOSE()
cell_sample_flush_valve1.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
cell_media_flush_valve.OPEN()
update_valve_states()
stop_flushing_all_channels()
time.sleep(2.5)
bead_tube.goToCoordinates()
time.sleep(2.5)
for i in range(0,3):
set_flush_pressures(2000.0,2000.0,200.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(2000.0,2000.0,200.0)
time.sleep(2.5)
stop_flushing_all_channels()
bad_collection_tube.goToCoordinates()
time.sleep(2.5)
#Droplets start emerging 27 seconds after this
#This will make the oil flow stable before we turn the bead channel and the outlet valve ON
bead_lysis_buffer_flush_valve.CLOSE()
cell_bypass_valve.OFF()
bead_bypass_valve.ON()
oil_bypass_valve.OFF()
#outlet_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(2.5*storedCellPress,storedBeadPress,storedOilPress) #Empirically Determined. Can be obtained before each run as part of a "Calibration run"
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(10.0) #Keep this 10 to minimize cell loss.
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.OPEN()#Takes 19 seconds for droplets to emerge from here.
update_valve_states()
set_flush_pressures(storedCellPress,storedBeadPress,storedOilPress) #Leave it like this, I don't think it can get much better than this
time.sleep(5.0)
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
pidforOilChannel.restart_flow(oil_val,1.0,oilPress)
pidforCellChannel.restart_flow(cell_val,1.0,cellPress)
pidforBeadChannel.restart_flow(bead_val,0.3,beadPress)
#Add another 10 seconds to this to make sure you don't capture those shitty droplets.
time.sleep(23.0) #Empirically determine this to get the best time for when the droplets start emerging from the tubing.
good_collection_tube.goToCoordinatesFast()
time.sleep(40.0)
#outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.CLOSE()#Venting inside the schedule duration
cell_sample_flush_valve1.CLOSE()
cell_gas_vent_valve.OPEN()
update_valve_states()
set_flush_pressures(200.0,600.0,0.0)
#At this flow rate it takes 25 seconds for water to emerge after droplets. I think this is perfect
time.sleep(15.0)#Empirically determine this to find the best time for when all the droplets have been collected.
stop_flushing_all_channels()
time.sleep(2.0)
waste_tube.goToCoordinates()
time.sleep(2.0)
cell_media_flush_valve.OPEN()#Stop Venting
cell_sample_flush_valve1.CLOSE()
cell_gas_vent_valve.CLOSE()
cell_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(12.0)
stop_flushing_all_channels()
time.sleep(1.5)
#Cleaning the tubing going into the chip through the bypass valves
for i in range(0,6):
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(18.5)
stop_flushing_all_channels()
time.sleep(1.5)
bead_bypass_valve.ON()
cell_bypass_valve.ON()
update_valve_states()
#Cleaning out any remaining Cells or Beads stuck in the tubing.
for i in range(0,4):
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
def bead_injection_optimization_run(time_point_number):
global total_waste_collections
total_waste_collections+=1
waste_tube=waste_tube1
if total_waste_collections>8:
waste_tube=waste_tube2
time_point=time_point_valve.all_time_point_valves[time_point_number]
bead_tube=robot_action.all_time_points[time_point_number]
robot_action.enableRobot()
waste_tube.goToCoordinates()
setNewPIDKis(1.0,1.0,1.0)
oil_val=0.0
bead_val=55.0
cell_val=0.0
global record_data
global store_chip_values
store_chip_values=True
record_data=True
storedCellPress,storedBeadPress,storedOilPress=get_chip_stored_pressure_calibration_values(False)
print("Testing Chip:")
set_bead_channel_scaling_factor(scalingFactor60ul)
#outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(2.5)
for i in range(0,4):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(0.0,2000.0,0.0)
print(get_cell_channel_density())
print(get_oil_channel_density())
if time_point_number<9:
start_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
start_bead_vortex2()
set_stirrer_speed(300)
cell_bypass_valve.ON()
cell_media_flush_valve.CLOSE()
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(10.0)
cell_media_flush_valve.CLOSE()
cell_sample_flush_valve1.CLOSE()
cell_bypass_valve.ON()
update_valve_states()
time.sleep(16.75)
time_point.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
bead_bypass_valve.ON()
update_valve_states()
time.sleep(2.25)
bead_bypass_valve.OFF()
cell_bypass_valve.ON()
update_valve_states()
time.sleep(20.00)
set_stirrer_speed(0)
if time_point_number<9:
stop_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
stop_bead_vortex2()
bead_bypass_valve.ON()
cell_bypass_valve.ON()
time_point.CLOSE()
cell_sample_flush_valve1.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
cell_media_flush_valve.CLOSE()
update_valve_states()
stop_flushing_all_channels()
time.sleep(5.0)
bead_tube.goToCoordinates()
time.sleep(2.5)
for i in range(0,3):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
bad_collection_tube.goToCoordinates()
time.sleep(2.5)
#Droplets start emerging 27 seconds after this
#This will make the oil flow stable before we turn the bead channel and the outlet valve ON
bead_lysis_buffer_flush_valve.CLOSE()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
oil_bypass_valve.ON()
#outlet_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(0.0,27.5,0.0) #Empirically Determined. Can be obtained before each run as part of a "Calibration run"
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(10.0) #Keep this 10 to minimize cell loss.
bead_bypass_valve.OFF()
bead_lysis_buffer_flush_valve.OPEN()#Takes 19 seconds for droplets to emerge from here.
update_valve_states()
set_flush_pressures(0,27.5,0) #Leave it like this, I don't think it can get much better than this
time.sleep(5.0)
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
#pidforOilChannel.restart_flow(oil_val,1.0,oilPress)
#pidforCellChannel.restart_flow(cell_val,1.0,cellPress)
pidforBeadChannel.restart_flow(bead_val,0.1,beadPress)
#Add another 10 seconds to this to make sure you don't capture those shitty droplets.
time.sleep(25.0) #Empirically determine this to get the best time for when the droplets start emerging from the tubing.
good_collection_tube.goToCoordinatesFast()
time.sleep(35.0)
#outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.CLOSE()#Venting inside the schedule duration
cell_sample_flush_valve1.CLOSE()
cell_gas_vent_valve.OPEN()
update_valve_states()
set_flush_pressures(0.0,0.0,0.0)
#At this flow rate it takes 25 seconds for water to emerge after droplets. I think this is perfect
time.sleep(20.0)#Empirically determine this to find the best time for when all the droplets have been collected.
stop_flushing_all_channels()
time.sleep(2.0)
waste_tube.goToCoordinates()
time.sleep(2.0)
cell_media_flush_valve.OPEN()#Stop Venting
cell_sample_flush_valve1.CLOSE()
cell_gas_vent_valve.CLOSE()
cell_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(12.0)
stop_flushing_all_channels()
time.sleep(1.5)
#Cleaning the tubing going into the chip through the bypass valves
for i in range(0,6):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(18.5)
stop_flushing_all_channels()
time.sleep(1.5)
bead_bypass_valve.ON()
cell_bypass_valve.ON()
update_valve_states()
#Cleaning out any remaining Cells or Beads stuck in the tubing.
for i in range(0,4):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
def cell_injection_optimization_run(time_point_number):
global total_waste_collections
total_waste_collections+=1
waste_tube=waste_tube1
if total_waste_collections>8:
waste_tube=waste_tube2
time_point=time_point_valve.all_time_point_valves[time_point_number]
bead_tube=robot_action.all_time_points[time_point_number]
robot_action.enableRobot()
waste_tube.goToCoordinates()
setNewPIDKis(1.0,1.0,1.0)
oil_val=0.0
bead_val=0.0
cell_val=15.0
global record_data
global store_chip_values
store_chip_values=True
record_data=True
storedCellPress,storedBeadPress,storedOilPress=get_chip_stored_pressure_calibration_values(False)
print("Testing Chip:")
set_bead_channel_scaling_factor(scalingFactor60ul)
#outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(2.5)
for i in range(0,4):
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(2000.0,0.0,0.0)
print(get_cell_channel_density())
print(get_oil_channel_density())
if time_point_number<9:
start_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
start_bead_vortex2()
set_stirrer_speed(300)
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_bypass_valve.ON()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(10.0)
cell_media_flush_valve.CLOSE()
cell_sample_flush_valve1.OPEN()
cell_bypass_valve.ON()
update_valve_states()
time.sleep(16.75)
time_point.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
bead_bypass_valve.ON()
update_valve_states()
time.sleep(2.25)
bead_bypass_valve.ON()
cell_bypass_valve.OFF()
update_valve_states()
time.sleep(20.00)
set_stirrer_speed(0)
if time_point_number<9:
stop_bead_vortex() #Use only with 1ml of beads. Anything else is not suspended properly
else:
stop_bead_vortex2()
bead_bypass_valve.ON()
cell_bypass_valve.ON()
time_point.CLOSE()
cell_sample_flush_valve1.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
cell_media_flush_valve.OPEN()
update_valve_states()
stop_flushing_all_channels()
time.sleep(5.0)
bead_tube.goToCoordinates()
time.sleep(2.5)
for i in range(0,3):
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
bad_collection_tube.goToCoordinates()
time.sleep(2.5)
#Droplets start emerging 27 seconds after this
#This will make the oil flow stable before we turn the bead channel and the outlet valve ON
bead_lysis_buffer_flush_valve.CLOSE()
cell_bypass_valve.OFF()
bead_bypass_valve.ON()
oil_bypass_valve.ON()
#outlet_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(15.0,0.0,0.0) #Empirically Determined. Can be obtained before each run as part of a "Calibration run"
print(get_cell_channel_density())
print(get_oil_channel_density())
time.sleep(10.0) #Keep this 10 to minimize cell loss.
bead_bypass_valve.ON()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
set_flush_pressures(15.0,0.0,0.0)#Also empirically determined.
time.sleep(5.0)
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
#pidforBeadChannel.restart_flow(bead_val,1.0,beadPress)
pidforCellChannel.restart_flow(cell_val,0.1,cellPress)
#pidforOilChannel.restart_flow(oil_val,1.0,oilPress)
#Add another 10 seconds to this to make sure you don't capture those shitty droplets.
time.sleep(25.0) #Empirically determine this to get the best time for when the droplets start emerging from the tubing.
good_collection_tube.goToCoordinatesFast()
time.sleep(35.0)
#outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.CLOSE()#Venting inside the schedule duration
cell_sample_flush_valve1.CLOSE()
cell_gas_vent_valve.OPEN()
update_valve_states()
set_flush_pressures(200.0,0.0,0.0)
#At this flow rate it takes 25 seconds for water to emerge after droplets. I think this is perfect
time.sleep(22.0)#Empirically determine this to find the best time for when all the droplets have been collected.
stop_flushing_all_channels()
time.sleep(2.0)
waste_tube.goToCoordinates()
time.sleep(2.0)
cell_media_flush_valve.OPEN()#Stop Venting
cell_sample_flush_valve1.CLOSE()
cell_gas_vent_valve.CLOSE()
cell_bypass_valve.OFF()
update_valve_states()
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(12.0)
stop_flushing_all_channels()
time.sleep(1.5)
#Cleaning the tubing going into the chip through the bypass valves
for i in range(0,6):
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(18.5)
stop_flushing_all_channels()
time.sleep(1.5)
bead_bypass_valve.ON()
cell_bypass_valve.ON()
update_valve_states()
#Cleaning out any remaining Cells or Beads stuck in the tubing.
for i in range(0,4):
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
#Remember to load 2ml of lysis buffer in eppendorf tubes for all the time points you want to recover before you begin
def recover_beads(time_point_number_list):
waste_tube=waste_tube1
robot_action.enableRobot()
waste_tube.goToCoordinates()
time.sleep(2.5)
bead_bypass_valve.ON()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
for i in range(0,4):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
for time_point_number in time_point_number_list:
print("Recovering time point "+ str(time_point_number)+ " beads.")
time_point=time_point_valve.all_time_point_valves[time_point_number]
bead_tube=robot_action.all_time_points[time_point_number]
bead_tube.goToCoordinates()
time.sleep(2.5)
bead_lysis_buffer_flush_valve.CLOSE()
time_point.OPEN()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(95.0)
time_point.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
for i in range(0,2):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
def first_clean(time_point_number_list):
start_bead_vortex()
start_bead_vortex2()
time.sleep(20.0)
waste_tube=waste_tube2
robot_action.enableRobot()
waste_tube.goToCoordinates()
time.sleep(2.5)
bead_bypass_valve.ON()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
for i in range(0,4):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
for time_point_number in time_point_number_list:
print("Cleaning tubing for time point "+ str(time_point_number))
time_point=time_point_valve.all_time_point_valves[time_point_number]
time.sleep(2.5)
bead_lysis_buffer_flush_valve.CLOSE()
time_point.OPEN()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(17.5)
time_point.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
for i in range(0,2):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
stop_bead_vortex()
stop_bead_vortex2()
def blow_dry(time_point_number_list):
waste_tube=waste_tube1
robot_action.enableRobot()
waste_tube.goToCoordinates()
time.sleep(2.5)
for time_point_number in time_point_number_list:
print("Drying container for time point "+ str(time_point_number))
time_point=time_point_valve.all_time_point_valves[time_point_number]
time_point.OPEN()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(120.0) #Drying each container for 2 minutes
time_point.CLOSE()
update_valve_states()
time.sleep(2.5)
def second_clean(time_point_number_list):
waste_tube=waste_tube1
robot_action.enableRobot()
waste_tube.goToCoordinates()
time.sleep(2.5)
bead_bypass_valve.ON()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
for i in range(0,4):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
for time_point_number in time_point_number_list:
print("Cleaning tubing for time point "+ str(time_point_number))
time_point=time_point_valve.all_time_point_valves[time_point_number]
time.sleep(2.5)
bead_lysis_buffer_flush_valve.CLOSE()
time_point.OPEN()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(15.0)
time_point.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
for i in range(0,2):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
def time_point_sampling_run(time_point_number):
max_flow_rate_through_chip=875.4577
time_point=time_point_valve.all_time_point_valves[time_point_number]
new_time_to_manifold=(max_flow_rate_through_chip/400.0)*time_point.get_time_to_manifold()
new_time_to_injection_loop=(max_flow_rate_through_chip/400.0)*11.0
total_time_to_injection=new_time_to_injection_loop+new_time_to_manifold
setNewPIDKis(0.75,1.5,1.5)
oil_val=210.0
aq_phase_val=100.0
global record_data
record_data=True
print("Testing Chip:")
droplet_sampling_start_time=datetime.now()
cell_channel_start_time=droplet_sampling_start_time-timedelta(seconds=30.0)
bead_channel_start_time=droplet_sampling_start_time-timedelta(seconds=total_time_to_injection+40.0)
cell_channel_exec_list=[]
bead_channel_exec_list=[]
#Planning Bead Channel Independently
bead_channel_exec_list.append(("outlet_bypass_valve.ON()\n"+
"oil_bypass_valve.ON()\n"+
"cell_bypass_valve.ON()\n"+
"cell_media_flush_valve.OPEN()\n"+
"bead_lysis_buffer_flush_valve.OPEN()\n"+
"update_valve_states()\n"+
"print(get_cell_channel_density())\n"+
"set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)\n"+
"set_flow_rates(0.0,400.0,0.0)\n",bead_channel_start_time))
newTime=bead_channel_start_time+timedelta(seconds=15.0)
bead_channel_exec_list.append(("time_point.OPEN()\n"+
"bead_lysis_buffer_flush_valve.CLOSE()\n"+
"update_valve_states()\n",newTime))
newTime+=timedelta(seconds=5.0)
bead_channel_exec_list.append(("set_stirrer_speed(175)\n"+
"bead_lysis_buffer_flush_valve.OPEN()\n"+
"time_point.CLOSE()\n"+
"update_valve_states()\n",newTime))
newTime+=timedelta(seconds=20.0)
bead_channel_exec_list.append(("time_point.OPEN()\n"+
"bead_lysis_buffer_flush_valve.CLOSE()\n"+
"update_valve_states()\n",newTime))
newTime+=timedelta(seconds=(new_time_to_manifold+15.0)) #Get 100ul of beads
bead_channel_exec_list.append(("time_point.CLOSE()\n"+
"bead_lysis_buffer_flush_valve.OPEN()\n"+
"update_valve_states()\n",newTime))
bead_channel_exec_list.append(("set_flow_rates(aq_phase_val,aq_phase_val,oil_val)\n"+
"outlet_bypass_valve.OFF()\n"+
"update_valve_states()\n"+
"set_stirrer_speed(0)\n",droplet_sampling_start_time))
#Planning Cell Channel Independently
cell_channel_exec_list.append(("cell_bypass_valve.OFF()\n"+
"update_valve_states()\n"+
"cellPress,beadPress,oilPress=get_latest_pressure_measurements()\n"+
"pidforCellChannel.restart_flow(400.0,0.75,cellPress)\n",cell_channel_start_time))
newTime=cell_channel_start_time+timedelta(seconds=15.0)
cell_channel_exec_list.append(("oil_bypass_valve.OFF()\n"+
"update_valve_states()\n"+
"cellPress,beadPress,oilPress=get_latest_pressure_measurements()\n"+
"pidforOilChannel.restart_flow(oil_val,1.5,oilPress)\n",newTime))
#Merge and Execute Schedules for these Channels
execution_list=bead_channel_exec_list+cell_channel_exec_list
exec(getMergedExecutionSchedule(execution_list))
#Continue with Normal Schedule
time.sleep(40.0)
setNewPIDKis(0.01,0.01,0.01)
time.sleep(80.0)
setNewPIDKis(0.75,1.5,1.5)
outlet_bypass_valve.ON()
update_valve_states()
set_flow_rates(400.0,400.0,aq_phase_val)
time.sleep(10.0)
set_flow_rates(400.0,400.0,0.0)
oil_bypass_valve.ON()
update_valve_states()
time.sleep(15.0)
set_flow_rates(0.0,400.0,0.0)
cell_bypass_valve.ON()
update_valve_states()
time.sleep(15.0)
set_flow_rates(0.0,0.0,0.0)
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
record_data=False
def chip_calibration_run():
setNewPIDKis(0.75,1.5,1.5)
oil_val=210.0
aq_phase_val=70.0
global record_data
record_data=True
print("Testing Chip:")
outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
print(get_cell_channel_density())
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
set_flow_rates(0.0,400.0,0.0)
time.sleep(15.0)
cell_bypass_valve.OFF()
update_valve_states()
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
pidforCellChannel.restart_flow(400.0,0.75,cellPress)
time.sleep(15.0)
oil_bypass_valve.OFF()
update_valve_states()
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
pidforOilChannel.restart_flow(oil_val,1.5,oilPress)
time.sleep(15.0)
set_flow_rates(aq_phase_val,aq_phase_val,oil_val)
outlet_bypass_valve.OFF()
update_valve_states()
time.sleep(40.0)
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
setNewPIDKis(0.01,0.01,0.01)
time.sleep(80.0)
cellPress,beadPress,oilPress=get_latest_pressure_measurements()
setNewPIDKis(0.75,1.5,1.5)
outlet_bypass_valve.ON()
update_valve_states()
set_flow_rates(400.0,400.0,aq_phase_val)
time.sleep(10.0)
set_flow_rates(400.0,400.0,0.0)
oil_bypass_valve.ON()
update_valve_states()
time.sleep(15.0)
set_flow_rates(0.0,400.0,0.0)
cell_bypass_valve.ON()
update_valve_states()
time.sleep(15.0)
set_flow_rates(0.0,0.0,0.0)
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
record_data=False
def chip_test_PID():
#Turning the flows and valves on step by step and also closing them step by step to prevent backflow
#Backflow is a major problem and hopefully this will be a great solution to that problem.
oil_val=210.0
aq_phase_val=70.0
global record_data
record_data=True
print("Testing Chip:")
outlet_bypass_valve.ON()
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
print(get_cell_channel_density())
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
set_flow_rates(0.0,400.0,0.0)
time.sleep(15.0)
cell_bypass_valve.OFF()
update_valve_states()
pidforCellChannel.clear()
set_flow_rates(400.0,400.0,0.0)
time.sleep(15.0)
oil_bypass_valve.OFF()
update_valve_states()
pidforOilChannel.clear()
set_flow_rates(400.0,400.0,oil_val)
time.sleep(15.0)
cellPress,beadPress,oilPress=get_average_pressure_measurments_for_previous_run(135,140)
set_flush_pressures(cellPress,beadPress,oilPress)
outlet_bypass_valve.OFF()
update_valve_states()
time.sleep(120.0)
stop_flushing_all_channels()
outlet_bypass_valve.ON()
update_valve_states()
set_flow_rates(400.0,400.0,aq_phase_val)
time.sleep(10.0)
set_flow_rates(400.0,400.0,0.0)
oil_bypass_valve.ON()
update_valve_states()
time.sleep(15.0)
set_flow_rates(0.0,400.0,0.0)
cell_bypass_valve.ON()
update_valve_states()
time.sleep(15.0)
set_flow_rates(0.0,0.0,0.0)
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
record_data=False
def chip_bead_channel_flush():
waste_tube1.goToCoordinates()
time.sleep(2.5)
global record_data
record_data=True
print("Testing Chip:")
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.OFF()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
set_bead_channel_scaling_factor(scalingFactor60ul)
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(60.0)
stop_flushing_all_channels()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
record_data=False
def bead_channel_flush():
global record_data
record_data=True
print("Testing Chip:")
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
print(get_cell_channel_density())
print(get_oil_channel_density())
#set_cell_channel_scaling_factor(digitalDistilledWaterScalingFactor60_75ulPIDRange)
set_bead_channel_scaling_factor(digitalDistilledWaterScalingFactor)
for i in range(0,6):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
stop_flushing_all_channels()
bead_lysis_buffer_flush_valve.CLOSE()
update_valve_states()
record_data=False
def first_time_point_flush(var):
global record_data
record_data=True
time_point=time_point_valve.all_time_point_valves[1]
print("Testing Chip:")
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.CLOSE()
time_point.OPEN()
update_valve_states()
print(get_cell_channel_density())
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
set_bead_channel_scaling_factor(distilledWaterScalingFactor)
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(60.0)
print(var)
stop_flushing_all_channels()
time_point.CLOSE()
update_valve_states()
record_data=False
def chip_cell_channel_flush():
global record_data
record_data=True
print("Testing Chip:")
oil_bypass_valve.ON()
cell_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
bead_bypass_valve.ON()
update_valve_states()
#print(get_cell_channel_density())
#print(get_oil_channel_density())
#set_bead_channel_scaling_factor(digitalDistilledWaterScalingFactor)
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(60.0)
stop_flushing_all_channels()
cell_media_flush_valve.CLOSE()
cell_bypass_valve.ON()
update_valve_states()
record_data=False
def chip_bead_and_cell_channel_flush():
global record_data
record_data=True
print("Testing Chip:")
oil_bypass_valve.ON()
cell_bypass_valve.OFF()
bead_bypass_valve.OFF()
cell_media_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.OPEN()
update_valve_states()
#set_bead_channel_scaling_factor(analogDistilledWaterScalingFactor)
#set_cell_channel_scaling_factor(digitalDistilledWaterScalingFactor60_75ulPIDRange)
#print(get_cell_channel_density())
set_flush_pressures(2000.0,2000.0,0.0)
time.sleep(60.0)
stop_flushing_all_channels()
bead_lysis_buffer_flush_valve.CLOSE()
cell_media_flush_valve.CLOSE()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
update_valve_states()
record_data=False
def simple_flush():
#global record_data
#record_data=True
print("Flushing Oil and Water through Oil and Cell Bypass valves:")
oil_bypass_valve.ON()
cell_bypass_valve.ON()
cell_media_flush_valve.OPEN()
print(get_cell_channel_density())
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
update_valve_states()
time.sleep(5.0)
sin_pressure_wave(1800.0,1800.0,250.0,60.0)
time.sleep(5.0)
#record_data=False
def bead_channel_calibration():
set_bead_channel_scaling_factor(scalingFactor55ulFicoll)
global record_data
setNewPIDKis(0.1,1.0,0.1)
print("Bead Channel Calibration")
update_valve_states()
for i in range(0,4):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
set_flush_pressures(0.0,0.0,0.0)
time.sleep(2.5)
print(get_cell_channel_density())
print(get_oil_channel_density())
stop_flushing_all_channels()
record_data=True
time.sleep(5.0)
set_flow_rates(0.0,55.0,0.0)
time.sleep(120.0)
def PID_test():
global record_data
print("PID test through Bypass valves")
cell_ipa_flush_valve.CLOSE()
cell_aceticAcidSDS_flush_valve.CLOSE()
cell_air_flush_valve.CLOSE()
cell_media_flush_valve.OPEN()
cell_sample_flush_valve1.CLOSE()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
bead_ipa_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
bead_air_flush_valve.CLOSE()
oil_bypass_valve.ON()
update_valve_states()
record_data=True
#print(get_bead_channel_density())
print(get_cell_channel_density())
time.sleep(5.0)
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
#set_bead_channel_scaling_factor(distilledWaterScalingFactor)
set_flow_rates(65.0,65.0,0.0)
time.sleep(60.0)
set_flow_rates(0.0,0.0,0.0)
time.sleep(5.0)
def sampling_schedule():
simple_flush() #Gets rid of Bubbles in the Flow meters and pumps clean liquid through
reset_valve_states()
set_stirrer_speed(175)
time.sleep(5.0)
PID_flush_though_chip()
reset_valve_states()
time.sleep(5.0)
prime_the_tubing()
stop_stirrer()
def bead_flush_test():
set_stirrer_speed(250)
time.sleep(15.0)
prime_the_tubing()
stop_stirrer()
def initial_flush():
print("Flushing Water and Oil through bypass valves")
cell_ipa_flush_valve.CLOSE()
cell_aceticAcidSDS_flush_valve.CLOSE()
cell_air_flush_valve.CLOSE()
cell_media_flush_valve.OPEN()
cell_sample_flush_valve1.CLOSE()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
bead_ipa_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
bead_air_flush_valve.CLOSE()
oil_bypass_valve.ON()
update_valve_states()
time.sleep(5.0)
sin_pressure_wave(1800.0,1800.0,0.0,60.0)
time.sleep(5.0)
def smoothPID():
global record_data
print("Fast Flush")
cell_ipa_flush_valve.CLOSE()
cell_aceticAcidSDS_flush_valve.CLOSE()
cell_air_flush_valve.CLOSE()
cell_media_flush_valve.OPEN()
cell_sample_flush_valve1.CLOSE()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
bead_ipa_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
bead_air_flush_valve.CLOSE()
oil_bypass_valve.ON()
update_valve_states()
record_data=True
#print(get_bead_channel_density())
print(get_cell_channel_density())
time.sleep(5.0)
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
set_bead_channel_scaling_factor(distilledWaterScalingFactor)
set_flow_rates(500.0,500.0,0.0)
time.sleep(60.0)
set_flow_rates(0.0,0.0,0.0)
time.sleep(5.0)
print("Slow Flush")
cell_ipa_flush_valve.CLOSE()
cell_aceticAcidSDS_flush_valve.CLOSE()
cell_air_flush_valve.CLOSE()
cell_media_flush_valve.OPEN()
cell_sample_flush_valve1.CLOSE()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
bead_ipa_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
bead_air_flush_valve.CLOSE()
oil_bypass_valve.ON()
update_valve_states()
record_data=True
#print(get_bead_channel_density())
print(get_cell_channel_density())
time.sleep(5.0)
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
#set_bead_channel_scaling_factor(distilledWaterScalingFactor)
clear_PID_controllers()
set_flow_rates(65.0,65.0,0.0)
time.sleep(60.0)
set_flow_rates(0.0,0.0,0.0)
time.sleep(5.0)
def oil_calibration():
global record_data
record_data=True
print("Calibration Data collection Started")
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
print(get_cell_channel_density())
set_flow_rates(200.0,0.0,0.0)
time.sleep(60.0)
set_flow_rates(0.0,0.0,0.0)
record_data=False
def smootherPIDTest():
global record_data
print("Fast Flush")
cell_ipa_flush_valve.CLOSE()
cell_aceticAcidSDS_flush_valve.CLOSE()
cell_air_flush_valve.CLOSE()
cell_media_flush_valve.OPEN()
cell_sample_flush_valve1.CLOSE()
cell_bypass_valve.ON()
bead_bypass_valve.ON()
bead_ipa_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
bead_air_flush_valve.CLOSE()
oil_bypass_valve.ON()
update_valve_states()
record_data=True
#print(get_bead_channel_density())
print(get_cell_channel_density())
time.sleep(5.0)
set_oil_channel_scaling_factor(evagreenDropletOilScalingFactor)
set_bead_channel_scaling_factor(distilledWaterScalingFactor)
set_flow_rates(500.0,500.0,0.0)
time.sleep(60.0)
set_flow_rates(65.0,65.0,0.0)
time.sleep(60.0)
set_flow_rates(0.0,0.0,0.0)
time.sleep(5.0)
def clear_second_time_point():
second=time_point_valve.all_time_point_valves[2]
second.OPEN()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
for i in range(0,5):
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(2.5)
stop_flushing_all_channels()
time.sleep(2.5)
reset_valve_states()
def get_priming_timing():
second=time_point_valve.all_time_point_valves[2]
second.OPEN()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(1.5)
stop_flushing_all_channels()
def test_pulsatile_chip():
cellPress=0.0
beadPress=170.0
oilPress=0.0
for i in range(0,5):
bead_air_flush_valve.CLOSE()
bead_lysis_buffer_flush_valve.OPEN()
bead_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(5.0)
set_flush_pressures(2*cellPress,2*beadPress,2*oilPress)
bead_bypass_valve.OFF()
update_valve_states()
time.sleep(5.0)
bead_air_flush_valve.OPEN()
bead_lysis_buffer_flush_valve.CLOSE()
bead_bypass_valve.ON()
update_valve_states()
set_flush_pressures(0.0,2000.0,0.0)
time.sleep(5.0)
set_flush_pressures(2*cellPress,2*beadPress,2*oilPress)
bead_bypass_valve.OFF()
update_valve_states()
time.sleep(5.0)
def keep_suspension():
cell_gas_vent_valve.OPEN()
update_valve_states()
set_flush_pressures(2000.0,0.0,0.0)
time.sleep(10.0)
This lets you test whether pressure values used for the Microfluidic Chip during the previous run were in the correct pressure ranges or not. If your strored Pressure Values were not in this range then something was wrong during the previous run. Most likely with your Chip. You will see a warning if the Pressures were out of range.
get_chip_stored_pressure_calibration_values()
def test_for_gas_leaks():
stop_vent()
print("Testing Cell Channel, the sounds should stop after a while.")
time.sleep(5.0)
set_cell_channel_pressure(2000.0)
time.sleep(20.0)
print("Depressurizing Cell Channel and testing Bead Channel. The sound should stop after a while but it will take a little longer to go away.")
set_cell_channel_pressure(0.0)
set_bead_channel_pressure(2000.0)
time.sleep(40.0)
print("Depressurizing Bead Channel")
set_bead_channel_pressure(0.0)
time.sleep(5.0)
print("Starting Venting, you will hear a low volume sound.")
start_vent()
test_for_gas_leaks()
start_vent()
Is Automatically Executed after a Schedule Ends by Default. If you don't want the system to vent gas from the pressure source then you should manually execute stop_vent()
.
start_vent()
Starts the Magenetic Stirrer and Slowly Vents the Cell Container 1 and Media Flush Containers with 5%CO2 if Connected to the Tank. Execute when you have just loaded the Cells and Need to Keep them in Suspension or need to flush existing air out of containers with 5% CO2. This function will vent with House Air if its connect to that pressure source.
Starts venting and Magnetic Stirrer
start_vent()
Stops venting and Magnetic Stirrer
stop_vent()
execute_schedules()
at a Time. DON'T EXECUTE ANOTHER CELL till another one has not completed Executing.execute_schedules()
.execute_schedules()
function to know whether the Cell you are executing is a Schedule or not.execute_schedules()
hasn't stopped executing.Scheduler has been Shutdown!
and play a sound to indicate completion of execution.The function execute_schedules
is used to Execute a Schedule from the Schedule Definitions Above.
execute_schedules
takes three inputs. A scheduleList
, time interval in seconds, and a Boolean Value. The Boolean Value determines whether the time interval is between the start of the schedules in the scheduleList or is between the end of the previous schedule and start of the next schedule. By Default the interval it considers is between the schedules.
scheduleLists also have a particular Format. It is a list of Tuples. Each Tuple has three required values and the fourth value can be a value that can be passed to the schedule during execution. The first Part of the scheduleList is the name of the schedule function. The second value is the number of times you want to repeat that schedule. The third value is the duration of the schedule. Execution will stop as soon as this amount of time is reached.
EXAMPLE:
scheduleList=[(prime_the_cell_channel,2,20.0),(bead_bypass_flush,3,30.0,"Testing")]
execute_schedules(scheduleList,10.0,False)
Here prime_the_cell_channel
schedule will be executed twice and the duration of this schedule is 20 seconds. We are not passing any values to this schedule.
After this bead_bypass_flush
schedule will be execute thrice and the duration of this schedule is 30 seconds. We are passing the value "Testing"
to this schedule.
execute_schedules
will execute all the schedules in scheduleList
with a gap of 10 seconds between the end of each schedules and the start of the next one.
This is a hyperlinked section. Each Procedure is a sequence of Schedules that need to be executed in a particular order to complete a Particular Protocol. For Example, Clicking on the sections below leads you to a list of instructions and Hyperlinks on how to do any of the follow experiments using the Chrono-Seq Device.
Priming is to remove any bubbles and debris from inside the tubing for smooth operation of the Device. We will prime all three channels. Cell, Oil and Bead Channels. First we prime the Cell Channel.
#Test for Gas Leaks
test_for_gas_leaks()
#Prime the Cell Channel through manifold
scheduleList=[(prime_the_cell_channel,1,20.0)]
execute_schedules(scheduleList,10.0)
Now we need to prime the remaining section of the Cell channel including the flow sensor.
#Connect the Cell Channel Outlet from Manifold to Flow Meter
scheduleList=[(prime_the_cell_channel,2,20.0)]
execute_schedules(scheduleList,10.0)
#Prime cell tubing without plugging into flow meter
stop_vent()
set_oil_channel_pressure(500.0)
time.sleep(5.0)
set_oil_channel_pressure(0.0)
![]() |
![]() |
#You will see oil in the flow through container
set_oil_channel_pressure(2000.0)
time.sleep(7.0)
set_oil_channel_pressure(0.0)
Just execute the Cell Below. Lysis buffer should emerge from the tip of the Bead Bypass tubing connected to the XYZ Robot.
#Prime Bead bypass
scheduleList=[(bead_bypass_flush,2,20.0)]
execute_schedules(scheduleList,10.0)
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/dIA_325XVqU?si=qEpW8N-eFohvNki5" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
![]() |
![]() |
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/zzyjBlkUTCI?si=co8C_A7FkmexRUdk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
✶ Important Note: Do this only one reservoir at a time to avoid dust from entering the containers. Swiftly swap the containers but make sure YOU DON'T SPILL LYSIS BUFFER on the inside portion of the Reservoir Cap. This can later crystalize and cause problems with Blockages. So you have two priorities:
1. Don't let dust enter by doing the change quickly. <input type="checkbox">
2. Don't spill the Lysis buffer in haste. <input type="checkbox">
test_for_gas_leaks()
below.#Testing for Leaks
test_for_gas_leaks()
timepoint_reservoirs_to_clean
with the reservoirs numbers.#Remember to load 2ml of lysis buffer in 50ml tubes for all the Reservoirs you want to prime.
timepoint_reservoirs_to_clean=[9,10,11] #Put Reservoir Numbers you need to Prime in this list
scheduleList=[(second_clean,1,22.5+27.5*len(timepoint_reservoirs_to_clean),timepoint_reservoirs_to_clean)]
execute_schedules(scheduleList,10.0)
![]() |
![]() |
#Prime the Outlet Tubing
scheduleList=[(prime_outlet_tubing,2,20.0)]
execute_schedules(scheduleList,10.0)
prime_the_chip_tubing
in the Cell below.
scheduleList=[(prime_the_chip_tubing,1,20.0)]
execute_schedules(scheduleList,10.0)
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/VM9P_W1SP1A?si=Q-yJuhCVlz2SIYCN" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
Note:Do not try to reinsert the tubing if you inserted it into the wrong inlet. This will generated particles that can block the chip and/or cause delamination especially for the Bead Channel. If you made a mistake use a different chip. Chips are single use only. You can push/pull the Outlet tubing a little bit if necessary.
![]() |
![]() |
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/CrPHzVoak7Y?si=XDaIRLAc2n982bUA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/B9G68_iSrSc?si=XDvKL6vMBNNrdOFi" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
timeAndCellTupleList
below with the value of one of the Bead reservoirs you used for Priming.timeAndCellTupleList=[(9,1)]
would work.# Main Code that Runs the Device.
def build_time_point_and_cell_sample_scheduleList():
timeAndCellTupleList=[(9,1)] # CHANGE THIS.Each Tuple represents a Bead Reservoir and Cell Reservoir Combo for Injection
timepointAndCellScheduleList=[]
for timeAndcellTuple in timeAndCellTupleList:
total_run_time=385.0
timepointAndCellScheduleList.append((get_sample_from_multiple_cell_tubes_ficoll,1,total_run_time,timeAndcellTuple))
return timepointAndCellScheduleList
scheduleList=[]+build_time_point_and_cell_sample_scheduleList()
print(scheduleList)
execute_schedules(scheduleList,600.0,True)
get_chip_stored_pressure_calibration_values()
test_for_gas_leaks()
✶ IMPORTANT You will have to pull the tubing for the Cell Sample Reservoir 1 up till the 15ml Mark to avoid the Magnetic Stirring Disk from Colliding with it for every rotation of the Disk. Loosen the Nut to pull the tubing up.
Location of Magnetic Stirrers | Pouch with Magnetic Stirrers |
---|---|
![]() |
![]() |
test_for_gas_leaks()
Raw NBConvert
. Remember to change the Cell Type to Code
before you execute.scheduleList=[(keep_suspension,5,10.0)]
execute_schedules(scheduleList,900.0,True) #Execute the keep_suspension schedule every 15 minutes.
robot_action.tubeUp()
robot_action.disableRobot()
Ice Box 1 Lid | Ice Box 2 Lid |
---|---|
![]() |
![]() |
robot_action.robotGoHome()
test_robot()
failed_chip_injection_flush(20.0)
. This code should be in the cell after the next one.%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/qFouf2HrKSk?si=kXKrsZvVZXmpvY5z" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/J2O1kA4chU0?si=LKIMxJRw85NZYhSt" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/qF8IYtwAWqE?si=AqH0lItvhQP_Bf4I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/HMAVntu9zqA?si=cPHgSLX0H3qruqga&start=281" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/7TSY_pSxzMU?si=niAMMZxHK96v8nbr&start=155" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
timeAndCellTupleList
stores the Combination for Bead Reservoir numbers and Cell Sample Reservoirs you want to run for your experiment.EXAMPLE 1:
timeAndCellTupleList=[(8,1),(9,1)]
In this example the ChronoSeq Device will sample Cells from Cell Sample Reservoir 1, and beads from Bead Reservoir 8 for the first injection. This is represented in the list as the Tuple (8,1) After this injection is complete, the ChronoSeq Device will sample Cells from Cell Sample Reservoir 1, and beads from Bead Reservoir 9 for the second injection. This is represented in the list as the Tuple (9,1) You can add more tuples for more injections.
EXAMPLE 2:
timeAndCellTupleList=[(11,1),(12,2),(13,3)]
In this example, the ChronoSeq Device will sample Cells from Cell Sample Reservoir 1, and beads from Bead Reservoir 11 for the first injection. This is represented in the list as the Tuple (11,1) For the second injection, the ChronoSeq Device will sample Cells from Cell Sample Reservoir 2, and beads from Bead Reservoir 12. This is represented in the list as the Tuple (12,2) For the third injection, the ChronoSeq Device will sample Cells from Cell Sample Reservoir 3, and beads from Bead Reservoir 13. This is represented in the list as the Tuple (13,3)
execute_schedules
decides the interval between the injections. As explain previously here.EXAMPLE:
execute_schedules(scheduleList,600.0,True)
The 600.0 means 600.0 seconds. True
means this interval will be between the start time of one injection and the start time of the next injection. So every 10 minutes the machine will start the program for Sampling Cells and Beads from the Tuples in the timeAndCellTupleList
. If there is only one Tuple then the execute_schedules
function will end after executing that tuple. A sound will always play after all the Tuples in the list have finished executing.
emergency_stop
will allow the current injection/schedule to finish executing. After this none of the schedules in the schedulelist or Tuples in the Tuple list will be executed and execution will stop. A sound may or many not play. You can find it in the second cell after the next one. Or here# Main Code that Runs the Device.
def build_time_point_and_cell_sample_scheduleList():
timeAndCellTupleList=[(9,1),(10,1),(11,1)] # CHANGE THIS.Each Tuple represents a Bead Reservoir and Cell Reservoir Combo for Injection
timepointAndCellScheduleList=[]
for timeAndcellTuple in timeAndCellTupleList:
total_run_time=385.0
timepointAndCellScheduleList.append((get_sample_from_multiple_cell_tubes_ficoll,1,total_run_time,timeAndcellTuple))
return timepointAndCellScheduleList
scheduleList=[]+build_time_point_and_cell_sample_scheduleList()
print(scheduleList)
execute_schedules(scheduleList,600.0,True) # CHANGE THIS. Running every 10 minutes fixed intervals irrespective of length of program
#Use if there is a blockage in between two schedules.
failed_chip_injection_flush(20.0)
emergency_stop()
test_for_gas_leaks()
timepoints_to_recover
below with all the Bead Reservoir Numbers that were used for this experiment.#Remember to load 2ml of lysis buffer in 50ml Tubes for all the Bead Reservoirs you used for this experiment
timepoints_to_recover=[9,10,11] #List all the Bead Reservoir Numbers Here
scheduleList=[(recover_beads,1,22.5+107.5*len(timepoints_to_recover),timepoints_to_recover)]
execute_schedules(scheduleList,10.0)
robot_action.disableRobot()
robot_action.tubeUp()
robot_action.robotGoHome()
test_for_gas_leaks()
timepoint_reservoirs_to_clean
below with all the Bead Reservoir Numbers that were used for this experiment.#Remember to load 5ml of Distilled Water in the Bead Reservoirs before executing this Cell
timepoint_reservoirs_to_clean=[9,10,11] #Put Reservoir Numbers you used during the experiment in this list
scheduleList=[(second_clean,1,22.5+27.5*len(timepoint_reservoirs_to_clean),timepoint_reservoirs_to_clean)]
execute_schedules(scheduleList,10.0)
This is a STOPING STEP. You can Shutdown the Device, turn off the Power, and then Turn off the Gas Supply and Continue the next day. Remember to run the Jupyter Cells labeled "Execute" till you reach the Main Menu before continuing. Do not delay more than 1 day for resuming the cleanup otherwise the Flow Meters can get Damaged.
stop_vent()
robot_action.robotGoHome()
robot_action.disableRobot()
Assembled 50ml Flusing Reservoir | 50ml Flushing Reservoir Location |
---|---|
![]() |
![]() |
cell_bypass_valve.OFF()
update_valve_states()
cell_bypass_valve.ON()
update_valve_states()
Assembled Large GL45 Reservoir | Large GL45 Reservoir Bottle Location |
---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
oil_bypass_valve.OFF()
update_valve_states()
oil_bypass_valve.ON()
update_valve_states()
This is a STOPING STEP. You can Shutdown the Device, turn off the Power, and then Turn off the Gas Supply and Continue the next day. Remember to run the Jupyter Cells labeled "Execute" till you reach the Main Menu before continuing.
Location of Magnetic Stirrers | Pouch with Magnetic Stirrers |
---|---|
![]() |
![]() |
test_for_gas_leaks()
scheduleList=[(prime_the_cell_channel,60,60.0)]
execute_schedules(scheduleList,10.0)
robot_action.tubeUp()
robot_action.disableRobot()
dry_cell_channel(30*60.0)
Priming is to remove any bubbles and debris from inside the tubing for smooth operation of the Device. First we prime the Cell Channel.
#Test for Gas Leaks
test_for_gas_leaks()
#Prime the Cell Channel through manifold
scheduleList=[(prime_the_cell_channel,1,20.0)]
execute_schedules(scheduleList,10.0)
Now we need to prime the remaining section of the Cell channel including the flow sensor.
#Connect the Cell Channel Outlet from Manifold to Flow Meter
scheduleList=[(prime_the_cell_channel,2,20.0)]
execute_schedules(scheduleList,10.0)
![]() |
![]() |
![]() |
![]() |
def build_time_point_and_cell_sample_scheduleList():
timeAndCellTupleList=[(1,1)] # Timepoint Collection Tube and Cell Reservoir Combination
timepointAndCellScheduleList=[]
for timeAndcellTuple in timeAndCellTupleList:
total_run_time=63.0 #The rest of the run takes 160seconds
timepointAndCellScheduleList.append((get_sample_cells_only,1,total_run_time,timeAndcellTuple))
return timepointAndCellScheduleList
scheduleList=[]+build_time_point_and_cell_sample_scheduleList()
print(scheduleList)
execute_schedules(scheduleList,600.0,True) #Running every 10 minutes fixed intervals irrespective of length of program
✶ IMPORTANT You will have to pull the tubing for the Cell Sample Reservoir 1 up till the 15ml Mark to avoid the Magnetic Stirring Disk from Colliding with it for every rotation of the Disk. Loosen the Nut to pull the tubing up.
Location of Magnetic Stirrers | Pouch with Magnetic Stirrers |
---|---|
![]() |
![]() |
test_for_gas_leaks()
scheduleList=[(keep_suspension,1,10.0)] # Will Execute 21 Times.
execute_schedules(scheduleList,900.0,True) #Executes the keep_suspension schedule every 15 minutes.
✶ IMPORTANT You will have to pull the tubing for the Cell Sample Reservoir 1 up till the 15ml Mark to avoid the Magnetic Stirring Disk from Colliding with it for every rotation of the Disk. Loosen the Nut to pull the tubing up.
Location of Magnetic Stirrers | Pouch with Magnetic Stirrers |
---|---|
![]() |
![]() |
test_for_gas_leaks()
robot_action.tubeUp()
robot_action.disableRobot()
Ice Box 1 Lid | Ice Box 2 Lid |
---|---|
![]() |
![]() |
All Tubes Loaded for the Experiment |
---|
![]() |
robot_action.robotGoHome()
test_robot()
timeAndCellTupleList
has been prepopulated with 24 tuples. This indicates 24 samples will be taken from the Cell Suspension in Cell Sample Reservoir 1.[(3,1),(2,1),(3,1)]
is a valid list. Samples will be taken from Reservoir 1 and Deposited in Positions, 3 , 2 and then 3 again in Ice Box 2.execute_schedules(scheduleList,600.0,True)
Indicates that each Cell Suspension Sample will be taken every 10 minutes.600.0
to change the sampling duration. Minimum Duration is 73.0
.def build_time_point_and_cell_sample_scheduleList():
timeAndCellTupleList=[(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1)] # Timepoint Collection Tube and Cell Reservoir Combination
timepointAndCellScheduleList=[]
for timeAndcellTuple in timeAndCellTupleList:
total_run_time=63.0 #The rest of the run takes 160seconds
timepointAndCellScheduleList.append((get_sample_cells_only,1,total_run_time,timeAndcellTuple))
return timepointAndCellScheduleList
scheduleList=[]+build_time_point_and_cell_sample_scheduleList()
print(scheduleList)
execute_schedules(scheduleList,600.0,True) #Running every 10 minutes fixed intervals irrespective of length of program
stop_vent()
Assembled 50ml Flusing Reservoir | 50ml Flushing Reservoir Location |
---|---|
![]() |
![]() |
Assembled Large GL45 Reservoir | Large GL45 Reservoir Bottle Location |
---|---|
![]() |
![]() |
robot_action.tubeUp()
robot_action.disableRobot()
robot_action.robotGoHome()
time.sleep(10.0)
waste_tube1.goToCoordinates()
cell_bypass_valve.OFF()
update_valve_states()
cell_bypass_valve.ON()
update_valve_states()
robot_action.tubeUp()
robot_action.disableRobot()
stop_vent()
This is a STOPING STEP. You can Shutdown the Device, turn off the Power, and then Turn off the Gas Supply and Continue the next day. Remember to run the Jupyter Cells labeled "Execute" till you reach the Main Menu before continuing.
Location of Magnetic Stirrers | Pouch with Magnetic Stirrers |
---|---|
![]() |
![]() |
test_for_gas_leaks()
scheduleList=[(prime_the_cell_channel,60,60.0)]
execute_schedules(scheduleList,10.0)
dry_cell_channel(30*60.0)
Disconnect Tubing from PEEK Union | Reconnect Tubing to Bead Bypass Valve |
---|---|
![]() |
![]() |
Secure Tubing In Place | Store PEEK Union Back on Microscope Stage Using Tape |
---|---|
![]() |
![]() |
Executing the function in the cell below means that the current schedule will keep running but all other schedules in queue will be removed and another different Schedule Can be Executed Directly after that.
emergency_stop()
Recorded data can be very useful for troubleshooting problems with the Device. Can be executed at anytime during the run. You can also wait for the Scheduler to Stop Execution before plotting.
get_chip_stored_pressure_calibration_values()
plot_flow_data(True)
def plot_channel_data(channel_measurements,type_of_measurement,channel_name,save_plots=False):
assert type_of_measurement in ("Pressure","Flow")
if type_of_measurement is "Pressure":
ylabel="Pressure (mBar)"
else:
ylabel="Flow (ul/min)"
channel_measurement_df=pd.DataFrame(channel_measurements,columns=[type_of_measurement,"Time","Sample"])
channel_measurement_df=channel_measurement_df[channel_measurement_df.Time>=163.0]
channel_measurement_df=channel_measurement_df[channel_measurement_df.Time<=223.0]
print(channel_measurement_df.shape) #Rows and columns
sub_plots=sns.relplot(x="Time",y=type_of_measurement,col="Sample",col_wrap=2,data=channel_measurement_df,kind="line")
sub_plots.set_xlabels("Time (Seconds)")
sub_plots.set_ylabels(ylabel)
plt.subplots_adjust(top=0.9)
sub_plots.fig.suptitle("%s Channel Plot of %s vs Time"%(channel_name,type_of_measurement))
if save_plots is True:
sub_plots.savefig(channel_name+type_of_measurement+".png",dpi=600)
def plot_flow_data(save_plots=False):
"""Pass the variable save_plots a True value to save the plots to the current working directory.
By default this is set to False.
"""
plot_channel_data(cellChannelPressureMeasurements,"Pressure","Cell",save_plots)
plot_channel_data(cellChannelFlowMeasurements,"Flow","Cell",save_plots)
plot_channel_data(oilChannelPressureMeasurements,"Pressure","Oil",save_plots)
plot_channel_data(oilChannelFlowMeasurements,"Flow","Oil",save_plots)
plot_channel_data(beadChannelPressureMeasurements,"Pressure","Bead",save_plots)
plot_channel_data(beadChannelFlowMeasurements,"Flow","Bead",save_plots)
plot_flow_data(True)
You can type in custom commands in this section to Troubleshoot the device. Recommended for Advanced Users only.
oil_bypass_valve.OFF()
update_valve_states()
stop_vent()
set_oil_channel_pressure(0.0)
reset_valve_states()
#Add Test Code Here
time.sleep(90*60.0)
dry_cell_channel(30*60.0)
Execute the Cell Below to Shutdown the Device.
shutdown_device()
time.sleep(5.0)
#test