Skip to content

Commit b76df9b

Browse files
committed
Population sorting is done according to the popfile. Closes #18.
1 parent 7e41cb6 commit b76df9b

File tree

1 file changed

+55
-10
lines changed

1 file changed

+55
-10
lines changed

plotter/structplot.py

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,16 @@ def dataminer(indfile_name, fmt, popfile=None):
4141

4242
# Parse popfile if provided
4343
if popfile:
44-
# Assuming popfile has 2 columns with pop name in 1st column and number
45-
# of samples in the 2nd column
46-
poparray = np.genfromtxt(popfile, dtype=None)
44+
# Assuming popfile has 3 columns with pop name in 1st column, number
45+
# of samples in the 2nd column and input file order number in the 3rd.
46+
datatype = np.dtype([("popname", "|U20"), ("num_indiv", int),
47+
("original_order", int)])
48+
poparray = np.genfromtxt(popfile, dtype=datatype)
4749
# Final pop list
48-
poplist = [(x, y.decode("utf-8")) for x, y in
49-
zip(np.cumsum([x[1] for x in poparray]),
50-
[x[0] for x in poparray])]
50+
poplist = [([x]*y, z) for x, y, z in
51+
zip([x[0] for x in poparray],
52+
[x[1] for x in poparray],
53+
[x[2] for x in poparray])]
5154

5255
# Parse structure/faststructure output file
5356
if fmt == "fastStructure":
@@ -89,11 +92,52 @@ def dataminer(indfile_name, fmt, popfile=None):
8992
# is the boundary of a population in the x-axis
9093
poplist = Counter(poplist)
9194
poplist = [(x, None) for x in np.cumsum(list(poplist.values()))]
95+
print("oh")
9296

9397

98+
if popfile:
99+
# Re-order the qvalues to match what is specified in the popfile.
100+
qvalues = re_order(qvalues, poplist)
101+
94102
return qvalues, poplist
95103

96104

105+
def re_order(qvalues, poplist):
106+
"""
107+
Recieves a list of q-values, re-orders them according to the order
108+
specified in the popfile and returns that list.
109+
"""
110+
qvalues = qvalues.tolist()
111+
locations_dict = {pos:(index, len(loc)) for index, (loc, pos) in
112+
enumerate(poplist)}
113+
114+
offsets = [None] * len(poplist)
115+
116+
117+
def compute_offset(pos):
118+
"""
119+
Recursively compute the offset values.
120+
"""
121+
# compute new offset from offset and length of previous position. End of
122+
# recursion at position 1: we’re at the beginning of the list
123+
offset = sum(compute_offset(pos-1)) if pos > 1 else 0
124+
# get index at where to store current offset + length of current location
125+
index, length = locations_dict[pos]
126+
offsets[index] = (offset, length)
127+
128+
return offsets[index]
129+
130+
131+
compute_offset(len(poplist))
132+
133+
qvalues = [value for offset, length in offsets for value in
134+
qvalues[offset:offset + length]]
135+
136+
qvalues = np.array(qvalues)
137+
138+
return qvalues
139+
140+
97141
def plotter(qvalues, poplist, outfile):
98142
"""
99143
Plot the qvalues histogram.
@@ -120,8 +164,7 @@ def plotter(qvalues, poplist, outfile):
120164
ax = fig.add_subplot(111, xlim=(0, numinds), ylim=(0, 1))
121165

122166
for i in range(qvalues.shape[1]):
123-
# Get bar color. If K exceeds the 12 colors in colors, generate random
124-
# color
167+
# Get bar color. If K exceeds the 12 colors, generate random color
125168
try:
126169
clr = colors[i]
127170
except IndexError:
@@ -138,13 +181,15 @@ def plotter(qvalues, poplist, outfile):
138181

139182
# Annotate population info
140183
if poplist:
184+
orderings = [(x, y[0][0]) for x, y in zip(np.cumsum([len(x[0]) for x in
185+
poplist]), poplist)]
141186
count = 1
142-
for ppl, vals in enumerate(poplist):
187+
for ppl, vals in enumerate(orderings):
143188
# Add population delimiting lines
144189
plt.axvline(x=vals[0], linewidth=1.5, color='black')
145190
# Add population labels
146191
# Determine x pos
147-
xpos = vals[0] - ((vals[0] - poplist[ppl - 1][0]) / 2) if ppl > 0 \
192+
xpos = vals[0] - ((vals[0] - orderings[ppl - 1][0]) / 2) if ppl > 0 \
148193
else vals[0] / 2
149194
# Draw text
150195
ax.text(xpos, -0.05, vals[1] if vals[1] else "Pop{}".format(count),

0 commit comments

Comments
 (0)