private void CheckSpeedsValidity(LiquidClass liquidClass) { int maxSpeed = TeachingControllerDelegate.Instance.Controller.MaxPipettingSpeed; CheckSpeedValidity(liquidClass.AspirationSinglePipetting.AspirationSpeed, maxSpeed, "AspirationSpeed"); CheckSpeedValidity(liquidClass.DispenseSinglePipetting.DispenseSpeed, maxSpeed, "DispenseSpeed"); }
private void OnLiquidClassDeleteMenuItemClick(object sender, RoutedEventArgs e) { LiquidClass selectedLC = (LiquidClass)this.lb_liquidclass.SelectedItem; PipettorElementManager.Instance.DeletePipettorElement <LiquidClass>(selectedLC.TypeName); DeleteTabItem(selectedLC.TypeName); }
//– Dispense back into vessel and then pipette nothing //– Ignore clot error and continue //– Discard the DITI and pipette nothing private void ProcessClot(Labware labware, int wellID, double volume, LiquidClass liquidClass, out PipettingResult pipettingResult, string barcode = "") { string labwareLabel = labware.Label; ClotDetectedForm clotForm = new ClotDetectedForm(); clotForm.ShowDialog(); e_RSPErrorCode res = e_RSPErrorCode.RSP_ERROR_NONE; var userSelection = clotForm.UserSelection; pipettingResult = PipettingResult.ok; DitiTrackInfo trackInfo = new DitiTrackInfo(Labware.WasteLabel, 1, true, false); switch (userSelection) { case ClotDetectedAction.dispenseBackThenDropDiti: pipettingResult = PipettingResult.clotDispenseBack; res = MoveController.Instance.Move2Z(_eARM.左臂, labware.ZValues.ZDispense); ThrowCriticalException(res, "遇到凝块,移动到ZDispense"); res = MoveController.Instance.Dispense(volume + excessVolume, liquidClass.AspirationSinglePipetting.AspirationSpeed, startSpeedV, endSpeedV); ThrowCriticalException(res, "遇到凝块,打回容器"); DropTip(out trackInfo); break; case ClotDetectedAction.dropDiti: pipettingResult = PipettingResult.clotDropDiti; DropTip(out trackInfo); break; case ClotDetectedAction.ignore: pipettingResult = PipettingResult.clotIgnore; break; } }
private void OnBtnSaveClick(object sender, RoutedEventArgs e) { // The DataContext must be LiquidClass LiquidClass liquidClass = this.DataContext as LiquidClass; if (liquidClass == null) { throw new InvalidOperationException("DataContext of LiquiClassEditor must be an instance of LiquidClass"); } try { CheckSpeedsValidity(liquidClass); PipettorElementManager.Instance.SavePipettorElement(liquidClass); } catch (Exception ex) { if (newInfoHandler != null) { newInfoHandler(ex.Message, true); } } }
private void OnLiquidClassDuplicateMenuItemClick(object sender, RoutedEventArgs e) { LiquidClass liquidClass = ((LiquidClass)this.lb_liquidclass.SelectedItem).Clone() as LiquidClass; LiquidClassEditor editor = new LiquidClassEditor(AddInfo); editor.DataContext = liquidClass; this.AddTabItem(editor); }
private void OnLiquidClassNewMenuItemClick(object sender, RoutedEventArgs e) { LiquidClass liquidClass = new LiquidClass(); LiquidClassEditor editor = new LiquidClassEditor(AddInfo); editor.DataContext = liquidClass; this.AddTabItem(editor); }
private void DoTracking(Labware labware, double volume, LiquidClass liquidClass) { double crossSectionArea = labware.WellsInfo.WellRadius * labware.WellsInfo.WellRadius * Math.PI; double distance2Go = volume / crossSectionArea; double seconds = volume / liquidClass.AspirationSinglePipetting.AspirationSpeed; double goDownSpeed = distance2Go / seconds; var res = MoveController.Instance.MoveZAtSpeed(_eARM.左臂, distance2Go, goDownSpeed); ThrowCriticalException(res, "液面跟随!"); }
private void OnLiquidClassXmlFileCreated(object sender, FileSystemEventArgs e) { LiquidClass liquidClass = this.CreatedPipettorElement.Pop() as LiquidClass; if (liquidClass == null) { throw new InvalidOperationException("LiquidClass instance was supposed to be existing."); } this._liquidClasses.Add(e.FullPath, liquidClass); this.PropertyChanged(this, new PropertyChangedEventArgs("LiquidClasses")); }
private void OnLiquidClassEditMenuItemClick(object sender, RoutedEventArgs e) { LiquidClass selectedLC = (LiquidClass)this.lb_liquidclass.SelectedItem; if (this.ActivateEditingTab(selectedLC.TypeName)) { return; } LiquidClassEditor editor = new LiquidClassEditor(AddInfo); editor.DataContext = selectedLC; this.AddTabItem(editor); }
public void LiquidClassDeserializeTest() { LiquidClass liquidClass = LiquidClass.Create(this._xmlFileLiquidClass); Assert.AreEqual <int>(liquidClass.AspirationSinglePipetting.AspirationSpeed, 400); Assert.AreEqual <int>(liquidClass.AspirationSinglePipetting.Delay, 200); Assert.AreEqual <int>(liquidClass.AspirationSinglePipetting.ExcessVolume, 20); Assert.AreEqual <int>(liquidClass.AspirationSinglePipetting.LeadingAirgap, 15); Assert.AreEqual <int>(liquidClass.AspirationSinglePipetting.SystemTrailingAirgap, 10); Assert.AreEqual <int>(liquidClass.AspirationSinglePipetting.TrailingAirgap, 50); Assert.AreEqual <int>(liquidClass.DispenseSinglePipetting.DispenseSpeed, 300); Assert.AreEqual <int>(liquidClass.DispenseSinglePipetting.Delay, 150); Assert.AreEqual <bool>(false, liquidClass.DispenseSinglePipetting.TrailingAirgapAfterDispense); Assert.AreEqual <bool>(true, liquidClass.DispenseMultiPipetting.TrailingAirgapAfterDispense); }
public void LiquidClassSerializeTest() { LiquidClass liquidClass = new LiquidClass(); liquidClass.TypeName = "LiquidClass Serialization Test"; liquidClass.AspirationSinglePipetting.AspirationSpeed = 400; liquidClass.AspirationSinglePipetting.Delay = 200; liquidClass.AspirationSinglePipetting.ExcessVolume = 20; liquidClass.AspirationSinglePipetting.LeadingAirgap = 15; liquidClass.AspirationSinglePipetting.SystemTrailingAirgap = 10; liquidClass.AspirationSinglePipetting.TrailingAirgap = 50; liquidClass.DispenseMultiPipetting.DispenseSpeed = 400; liquidClass.DispenseMultiPipetting.Delay = 250; liquidClass.DispenseMultiPipetting.TrailingAirgapAfterDispense = true; liquidClass.DispenseSinglePipetting.DispenseSpeed = 300; liquidClass.DispenseSinglePipetting.Delay = 150; liquidClass.DispenseSinglePipetting.TrailingAirgapAfterDispense = false; liquidClass.Serialize(this._xmlFileLiquidClass); }
public void Dispense(string labwareLabel, List <int> wellIDs, List <double> volumes, LiquidClass liquidClass, out PipettingResult pipettingResult, string barcode = "") { int wellID = wellIDs.First(); double volume = Math.Round(volumes.First(), 1); string sWellID = wellID.ToString(); string sCommandDesc = string.Format("Dispense to:{0} at:{1} volume:{2},{3}", labwareLabel, wellID, volume, liquidClass); log.InfoFormat(sCommandDesc); //air gap int airGap = liquidClass.AspirationSinglePipetting.TrailingAirgap + liquidClass.AspirationSinglePipetting.LeadingAirgap; volume += airGap; Move2Position(labwareLabel, wellID); Move2Position(labwareLabel, wellID, "ZDispense"); var res = MoveController.Instance.Dispense(volume, maxSpeedV, startSpeedV, endSpeedV); pipettingResult = res == e_RSPErrorCode.RSP_ERROR_NONE ? PipettingResult.ok : PipettingResult.abort; PipettingTrackInfo pipettingTrackInfo = new PipettingTrackInfo(labwareLabel, sWellID, volume, pipettingResult, barcode, false); ThrowCriticalException(res, "喷液"); Move2Position(labwareLabel, wellID); }
public void Aspirate(string labwareLabel, List <int> wellIDs, List <double> volumes, LiquidClass liquidClass, out PipettingResult pipettingResult, string barcode = "") { string errMsg = ""; pipettingResult = PipettingResult.ok; int wellID = wellIDs.First(); double volume = volumes.First(); double leadingAirGap = liquidClass.AspirationSinglePipetting.LeadingAirgap; string sCommandDesc = string.Format("Aspirate volume:{0} from:{1} in:{2},lc:{3}", volume, wellID, labwareLabel, liquidClass.SaveName); log.Info(sCommandDesc); Move2Position(labwareLabel, wellID); var labware = layout.FindLabware(labwareLabel); Move2Position(labwareLabel, wellID, "ZStart"); //aspirate air gap var res = MoveController.Instance.Aspirate(leadingAirGap, maxSpeedV, startSpeedV, endSpeedV); ThrowCriticalException(res, "吸液"); int speedMMPerSecond = 30; res = MoveController.Instance.DetectLiquid(labware.ZValues.ZStart, labware.ZValues.ZMax, speedMMPerSecond); ThrowCriticalException(res, "液面检测移动"); MoveController.Instance.StopLiquidDetection(); //检测不到或液体不够,循环询问, double z = MoveController.Instance.GetZPos(_eARM.左臂); bool bok = z < labware.ZValues.ZMax; bool hasEnoughLiquid = false; if (bok) { hasEnoughLiquid = IsEnoughLiquid(labware, volume, liquidClass.AspirationSinglePipetting.SubMergeMM); if (!hasEnoughLiquid) { bok = false; } } if (!bok) { string title = !hasEnoughLiquid ? "液体不足" : ""; LiquidNotDetected liquidNotDetectForm = new LiquidNotDetected(title); liquidNotDetectForm.ShowDialog(); var userSelection = liquidNotDetectForm.UserSelection; switch (userSelection) { case NextActionOfNoLiquid.abort: pipettingResult = PipettingResult.abort; errMsg = "无法检测到液体,放弃运行程序!"; log.Error(errMsg); throw new CriticalException(errMsg); case NextActionOfNoLiquid.aspirateAir: pipettingResult = PipettingResult.air; Move2Position(labwareLabel, wellID); res = MoveController.Instance.Aspirate(volumes.First(), maxSpeedV, startSpeedV, endSpeedV); ThrowCriticalException(res, "吸空气"); break; case NextActionOfNoLiquid.gotoZMax: Move2Position(labwareLabel, wellID, "ZMax"); pipettingResult = PipettingResult.zmax; res = MoveController.Instance.Aspirate(volumes.First(), maxSpeedV, startSpeedV, endSpeedV); ThrowCriticalException(res, "ZMax吸液体"); break; case NextActionOfNoLiquid.retry: log.Debug("retry liquid detection"); break; case NextActionOfNoLiquid.skip: log.Info("Skipped the pipetting"); pipettingResult = PipettingResult.nothing; return; } } else //tracking 吸液 { DoTracking(labware, volume, liquidClass); } res = MoveController.Instance.Aspirate(volume + excessVolume, liquidClass.AspirationSinglePipetting.AspirationSpeed, startSpeedV, endSpeedV); if (res == e_RSPErrorCode.RSP_ERROR_NONE) { pipettingResult = PipettingResult.ok; } else if (res == e_RSPErrorCode.凝块) { ProcessClot(labware, wellID, volume, liquidClass, out pipettingResult, barcode); } else if (res == e_RSPErrorCode.泡沫) { //currently ignore, just mark the result pipettingResult = PipettingResult.bubble; } else { ThrowCriticalException(res, "吸液"); res = MoveController.Instance.Dispense(excessVolume, liquidClass.AspirationSinglePipetting.AspirationSpeed, startSpeedV, endSpeedV); ThrowCriticalException(res, "喷液"); //到zStart吸 trailing airGap Move2Position(labwareLabel, wellID, "ZStart"); double trailingAirGap = liquidClass.AspirationSinglePipetting.TrailingAirgap; MoveController.Instance.Aspirate(trailingAirGap, liquidClass.AspirationSinglePipetting.AspirationSpeed, startSpeedV, endSpeedV); //delay int delayMS = liquidClass.AspirationSinglePipetting.Delay; Thread.Sleep(delayMS); } //Move 2 ZTravel Move2Position(labwareLabel, wellID); }