Question

Iterative VariableSetter in Looped Custom Transformer


Badge +1
Hi,

 

 

I have a custom transformer with a loop and I want to change a published parameter at the end of each iteration.  I have tried to set the VariableSetter to the Published Parameter + 5 (which is what I want to increase the variable by each time) but it does not seem to be working.

 

 

Is there another way to make a Published Parameter iterative?

 

 

Thanks,

26 replies

Userlevel 2
Badge +17
Hi,

 

 

A parameter value cannot be changed at run-time. This may be a workaround:

 

Create a new attribute and assign the parameter value to the attribute before starting the iteration (ParameterFetcher or AttributeCreator).

 

Change the attribute value for each iteration.

 

 

Takashi
Badge +1
Thank you Takashi.

 

 

Inside "Attribute Creator", would I set the Attribute Name to the new attribute, and the Value to the Published Parameter, or is it the other way around?

 

 

I am quite confused by Published Parameters, and I'm also having trouble working out how to get the attributes from my main workspace into my Custom Transformer so I can use them in the "Group By" function of my AnchoredSnapper transformer...  Are you able to explain simply how to do this?

 

 

Thanks,
Badge +3
how does that change the parameter Takashi?

 

 

I was wondering what the goal of this is anyway.

 

If u (could)iterate the parameter....wich proces is going to use it? As u stil are within a local loop.

 

 

 

If your goal is to use the changed parameter wihtin the loop but after the change and before looptermination, it is best to use variableSetter and Retriever combo.
Badge +3
To get attributes from main space in your custom yyou must do following.

 

 

First your main space must have only 1 instance of the custom transformer in it.

 

Make sure at least one input is connected.

 

You double click on the input(icon) of your custom, a list of attributes connected to the custominput is shown..(edit transformer input) .pick some.
Badge +3

 

 

 

Again, this can only be done whne there is only 1 instance of the customtransformer in the workspace.

 

 

So if u got like 4 in main and  you decide you need another inputattribute...yes..you then have to remove 3 instances to do so...

 

 

It used to be quite a battle, in prior fme versions...;)
Badge +1
ok thanks Gio. 

 

 

In regards to the iteration, I am trying to create a loop with an AnchoredSnapper so that in each iteration the snap tolerance is increased by 5m (this is due to the fact that I have a lot of files all which require different snap tolerances). 

 

 

I don't quite understand Takashi's solution as when I use AttributeCreator to set the snap_tolerance attriubute to the Published Parameter, it turns the snap_tolerance also into a PUblished Parameter, and I'm not able to change this value once the iteration starts.

 

 

Basically, I just want to be able to do a simple iteration with the snap_tolerance value increasing by 5m at the end of each iteration....
Userlevel 2
Badge +17
Yes, you can create a new attribute and assign a parameter value with an AttributeCreator, like this.

 

 

 

A quick way to define "Group By" parameter linked to the AnchoredShapper is:

 

Find the AnchoredSnapper in the Navigator, right-click its "Group By" parameter to show a context menu, and click "Create User Parameter" command in the menu.

 

You can then define the parameter easily.

 

 

Userlevel 2
Badge +17
Gio, I think this is one of usual ways.

 

 

Badge +1
Thank you Takashi, I have tried to recreate a similar workflow.

 

 

Is there any way to check that the iterations with the +5 increase is actually working as it should be?
Userlevel 2
Badge +17
Are you perhaps trying to change the Tolerance parameter of the AnchoredSnapper in the loop?

 

The way I mentioned can be applied for general parameters. But the tolerance should be a constant, it can not be assigned an attribute value.

 

There may be no way to change in a data flow...
Badge +1
Hi Takashi,

 

 

Yes I want to change the tolerance parameter in the Anchored Snap......  So there is no way to do this?
Badge +3
Yes, but how does that change a user defined paramter at runtime?

 

 

 

That can only be done using tcl or phyton, is it not?

 

 

I understand what u wnat to do.

 

I don't see any relation or use for a parameter though.

 

 

 

Tehcnically it is a variabel you are suing to do that.

 

So u only need to create a variable like Snapping_Tolerance. prior to calling the transformer (wich has at least to inputs)

 

You do the snapping and insert the loop at the Untouched port.

 

Snapped to output.

 

 

When you do this, you will notice it is a blocking transfomer and must be exported as an .fmx.

 

The customftransformer wil turn blue.

 

It will have iterationcount and attribute to hold iteration.

 

 

 

There is not much to it...

 

 

 

 

 

The expressionevaluator does the incrementing.

 

(you can create attributes and or parameters to control it of course..)
Badge +1
Thanks Gio.

 

 

In the AttributeCreator_3 in your example, what do I set the new Snapping_tolerance attribute to as its Value?  I had previously set the value to a Parameter I created, but according to Takashi this won't work as I can't change Parameters in the loop...?

 

Badge +3
Yes the parameter u cannot change (uless u use python or tcl; there is topic somewhere june/july2014) showing this.

 

