コード例 #1
0
ファイル: constructs.py プロジェクト: par2/lamana-test
    def _set_stresses(cls, df):                                       # == side_()
        '''Return updated DataFrame with stresses per side_ of neutral axis.'''
        #print('Assigning stress states to sides for a given stack.')
        cols = ['layer', 'side', 'matl', 'type', 't(um)']
        n_rows = len(df.index)
        half_the_stack = n_rows // 2
        #print(half_the_stack)
        n_middles = df['type'].str.contains(r'middle').sum()
        #print(n_middles)

        # Default
        df.loc[:, 'side'] = 'None'
        side_loc = df.columns.get_loc('side')
        # Middle for Snapshot
        if n_middles == 1:
            df.iloc[half_the_stack, side_loc] = 'INDET'
        # For the neutral axis
        elif n_rows % 2 != 0 and n_rows != 1:
            df.iloc[half_the_stack, side_loc] = 'None'             # for odd p
        # Other plies
        '''Replace with p'''
        if n_rows > 1:
            df.iloc[:half_the_stack, side_loc] = 'Tens.'           # applies to latest column 'side'
            df.iloc[-half_the_stack:, side_loc] = 'Comp.'

        df = ut.set_column_sequence(df, cols)
        return df
コード例 #2
0
ファイル: constructs.py プロジェクト: par2/lamana-test
 def stack_to_df(cls, stack):
     '''Return a DataFrame of converted stacks with materials (list of dicts).'''
     df = pd.DataFrame(stack).T
     df.reset_index(level=0, inplace=True)              # reset index; make new column
     df.columns = ['layer', 'type', 't(um)', 'matl']    # rename columns
     recolumned = ['layer', 'matl', 'type', 't(um)']
     df = ut.set_column_sequence(df, recolumned)        # uses ext. f(x)
     df[['t(um)']] = df[['t(um)']].astype(float)        # reset numeric dtypes
     return df
コード例 #3
0
ファイル: test_utils.py プロジェクト: par2/lamana
def test_set_columns_seq2():
    '''Check reorders columns and adds columns not in sequence to the end.'''
    data = {'apple': 4, 'strawberry': 3, 'orange': 3, 'banana': 2}
    df = pd.DataFrame(data, index=['amount'])

    # Excluded names are appended to the end of the DataFrame
    seq = ['apple', 'strawberry']
    # apple  strawberry banana  orange
    actual = ut.set_column_sequence(df, seq)
    expected = pd.DataFrame(data, index=['amount'],
                            columns=['apple', 'strawberry', 'banana', 'orange'])
    ut.assertFrameEqual(actual, expected)
コード例 #4
0
ファイル: test_utils.py プロジェクト: par2/lamana
def test_set_columns_seq1():
    '''Check reorders columns to existing sequence.'''
    # Pandas orders DataFrame columns alphabetically
    data = {'apple': 4, 'orange': 3, 'banana': 2, 'blueberry': 3}
    df = pd.DataFrame(data, index=['amount'])
    # apple  banana  blueberry  orange

    # We can resequence the columns
    seq = ['apple', 'orange', 'banana', 'blueberry']
    actual = ut.set_column_sequence(df, seq)
    expected = pd.DataFrame(data, index=['amount'], columns=seq)
    ut.assertFrameEqual(actual, expected)
