func assign_minor_layouts(group []string, plate *wtype.LHPlate, plateID string) (mgrps [][]string, masss map[int]string) { mgrps = make([][]string, 0, 10) masss = make(map[int]string, 10) // in this version we just use the number of wells in a column colsize := plate.WlsY row := 1 col := 1 for i := 0; i < len(group); i += colsize { // make a layout group grp := make([]string, 0, 8) grpsize := len(group) - i for j := 0; j < grpsize; j++ { if i+j >= len(group) { break } grp = append(grp, group[i+j]) } // get its assignment ass := plateID + ":" + wutil.NumToAlpha(row) + ":" + strconv.Itoa(col) + ":" + strconv.Itoa(0) + ":" + strconv.Itoa(1) mgrps = append(mgrps, grp) masss[col-1] = ass col += 1 } return mgrps, masss }
func Get_Next_Well(plate *LHPlate, component *LHComponent, curwell *LHWell) (*LHWell, bool) { nrow, ncol := 0, 1 vol := component.Vol if curwell != nil { // quick check to see if we have room vol_left := get_vol_left(curwell) if vol_left >= vol { // fine we can just return this one return curwell, true } // we need a defined traversal of the wells crds := curwell.Crds tx := strings.Split(crds, ":") nrow = wutil.AlphaToNum(tx[0]) ncol = wutil.ParseInt(tx[1]) } wellsx := plate.WlsX wellsy := plate.WlsY var new_well *LHWell for { nrow, ncol = next_well_to_try(nrow, ncol, wellsy, wellsx) if nrow == -1 { return nil, false } crds := wutil.NumToAlpha(nrow) + ":" + strconv.Itoa(ncol) new_well = plate.Wellcoords[crds] cnts := new_well.WContents if len(cnts) == 0 { break } cont := cnts[0].Name() if cont != component.Name() { continue } vol_left := get_vol_left(new_well) if vol < vol_left { break } } return new_well, true }
func NewLHPlate(platetype, mfr string, nrows, ncols int, height float64, hunit string, welltype *LHWell, wellXOffset, wellYOffset, wellXStart, wellYStart, wellZStart float64) *LHPlate { var lhp LHPlate lhp.Type = platetype lhp.ID = GetUUID() lhp.Mnfr = mfr lhp.WlsX = ncols lhp.WlsY = nrows lhp.Nwells = ncols * nrows lhp.Height = height lhp.Hunit = hunit lhp.Welltype = welltype lhp.WellXOffset = wellXOffset lhp.WellYOffset = wellYOffset lhp.WellXStart = wellXStart lhp.WellYStart = wellYStart lhp.WellZStart = wellZStart wellcoords := make(map[string]*LHWell, ncols*nrows) // make wells rowarr := make([][]*LHWell, nrows) colarr := make([][]*LHWell, ncols) arr := make([][]*LHWell, nrows) wellmap := make(map[string]*LHWell, ncols*nrows) for i := 0; i < nrows; i++ { arr[i] = make([]*LHWell, ncols) rowarr[i] = make([]*LHWell, ncols) for j := 0; j < ncols; j++ { if colarr[j] == nil { colarr[j] = make([]*LHWell, nrows) } arr[i][j] = NewLHWellCopy(*welltype) crds := wutil.NumToAlpha(i+1) + ":" + strconv.Itoa(j+1) wellcoords[crds] = arr[i][j] arr[i][j].Crds = crds colarr[j][i] = arr[i][j] rowarr[i][j] = arr[i][j] wellmap[arr[i][j].ID] = arr[i][j] arr[i][j].Plate = &lhp arr[i][j].Plateinst = lhp.Inst arr[i][j].Plateid = lhp.ID arr[i][j].Platetype = lhp.Type arr[i][j].Crds = crds } } lhp.Wellcoords = wellcoords lhp.HWells = wellmap lhp.Cols = colarr lhp.Rows = rowarr return &lhp }
func AdvancedExecutionPlanner(request *LHRequest, parameters *liquidhandling.LHProperties) *LHRequest { // in the first instance we assume this is done component-wise // we also need to identify dependencies, i.e. if certain components // are only available after other actions // this will only work if the components to be added are to go in the same order // get the layout groups minorlayoutgroups := request.Output_minor_group_layouts ass := request.Output_assignments inass := request.Input_assignments output_solutions := request.Output_solutions input_plates := request.Input_plates output_plate_layout := request.Output_plate_layout plate_lookup := request.Plate_lookup // highly inelegant... we should swap Tip Box Setup // around to take place after, then this whole thing // is a non-issue tt := make([]*wtype.LHTip, 1) tt[0] = request.Tip_Type.Tiptype parameters.Tips = tt instructions := liquidhandling.NewRobotInstructionSet(nil) // need to deal with solutions order := request.Input_order for _, name := range order { //fmt.Println(name) // cmpa holds a list of inputs required per destination // i.e. if destination X requires 15 ul of h2o this will be listed separately // at this point all of the requests must be for volumes, // we need a mapping from these to where they belong // do we? /* cmpa:=value.([]map[string]interface{}) cmp_map:=make(map[string]interface{}, len(cmpa)) for _,cmp:=range cmpa{ srcid:=cmp.Srcid cmp_map[srcid]=cmp } */ for n, g := range minorlayoutgroups { grp := []string(g) // get the group assignment string assignment := ass[n] // the assignment has the format plateID:row:column:incrow:inccol // where inc defines how the next one is to be calculated // e.g. {GUID}:A:1:1:0 // {GUID}:A:1:0:1 asstx := strings.Split(assignment, ":") plate := asstx[0] toplatenum := wutil.ParseInt(plate) row := wutil.AlphaToNum(asstx[1]) col := wutil.ParseInt(asstx[2]) incrow := wutil.ParseInt(asstx[3]) inccol := wutil.ParseInt(asstx[4]) whats := make([]string, len(grp)) pltfrom := make([]string, len(grp)) pltto := make([]string, len(grp)) plttypefrom := make([]string, len(grp)) plttypeto := make([]string, len(grp)) wellfrom := make([]string, len(grp)) wellto := make([]string, len(grp)) vols := make([]*wunit.Volume, len(grp)) fvols := make([]*wunit.Volume, len(grp)) tvols := make([]*wunit.Volume, len(grp)) for i, solID := range grp { sol := output_solutions[solID] // we need to get the relevant component out smpl := get_aggregate_component(sol, name) // we need to know where this component was assigned to inassignmentar := []string(inass[name]) inassignment, ok := get_assignment(inassignmentar, &input_plates, smpl.Vol) if !ok { wutil.Error(errors.New(fmt.Sprintf("No input assignment for %s with vol %-4.1f", name, smpl.Vol))) } inasstx := strings.Split(inassignment, ":") inplt := inasstx[0] inrow := string(inasstx[1]) incol := wutil.ParseInt(inasstx[2]) // we can fill the structure now whats[i] = name pltfrom[i] = plate_lookup[string(inplt)] pltto[i] = plate_lookup[output_plate_layout[toplatenum]] wellfrom[i] = inrow + strconv.Itoa(incol) wellto[i] = wutil.NumToAlpha(row) + strconv.Itoa(col) v := wunit.NewVolume(smpl.Vol, smpl.Vunit) v2 := wunit.NewVolume(0.0, "ul") vols[i] = &v // TODO Get the proper volumes here fvols[i] = &v2 tvols[i] = &v2 row += incrow col += inccol } ins := liquidhandling.NewTransferInstruction(whats, pltfrom, pltto, wellfrom, wellto, plttypefrom, plttypeto, vols, fvols, tvols /*, parameters.Cnfvol*/) instructions.Add(ins) } } inx := instructions.Generate(request.Policies, parameters) instrx := make([]liquidhandling.TerminalRobotInstruction, len(inx)) for i := 0; i < len(inx); i++ { instrx[i] = inx[i].(liquidhandling.TerminalRobotInstruction) } request.Instructions = instrx return request }