But you can use this as a input, to easily set a starting value.

 

In my case i did this in the attributecreator3.

 

The expressionevaluator takes care of the iteration (u can also create a parameter, to easily control this value)

 

 

 

 

You can use a parameter or attribute in stead of entering 5.0.

 

 

 

Badge +3

btw. an easy way to convert the transformer parameters to published parameters, is by selecting the create user parameter on the transformer parameters (at the little pull-down arrow).

Badge +3
...erhhm the last pic is not possible..of course..that would be trying to set a parameter.

 

 

U can only do that using a attribute. So snap_incr must be an attribute.

 

 

srry bout that..;)
Badge +3
..okay..i see where u come from now.... bit dense ..lol.

 

 

It doesn't allow for attributes. Took me a bit long to notice..

 

 

 

Badge +1
Yeh that's where I am getting stuck!  It seems silly that it only takes a Parameter and not an Attribute...
Userlevel 2
Badge +17
I looked at your previous post.

 

Snapping tolerances (http://fmepedia.safe.com/CommunityAnswers?id=906a0000000d4lGAAQ)

 

 

If your final goal is to resolve the missing links between end nodes of neighbor lines, this approach might help you. This way doesn't use the AnchoredSnapper.

 

 

1) Add unique ID and z-value (elevation of the contour) to every line as attributes (e.g. "_id" and "_z"), if the original lines don't have such attributes.

 

 

2) Create start and end points of every line (Snipper, or CoordinateExtractor+VertexCreator).

 

 

3) Send all the points to the Candidate port of a NeighborFinder.

 

Group By: _z

 

Maximum Distance: <specify approximate maximum distance+ between two end nodes that should be connected>

 

Close Candidate List Name: <specify a list name, e.g. "close">

 

 

4) For every Matched point, create an attribute storing a pair of "_id" (ID of the point) and "close{0}._id" (ID of the closest neighbor point), in the ascending order. i.e. "small ID - large ID".

 

* If you are using FME 2013 or earlier, sort the list by distance ascending beforehand.

 

 

5) Remove duplicate features on the ID pair.

 

 

6) Transform every point into a line segment that connects the point and the closest neighbor point.

 

Vertex Creator

 

Mode: Add Point

 

X Value: close{0).closest_candidate_x

 

Y Value: close{0}.closest_candidate_y

 

 

Resulting lines would be the missing links.

 

 

Notes

 

1) If there was a shorter contour line than the distance to the neighbor, the closest point could be other end node of the same line. In such a case, you will have to choose the closest point except the point of the same line from the list.

 

2) If it's guaranteed that the orientation of every source line is identical, the procedure can be simpler. i.e. send end points to Base, send start points to Candidate of the NeighborFinder; omit step 4 and 5. ID attribute and "close{}" list will also be unnecessary.

 

3) Since computational error may occur in the procedure, you might have to consider a slight tolerance when connecting lines.

 

Badge +1
Thanks Takashi, I'll give it a go. 

 

 

However, I'm not sure if your approach will help in certain cases where I have ends of contour lines that are about 100m apart, but I still want to join them to create an area....  That is why I wanted to use the Iterative Loop and set tolerances progressively larger and larger.

 

Badge +1
Hi Takashi,

 

In regards to your Note 2), how do I differentiate between the Start and End points to send into the Candidate of the Neighbor Finder?

 

Thanks

 

Userlevel 2
Badge +17
You can set an attribute to the "Maximum Distance" parameter of the NeighborFinder, so it may be easier to use the NeighborFinder than the AnchoredSnapper, even if the iteration is still necessary.

 

 

This screenshot illustrates the Note 2) case.

 

 

Badge +1
ok thanks Takashi I will give it a go.
Badge +3
Hi,

 

 

You can get the begin-and endpoints as well as the ends of the lines (te last pieces), relate them using unconditional relating.

 

Then calculate the intersections.

 

 

(limit intersections wich fall witihn the hullaccumulated of all objects).

 

Check if intersectpoints are witin linepieces.

 

Calculate extention to intersectpoint.

 

Select extention per peice wich is shortest.

 

 

(a couple of posts down i have posted the affiner for a 2D intersection, basic math..not too diff.)

 

You can set a maximumrange and use it in a loop if needed.

 

 

This is for snapping by extension of course, you can add a tolerance angle to intersectioncalculation if u need more freedom.

 

 

Badge +3
Hi,

 

I noticed you talking about contours (bit late).

 

 

Open ends on contours only occur at the border, if i'm not mistaken.

 

To close the entire area, that is to create area/polygon of all, i use a different approach.

 

 

 

I create a concave hull off the total of the contours. Then snap open ended contours to this border.

 

Then a intersector of the lines that snapped (or cross if u sue extend) with the border.

 

This gives u all the required topology to create areas of all the contour lines.

 

 

If you are interested and still read this, i have a couple of workspaces using this technique..

Reply