The spreadsheet has now been updated, and can be downloaded from:

Similar code has also been updated in the xlwScipy spreadsheet:

A typical graph example is shown in the scree shot below:

See linking to the Python Matplotlib library for more details. The code in the post has now also been updated.

]]>

Using an XY chart in place of the line chart is one way to get the correct trend line (which will work for any sequence of x values), but there is another way:

Right click on the X axis, and select Format Axis … then set Axis Type to Date axis:

The line chart and the XY chart now display the same (correct) trend line.

The trend line will also still work correctly if there are one or more negative x values (although the values do not display in the axis labels):

But be careful, the line chart treats the x values as being date numbers, and truncates all decimal values to the integer part:

For more details see Jon Peltier’s blog.

]]>

The problem was caused by using a line chart, rather than an XY (scatter) chart. A line chart treats the x-axis values as text labels, even when the data range is formatted as numbers. When calculating a trend line Excel treats the x range as a consecutive sequence of integers starting at 1, regardless of the value displayed. As a result, if the x values are any other sequence the trend line equation displayed will be totally different to the correct one.

The solution is simple, convert the chart to an XY chart.

As an example, the screenshot below shows the function:

y = 2x^4 + 3x^3 – 4x^2 + 5x + 1

plotted on a line chart:

The trend line is a good fit to the plotted points, but the calculated trend line formula is totally different to the correct one.

The chart type can be changed to an XY (Scatter) type, using the Chart-Tools, Design ribbon:

The function formula then displays correctly:

]]>

From the ABC:

Remembering John Clarke

From North Palmerston City Council –

After an off-night at N Palmerston, John Cleese named the city “the suicide capital of New Zealand”. John Clarke, who was born there, suggested that the city council should respond by naming the local rubbish dump after Cleese, which they duly did, complete with official signage. Much to the amusement of Eric Idle:

]]>

The RCInteract function will generate a moment-axial load interaction diagram to a number of design codes. For AS 3600, and now AS 5100 as well, it will also adjust the results according to the specified confinement steel.

The screen shot below shows input and plotted results for 65 MPa concrete to AS 3600 including the effect of compression steel (blue line), and with compression steel ignored:

If the confinement option is set to 1 the compression steel is included for axial loads <= 0.5Phi.Nu:

Confinement option 2 applies the AS 3600 limitations for standard confinement to Cl. 10.7.3, for concrete grades >= 65 MPa:

Confinement option 3 gives results where special confinement to Cl. 10.7.3 is provided, i.e. compression steel is included for all axial loads.

The function input is (arguments in italics are optional):

RCInteract(UMomin, *PRange, NSteps, Muin, Code, CompFace, AxLoadA, Confinement*):

- UMomin: Section details (Range D4:D16 in the example data)
*PRange:*Axial load range; default = 0 to Phi.Pu*NSteps:*Number of output increments; default = 20*Muin:*Array of moments for each axial load, defining the compression face; default = use CompFace*Code:*Design code; default = 1 = AS 3600 and AS 5100-2017*CompFace:*Compression Face, 1 = top face, anything else = bottom face; default = 1*AxLoadA:*Array of output axial loads; default = use Prange and NSteps*Confinement:*Confinement option (Code = 1 only); default = -1 (include compression steel for all loads)

Output is an array with 3 or 1 columns, depending on whether AxLoadA was specified; see below:

To display all results the function must be entered as an array function, by selecting the required output range and pressing Ctrl-Shift-Enter. See Using Array Functions and UDFs for details.

]]>

The main new feature in the latest version is a new RCInteract function, which generates an axial load-moment capacity interaction diagram, including corrections for confinement steel type, to AS 3600.

The screen shot below shows sample input and output. Further details will be given in the next post.

]]>

]]>

I recently updated to the latest version of NumPy (1.12.1), and today I discovered that some of my spreadsheets using NumPy arrays (via xlwings) were returning errors like:

IndexError: only integers, slices (`:`), ellipsis (`…`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

The problem was that using floats to index NumPy arrays previously generated a warning, but now generates an error:

DeprecationWarning to error

•Indexing with floats raises IndexError, e.g., a[0, 0.0].

•Indexing with non-integer array_like raises IndexError, e.g., a[‘1’, ‘2’]

•Indexing with multiple ellipsis raises IndexError, e.g., a[…, …].

•Non-integers used as index values raise TypeError, e.g., in reshape, take, and specifying reduce axis

You might ask, why use floats to index an array in the first place? The reason is that if a range is copied from Excel to Python then by default all the values are passed as float64. The array could be converted to all integers, but if the values are mixed integers and floats (such as an array of node numbers and coordinates) that won’t work. In previous versions the values to be used as array indices could just be left as floats, but now it is necessary to convert them to integers before using them as index values.

I will be working through my Python code posted here and update as required, but if you come across an IndexError anywhere, please let me know.

]]>

