Some multi-cultural songs

The latest concert of the excellent Willoughby Symphony Choir featured a collection of popular and folk songs, rather than their usual classical performances.  I was struck by the mixture of cultural influences in many of the songs, and have collected  a few of  my favourite performances with multi-cultural connections.

The first is a song usually associated with the African-American Roberta Flack, but written (I recently discovered) by the English folk singer, of Scottish ancestry, Ewan McColl.  Here it is performed by the Irish folk musician Christy Moore, performed in Scotland:

The next is an English song of life at sea, “A Sailor’s Life”, performed by Sheila Chandra with a unique mixture of Indian and English musical influences:

Next up, the Arabic song “El Helwa Di”, sung by American Anais Mitchell:

Finally, the last performance from today’s concert was the Scottish Song “Blooming Heather”, jointly performed by choir and audience. Here is a performance from Yorkshire lass Kate Rushby, assisted by a (rather larger) audience at the 2007 Cambridge Folk festival:

Posted in Bach | Tagged , , , , , | Leave a comment

Using Section Properties- Group

Following a recent comment I have updated the documentation for finding the section properties of groups of shapes in the Section-Properties-Group spreadsheet.  The revised file can be downloaded from:

Section Properties07-Group.zip

The screenshots below illustrate use of the Group function to find the composite section properties for a circular concrete section with steel reinforcement, taking account of the relative stiffness of the two materials.

First define the concrete shape on the DefShapes sheet:

Note that X and Y axes are tangential to the circle.  To simplify the generation of the reinforcement we want the circle centre at the origin, so in the groups table on the same sheet enter an offset of -R (450mm) for X and Y.  Enter 1 for the elastic modulus, then click the “Create new group” button:

The area should now be the same as in the section property results, but the centroid is moved to the origin, and the associated properties about the X and Y axes will be different.

The reinforcement diameter should now be defined in the section properties input:

The details of the reinforcing bars are now added in the group table.  Note that:

  • The bar data overwrites the data for the concrete.
  • The X and Y offsets are defined so that the centre of all the bars is on the Y axis at the required level (in this case 450 mm – 50 mm cover -24 mm bar diameter).
  • The individual bars are defined by a rotation angle about the origin.
  • The elastic modulus is defined as the modulus for steel/concrete (200/30) -1, because the steel is displacing concrete.

After entering the required details click the “Add shapes to group” button.  The Group Properties table will update:

The combined shape and group properties can now be seen on the “Coords_Group” sheet; click the “Recalc Group Properties” button, then the “Plot Group” button:

Details of each shape can also be viewed on the “Group data” sheet.  This table should always be checked to ensure that the correct number of elements are included.  Note that if shapes are accidentally added twice at the same location, this will not be obvious on the plot, but they will appear twice in the group data table.

The shape can also be modified by adding additional groups, or subtracting shapes using a negative elastic modulus.  In the example below the section properties are adjusted for the bottom region of the concrete being in tension, and therefore deducted from the concrete area.  The tension region is defined as a circular segment with a chord angle of +- 60degrees from the X axis:

This is then entered in the group table, rotated  through -90 degrees, so that the chord is parallel to the X axis:

Finally the three  reinforcement bars now in the tension zone are no longer displacing active concrete, so the area of these bars should be  added back, with an elastic modulus of 1:

The revised cross-section and section properties may now be plotted on the Coords_Group sheet:

Posted in Coordinate Geometry, Excel, Maths, Newton, Numerical integration, UDFs, VBA | Tagged , , , , , | 8 Comments

Passing variable argument lists from Excel to Python via xlwings

When calling a Python function it is sometimes necessary to pass a variable number of arguments.  Examples from the xlw_Scipy spreadsheet include:

  • Curve fitting functions, for which the functions to be fitted may have any number of arguments.
  • The Scipy statistics and distance functions have different optional arguments, depending on the statistic or distance metric being used.

Options to provide the required data are:

  • Pass a single range to Python, and extract the required arguments in Python code.
  • Pass a single range to VBA, and extract the required arguments in VBA code, passing  to Python as a single array.
  • Use a VBA ParamArray argument to combine any number of VBA arguments into a single array which can be passed to Python.
  • Use a single range or ParamArray to pass pairs of argument names and values to Python, where it can be easily converted to a dictionary.
  • Use the xlwings Dictionary converter, that turns a 2 column range into Python dictionary format.

