Multiple Ghpython

Tuples that contain single element.

Let's start with Command: EditPythonScript

a=[1]
print a,
print type(a)

If you put ',' at the end of print statement, "start a new line" is not performed.
You may get:
|[1] <type 'list'>
a=[1,2]
print a,
print type(a)

You may get:
|[1, 2] <type 'list'>
Let's try tuples cases. First, try
a=(1,2)
print a,
print type(a)

the you get
|(1, 2) <type 'tuple'>
** However ** when you run
a=(1)
print a,
print type(a)

you get
|1 <type 'int'>
In order to make sure to let a as a tuple type object
a=(1,)
print a,
print type(a)

Safely, you get
|(1,) <type 'tuple'>
In turn, let's try
a=(1,2,(3))
print a,
print type(a)

You get
|(1, 2, 3) <type 'tuple'>
If you want to let the third element a tuple type object, you can write:
a=(1,2,(3,))
print a,
print type(a)

You may get
|(1, 2, (3,)) <type 'tuple'>
Conguraturation :)

GhPython and transmitting variables

Let's move on to Grasshopper and GhPython environment.
Type Command: Grasshopper
and place two GhPython components on your canvas.
Name them as "fromPython" and "toPython".
Connect them like
01.png
In the "toPython" component, type

print x

Plus, in the "fromPython" component, type
a=1

Hit "Test" button. You may get
02.png
Congratulation :)
The type should not be integer. For example,
03.png
** However, ** if you try to transmit a list or a tuple type object, you may get
04.png
This is completely different from the expected result. We expected that (1,2,3) is printed out.
This may caused because the Grasshopper automatically unpack list or tuple type objects and your python script code is called repeatedly for each element in the list or tuple object. Therefore, we should wrap a tuple type object (1,2,3) by another tuple type object. In the fromPython component let's rewrite as
a=((1,2,3),)

Then, you may get
05.png
If you want to transfer a nested tuple like ((1,2),3), if you make sure that it is wraped by another tuple, the structure is not destroyed by the Grasshopper.
06.png

Unpacking

When you received a tuple like x=((1,2),3) you can unpack it by stating like ((x,y),R)=x

print x
((x,y),R)=x #unpacking
print x,
print y,
print R
print ((x,y),R)

You may get
|((1, 2), 3)
|
|1 2 3
|
|((1, 2), 3)

Combination with rhinoscriptsyntax

Once you received a tuple, you can create geometries such as points and circles.
In the toPython component, let's try

import rhinoscriptsyntax as rs
print x
((x0,y0),R)=x #unpacking
a=rs.AddCircle((x0,y0,0),R)

You get
07.png

Applying an interactive user interface

Set up two input parameters "P" and "r" for the "fromPython" component.
Specify "P" as Point3d type object.
Specify "r" as float type value.
Modify the code written in "fromPython" as

import Rhino.Geometry as rg
a=(((P.X,P.Y),r),)

Connect "P" with a Point parameter component.
Connect "r" with a floating point slider component.
08.png
(Be sure the maximum value of the slider is greater than 1.0 otherwise you can not see the created circle)
Then you can change the position and radius of the circle in an interactive way.
10.png

Using Grasshopper list

Right-click "x" in the "toPython" component and specify it as a "List Access" type parameter.
09.png
Now, modify the script code in the "toPython" component as:

import rhinoscriptsyntax as rs
print x
a=list()
for ((x0,y0),R) in x:
    a.append(rs.AddCircle((x0,y0,0),R))

You get the same result but it has been rewritten in the "list and for" style.
10.png
Therefore, if you just duplicate the "fromPython" component,
11.png
you get
12.png

Gaussian hill

single hill

Set up a GhPython component like
15.png
Set up the input parameters as
P:Point3d
A,C:Floating point numbers
Then write a script that transmit ((P.X,P.Y),A,C) to another GhPython component.

import Rhino.Geometry as rg
a=(((P.X,P.Y),A,C),)

Place another GhPython component which is to receive the tuple. Connect them like
16.png
Plus, write the scirpt which receive the tuple and generate a surface.
import rhinoscriptsyntax as rs
import math
dots=list()
for i in rs.frange(-5.0,5.0,0.5):
    for j in rs.frange(-5.0,5.0,0.5):
        dots.append((i,j))
 
((x0,y0),A,C)=hill#Unpacking
func=lambda (x,y):(A*math.exp(-((x-x0)**2+(y-y0)**2)/(2*(C**2))))
 
z=map(func,dots)
a=list()
for ((x,y),z) in zip(dots,z):
    a.append(rs.AddPoint(x,y,z))

You may get
17.png

list of hills

Let's rename the input parameter "hill" to "hills".
Plus, specify "hills" as "List Access" type parameter.
Comment out the unpacking line.
Modify the lambda function as

((x0,y0),A,C)=hill #Unpacking
func=lambda (x,y),((x0,y0),A,C):(A*
math.exp(-((x-x0)**2+(y-y0)**2)/(2*(C**2))))

Add a new function that compute the sum of lambda functions
def Func(xy):
    z=0
    for hill in hills:
        z+=func(xy,hill)
    return z

Finally, replace z=map(func,dots) with z=map(Func,dots).
The following is our final code.
import rhinoscriptsyntax as rs
import math
dots=list()
for i in rs.frange(-5.0,5.0,0.5):
    for j in rs.frange(-5.0,5.0,0.5):
        dots.append((i,j))
((x0,y0),A,C)=hill #Unpacking        
func=lambda (x,y),((x0,y0),A,C):(A*
math.exp(-((x-x0)**2+(y-y0)**2)/(2*(C**2))))
def Func(xy):
    z=0
    for hill in hills:
        z+=func(xy,hill)
    return z
z=map(Func,dots)
a=list()
for ((x,y),z) in zip(dots,z):
    a.append(rs.AddPoint(x,y,z))

13.png
You may get the same result as the previous one.
17.png
But, it is rewritten in a "list and for" style.
Therefore, you can dupulicate the "Hill" components
18.png
and then you can get
19.png