Download VBAFormat.xlsb

Sub AddTolerance() 'SkipVought 2017 3.14 'Ammended to use selected range as input: Doug Jenkins 2017 3.15 'Output to the column to the right of the input range, or to the last column of selected range if NumCols > 4 Dim sVal As String, sMax As String, sMin As String Dim p1 As Long, p2 As Long, NumRows As Long, NumCols As Long, i As Long Dim RowVals As Range With Selection NumRows = .Rows.Count NumCols = .Columns.Count If NumCols < 4 Then NumCols = 4 For i = 1 To NumRows Set RowVals = .Cells.Offset(i - 1, 0).Resize(1, NumCols) sVal = RowVals(1, 1).Value 'The value sMax = "+" & RowVals(1, 2).Value 'The max tolerance sMin = RowVals(1, 3).Value 'The min tolerance With RowVals(1, NumCols) .Value = sVal & sMax & sMin p1 = InStr(.Value, "+") p2 = InStr(.Value, "-") With .Characters(Start:=p1, Length:=p2 - p1).Font .Superscript = True .Subscript = False End With With .Characters(Start:=p2, Length:=Len(.Value) - p2 + 1).Font .Superscript = False .Subscript = True End With End With Next i End With End Sub

Results are shown in the screenshot below:

The data consists of three adjacent columns: values and upper and lower tolerances. To run the macro either select just the input data range, or extend the range to the right, then press Alt-F8 and select AddTolerance. The output results will either be written to the column to the right of the input data, or if a wider range was selected, in the last column of the selected range, as shown above.

As another example, I have written a macro to convert text strings with exponents in “^x” format to superscript format, as shown below:

Sub FormatExp() ' Convert ^x to superscript format 'Output to the column to the right of the input range, or to the last column of selected range if NumCols > 2 Dim sVal As String, sMax As String, sMin As String Dim p1 As Long, p2 As Long, NumRows As Long, NumCols As Long, i As Long, NewString As String Dim RowVals As Range, j As Long, k As Long, k2 As Long, m As Long, Sup As Boolean, str As String, NumE As Long, EPosA() As Long, StrLen As Long With Selection NumRows = .Rows.Count NumCols = .Columns.Count If NumCols = 1 Then NumCols = 2 For i = 1 To NumRows Set RowVals = .Cells.Offset(i - 1, 0).Resize(1, NumCols) sVal = RowVals(1, 1).Value 'The value StrLen = Len(sVal) ' Count number of ^ characters NumE = 0 For j = 1 To StrLen If Mid(sVal, j, 1) = "^" Then NumE = NumE + 1 Next j If NumE = 0 Then RowVals(1, NumCols).Value = sVal Else ' find positions of ^ characters and length of exponent value ReDim EPosA(1 To NumE, 1 To 2) m = 0 For j = 1 To StrLen If Mid(sVal, j, 1) = "^" Then m = m + 1 EPosA(m, 1) = j k = InStr(j, sVal, " ") - 1 k2 = InStr(j, sVal, ")") - 1 If k2 > 0 Then If k < 1 Or k2 < k Then k = k2 End If If k < 1 Then k = Len(sVal) EPosA(m, 2) = k - j End If Next j ' Remove ^ characters NewString = "" For j = 1 To NumE If j = 1 Then m = 1 Else m = EPosA(j - 1, 1) + 1 NewString = NewString & Mid(sVal, m, EPosA(j, 1) - m) Next j NewString = NewString & Right(sVal, EPosA(NumE, 2)) ' Convert exponents to superscript format With RowVals(1, NumCols) .Value = NewString For j = 1 To NumE m = EPosA(j, 1) + 1 - j .Characters(Start:=m, Length:=EPosA(j, 2)).Font.Superscript = True Next j End With End If Next i End With End Sub

]]>

Birdland Films was created by Kerinne Jenkins in 2017, as a home for her own work across a number of platforms, but more importantly as a starting point. To establish a place where other like minded filmmakers, creatives and artists could come to collaborate and create.

Inspired by the feel, the tone and the emotion in the Patti Smith song ‘Birdland’;

I am helium raven and this movie is mine.

And we are free to create anything we could possibly imagine.

Whether it’s a film, a podcast, a music video, an installation, a play or a poem. Whether it’s for long or short, for big screens or small, there is no one format that we will limit ourselves to. Birdland Films hopes to grow and change with every person who comes into the fold.

But there is one rule of Birdland.

That at the heart of any project is a focus on character and story. It might seem like we’re stating the obvious, but we want to make sure that this comes through in anything we make, whether it’s a traditional narrative, a case study, a commercial or an installation.

Let’s never get too distracted by all the other parts of the process that we forget why we wanted to make these things in the first place.

]]>