The advantages and disadvantages of these methods are discussed below, with examples in the spreadsheet PassParamarray.xlsb and associated Python code, which can be downloaded from PassParamarray.zip.

In the examples below data is passed to Python functions in various formats.  The functions return two columns with the value of each argument (or the value of the first element in the case of an array), and the argument data type.

In the first three examples the data is passed to VBA as a single column or row.  In the first two cases this array is passed directly to the Python function.  In the third any text defining a spreadsheet range is converted to a variant array, before being passed to Python.

The VBA code for the xl_Range1 function is:

Function xl_Range1(DRange As Variant)
Dim NRows As Long, i As Long, RangeA() As Variant

DRange = DRange.Value2
NRows = UBound(DRange)
ReDim RangeA(1 To NRows)
For i = 1 To NRows
On Error Resume Next
RangeA(i) = Range(DRange(i, 1)).Value2
If IsArray(RangeA(i)) = False Then
If RangeA(i) = 0 Then RangeA(i) = DRange(i, 1)
RangeA(i) = Array(RangeA(i))
End If
Next i
xl_Range1 = RtnRange1(RangeA)
End Function

xl_Range1 calls the auto-generated VBA function RtnRange1, which passes the data to the Python function:

@xw.func
@xw.arg('rng', ndim = 1)    
def RtnRange1(rng): 
    """
    Return a value and  data type from each value in rng
    rng contains arrays or values 
    """
    rtn = []
    i =0
    for val in rng:
        if type(val) is tuple:
            if type(val[0]) is tuple:
                rtn.append([val[0][0], str(type(val))])
            else:
                rtn.append([val[0], str(type(val))])
        else:
            rtn.append([val, str(type(val))])
    return rtn

Passing a single range, the arguments must be either single values, or range addresses or names that can be converted to arrays in the VBA code. An alternative is to use the VBA ParamArray object, that allows any number of values or ranges to be passed to VBA, as shown in the three examples below:

The xlwParamA function (first two examples above) converts each element of the ParamArray to an array of values.

Function xlwParamA(ParamArray x() As Variant)
Dim Res As Variant, i As Long
   On Error GoTo rtnerr:
   
    For i = 0 To UBound(x)
        If TypeName(x(i)) = "Range" Then x(i) = x(i).Value2
        If IsArray(x(i)) = False Then x(i) = Array(x(i))
    Next i
    
    Res = Py.CallUDF("PassParamarray", "RtnArray", Array(x), ThisWorkbook, Application.Caller) 'RtnArray(x)

    xlwParamA = Res
    Exit Function
rtnerr:
    xlwParamA = Err.Description
    
End Function

The ParamArray object is then passed to the Python RtnArray function:

@xw.func
def RtnArray(x): 
    """
    Return a value and  data type from each value in rng
    """
    rtn = []
    for val in x:
        if type(val) is tuple:
            if type(val[0]) is tuple:
                rtn.append([val[0][0], str(type(val))])
            else:
                rtn.append([val[0], str(type(val))])
        else:
            rtn.append([val, str(type(val))])
    return rtn

In the third example the data is passed to Python as a list of arguments, using the Python *args notation:

@xw.func
def RtnRange3(*args): 
    """
    Return a value and  data type from each value in rng
    rng contains arrays or values 
    """
    rtn = []
    i =0
    for val in args:
        if type(val) is list:
            if type(val[0]) is list:
                rtn.append([val[0][0], str(type(val))])
            else:
                rtn.append([val[0], str(type(val))])
        else:
            rtn.append([val, str(type(val))])
    return rtn

xlwings recognises Python *args as being equivalent to a VBA ParamArray, and automatically generates appropriate code for the UDF:

Function RtnRange3(ParamArray args())
        If TypeOf Application.Caller Is Range Then On Error GoTo failed
        ReDim argsArray(1 To UBound(args) - LBound(args) + 1)
        For k = LBound(args) To UBound(args)
        argsArray(1 + k - LBound(args)) = args(k)
        Next k
        RtnRange3 = Py.CallUDF("PassParamarray", "RtnRange3", argsArray, ThisWorkbook, Application.Caller)
        Exit Function
