Skip to content
Snippets Groups Projects
Commit 08f03ccf authored by ferrari's avatar ferrari
Browse files

Add script for bombyx ipi labelling

parent e71078b3
No related branches found
No related tags found
No related merge requests found
import ipi_extract as ipi
import pandas as pd
import argparse
import numpy as np
import os
import matplotlib.pyplot as plt
from functools import partial
from matplotlib.widgets import Button
import sys
class BetterIter(object):
def __init__(self, to_wrap):
self.wrapped = iter(to_wrap)
self.max_num = len(to_wrap)
self.to_wrap = to_wrap
self.overlap = False
def __iter__(self):
return self
def _test_done(self ,list_pass):
self.overlap = len(list_pass) >= self.max_num
def __next__(self):
while True:
try:
val = next(self.wrapped)
except StopIteration:
self.wrapped = iter(self.to_wrap)
val = next(self.wrapped)
self.done_file.seek(0)
list_pass = [int(v) for v in self.done_file.read().split('\n') if len(v)]
self._test_done(list_pass)
if (val not in list_pass) or self.overlap:
break
self.current = val
return val
def _next_file(event, refs, order, df, save, args, outpath, done_file):
tmp = pd.DataFrame.from_dict(refs['callback'].df, orient='index')
ind = order.current
tmp['file'] = df.iloc[ind].filepredmax
tmp['passage'] = df.iloc[ind].ipassage
tmp['nb_ind'] = df.iloc[ind].nbindiv
tmp['pred_max'] = df.iloc[ind].predmax
tmp['annotator'] = args.annotator
save.append(tmp)
df_ann = pd.concat(save)
df_ann.to_hdf(outpath, 'df')
if len(tmp):
done_file.write(f'{df.iloc[ind].ipassage}\n')
done_file.flush()
ind = order.__next__()
try:
ipi.reset(refs['callback'], os.path.join(args.wd, df.iloc[ind].filepredmax.strip('/')), args.channel)
refs['fig'].canvas.set_window_title('IPI of ' + df.iloc[ind].filepredmax.rsplit('/', 1)[-1])
except (RuntimeError,FileNotFoundError) as e:
print(e, 'Opening next file')
_next_file(event, refs, order, df, save, args, outpath, done_file)
def main(args):
if args.out == '':
outpath = args.input.rsplit('.', 1)[0] + f'_{args.annotator}.h5'
else:
outpath = args.out
save = []
if os.path.isfile(outpath) and not args.erase:
save.append(pd.read_hdf(outpath))
df = pd.read_pickle(args.input)
done_file = open(args.done_file, 'a+')
done_file.seek(0)
file_list = [int(v) for v in done_file.read().split('\n') if len(v)]
df = df[~df.ipassage.isin(file_list)]
overlap = False
if not len(df):
df = pd.read_pickle(args.input)
overlap = True
if args.nb_ind != -1:
df = df[df.nbindiv <= args.nb_ind]
samples_order = BetterIter(np.random.choice(len(df), len(df), replace=False))
samples_order.done_file = done_file
samples_order.overlap = overlap
ind = samples_order.__next__()
try:
ref_dict = ipi.init(os.path.join(args.wd, df.iloc[ind].filepredmax.strip('/')), args.channel)
except(RuntimeError,FileNotFoundError) as e:
print(e, 'Opening next file')
ind = samples_order.__next__()
ref_dict = ipi.init(os.path.join(args.wd, df.iloc[ind].filepredmax.strip('/')), args.channel)
next_file = partial(_next_file, refs=ref_dict, order=samples_order, df=df, save=save, args=args, outpath=outpath,
done_file=done_file)
next_ax = plt.subplot(ref_dict['gridspec'][-1, -2:])
next_button = Button(next_ax, 'Next file')
next_button.on_clicked(next_file)
plt.draw()
plt.pause(0.2)
ref_dict['fig'].set_constrained_layout(False)
plt.show()
tmp = pd.DataFrame.from_dict(ref_dict['callback'].df, orient='index')
ind = samples_order.current
tmp['file'] = df.iloc[ind].filepredmax
tmp['passage'] = df.iloc[ind].ipassage
tmp['nb_ind'] = df.iloc[ind].nbindiv
tmp['pred_max'] = df.iloc[ind].predmax
save.append(tmp)
df_ann = pd.concat(save)
df_ann['annotator'] = args.annotator
df_ann.to_hdf(outpath, 'df')
done_file.close()
return 0
if __name__ == '__main__':
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("input", type=str, help="Input metadata file")
parser.add_argument("annotator", type=str, help="Your name")
parser.add_argument("--out", type=str, default='', help="Output file. Default to the input_path'.annotator.h5'")
parser.add_argument("--channel", type=int, default=0, help="Sound channel to be analysed. Indices start from 0.")
parser.add_argument("--nb_ind", type=int, default=1, help="Maximum number of individual for each track. -1 for no limit")
parser.add_argument("--erase", action='store_true', help="If out file exist and this option is not given,"
" the computation will be halted")
parser.add_argument("--wd", type=str, default='/nfs/NASDELL/SABIOD/SITE/BOMBYX/', help='Path to root dir'
' containing Bombyx files')
parser.add_argument("--done_file", type=str,
default='/nfs/NASDELL/SABIOD/SITE/BOMBYX/manip_2021/IPI_scripts/done_file.csv',
help='Path to file listing files done')
args = parser.parse_args()
sys.exit(main(args))
\ No newline at end of file
...@@ -5,8 +5,7 @@ import scipy.signal as sg ...@@ -5,8 +5,7 @@ import scipy.signal as sg
import soundfile as sf import soundfile as sf
import os import os
import sys import sys
from matplotlib.widgets import Button, Cursor, MultiCursor, CheckButtons, RadioButtons, AxesWidget, TextBox from matplotlib.widgets import Button, Cursor, RadioButtons, AxesWidget
from matplotlib.patches import Circle
from fractions import Fraction from fractions import Fraction
from pydub import AudioSegment from pydub import AudioSegment
from pydub.playback import play from pydub.playback import play
...@@ -422,9 +421,21 @@ class Callback(object): ...@@ -422,9 +421,21 @@ class Callback(object):
self.view_ax[ind][2].set_xlabel(f'Corr man:{dic["ipi_corr_man"]:.3f} auto:{dic["ipi_corr_auto"]:.3f}') self.view_ax[ind][2].set_xlabel(f'Corr man:{dic["ipi_corr_man"]:.3f} auto:{dic["ipi_corr_auto"]:.3f}')
self.view_ax[ind][3].set_xlabel(f'Ceps man:{dic["ipi_ceps_man"]:.3f} auto:{dic["ipi_ceps_auto"]:.3f}') self.view_ax[ind][3].set_xlabel(f'Ceps man:{dic["ipi_ceps_man"]:.3f} auto:{dic["ipi_ceps_auto"]:.3f}')
def _set_visible(self, ind=None, state=False):
if ind is None:
ind = self.curr
self.view_data[ind][0][1][0].set_visible(state)
self.view_data[ind][0][1][1].set_visible(state)
self.view_data[ind][1][1][0].set_visible(state)
self.view_data[ind][1][1][1].set_visible(state)
self.view_data[ind][2][1].set_visible(state)
self.view_data[ind][3][1].set_visible(state)
def reset_curr(self, event): def reset_curr(self, event):
self.df[self.offset[self.curr_ind[self.curr], 0]] = EMLN.copy() self.df[self.offset[self.curr_ind[self.curr], 0]] = EMLN.copy()
self._set_label() self._set_label()
self._set_visible()
plt.draw() plt.draw()
def reset(self, song, sr, song_resample): def reset(self, song, sr, song_resample):
...@@ -439,8 +450,11 @@ class Callback(object): ...@@ -439,8 +450,11 @@ class Callback(object):
self.scat.set_offsets(self.offset) self.scat.set_offsets(self.offset)
self.curr_ind = 3 * [None] # Ind of click for each plot self.curr_ind = 3 * [None] # Ind of click for each plot
self.curr_vert = 3 * [0] # Current vertical line of sig/spec for each plot self.curr_vert = 3 * [0] # Current vertical line of sig/spec for each plot
for i in range(3):
self.view_data[i][1][0].set_clim(2000,2100)
for i in range(3): for i in range(3):
self._set_label(i, EMLN) self._set_label(i, EMLN)
self._set_visible(i)
plt.draw() plt.draw()
...@@ -526,8 +540,9 @@ def init(in_path, channel, low=2e3, high=20e3): ...@@ -526,8 +540,9 @@ def init(in_path, channel, low=2e3, high=20e3):
data_view[i][0][1][0].set_visible(False) data_view[i][0][1][0].set_visible(False)
data_view[i][0][1][1].set_visible(False) data_view[i][0][1][1].set_visible(False)
data_view[i][1][0] = ax_view[i][1].specgram(np.random.normal(0, 1, int(20e-3 * sr)), data_view[i][1][0] = ax_view[i][1].specgram(np.random.normal(0, 1e-6, int(20e-3 * sr)),
Fs=sr, NFFT=128, noverlap=127, cmap='jet')[-1] Fs=sr, NFFT=128, noverlap=127, cmap='jet')[-1]
data_view[i][1][0].set_clim(2000,2100)
data_view[i][1][1] = (ax_view[i][1].axvline(0.01, c='k', linestyle='--'), ax_view[i][1].axvline(0.01, c='k')) data_view[i][1][1] = (ax_view[i][1].axvline(0.01, c='k', linestyle='--'), ax_view[i][1].axvline(0.01, c='k'))
data_view[i][1][1][0].set_visible(False) data_view[i][1][1][0].set_visible(False)
data_view[i][1][1][1].set_visible(False) data_view[i][1][1][1].set_visible(False)
...@@ -560,10 +575,7 @@ def init(in_path, channel, low=2e3, high=20e3): ...@@ -560,10 +575,7 @@ def init(in_path, channel, low=2e3, high=20e3):
m_cursor[i].linev[0].set_linestyle('--') m_cursor[i].linev[0].set_linestyle('--')
m_cursor[i].linev[1].set_linestyle('--') m_cursor[i].linev[1].set_linestyle('--')
callback.view_data = data_view callback.view_data = data_view
plt.draw() return {'callback': callback, 'fig': fig, 'gridspec': gs, 'buttons':
plt.pause(0.2)
fig.set_constrained_layout(False)
return {'callback': callback, 'fig': fig, 'buttons':
{'b_left': b_left, 'b_right': b_right, 'play_b': play_b, 'resize_b': resize_b, 'r_button': r_button, {'b_left': b_left, 'b_right': b_right, 'play_b': play_b, 'resize_b': resize_b, 'r_button': r_button,
'fs_click': cid, 'reset_b': reset_b}} # Needed to keep the callbacks alive 'fs_click': cid, 'reset_b': reset_b}} # Needed to keep the callbacks alive
...@@ -582,6 +594,9 @@ def main(args): ...@@ -582,6 +594,9 @@ def main(args):
print(f'Out file {outpath} already exist and erase option isn\'t set.') print(f'Out file {outpath} already exist and erase option isn\'t set.')
return 1 return 1
ref_dict = init(args.input, args.channel) ref_dict = init(args.input, args.channel)
plt.draw()
plt.pause(0.2)
ref_dict['fig'].set_constrained_layout(False)
plt.show() plt.show()
df = pd.DataFrame.from_dict(ref_dict['callback'].df, orient='index') df = pd.DataFrame.from_dict(ref_dict['callback'].df, orient='index')
df.to_hdf(outpath, 'df') df.to_hdf(outpath, 'df')
...@@ -593,7 +608,7 @@ if __name__ == '__main__': ...@@ -593,7 +608,7 @@ if __name__ == '__main__':
class ArgumentParser(argparse.ArgumentParser): class ArgumentParser(argparse.ArgumentParser):
def error(self, message): def error(self, message):
if message.startswith('the following arguments are required:'): if message.startswith('the following arguments are required:'):
raise ValueError() raise ValueError(message)
super(ArgumentParser, self).error(message) super(ArgumentParser, self).error(message)
parser = ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser = ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment