SikuliXIDE; Mojave; Robot Framework: How does one get Region objects to work in Jython functions that are passed in from Robot Framework

Asked by Melvin Raymond on 2019-05-07

I am passing captured Region objects from RFW to some Jython functions within the SikuliX IDE, but RFW will convert the object to a string. In other words Region(820,467,120,50) is now a string that gets passed to a variable in the function. Thus if I try to use that for setting regions of interest, I believe I'll have to get those numbers converted back to integers or setROI(region) will not work.

I believe that I can parse all those numbers out of the string and convert each to an integer like : X, Y, H, W so instead of using setROI(region) I'd have to use setROI(X, Y, H, W). The problem with doing this is the regions I pass into the function will have different sized integers so parsing would be a pain. Is there something easier than parsing to get the function region variable into a state that will make it work? Below is the Jython function I'm using. It all works except the part with the "region" variable. I can substitute the real Region object into it and it works fine so I know the RFW is messing it up.

# Function opens the Column Options context menu for a specified DataSets X or Y column you must already be
# in Table View or Graph and Table view and use the correct variables
# selected_view = T_VIEW, or GT_VIEW so it knows what Region to look for the overflow elipses in
# dataset = DATA_SET_1 or some other recorded image and name for a dataset
# column = COLUMN_X, or COLUMN_Y so it defines region of interest for locating correct elipses
# region = T_X_REGION, T_Y_REGION, GT_X_REGION, GT_Y_REGION to define region with elipses to click
# overflow = image object of elipses to click and open context menu
# appregion to set Region of Interest back to the full app view
  def column_options_context_menu (self, selected_view, dataset, column, region, overflow, appregion):
    dataset = dataset[1:-1] # parse off double quotes caused by RFW
    overflow = overflow[1:-1] # parse off double quotes caused by RFW
    if exists(dataset, 5):
      print "Dataset found"
      raise ValueError("dataset doesn't appear to be visible")
    if selected_view == "1":
      print "Table View" # No graph visible here
      if column == "1":
        print "Working with X column"
      elif column == "2":
        print "working with Y column"
        raise ValueError("column variable 1 is incorrect")
    elif selected_view == "2": # graph and table will be visible
      print "Graph and Table view"
      if column == "1":
        print "Working with X column"
      elif column == "2":
        print "working with Y column"
        raise ValueError("column variable 2 is incorrect")
      raise ValueError("selected_view variable is incorrect")
    mouseMove(100, 0) # move in case Graph is there as it changes the curser to crosshair
    wait(1) # time for switching cursor back to arrow once off the Graph
    wait(2) # give enough time for the context menu to appear
    setROI(region) # reset Region of Interest back to the full app region view

Question information

English Edit question
Sikuli Edit question
No assignee Edit question
Solved by:
Melvin Raymond
Last query:
Last reply:
RaiMan (raimund-hocke) said : #1

How do you use the function from RFW?

Melvin Raymond (fribian) said : #2

Oh, so I use this defined region constant:

${T_X_REGION} Region(820,467,120,50)

I'm calling the above function using this RFW command:

 column options context menu ${T_VIEW} ${DATA_SET_1} ${COLUMN_X} ${T_X_REGION} ${OVERFLOW} ${APP_REGION}

So in this case I've already set up the app so it's in Table view, then I send the "region" variable the ${T_X_REGION} which will define a small area on the table for use in another function later on.

Melvin Raymond (fribian) said : #3

For a larger perspective:

Test Manual Decimal Place Values Test (Table View)
    [Documentation] Test verifies Decimal Place settings
    Log Executing Manual Decimal Place values Test
    Log Filling the Data Table with some values
    select experiment type ${MANUAL_ENTRY}
    view options ${VIEW_OPTIONS} ${TABLE}
    initialize table ${TESTAPP} ${TABLE_LOCATOR}
    write to selected cell ${CELL_LOCATOR} 2
    grid movement ${MOVEDOWN} 1
    write to selected cell ${CELL_LOCATOR} 31.5
    grid movement ${MOVEDOWN} 1
    write to selected cell ${CELL_LOCATOR} 55.67
    grid movement ${MOVEDOWN} 1
    write to selected cell ${CELL_LOCATOR} 888.901
    grid movement ${MOVEDOWN} 1
    grid movement ${MOVEUP} 1
    Log Selecting Decimal Place from Column Options dialog
    column options context menu ${T_VIEW} ${DATA_SET_1} ${COLUMN_X} ${T_X_REGION} ${OVERFLOW} ${APP_REGION}
    select column context ${COLUMN_OPTIONS} ${OPTIONS_EXIT}
    select displayed precision ${DECIMAL_PLACES_RADIO} ${SPINNER} 9 ${APPLY} ${OPTIONS_EXIT}

Melvin Raymond (fribian) said : #4

I was doing a little thinking this morning while riding the bike to work. It doesn't solve the problem with passing the correct object from Robot Framework to Sikuli Jython functions but could possibly be a workaround just in case:

I could call an external function that takes the "region" object that has been sent to my Jython function. That external function could parse out the "X", "Y", "W", "H" , and then turn them inter Integers. Then those integers could be stuffed into a tuple object. The tuple object could be returned back to me. Then I could reference the tuple items in the setROI(x, y, w, h) to set my Region of Interest. I'm just familiarizing myself with tuples as of yesterday, so perhaps this could be a workaround that once it's working could be used for any Region(x, y, w, h) sent to the Jython function from Robot Framework. I might be wrong about this but it was something I was pondering.

Just FYI: The reason for sending objects to the Jython functions is to keep all images outside of the functions so if something changes I'll be able to fix the object in just 1 place as opposed to digging through all my Jython functions to fix the object.

RaiMan (raimund-hocke) said : #5

In a function where you get a string instead of an objec from RFWt, simply say

region = eval(regionString)

Take care, that the string contains something, that is valid Python!

Melvin Raymond (fribian) said : #6

Raiman! Excellent! That worked. You make that look so easy and it was. This saved my bacon once again. Thank you Raiman! Now I need to look into what "eval" actually is and how it works. Learned something really good this morning. Problem solved by Raiman.

Melvin Raymond (fribian) said : #7

By the way, just for those who might need to know. I simply put region = eval(region) and app region = eval(app region) into the function below to covert the arguments into a usable form that setROI could use:

  def column_options_context_menu (self, selected_view, dataset, column, region, overflow, appregion):
    region = eval(region) # converts Region object so it can be used in setROI(region) due to RFW
    appregion = eval(appregion) # converts Region object back to usable form for setROI(appregion)

RaiMan (raimund-hocke) said : #8

Since Python/Jython is an interpreting language, you can create strings of valid code at runtime and

eval: let the python expression be evaluated and get the result

exec: just run the given string as python code in the current context (global variables)

all the best