failed:
        RtnRange3 = Err.Description
End Function

The final set of examples transfer pairs of values, or values and ranges, in a format that can easily be converted to a Python dictionary and used as keyword arguments for Python functions. In these examples the Python function returns a three column range, with the dictionary keys, as well as the value and data type for each item:

The first three examples above are similar to the earlier single column examples, except with the addition of data for the dictionary keys (see the download file for VBA and Python code).

The next two examples make use of the VBA ParamArray object to pass an array of values or arrays. As before, the version using the Python *args argument allows the VBA code to be generated automatically, and is recommended:

@xw.func
def RangeDict3(*args): 
    """
    Convert paramarray to dictionary and return index, value and types 
    """
    kwargs = dict(args[i:i+2] for i in range(0, len(args), 2))
    rtn = []
    for indx in kwargs:
        rtnv = kwargs[indx]
        if type(rtnv)is list: rtnv = rtnv[0]
        if type(rtnv)is list: rtnv = rtnv[0]
        rtn.append([indx, rtnv, str(type(kwargs[indx]))])
    
    return rtn

Using the xlwings add-in Import Functions automatically generates the VBA code for the UDF:

Function RangeDict3(ParamArray args())
        If TypeOf Application.Caller Is Range Then On Error GoTo failed
        ReDim argsArray(1 To UBound(args) - LBound(args) + 1)
        For k = LBound(args) To UBound(args)
        argsArray(1 + k - LBound(args)) = args(k)
        Next k
        RangeDict3 = Py.CallUDF("PassParamarray", "RangeDict3", argsArray, ThisWorkbook, Application.Caller)
        Exit Function
failed:
        RangeDict3 = Err.Description
End Function

Finally the xlwings Dictionary converter allows a two column range to be passed as keys and values of a Python dictionary, without additional coding:

@xw.func
@xw.arg('args', dict)
def RangeDict(args): 
    """
    Return a specified item from a dictionary of range addresses
    """
    rtn = []
    
    for indx in args:
        rtnv = args[indx]
        rtn.append([indx, rtnv, str(type(rtnv))])
    
    return rtn
Posted in Arrays, Excel, Link to Python, NumPy and SciPy, UDFs, VBA, xlwings | Tagged , , , , , , , , | 2 Comments

Two songs = 2/3 Wikipedia

It is said that a picture is worth a 1000 words.

On the same basis, a poem is worth 1000 pictures, and a song is worth 1000 poems.

So two songs are worth 2 billion words, which is about 2/3 of all the words in Wikipedia.

Enjoy:

Another Okenyo song with video directed by my daughter:

… and from Anais Mitchell “Before the Eyes of Storytelling Girls“:

I could tell you stories like the government tells lies
ah, but no one listens anymore
in the rooms, the women come and go
talking on the mobile phones
and the television talks about the war
when i was a baby, there was laughter in my house
my daddy smoked domestic cigarettes
and Thursday nights on the radio
live in concert- live from Cairo:
mother of Egypt!

mama, mama, be with me
with the music in your breast
in your glittering evening dress
and the white flag in your fist trembling

I could tell you stories like the past was dead and
gone
but I know nothing changes in this world
every day the muezzin calls
the sun comes up and Baghdad falls
before the eyes of storytelling girls
she was just a poor man’s daughter
going down into the sultan’s bed
he was desert, she was water
and he remembered every word she said, that she said,

and I say, grandma, grandma, be with me
in your tragic wedding gown
with your long hair hanging down
and the stories tumbling out, tumbling

I could tell you stories like the government tells lies
ah, but no one listens anymore
in the rooms the women come and go
talking on the mobile phones
and the television talks about the war, about the war
the television talks about the war

Posted in Bach | Tagged , , | 3 Comments

New Links – 2018

Some new links to active Excel related blogs:

David Hagar has been active in the Excel community for many years, and has published the Excel For You blog since 2013.  I was led to it by a recent post on a UDF generating a list of antonyms.Excel For You.

Excel Matters is the blog of self-confessed Excel addict Rory Archibald.

My Spreadsheet Lab is run by Kevin Lehrbass and has a wide range of useful articles, plus numerous links valuable links.

 

 

Posted in Computing - general, Excel | Tagged , , , , | Leave a comment