How to project a 3D Bone POSE Matrix to 2D (XZ) Plane?
Since nobody else posted an answer yet, i had a try which might help you. 


Note

This works only with the following options enabled


Inherit Rotation
Inherit Scale




Also drivers/constraints don't work.



import bpy
from mathutils import Vector, Matrix

obj = bpy.data.objects['Armature']
pb  = obj.pose.bones['Bone.001']

# constant
VEC_Y = Vector((0.0, 1.0, 0.0))

# components
loc, rot, scale = pb.matrix.decompose()

# projection
y_world = rot * VEC_Y
y_proj = y_world.copy()
y_proj.y = 0.0
factor = y_proj.magnitude
y_proj.normalize()

x_proj = VEC_Y.copy()
z_proj = x_proj.cross(y_proj)

# new world matrix
mat_rot_new = Matrix((x_proj, y_proj, z_proj))
mat_rot_new.transpose()

mat_scale = Matrix.Identity(3)
for i in range(3):
    # uncomment to uniformly scale the bone
    # to match the length of the projected bone
    mat_scale[i][i] = scale[i] # * factor

mat_world_new = mat_rot_new * mat_scale
mat_world_new.resize_4x4()
mat_world_new.translation = loc.copy()

# new local matrix
mat_world_old_inv = pb.matrix.inverted()
mat_basis_new = pb.matrix_basis * mat_world_old_inv * mat_world_new
# pb.matrix_basis = mat_basis_new

def get_mat_offset(pose_bone):
    """ calculate the (local) rest matrix of the bone """
    bone = pose_bone.bone
    mat_offset = bone.matrix.to_4x4()
    mat_offset.translation = bone.head.copy()
    mat_offset.translation.y += bone.parent.length
    return mat_offset

# ================================ Debug =====================================
# visualize source and target transformation with an empty for easy testing

def get_empty(name):
    empty = bpy.data.objects.get(name)
    if empty is None:
        empty = bpy.data.objects.new(name, None)
        empty.show_x_ray = True
        empty.empty_draw_type = "ARROWS"
        bpy.context.scene.objects.link(empty)
    return empty

mat_parent = pb.parent.matrix
mat_offset = get_mat_offset(pb)

get_empty("Source").matrix_world = mat_parent * mat_offset * pb.matrix_basis
get_empty("Target").matrix_world = mat_parent * mat_offset * mat_basis_new

for child in pb.children:
    # adjust the children bones so their world matrix remains unchanged
    mat_offset = get_mat_offset(child)
    mat_offset_inv = mat_offset.inverted()
    mat_basis_new_inv = mat_basis_new.inverted()

    mat_basis_child = (mat_offset_inv * 
                       mat_basis_new_inv * 
                       pb.matrix_basis * 
                       mat_offset * 
                       child.matrix_basis)

    if child.bone.use_connect == True:
        mat_basis_child.translation = 0.0, 0.0, 0.0

    get_empty("PB_" + child.name).matrix_world = mat_world_new * mat_offset * mat_basis_child

# =============================================================================