Пример #1
0
// default setup agent
func BasicSetupAgent(request *LHRequest, params *liquidhandling.LHProperties) *LHRequest {
	// this is quite tricky and requires extensive interaction with the liquid handling
	// parameters

	// the principal question is how to define constraints on the system

	// I think this needs to remain tbd for now
	// instead we can rely on the preference system I already use

	plate_lookup := make(map[string]string, 5)
	tip_lookup := make([]*wtype.LHTipbox, 0, 5)

	tip_preferences := params.Tip_preferences
	input_preferences := params.Input_preferences
	output_preferences := params.Output_preferences

	// how do we set the below?
	// we don't know how many tips we need until we generate
	// instructions; ditto input or output plates until we've done layout

	// input plates
	input_plates := request.Input_plates

	// output plates
	output_plates := request.Output_plates

	// tips
	tips := request.Tips

	// we put tips on first

	setup := request.Setup

	if len(setup) == 0 {
		setup = wtype.NewLHSetup()
	}

	for _, tb := range tips {
		// get the first available position from the preferences
		pos := get_first_available_preference(tip_preferences, setup)
		if pos == -1 {
			RaiseError("No positions left for tipbox")
		}

		position := "position_" + strconv.Itoa(pos)
		setup[position] = tb
		plate_lookup[tb.ID] = position
		tip_lookup = append(tip_lookup, tb)
	}

	setup["tip_lookup"] = tip_lookup

	// this logic may not transfer well but I expect that outputs are more constrained
	// than inputs for the simple reason that most output takes place to single wells
	// while input takes place from reservoirs

	// outputs

	for _, p := range output_plates {
		pos := get_first_available_preference(output_preferences, setup)
		if pos == -1 {
			RaiseError("No positions left for output")
		}
		position := "position_" + strconv.Itoa(pos)
		setup[position] = p
		plate_lookup[p.ID] = position
		params.AddPlate(position, p)
	}

	// inputs

	for _, p := range input_plates {
		pos := get_first_available_preference(input_preferences, setup)
		if pos == -1 {
			RaiseError("No positions left for input")
		}
		position := "position_" + strconv.Itoa(pos)
		setup[position] = p
		plate_lookup[p.ID] = position
		params.AddPlate(position, p)
	}

	request.Setup = setup
	request.Plate_lookup = plate_lookup
	return request
}
Пример #2
0
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
}