コード例 #5
0
ファイル: constructs.py プロジェクト: par2/lamana-test
        def _update_dimensions(LFrame):
            '''Update Laminate DataFrame with new dimensional columns.

            This function takes a primitive LFrame (converted Stack) and adds
            columns: label, h(m), d(m), intf, k, Z(m), z(m), z(m)*

            A number of pandas-like implementations are performed to achieve this.
            So the coding has a different approach and feel.

            Variables
            =========
            LFrame : DataFrame
                A primitive Laminate DateFrame containing ID columns.
            '''
            # For Implementation
            nplies = self.nplies
            p = self.p
            t_total = self.total
            #print('nplies: {}, p: {}, t_total (m): {}'.format(nplies, p, t_total))

            df = LFrame.copy()

            # WRANGLINGS --------------------------------------------------------------
            # Indexers ----------------------------------------------------------------
            # Many dimensional values are determined by index positions.

            # Revised Indexer
            df['idx'] = df.index                                       # temp. index column for idxmin & idxmax
            interface_tens = df[df['side'] == 'Tens.'].groupby('layer')['idx'].idxmin()
            discontinuity_tens = df[(df['side'] == 'Tens.')
                & (df['type'] != 'middle')].groupby('layer')['idx'].idxmax()
            discontinuity_comp = df[(df['side'] == 'Comp.')
                & (df['type'] != 'middle')].groupby('layer')['idx'].idxmin()
            interface_comp = df[df['side'] == 'Comp.'].groupby('layer')['idx'].idxmax()
            interface_idx = pd.concat([interface_tens, interface_comp])
            discont_idx = pd.concat([discontinuity_tens, discontinuity_comp])
            #print(discontinuity_tens.values)
            if nplies > 1:
                pseudomid = [discontinuity_tens.values[-1],
                             discontinuity_comp.values[0]]               # get disconts indices near neutral axis; for even plies
            mid_idx = len(df.index) // 2
            #print('middle index: ', mid_idx)

            # Indexer dict of outside and inside Indices
            idxs = {
                'interfaces': interface_idx.values.tolist(),             # for interfaces
                'disconts': discont_idx.values.tolist(),                 # for disconts.
                'middle': mid_idx,                                       # for neut. axis
                'intfTens': interface_tens.values.tolist(),              # for side_ interfaces
                'intfComp': interface_comp.values.tolist(),
                'unboundIntfT': interface_tens.values.tolist()[1:],
                'unboundIntfC': interface_comp.values.tolist()[:-1],
                'disTens': discontinuity_tens.values.tolist(),           # for disconts
                'disComp': discontinuity_comp.values.tolist(),
            }

            # Masks -------------------------------------------------------------------
            # Interface Mask
            s = df['idx'].copy()
            s[:] = False                                                 # convert series to bool values
            s.loc[idxs['interfaces']] = True
            mask = s                                                     # boolean mask for interfaces

            # COLUMNS -----------------------------------------------------------------
            # label_ ------------------------------------------------------------------
            # Gives name for point types
            df['label'] = np.where(mask, 'interface', 'internal')        # yes!; applies values if interface, else internal
            if p != 1:
                df.loc[idxs['disconts'], 'label'] = 'discont.'           # yes!; post-fix for disconts.
            if (p % 2 != 0) & ('middle' in df['type'].values):
                df.loc[idxs['middle'], 'label'] = 'neut. axis'
            internal_idx = df[df['label'] == 'internal'].index.tolist()  # additional indexer
            # '''Add neut. axis in the middle'''

            # h_ ----------------------------------------------------------------------
            # Gives the thickness (in m) and height w.r.t to the neut. axis (for middle)
            df['h(m)'] = df['t(um)'] * 1e-6
            df.loc[df['type'] == 'middle', 'h(m)'] = df['t(um)'] * 1e-6 / 2.
            if p != 1:                                                   # at disconts.
                df.loc[idxs['disTens'], 'h(m)'] = df['h(m)'].shift(-1)
                df.loc[idxs['disComp'], 'h(m)'] = df['h(m)'].shift(1)

            # d_ ----------------------------------------------------------------------
            # Gives the height for interfaces, neutral axes, disconts and internal points
            # Assign Laminate Surfaces and Neutral Axis to odd p, odd nply laminates
            df.loc[0, 'd(m)'] = 0                                        # first
            df.loc[idxs['middle'], 'd(m)'] = t_total / 2.                # middle
            df.iloc[-1, df.columns.get_loc('d(m)')] = t_total            # last

            # Assign Interfaces
            # Uses cumsum() for selected interfaces thickness to get d
            innerhTens = df.loc[df['label'] == 'interface',
                'h(m)'].shift(1)[idxs['unboundIntfT']]                   # shift h down, select inner interfaces
            df.loc[idxs['unboundIntfT'], 'd(m)'] = 0 + np.cumsum(innerhTens)
            #print(np.cumsum(innerhTens))
            innerhComp = df.loc[df['label'] == 'interface',
                'h(m)'].shift(-1)[idxs['unboundIntfC']]                  # shift h up, select inner interfaces
            df.loc[idxs['unboundIntfC'],
                'd(m)'] = t_total - np.cumsum(innerhComp[::-1])[::-1]
            #print(t_total - np.cumsum(innerhComp[::-1])[::-1])          # inverted cumsum()

            # Assign Other Points
            if p > 1:                                                    # at disconts.
                df.loc[idxs['disTens'], 'd(m)'] = df['d(m)'].shift(-1)
                df.loc[idxs['disComp'], 'd(m)'] = df['d(m)'].shift(1)
            if p > 2:
                df = Laminate._make_internals(df, p, column='d(m)')      # at internals
                ##df = _make_internals(df, p, column='d(m)')               # at internals

            # intf_ -------------------------------------------------------------------
            # Enumerates proximal interfaces; n layer, but n+1 interfaces
            df['intf'] = df.loc[:, 'layer']
            df.loc[df['side'] == 'Comp.', 'intf'] += 1

            if (p % 2 != 0) & (nplies % 2 != 0):
                '''Need an INDET for numeric dtype.  Default to Nan for now'''
                ##df.loc[df['label'] == 'neut. axis', 'intf'] = 'INDET'
                df.loc[idxs['middle'], 'intf'] = np.nan                  # using indep. indexer vs. label_

            # Reset the dtype to float
            df[['intf']] = df[['intf']].astype(np.float64)

            # k_ ----------------------------------------------------------------------
            # Normally the layer number, but now tracks the ith fractional level per layer
            # See definition in (Staab 197), k is is the region between k and k-1 level
            # Like intf_, k_ is aware of neutral axis

            # k_ == intf_ (proximal interface)
            df.loc[df['label'] == 'interface',
                'k'] = df.loc[df['label'] == 'interface', 'intf']        # at interfaces
                ##'k'] = df.loc[df['label'] == 'interface', 'intf']-1      # at interfaces

