def get_mgr_concatenation_plan(mgr, indexers):
<EOL>mgr_shape = list(mgr.shape)<EOL>for ax, indexer in indexers.items():<EOL><INDENT>mgr_shape[ax] = len(indexer)<EOL><DEDENT>mgr_shape = tuple(mgr_shape)<EOL>if <NUM_LIT:0> in indexers:<EOL><INDENT>ax0_indexer = indexers.pop(<NUM_LIT:0>)<EOL>blknos = algos.take_1d(mgr._blknos, ax0_indexer, fill_value=-<NUM_LIT:1>)<EOL>blklocs = algos.take_1d(mgr._blklocs, ax0_indexer, fill_value=-<NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>if mgr._is_single_block:<EOL><INDENT>blk = mgr.blocks[<NUM_LIT:0>]<EOL>return [(blk.mgr_locs, JoinUnit(blk, mgr_shape, indexers))]<EOL><DEDENT>ax0_indexer = None<EOL>blknos = mgr._blknos<EOL>blklocs = mgr._blklocs<EOL><DEDENT>plan = []<EOL>for blkno, placements in libinternals.get_blkno_placements(blknos,<EOL>mgr.nblocks,<EOL>group=False):<EOL><INDENT>assert placements.is_slice_like<EOL>join_unit_indexers = indexers.copy()<EOL>shape = list(mgr_shape)<EOL>shape[<NUM_LIT:0>] = len(placements)<EOL>shape = tuple(shape)<EOL>if blkno == -<NUM_LIT:1>:<EOL><INDENT>unit = JoinUnit(None, shape)<EOL><DEDENT>else:<EOL><INDENT>blk = mgr.blocks[blkno]<EOL>ax0_blk_indexer = blklocs[placements.indexer]<EOL>unit_no_ax0_reindexing = (len(placements) == len(blk.mgr_locs) and<EOL>((ax0_indexer is None and<EOL>blk.mgr_locs.is_slice_like and<EOL>blk.mgr_locs.as_slice.step == <NUM_LIT:1>) or<EOL>(np.diff(ax0_blk_indexer) == <NUM_LIT:1>).all()))<EOL>if unit_no_ax0_reindexing:<EOL><INDENT>join_unit_indexers.pop(<NUM_LIT:0>, None)<EOL><DEDENT>else:<EOL><INDENT>join_unit_indexers[<NUM_LIT:0>] = ax0_blk_indexer<EOL><DEDENT>unit = JoinUnit(blk, shape, join_unit_indexers)<EOL><DEDENT>plan.append((placements, unit))<EOL><DEDENT>return plan<EOL>
Construct concatenation plan for given block manager and indexers.

Parameters
----------
mgr : BlockManager
indexers : dict of {axis: indexer}

Returns
-------
plan : list of (BlockPlacement, JoinUnit) tuples