Biomek Scripting Tools

SO, what I’m exploring is controlling Biomek externally and/or adding features to use in Biomek that were made externally. I don’t have a desired language, but I know you can use Visual Basic or C# for it if you are using Visual Studio. This is more of a “poke around while trying not to break things” endeavor to add custom functionality in what little free time I have. I’m most interested in trying to add custom UI elements for users to interact with while using methods or into Biomek 5.

There is a way to import the DLLs and have Visual studio create what looks to be essentially a “wrapper” for them. But, you’re pretty much flying blind this way so I’ve reached out to Beckman to get more details and possibly some documentation. I have also been told by folks at Beckman there are groups that have written their own entire application to replace Biomek 5 as the software controller, meaning PyLabRobot might be able to add a Biomek 5 API. But, there seems to be a lot of potential for adding small bits custom of functionality that aren’t quite that crazy or intense.

1 Like

This resource is amazing. Thanks for sharing. It’s so difficult to find good Biomek support.

I’d love to join the Discord group. Would you please send the invite again?

2 Likes

Here you go!

APU Invite

This one won’t expire but is limited to 100 uses (just in case a nefarious bot finds it).

1 Like

Thank you! Hope it does get 100 legit users. It’s so helpful to me already!!!

Could you please send the link again? It has expired.

1 Like

The last one I posted above is still active. You can find it here.

I have seen some questions about scripting being answered on the Biomek Programming subreddit:
https://www.reddit.com/r/BiomekProgramming/?rdt=36502

This is almost always VB.

1 Like

The way Biomek handles its multichannel tips always bothered me. You have to either use full boxes every time, or shuffle tips around until they’re in reasonable positions - but what if you put a clean tip in a spot that’s touched sample? Here’s a way to deal with that. At the end of the run, discard all the used tips. At the start of the next run, ask the user for an offset for each of your multichannel tip boxes (or use the same offset for all boxes). Then you can use that offset to automatically clear the tips from the boxes within the software, and when you pick up tips, you can used Advanced Load and pick up at column (13-Offset-Columns).

Here’s a friendly little utility that you can load into a script step. Open the secret menu with Ctrl-Shift-u and put this in the HTML section:

<HTML>

<style type="text/css">
  body {
    background-color: #f2f2f2;
    margin: 0;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }

  h1 {
    margin-bottom: 4px;
    padding: 4px;
    font-size: 1.8em;
    border-bottom: 2px solid #ed1c24;
  }

 .shortTextBox {
  width: 50px;
  text-align: center;
 }

  .content {
    margin-left: 20px;
    margin-right: 20px;
    margin-bottom: 20px;
    clear: both;
  }

</style>

<body class="content">
<h1>Set tip box as partially used for improved MC handling</h1>
<br><br>
<b>Position: <input type="text" BFXName="Position"></b>
<br><br>
<b>Empty columns on the right: <input type="text"  width="20" bfxName="ColsUsed"></b>
<br><br>
<b>Locates the labware on the deck by labware name and sets the "volume" dataset to 0 for the indicated number of columns.
</body>
</HTML>

And this in the code section:

'' This function locates the labware on the deck. If labware is not present
'' due to the labware not being present on conditional statement or lost, Nothing is returned
'' Parameters:
'' LabwareName: name of the labware to find

function FindLabwareByName(LabwareName)
  dim result, LabwarePosName, pos, lw

  set result = Nothing
  LabwarePosName = Pipettor.Deck.FindLabwarePosition(LabwareName)
  if Positions.VariantDictionary.IsBound(LabwarePosName) then
    set pos = Positions(LabwarePosName)
	If pos.StackDepth > 1 then
	  for each lw in pos.Stack
	    if (lw.Properties.VariantDictionary.IsBound("Name")) then
        if (lw.Properties.Name = LabwareName) then
		      set result = lw
        end if
		end if
	  next
	end if
	if result is Nothing then
	  if not IsNull(pos.Labware) and pos.Labware.Properties.VariantDictionary.IsBound("Name") then
      if (pos.Labware.Properties.Name = LabwareName) then
		    set result = pos.Labware
      end if
	  end if
	end if	
  end if
  
  if result is Nothing then
   Err.Raise vbObjectError+1, "Set used tip box columns", "Labware """ & LabwareName &""" Not Found. Check Spelling of Labware Name. If Labware Name is Correct, Check GLS USE Column To Make Sure Labware Is On Deck."
  else
   set FindLabwareByName = result
  end if
end function

function ColumnMajorToRowMajor  (wellNum, Row, Col)
 dim tmpcols, tmprow
 tmpcols = ((wellNum-1) \ Row)+ 1
 tmprow = (wellNum-1) mod Row + 1
 ColumnMajorToRowMajor = tmpcols + ((tmprow-1) * Col)
end function

Sub SetWellVolume (lw, well, volume)
 dim pod1
 lw.AmountsKnown = true
 lw.Known = True
 lw.Nominal = False
 lw.Properties.SenseEveryTime = False
 lw.SetWellAmount volume, well, pod1
 lw.ConfigureSeekStates array(well), 3
end Sub

set eng = Createobject("Biomek5.EngineObject")
pos = eng.EvaluateExpression (StepDictionary.Position)

set LabwarePos = FindLabwareByName(pos)
cols = eng.EvaluateExpression (StepDictionary.ColsUsed)

wellCount = LabwarePos.Class.WellsY*LabwarePos.Class.WellsX

tipsUsed = LabwarePos.Class.WellsY*(LabwarePos.Class.WellsX - cols) + 1

for l = tipsUsed to wellCount
 well = ColumnMajorToRowMajor(l, LabwarePos.Class.WellsY, LabwarePos.Class.WellsX)
 SetWellVolume LabwarePos, well, 0
next

StepDictionary.Description = "Set "& pos & "'s tip status to " & ColsUsed & " empty columns on the right side."

This requires a bit of user confidence, of course. And the code is modified from a Beckman utility so it’s probably a little crufty.

1 Like