#             if (p != 1) & (nplies%2 == 0):
#                 df.loc[pseudomid, 'k'] = (nplies/2.)+1                   # hack for even mids
#                 #df.loc[pseudomid, 'k'] = nplies/2.                       # replace middle values

            # Interfaces and discontinuities share the same k_
            if p > 1:                                                    # at disconts.
                df.loc[idxs['disTens'], 'k'] = df['k'].shift(-1)
                df.loc[idxs['disComp'], 'k'] = df['k'].shift(1)

                # Even plies have adjacent discontinuities at the neutral axis
                if nplies % 2 == 0:
                    df.loc[pseudomid, 'k'] = (nplies / 2.) + 1           # hack for even mids
                    ##df.loc[pseudomid, 'k'] = nplies / 2.                 # replace middle values

            # Auto calculate internal divisions
            if p > 2:                                                    # at internals
                df = Laminate._make_internals(df, p, column='k')
                ##df = _make_internals(df, p, column='k')
            '''Need an INDET. for numeric dtype.  Default to Nan for now'''
            #df.loc[df['label'] == 'neut. axis', 'k'] = 'INDET'
            #df.loc[df['label'] == 'neut. axis', 'k'] = np.nan

            # Odd plies have nuetral axes
            if (p % 2 != 0) & (nplies % 2 != 0):                         # using indep. indexer vs. label_
                df.loc[idxs['middle'], 'k'] = (df['k'].max() + df['k'].min()) / 2.
                ##df.loc[idxs['middle'], 'k'] = (df['k'].max()-df['k'].min())/2
                ##df.loc[idxs['middle'], 'k'] = np.nan                   # using indep. indexer vs. label_

            # Z_ ----------------------------------------------------------------------
            # Distance from ith level to the neutral access
            middle = t_total / 2.
            df['Z(m)'] = middle - df['d(m)']
            if (nplies == 1) & (p == 1):                                 # d_ = t_total here, so must amend
                df['Z(m)'] = t_total / 2.

            # z_ ----------------------------------------------------------------------
            # Distance from ith Z-midplane level to the neutral access
            # Two flavors are implemented for linearly and log-distributed z_ (z(m) and z(m)*)
            t_mid = df.loc[df['label'] == 'interface', 'h(m)'] / 2.       # for midplane calc.
            df.loc[(df['label'] == 'interface') & (df['side'] == 'Tens.'),
                'z(m)'] = df.loc[df['label'] == 'interface',
                'Z(m)'] - t_mid                                          # at interfaces
            df.loc[(df['label'] == 'interface') & (df['side'] == 'Comp.'),
                'z(m)'] = df.loc[df['label'] == 'interface',
                'Z(m)'] + t_mid                                          # at interfaces
            if nplies % 2 == 0:
                df.loc[pseudomid, 'z(m)'] = 0                            # replace middle values
            if p > 1:                                                    # at disconts.
                df.loc[idxs['disTens'], 'z(m)'] = df['z(m)'].shift(-1)
                df.loc[idxs['disComp'], 'z(m)'] = df['z(m)'].shift(1)
            if p > 2:
                # Equi-partitioned, Linear Intervals (legacy code); z(m)
                df = Laminate._make_internals(df, p, column='z(m)')
                ##df = _make_internals(df, p, column='z(m)')
            if p % 2 != 0:
                ##df.loc[df['label'] == 'neut. axis', 'z(m)'] = 0
                df.loc[idxs['middle'], 'z(m)'] = 0                       # using indep. indexer vs. label_

            ####
            # Non-equi-partitioned Intervals; "Travelling" Midplanes; z(m)*
            '''Possibly offer user options to use either method'''
            lastT = df[(df['side'] == 'Tens.') & (df['type'] != 'middle')].groupby('layer')['Z(m)'].last()
            lastC = df[(df['side'] == 'Comp.') & (df['type'] != 'middle')].groupby('layer')['Z(m)'].first()

            last = pd.concat([lastT, lastC])
            last.name = 'lasts'
            joined = df.join(last, on='layer')
            joined['z_intervals'] = (joined['Z(m)'] - joined['lasts']) / 2.
            #print(joined)
            #print(last)
            df['z(m)*'] = joined['Z(m)'] - joined['z_intervals']
            df.loc[df['type'] == 'middle', 'z(m)*'] = df['Z(m)'] / 2.
            if (p == 1) & (nplies == 1):
                df.loc[0, 'z(m)*'] = 0
            ####
            del df['idx']

            sort_columns = ['layer', 'side', 'type', 'matl', 'label', 't(um)',
                            'h(m)', 'd(m)', 'intf', 'k', 'Z(m)', 'z(m)', 'z(m)*']
            self.LFrame = ut.set_column_sequence(df, sort_columns)