Supplying Your Own Limb Properties ---------------------------------- Some analysis functions calculate their results from a series of properties per limb profile point. Usually, when the underlying model permits some sort of latitude, like accounting for the cross-section the limb has at each point, the analysis function will accept another function to calculate these properties for each profile point. (The :func:`beckhoff1964` analysis function, for example, accepts this in its ``shape`` keyword argument.) The downside to that is that one cross-sectional shape gets assumed for each profile point. For many bows, this is a good enough approximation. However, in some scenarios or for some bows, more accuracy is required and properties have to be calculated on a per-profile basis. There are two ways to go about this: The Completely Manual Approach :::::::::::::::::::::::::::::: Obviously, you get the most direct control when you look up the properties an analysis function calculates, and supply them manually. So, for :func:`beckhoff1964`, you would be required to provide second moment of area in column ``I`` and the distance from neutral plane to belly in column ``e_belly``:: >>> my_df # the DataFrame with just the bare necessities l width thickness 0 0.0 1.2 0.9 1 10.0 1.6 1.0 ... 10 80.0 3.6 2.1 >>> my_df['I'] = [0.05, 0.1, ..., 1.9] >>> my_df l width thickness I 0 0.0 1.2 0.9 0.05 1 10.0 1.6 1.0 0.10 ... 10 80.0 3.6 2.1 1.90 …and so on, until all required columns are filled with values. If you then do:: >>> results, _ = pb.analysis.beckhoff1964(my_df, some_moe, some_mor) The Beckhoff analysis will use your supplied values. .. rubric:: Pros: * Complete control * Derive properties by whichever method you desire .. rubric:: Cons: * Manual filling is a lot of work * Need to derive all the properties manually The Function-aided Approach ::::::::::::::::::::::::::: If using geometrical shapes makes a good enough approximation, you can leverage some automation by using the provided property functions, or write your own. Say your bow has a profile change somewhere in the limb, tapering from a rounded-back/flat-belly shape in the inner limb to a narrowed rectangular shape, you can fill them in this way:: >>> my_df # note the ‘shoulder’ between rows 3 and 4 l width thickness 0 0.0 0.9 1.30 1 7.0 1.0 1.40 2 12.0 1.0 1.50 3 19.0 1.1 1.50 4 22.0 2.7 1.10 5 33.0 3.1 1.15 6 45.0 3.4 1.20 7 57.0 3.5 1.40 8 55.0 2.1 2.50 9 60.0 2.1 2.60 >>> # step 1: rectangular I for the outer limb >>> my_df.loc[0:3, 'I'] = pb.rect_I(df['width'], ... df['thickness']) >>> my_df l width thickness I 0 0.0 0.9 1.30 0.164775 1 7.0 1.0 1.40 0.228667 2 12.0 1.0 1.50 0.281250 3 19.0 1.1 1.50 0.309375 4 22.0 2.7 1.10 NaN 5 33.0 3.1 1.15 NaN 6 45.0 3.4 1.20 NaN 7 57.0 3.5 1.40 NaN 8 55.0 2.1 2.50 NaN 9 60.0 2.1 2.60 NaN >>> # step 2: rectangular I for the handle >>> my_df.loc[7:9, 'I'] = pb.rect_I(my_df['width'], ... my_df['thickness']) >>> my_df l width thickness I 0 0.0 0.9 1.30 0.164775 1 7.0 1.0 1.40 0.228667 2 12.0 1.0 1.50 0.281250 3 19.0 1.1 1.50 0.309375 4 22.0 2.7 1.10 NaN 5 33.0 3.1 1.15 NaN 6 45.0 3.4 1.20 NaN 7 57.0 3.5 1.40 0.800333 8 55.0 2.1 2.50 2.734375 9 60.0 2.1 2.60 3.075800 >>> # step 3: half-round I for the remainder >>> my_df.loc[4:6, 'I'] = pb.halfround_I(my_df['width'], ... my_df['thickness']) >>> my_df l width thickness I 0 0.0 0.9 1.30 0.164775 1 7.0 1.0 1.40 0.228667 2 12.0 1.0 1.50 0.281250 3 19.0 1.1 1.50 0.309375 4 22.0 2.7 1.10 0.197217 5 33.0 3.1 1.15 0.258736 6 45.0 3.4 1.20 0.322422 7 57.0 3.5 1.40 0.800333 8 55.0 2.1 2.50 2.734375 9 60.0 2.1 2.60 3.075800 …and so on until you filled all the columns you need to fill. .. rubric:: Pros: * No calculating by hand * More accurate representation than one cross-sectional shape for every profile point .. rubric:: Cons: * Manually determining ‘areas of effect’ for different cross-section functions can still be too much work to apply on a large corpus * Only as accurate as the geometric shape approximates actual limb cross-section Bonus: Bundle Functions ....................... In addition to the simple limb property functions, there are also bundle functions that may make your life easier. Instead of filling column by column, first column ``I`` with a function :func:`rect_I` and then column ``e_belly`` with function :func:`rect_e_belly`, for example, you can fill multiple columns by using the bundle function :func:`rect` that takes a list of properties as an additional argument:: >>> my_df['I'], my_df['e_belly'] = pb.rect(my_df['width'], ... my_df['thickness'], ... ['I', 'e_belly']) Syntax can become a bit convoluted when you do multiple things at once like this, but the option might come in handy.