From 0149cbcd6101597bb90fd35900a2fa956b0bbf60 Mon Sep 17 00:00:00 2001 From: julien Date: Thu, 23 Aug 2018 16:19:55 +0200 Subject: [PATCH 001/299] bugfix in rttm2scp.py script, used by diartk - SAD misalignment between input/output of diartk fixed --- toolbox/rttm2scp.py | 104 ++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 72 deletions(-) diff --git a/toolbox/rttm2scp.py b/toolbox/rttm2scp.py index e27e35d..f0ab256 100755 --- a/toolbox/rttm2scp.py +++ b/toolbox/rttm2scp.py @@ -20,7 +20,8 @@ def read_rttm(input_path): # RTTM format is # SPEAKER fname 1 onset duration spkr rttm = fin.readlines() - sad = IntervalTree() + #sad = IntervalTree() + all_intervals = [] fname = "" for line in rttm: _, fname, _, onset, dur, _, _, _, _ = line.strip('\n').split() @@ -33,89 +34,48 @@ def read_rttm(input_path): line)) continue - interval = Interval(float(onset), float(onset) + float(dur)) - - # Search for intervals already added that overlap with current - # interval. If we find some, then we truncate the current - # interval to remove all overalps - ov = sad.search(interval) - interval, other_intervals = remove_overlap(ov, interval) - if interval[0] == interval[1]: - # continue if interval was removed + # add interval to list + all_intervals.append((float(onset), float(onset) + float(dur))) + + # sort intervals by their onset + all_intervals.sort() + + # look at each interval, add them in growing order of onset, + # trim the beginning if it overlaps with previous interval, + # and completely delete if it is contained by the previous interval. + sad = [] + prev_on = 0 + prev_off = 0 + for onset, offset in all_intervals: + if len(sad) == 0: + # don't check anything for first interval + sad.append((onset, offset)) + prev_on = onset + prev_off = offset + continue + + if onset < prev_off: + if offset <= prev_off: + # interval is completely contained in the previous one continue + onset = prev_off - sad.add(interval) - - # if other_intervals is not empty, add these intervals to tree - for new_interv in other_intervals: - if new_interv[0] == new_interv[1]: - # continue if interval was removed - continue + sad.append((onset, offset)) + prev_on = onset + prev_off = offset - sad.add(new_interv) - return sad, fname -def remove_overlap(ov, interval): - """Take as input an interval, and the set of the intervals it overlaps """ - """with, and output the interval trimmed (possibly to 0) so that there """ - """are no overlaps in the output""" - onset, offset = interval[0], interval[1] - other_intervals = [] - - for covered_int in ov: - if (onset >= covered_int[0]) and (offset <= covered_int[1]): - # if interval is already covered, return empty interval - onset = 0 - offset = 0 - elif (onset < covered_int[0]) and (offset >= covered_int[0])\ - and (offset <= covered_int[1]): - # change onset/offset to avoid overlap - onset = onset - offset = covered_int[0] - elif (onset <= covered_int[1]) and (offset > covered_int[1])\ - and (onset >= covered_int[0]): - onset = covered_int[1] - offset = offset - elif(onset <= covered_int[0]) and (offset >= covered_int[1]): - # case where the new interval contains a previously add one - # in this case return second interval - new_onset = covered_int[1] - new_offset = offset - onset = onset - offset = covered_int[0] - - temp_interval = Interval(new_onset, new_offset) - # call remove_overlap again with the newly created interval - # in case it also has overlap in ov - new_interval, _other_intervals = remove_overlap(ov, - temp_interval) - - other_intervals.append(new_interval) - other_intervals += _other_intervals - - - #else: - # # Do nothing, all problems are probably allready resolved ! - # # print('{} {} {}'.format(interval, ov, other_intervals)) - - return Interval(onset, offset), other_intervals - -def write_scp(tree, fname, output): +def write_scp(out_intervals, fname, output): """Write output in SCP format""" - # First order the intervals - out_intervals = [] - for interval in tree: - out_intervals.append((interval[0], interval[1])) - out_intervals = sorted(out_intervals, key=itemgetter(0)) with open(output, 'w') as fout: fout.write(u'') # write empty string in case out_intervals is empty for onset, offset in out_intervals: fout.write(u'{fname}_{on}_{off}={fname}.fea[{on},{off}]\n'.format( fname=fname, - on=int(onset)*100, - off=int(offset)*100)) + on=int(onset*100), + off=int(offset*100))) def main(): """Take diarization in RTTM format as input, and write """ From 91079c0d9810e6519174d6ec1f6591a14175bb43 Mon Sep 17 00:00:00 2001 From: Alex Cristia Date: Thu, 23 Aug 2018 17:26:35 +0200 Subject: [PATCH 002/299] minor --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 695171d..6d48521 100644 --- a/README.md +++ b/README.md @@ -49,12 +49,12 @@ Try the following first: 1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link and follow the prompted instructions -1. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.8 platform packages", so look for a title like that one. +1. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. -2. Clone this repo: +2. Clone the present repository: - - Open terminal - - Navigate to the directory in which you want the VM to be hosted + - Open a terminal window + - In it, navigate to the directory in which you want the VM to be hosted - type in: `$ git clone https://github.com/aclew/DiViMe` From 0bc5a879dc3a06c7efd9f0a2add0e0aa9743b6fe Mon Sep 17 00:00:00 2001 From: Alex Cristia Date: Thu, 23 Aug 2018 18:26:04 +0200 Subject: [PATCH 003/299] minor --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6d48521..77065b6 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Inside this mini-computer, we have put the following tools: * [LDC Speech Activity Detection](https://github.com/aclew/DiViMe#ldc_sad)(coming soon) * [Speech Activity Detection Using Noisemes](#noisemes_sad) * [OpenSmile SAD](#opensmile_sad) - * [ToCombo SAD](#tocombo_sad) + * [Threshold Optimized Combo SAD](#tocombo_sad) 2) Talker diarization (answers the question: who is talking?) @@ -415,5 +415,8 @@ The input TextGrid the system allows is a TextGrid in which all the tiers have s # References +Our work builds directly on that of others. The main references for tools currently included and/or data currently used to perform tests are: -WCE: Räsänen, O., Seshadri, S., & Casillas, M. (2018, June). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. In Interspeech 2018. +- A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. +- F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia feature extractor,” in Proceedings of the 21st ACM international conference on Multimedia. ACM, 2013, pp. 835–838. +- Räsänen, O., Seshadri, S., & Casillas, M. (2018, June). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. In Interspeech 2018. From 6d90cbdd4b98084d7e09b23868bf73db53db4347 Mon Sep 17 00:00:00 2001 From: Alex Cristia Date: Thu, 23 Aug 2018 18:28:54 +0200 Subject: [PATCH 004/299] minor --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77065b6..9889ab0 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ Try the following first: `$ cd divime` -2. Install HTK +4. Install HTK HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. @@ -73,7 +73,7 @@ HTK is used by some of these tools (until we find and implement an open-source r - Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). The download is probably called HTK-3.4.1.tar.gz, although the numbers may change if they update their code. - Move the HTK-*.tar.gz file into the root folder of this repository (alongside Vagrantfile), and rename it HTK.tar.gz -4. Type +5. Type `$ vagrant up` From ad91dfae431806604fbed4d9f4bdbaade39510f2 Mon Sep 17 00:00:00 2001 From: riebling Date: Mon, 27 Aug 2018 13:44:42 -0400 Subject: [PATCH 005/299] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9889ab0..f4ded7a 100644 --- a/README.md +++ b/README.md @@ -332,6 +332,7 @@ F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent devel-opments in ope ### TOCombo_SAD A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. +S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013 ### DiarTK From 08885fcfed284717ee62698088fcd1dd3f09b159 Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 4 Sep 2018 15:31:18 +0200 Subject: [PATCH 006/299] This closes #15 . Add script to get the AclewStarter dataset --- get_aclewStarter.sh | 58 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100755 get_aclewStarter.sh diff --git a/get_aclewStarter.sh b/get_aclewStarter.sh new file mode 100755 index 0000000..a1909bf --- /dev/null +++ b/get_aclewStarter.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# +# author = the ACLEW Team +# +# Use this script to download the aclew Starter from databrary and start using +# it with the DiViMe. +# This script should be launched from the DiViMe folder, which also contains +# the VagrantFile. + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` + +# url to dataset in zip format +aclewStarter_url=https://nyu.databrary.org/volume/390/zip/true +aclewStarter_folder=databrary390-Bergelson-Warlaumont-Cristia-Casillas-Rosemberg-Soderstrom-Rowland-Durrant-Bunce-Starter-ACLEW + +# create data directory to store dataset and download zip file +if [[ ! -d "aclewStarter" ]]; then + mkdir $BASEDIR/aclewStarter +fi + +cd $BASEDIR/aclewStarter + +echo "downloading the ACLEW Starter Dataset..." +wget $aclewStarter_url + +# unzip archive and keep data when there is both the audio file and +# the transcription. Delete the archive file +unzip true +rm true + +# regroup wavs and transcriptions and remove those that don't have a match +cd $aclewStarter_folder +mkdir transcript +mkdir wav + +mv sessions/*/*.wav wav/ +mv materials*/*.eaf transcript/ + +echo "processing all the ACLEW Starter files..." +for eaf in $(ls transcript/); do + base=$(echo $eaf | cut -d '-' -f 1) + if [[ -f wav/${base}.wav ]]; then + mv transcript/$eaf transcript/${base}.eaf + vagrant ssh -c "python varia/elan2rttm.py -i /vagrant/aclewStarter/$aclewStarter_folder/transcript/${base}.eaf -o /vagrant/aclewStarter/" + mv wav/${base}.wav ../ + else + rm transcript/$eaf + fi +done + +# When all the files are seen, delete the extracted raw folder +cd ../ +rm -rf $aclewStarter_folder + +echo "You can now use the ACLEW Starter dataset!" From 050117bd34a4fcb970ffb2e60902d0122ba3f996 Mon Sep 17 00:00:00 2001 From: jukaradayi Date: Tue, 4 Sep 2018 16:04:41 +0200 Subject: [PATCH 007/299] Add explanation + reference for ACLEW Starter dataset --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f4ded7a..cd75a97 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ We are hoping to add more tools in the future, including register detection, syl ## Who is the ACLEW DiViMe for? -Our target users have "difficult" recordings, e.g. recorded in natural environment, from sensitive populations, etc. Therefore, we are assuming users who are unable to share their audio recordings. Our primary test case involves language acquisition in children 0-3 years of age. +Our target users have "difficult" recordings, E.G. recorded in natural environment, from sensitive populations, etc. Therefore, we are assuming users who are unable to share their audio recordings. Our primary test case involves language acquisition in children 0-3 years of age. We are hoping to make the use of these tools as easy as possible, but some command line programming will be unavoidable. If you are worried when reading this, we can recommend the Software Carpentry programming courses for researchers, and particularly their [unix bash](http://swcarpentry.github.io/shell-novice) and [version control](http://swcarpentry.github.io/git-novice/) bootcamps. @@ -218,6 +218,20 @@ If you want to evaluate a diarization produced by the diartk tool, you will have `$ vagrant halt` +### ACLEW Starter Dataset + +The ACLEW Starter dataset is freely available, and can be downloaded in order to test the tools. +To download it, using your terminal, as explained before, go in the DiViMe folder and do: +`$ ./get_aclewStarter.sh` +This will create a folder called aclewStarter, in which you will find the audio files from the public dataset and their corresponding .rttm annotations. + +You can then use the tools mentioned before, by replacing the "data/" folder in the command given in the previous paragraph by "aclewStarter/", E.G for noisemes: +```$ vagrant ssh -c "tools/noisemes_sad.sh aclewStarter/"``` + +Reference for the ACLEX Starter dataset: + +Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved August 15, 2018 from http://doi.org/10.17910/B7.390. + ## More details for each tool ### LDC_SAD From a98112b4614a517fdd3f099877fb33801a524de3 Mon Sep 17 00:00:00 2001 From: jukaradayi Date: Tue, 4 Sep 2018 16:05:32 +0200 Subject: [PATCH 008/299] fix typo in README... --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cd75a97..5b4224f 100644 --- a/README.md +++ b/README.md @@ -228,7 +228,7 @@ This will create a folder called aclewStarter, in which you will find the audio You can then use the tools mentioned before, by replacing the "data/" folder in the command given in the previous paragraph by "aclewStarter/", E.G for noisemes: ```$ vagrant ssh -c "tools/noisemes_sad.sh aclewStarter/"``` -Reference for the ACLEX Starter dataset: +Reference for the ACLEW Starter dataset: Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved August 15, 2018 from http://doi.org/10.17910/B7.390. From 08f177b44b30f110b0dd86e8537ef018947dd96f Mon Sep 17 00:00:00 2001 From: riebling Date: Mon, 10 Sep 2018 13:44:25 -0400 Subject: [PATCH 009/299] patch broken HTK Makefile without it, HTK does not fully build (but luckily it builds enough for us to use!) --- Vagrantfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Vagrantfile b/Vagrantfile index fdf5f40..962c401 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -161,6 +161,7 @@ Vagrant.configure("2") do |config| su ${user} -c "tar zxf /vagrant/HTK.tar.gz" cd htk ./configure --without-x --disable-hslab + sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile make all make install fi From a462c143582c0d5c69f2f476ba43cc555552414d Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 11 Sep 2018 14:35:55 -0400 Subject: [PATCH 010/299] Candidate Dockerfile --- Dockerfile | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4e35753 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,111 @@ +#Download base image ubuntu 16.04 +FROM ubuntu:16.04 + +# Volume configuration: available during `docker build` time, read only +# (use docker build -v ? ) +#VOLUME ["/vagrant"] + +# hassle #1: default user name in Docker is 'root' +# -m forces to make home directory +RUN useradd -m vagrant + +# hassle #2: default Dockerfile shell is sh +SHELL ["/bin/bash", "-c"] + +# Update Software repository # Install packages from ubuntu repository +RUN apt-get update && apt-get install -y git make automake libtool autoconf patch subversion fuse \ + libatlas-base-dev libatlas-dev liblapack-dev sox libav-tools g++ \ + zlib1g-dev libsox-fmt-all apache2 sshfs gcc-multilib libncurses5-dev unzip wget bzip2 libboost-all-dev + +RUN apt-get install -y icedtea-netx-common icedtea-netx +RUN rm -rf /var/lib/apt/lists/* + + # Kaldi and others want bash - otherwise the build process fails +RUN [ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh + + # Install Anaconda and Theano +RUN echo "Downloading Anaconda-2.3.0..." +USER vagrant +WORKDIR /home/vagrant +RUN wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh +RUN bash /home/vagrant/Anaconda-2.3.0-Linux-x86_64.sh -b +RUN rm Anaconda-2.3.0-Linux-x86_64.sh +RUN if ! grep -q -i anaconda .bashrc; then \ + echo "export PATH=/home/vagrant/anaconda/bin:\$PATH" >> /home/vagrant/.bashrc; \ + fi + + # install Matlab runtime environment +USER root +RUN cd /tmp && wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip && unzip -q MCR_R2017b_glnxa64_installer.zip && ./install -mode silent -agreeToLicense yes + # add Matlab stuff to path +RUN echo 'LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH"' >> /home/vagrant/.bashrc +RUN rm /tmp/MCR_R2017b_glnxa64_installer.zip + + # Install OpenSMILE +RUN echo "Installing OpenSMILE" +USER vagrant +WORKDIR /home/vagrant +RUN wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz && tar zxvf OpenSMILE-2.1.tar.gz --no-same-owner && rm OpenSMILE-2.1.tar.gz + + # optionally Install HTK (without it, some other tools will not work) + # the idea is to make users independently download HTK installer since + # we cannot redistribute +WORKDIR /home/vagrant +USER root +RUN wget http://speechkitchen.org/vms/Data/HTK.tar.gz && tar zxf HTK.tar.gz --no-same-owner +WORKDIR /home/vagrant/htk +RUN ./configure --without-x --disable-hslab +# Fix bad Makefile +RUN sed -i "s/ /\t/g" HLMTools/Makefile && make all +RUN make install + + # Get OpenSAT and all the tools + # Install DiarTK, LDC SAD, LDC scoring, Rajat's LENA stuff + + #git clone http://github.com/srvk/ldc_sad_hmm + +USER vagrant +WORKDIR /home/vagrant +RUN git clone http://github.com/srvk/OpenSAT && cp -f OpenSAT/theanorc /home/vagrant/.theanorc && \ + git clone http://github.com/srvk/ib_diarization_toolkit && \ + git clone http://github.com/srvk/dscore && \ + git clone https://github.com/rajatkuls/lena-clean && \ + git clone https://github.com/srvk/Yunitator && \ + git clone https://github.com/srvk/To-Combo-SAD && \ + git clone https://github.com/srvk/tools.git && \ + git clone https://github.com/aclew/varia.git + + # Get tools: PDNN, coconut, ldc_sad_hmm +USER vagrant +WORKDIR /home/vagrant +RUN mkdir G && \ + cd G && \ + git clone http://github.com/yajiemiao/pdnn && \ + git clone http://github.com/srvk/coconut + + # get theanorc! + # need to figure out how to access this at 'docker build' time. Do it at 'docker run' time instead??? +#RUN cp /vagrant/.theanorc /home/vagrant/ + + # install theano + # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) + # and intervaltree (needed for rttm2scp.py) + # assume 'conda' is installed now (get path) + # now dependencies for Yunitator + +RUN export PATH=/home/vagrant/anaconda/bin:$PATH && \ + /home/vagrant/anaconda/bin/conda install -y theano=0.8.2 && \ + /home/vagrant/anaconda/bin/pip install pympi-ling tgt intervaltree && \ + /home/vagrant/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib && \ + /home/vagrant/anaconda/bin/conda install cudatoolkit && \ + /home/vagrant/anaconda/bin/conda install pytorch-cpu -c pytorch + +USER root + # Some cleanup + # If default user is given by USER, passwordless sudo not work??? +RUN touch /home/vagrant/.Xauthority && chown -R vagrant:vagrant /home/vagrant && apt-get autoremove -y + +# Open up HTTP / HTTPS ports +#EXPOSE 80 443 + +CMD ["/bin/bash"] \ No newline at end of file From 4d7994c347c34a012579a6ecbeb8bfc549be4001 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 18 Sep 2018 11:29:08 -0400 Subject: [PATCH 011/299] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b4224f..6dfc4ba 100644 --- a/README.md +++ b/README.md @@ -191,7 +191,7 @@ This means that LDC_SAD considered that the first 770 milliseconds of the audio The DiarTOOLNAME options are: - DiarTOOLNAME = diartk -- DiarTOOLNAME = yunitate @riebling please check +- DiarTOOLNAME = yunitate Notice there is one more parameter provided to the system in the call; in the example above "noisemes". This is because the DiarTK tool only does talker diarization (i.e., who speaks) but not speech activity detection (when is someone speaking). Therefore, this system requires some form of SAD. With this last parameter, you are telling the system which annotation to use. At present, you can choose between: From f42587ee1a3ac4d8db362315c2b4b6ef4e611bfd Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 26 Sep 2018 16:33:06 -0400 Subject: [PATCH 012/299] convert RTTM to Audacity labels --- toolbox/rttm2labels.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 toolbox/rttm2labels.py diff --git a/toolbox/rttm2labels.py b/toolbox/rttm2labels.py new file mode 100644 index 0000000..c1b90bf --- /dev/null +++ b/toolbox/rttm2labels.py @@ -0,0 +1,41 @@ +#! /usr/bin/python +''' +Created on Oct 4, 2014 +@author: fmetze,er1k +convert RTTM (segmented) to Audacity labels format +''' + +import sys +import datetime +import re + +def printbuf (begin, end, text): + datetime1 = datetime.datetime.utcfromtimestamp(begin) + datetime2 = datetime.datetime.utcfromtimestamp(end) + allseconds1 = 60 * datetime1.minute + 3600 * datetime1.hour + datetime1.second + allseconds2 = 60 * datetime2.minute + 3600 * datetime2.hour + datetime2.second + print "%s.%s\t%s.%s\t%s" % (allseconds1, datetime1.strftime('%f'), allseconds2, datetime2.strftime('%f'), text) + + +for l in sys.stdin: + + m = re.match("^(.*)\t(.*)\t(.*)\t(\S+)\t(\S+)\t(.*)\t(.*)\t(.*)\t(.*)$", l) + if m: + type, file = m.group(1, 2) + channel = int(m.group(3)) + starttime = float(m.group(4)) + duration = float(m.group(5)) + ortho = m.group(6) + stype = m.group(7) + name = m.group(8) + conf = m.group(9) + + printbuf (starttime, starttime+duration, name) + begin = starttime + + elif re.match(";.*", l) or re.match("#.*", l): + pass + + else: + raise Exception("cannot process line: " + l) + From e9d12f269eced0e84683166ae52542e6ef68ac2e Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Thu, 27 Sep 2018 10:11:49 -0400 Subject: [PATCH 013/299] Create README.md --- toolbox/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 toolbox/README.md diff --git a/toolbox/README.md b/toolbox/README.md new file mode 100644 index 0000000..235eca6 --- /dev/null +++ b/toolbox/README.md @@ -0,0 +1,13 @@ +## Toolbox ## +A place to store utility programs. (Not run scripts for proper Tools like DiarTK, Yunitator, OpenSmile, etc. which have their own repository) + +### rttm2labels.py ### +This tool accepts on standard input an RTTM file and produces on standard output a text file that can be imported and displayed along +audio waveforms in Audacity. Audacity prefers the label files to have a `.txt` extension, but any filename can work. + 1. Example usage: `cat test2.rttm | python toolbox/rttm2labels.py > test2.txt` + 2. Run Audacity, opening the corresponding WAV file, e.g. `audacity test2.wav` + 3. Using the menu File->Import->Labels... bring up the file selection dialog and navigate to the labels file e.g. test2.txt + 4. You should now see a labels track beneath the audio waveform track in Audacity's edit window + + ### other utilities here ### + From 7e70dd5b2844f0fc367135dd645d6999b49fd4b6 Mon Sep 17 00:00:00 2001 From: Alex Cristia Date: Mon, 1 Oct 2018 12:36:11 +0200 Subject: [PATCH 014/299] added references and fixed test output --- README.md | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6dfc4ba..874f548 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ Advanced topic: [Installing With Docker](https://github.com/srvk/DiViMe/wiki/Ins # Checking your installation -The very first time you use DiViMe, it is a good idea to run a quickstart test: +The very first time you use DiViMe, it is a good idea to run a quickstart test, which will be performed using the public files from the ACLEW Starter set (Bergelson et al., 2017): 1. Open a terminal 2. Navigate inside the DiViMe folder @@ -97,15 +97,31 @@ The very first time you use DiViMe, it is a good idea to run a quickstart test: This should produce the output: ``` -Testing noisemes... +Testing LDC SAD... +LDC SAD passed the test. + +Testing Speech Activity Detection Using Noisemes... Noisemes passed the test. -Testing DIARTK... -DiarTK passed the test. -Congratulations, everything is OK! -Connection to 127.0.0.1 closed. + +Testing OpenSmile SAD... +OpenSmile SAD passed the test. + +Testing Threshold Optimized Combo SAD... +Threshold Optimized Combo SAD passed the test. + +Testing DiarTK... +DiarTK passed the test. + +Congratulations, everything is OK! + +This is the simple test with a few short files. If you would like to run a test for use with daylong recordings, please run $ vagrant ssh -c "tools/test-daylong.sh". Note that this will download a very large recording. ``` +## Common errors and fixes + +- For LDC SAD, you may get an error "LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include LDC SAD. This error means that you cannot use LDC SAD, but you can use any other SAD/VAD. (For example, noisemes.) +- For LDC SAD, Noisemes, and DiarTK, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. The easiest way to fix it is to install HTK (again). -If something fails, please open an issue [here](https://github.com/aclew/DiViMe/issues). Please paste the complete output there. +If something elsefails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. # Update instructions @@ -432,6 +448,7 @@ The input TextGrid the system allows is a TextGrid in which all the tiers have s Our work builds directly on that of others. The main references for tools currently included and/or data currently used to perform tests are: -- A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. -- F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia feature extractor,” in Proceedings of the 21st ACM international conference on Multimedia. ACM, 2013, pp. 835–838. +- Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved October 1, 2018 from http://doi.org/10.17910/B7.390. +- Eyben, F. Weninger, F., Gross, F. & B. Schuller. (2013). Recent developments in opensmile, the munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. - Räsänen, O., Seshadri, S., & Casillas, M. (2018, June). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. In Interspeech 2018. +- Ziaei, A. Sangwan, A., & Hansen, J.H.L. (2016). Effective word count estimation for long duration daily naturalistic audio recordings. Speech Communication, 84, 15-23. From dfe8b61819cf0903ff360183b8e8da14272b1f61 Mon Sep 17 00:00:00 2001 From: Alex Cristia Date: Mon, 1 Oct 2018 14:02:38 +0200 Subject: [PATCH 015/299] updated readme finished adding references, added instructions for daylong check --- README.md | 135 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 114 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 874f548..628c4d4 100644 --- a/README.md +++ b/README.md @@ -116,13 +116,53 @@ Congratulations, everything is OK! This is the simple test with a few short files. If you would like to run a test for use with daylong recordings, please run $ vagrant ssh -c "tools/test-daylong.sh". Note that this will download a very large recording. ``` -## Common errors and fixes + + +# Checking your installation for daylong files + +Many of our users have very long files that they want to analyze. To check that our tools are working in your environment, we will test them using the one of the public files from the vanDam corpus (vanDam & Tully, 2016): + +1. Open a terminal +2. Navigate inside the DiViMe folder +3. Do +`$ vagrant up` +4. Do +`$ vagrant ssh -c "tools/test-daylong.sh"` + +This test will take quite some time. It will proceed to download that daylong file, and then process it with all of our tools. Afterwards, it should produce the output: + +``` +Downloading the daylong file... +Download complete. + +Processing annotations... +Annotations processed. + +Testing LDC SAD... +LDC SAD passed the test. + +Testing Speech Activity Detection Using Noisemes... +Noisemes passed the test. + +Testing OpenSmile SAD... +OpenSmile SAD passed the test. + +Testing Threshold Optimized Combo SAD... +Threshold Optimized Combo SAD passed the test. + +Testing DiarTK... +DiarTK passed the test. + +Congratulations, everything is OK! + +``` + +# Common installation errors and fixes - For LDC SAD, you may get an error "LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include LDC SAD. This error means that you cannot use LDC SAD, but you can use any other SAD/VAD. (For example, noisemes.) - For LDC SAD, Noisemes, and DiarTK, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. The easiest way to fix it is to install HTK (again). -If something elsefails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. - +If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. # Update instructions @@ -158,8 +198,6 @@ $ rm -r -f divime 2. If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. It is probably safer to make a copy (rather than moving them), in case you later decide to delete the whole vagrant folder. -[//]: # (Julien, you had a solution for not moving data at all -- can you please describe it in simple terms?) - 3. Launch the virtual machine anytime by navigating to your DiViMe folder on your terminal and performing: `$ vagrant up` @@ -220,7 +258,7 @@ Notice there is one more parameter provided to the system in the call; in the ex - rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. -Finally, if no parameter is provided, the system will default to ldc_sad. +Finally, if no parameter is provided, the system will default to noisemes. 6. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: @@ -252,12 +290,26 @@ Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderst ### LDC_SAD -Instructions coming. +Main reference for this tool: + +Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. + +#### General intro + +LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. -@riebling please add reference (you can find it in the interspeech paper) + +Associated references: +Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. +Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. ### Noisemes_sad +Main reference for this tool: + +Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) + + #### General intro This system will classify slices of the audio recording into one of 17 noiseme classes: @@ -281,8 +333,6 @@ This system will classify slices of the audio recording into one of 17 noiseme c - white_noise - radio -To learn more, read the source file -Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) #### Instructions for direct use @@ -302,7 +352,7 @@ This will analyze all .wav's inside the "data" folder. Created annotations will be stored inside the same "data" folder. -### Some more technical details +#### Some more technical details For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": @@ -357,16 +407,39 @@ The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the mor ### OpenSmile_SAD -F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent devel-opments in opensmile, the munich open-source multimedia feature extractor,” in Proceedings of the 21st ACM international conference on Multimedia. ACM, 2013, pp. 835–838. +Main reference for this tool: + +Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. + +#### General intro + +TO BE ADDED ### TOCombo_SAD +Main references for this tool: + A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. -S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013 +S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. + +#### General intro + +TO BE ADDED ### DiarTK -This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format as generated by one of the tools above. A script to run DiarTK (also known as ib_diarization_toolkit) can be found in `tools/diartk.sh`. Here is it's usage: +Main reference for this tool: + +D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. + +#### General intro + +TO BE ADDED + + +#### Instructions for direct use + +This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format as generated by one of the tools above. A script to run DiarTK (also known as ib_diarization_toolkit) can be found in `tools/diartk.sh`. Here is its usage: ``` Usage: diartk.sh where dirname is the name of the folder @@ -387,12 +460,20 @@ where `data/` is in the current working directory, and contains .wav audio as we ### LDC Diarization Scoring -@riebling please add reference (you can find it in the interspeech paper) +Main references for this tool: + +Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. +Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. + +#### General intro + +For SAD, we employ the evaluation included in the LDC SAD, which returns the false alarm (FA) rate (proportion of frames labeled as speech that were non-speech in the gold annotation) and missed speech rate (proportion of frames labeled as non-speech that were speech in the gold annotation). For TD, we employ the evaluation developed for the DiHARD Challenge, which returns a Diarization error rate (DER), which sums percentage of speaker error (mismatch in speaker IDs), false alarm speech (non-speech segments assigned to a speaker) and missed speech (unassigned speech). +One important consideration is in order: What to do with files that have no speech to begin with, or where the system does not return any speech at the SAD stage or any labels at the TD stage. This is not a case that is often discussed in the litera- ture because recordings are typically targeted at moments where there is speech. However, in naturalistic recordings, some ex- tracts may not contain any speech activity, and thus one must adopt a coherent framework for the evaluation of such instances. We opted for the following decisions. -Instructions coming +If the gold annotation was empty, and the SAD system returned no speech labels, then the FA = 0 and M = 0; but if the SAD system returned some speech labels, then FA = 100 and M = 0. Also, if the gold annotation was not empty and the sys- tem did not find any speech, then this was treated as FA = 0 and M=100. -https://github.com/aclew/varia +As for the TD evaluation, the same decisions were used above for FA and M, and the following decisions were made for mismatch. If the gold annotation was empty, regardless of what the system returned, the mismatch rate was treated as 0. If the gold annotation was empty but a pipeline returned no TD labels (either because the SAD in that system did not detect any speech, or because the diarization failed), then this was penalized via a miss of 100 (as above), but not further penalized in terms of talker mismatch, which was set at 0. # Troubleshooting @@ -419,13 +500,17 @@ vagrant up ``` If you don't want to destroy it, you can try opening the VirtualBox GUI, go to `File -> Settings or Preferences -> Network `, click on the `Host-only Networks` tab, then click the network card icon with the green plus sign in the right, if there are no networks yet listed. The resulting new default network should appear with the name ‘vboxnet0’. You can now try again with `vagrant up` -### Tools -If ldc_sad doesn't seem to work after vagrant up, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: + + +## Problems with some of the Tools +### LDC SAD, OpenSmile, DiarTK + +If ldc_sad, OpenSmile, DiarTK don't seem to work after vagrant up, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: ``` vagrant up --provision ``` This step will install HTK inside the VM, which is used by several tools including ldc_sad. -## Problems with some of the Tools + ### Noisemes If you use the noisemes_sad or the noisemes_full tool, one problem you may encounter is that it doesn't treat all of your files and gives you an error that looks like this: ``` @@ -439,7 +524,8 @@ MemoryError If this happens to you, it's because you are trying to treat more data than the system/your computer can handle. What you can do is simply put the remaining files that weren't treated in a seperate folder and treat this folder seperately (and do this until all of your files are treated if it happens again on very big datasets). After that, you can put back all of your data in the same folder. -## Input Format For Transcriptions + +### Input Format For Transcriptions If your transcriptions are in TextGrid format but the conversion doesn't seem to work, it's probably because it isn't in the right TextGrid format. The input TextGrid the system allows is a TextGrid in which all the tiers have speech segments (so remove tiers with no speech segments) and all the annotated segments for each tiers is indeed speech (so remove segments that are noises or other non-speech type). @@ -451,4 +537,11 @@ Our work builds directly on that of others. The main references for tools curren - Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved October 1, 2018 from http://doi.org/10.17910/B7.390. - Eyben, F. Weninger, F., Gross, F. & B. Schuller. (2013). Recent developments in opensmile, the munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. - Räsänen, O., Seshadri, S., & Casillas, M. (2018, June). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. In Interspeech 2018. +- Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. +- Sadjadi, S.O. & Hansen, J.H.L. (2013). Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux. IEEE Signal Processing Letters, 20(3), 197-200. +- VanDam, M., & Tully, T. (2016, May). Quantity of mothers’ and fathers’ speech to sons and daughters. Talk presented at the 171st Meeting of the Acoustical Society of America, Salt Lake City, UT. +- Vijayasenan, D. & Valente, F. (2012) Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings. Thirteenth Annual Conference of the International Speech Communication Association, 2012. +- Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) +- Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. - Ziaei, A. Sangwan, A., & Hansen, J.H.L. (2016). Effective word count estimation for long duration daily naturalistic audio recordings. Speech Communication, 84, 15-23. +- Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. From 0af76301aee3e9db8bb28ed0e3a282f246d58a9c Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Wed, 3 Oct 2018 11:31:10 +0200 Subject: [PATCH 016/299] Update main README.md for warning about the tricky installation finished step --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 628c4d4..d7542a9 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,8 @@ HTK is used by some of these tools (until we find and implement an open-source r `$ vagrant up` The first time you do this, it will take at least 20 minutes to install all the packages that are needed to build the virtual machine. +Once the virtual machine will be installed, it will stay stuck at "installation finished" for few minutes. However, the tools are not yet installed at this step. +You will need to wait for the tools to be installed, and to take back the control of the terminal to run the tools. The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/aclew/DiViMe/issues), describing your situation. From e9d7f919bc79a704438be9b33c48bc9216e4eb39 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Fri, 5 Oct 2018 14:05:49 +0200 Subject: [PATCH 017/299] Add ipdb dependency for noisemes_full --- Vagrantfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Vagrantfile b/Vagrantfile index 962c401..4029c1a 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -249,6 +249,9 @@ Vagrant.configure("2") do |config| su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" + # now dependencies for noisemes_full + su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" + # Some cleanup sudo apt-get autoremove -y From 542b9f833153ff813e937630330c1bbf689e201e Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Mon, 8 Oct 2018 18:25:12 +0200 Subject: [PATCH 018/299] Add missing packages for tocombo-sad (matlab runtime environment) --- Vagrantfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Vagrantfile b/Vagrantfile index 4029c1a..721cd2c 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -252,6 +252,9 @@ Vagrant.configure("2") do |config| # now dependencies for noisemes_full su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" + # Get some packages for tocombo_sad (matlab runtime environnement) + sudo apt-get install -y libxt-dev libx11-xcb1 + # Some cleanup sudo apt-get autoremove -y From 84fc2c2537c2a23d6a5009ea2436a07b1986e56f Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 10 Oct 2018 15:30:23 +0200 Subject: [PATCH 019/299] add sphinx doc --- .gitignore | 1 + docs/Makefile | 20 +++ docs/make.bat | 36 ++++ docs/source/conf.py | 169 ++++++++++++++++++ docs/source/index.rst | 25 +++ docs/source/initial_questions.md | 44 +++++ docs/source/install.md | 147 ++++++++++++++++ docs/source/references.md | 15 ++ docs/source/troubleshoot.md | 55 ++++++ docs/source/usage.md | 287 +++++++++++++++++++++++++++++++ 10 files changed, 799 insertions(+) create mode 100644 docs/Makefile create mode 100644 docs/make.bat create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/initial_questions.md create mode 100644 docs/source/install.md create mode 100644 docs/source/references.md create mode 100644 docs/source/troubleshoot.md create mode 100644 docs/source/usage.md diff --git a/.gitignore b/.gitignore index f9d8610..dd723a7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ # Generally ignore data directories data* +docs/build/* diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..c5a8db1 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = DiViMe +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..fba88a1 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build +set SPHINXPROJ=DiViMe + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..852725d --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +# +# DiViMe documentation build configuration file, created by +# sphinx-quickstart on Wed Oct 10 11:23:30 2018. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) +from recommonmark.parser import CommonMarkParser + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +source_suffix = ['.rst', '.md'] +#source_suffix = '.md' +source_parsers = {'.md': 'recommonmark.parser.CommonMarkParser',} + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'DiViMe' +copyright = u'2018, ACLEW' +author = u'ACLEW' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'1.0' +# The full version, including alpha/beta/rc tags. +release = u'1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + ] +} + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'DiViMedoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'DiViMe.tex', u'DiViMe Documentation', + u'ACLEW', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'divime', u'DiViMe Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'DiViMe', u'DiViMe Documentation', + author, 'DiViMe', 'One line description of project.', + 'Miscellaneous'), +] + + + diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..6823ed1 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,25 @@ +.. DiViMe documentation master file, created by + sphinx-quickstart on Wed Oct 10 11:23:30 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to DiViMe's documentation! +================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + initial_questions + install + usage + troubleshoot + references + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/initial_questions.md b/docs/source/initial_questions.md new file mode 100644 index 0000000..3be985e --- /dev/null +++ b/docs/source/initial_questions.md @@ -0,0 +1,44 @@ +# Initial questions + +## What is the ACLEW DiViMe? + +It is a collection of diarization tools, i.e., it allows users to add annotations onto a raw audio recording. At present, we have tools to do the following types of annotation: + +1) Speech activity detection (answers the question: when is someone talking?) + +2) Talker diarization (answers the question: who is talking?) + +We are hoping to add more tools in the future, including register detection, syllable quantification, and vocal maturity estimation. + +## Who is the ACLEW DiViMe for? + +Our target users have "difficult" recordings, E.G. recorded in natural environment, from sensitive populations, etc. Therefore, we are assuming users who are unable to share their audio recordings. Our primary test case involves language acquisition in children 0-3 years of age. + +We are hoping to make the use of these tools as easy as possible, but some command line programming will be unavoidable. If you are worried when reading this, we can recommend the Software Carpentry programming courses for researchers, and particularly their [unix bash](http://swcarpentry.github.io/shell-novice) and [version control](http://swcarpentry.github.io/git-novice/) bootcamps. + +## What exactly is inside the ACLEW DiViMe? + +A virtual machine is actually a mini-computer that gets set up inside your computer. This creates a virtual environment within which we can be sure that our tools run, and run in the same way across all computers (Windows, Mac, Linux). + +Inside this mini-computer, we have put the following tools: + +1) Speech activity detection (answers the question: when is someone talking?) + + * [LDC Speech Activity Detection](https://github.com/aclew/DiViMe#ldc_sad)(coming soon) + * [Speech Activity Detection Using Noisemes](#noisemes_sad) + * [OpenSmile SAD](#opensmile_sad) + * [Threshold Optimized Combo SAD](#tocombo_sad) + + +2) Talker diarization (answers the question: who is talking?) + + * [DiarTK](#diartk) + +3) Evaluation + +If a user has some annotations, they may want to know how good the ACLEW DiViMe parsed their audio recordings. In that case, you can use one tool we soon paln to provide to evaluate: + + * [LDC Diarization Scoring](https://github.com/aclew/DiViMe#ldc-diarization-scoring) + + + diff --git a/docs/source/install.md b/docs/source/install.md new file mode 100644 index 0000000..eada5a1 --- /dev/null +++ b/docs/source/install.md @@ -0,0 +1,147 @@ +# Installation instructions + +## First installation + +Try the following first: + +1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link and follow the prompted instructions + +1. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. + +2. Clone the present repository: + + - Open a terminal window + - In it, navigate to the directory in which you want the VM to be hosted + - type in: + +`$ git clone https://github.com/aclew/DiViMe` + +3. Change into it by + +`$ cd divime` + +4. Install HTK + +HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. + +- Go to the HTK download page http://htk.eng.cam.ac.uk/download.shtml +- Register by following the instructions on the left (under "Getting HTK": Register) +- Check that you have received your password via email; you will need it for the next step. +- Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). The download is probably called HTK-3.4.1.tar.gz, although the numbers may change if they update their code. +- Move the HTK-*.tar.gz file into the root folder of this repository (alongside Vagrantfile), and rename it HTK.tar.gz + +5. Type + +`$ vagrant up` + +The first time you do this, it will take at least 20 minutes to install all the packages that are needed to build the virtual machine. +Once the virtual machine will be installed, it will stay stuck at "installation finished" for few minutes. However, the tools are not yet installed at this step. +You will need to wait for the tools to be installed, and to take back the control of the terminal to run the tools. + +The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/aclew/DiViMe/issues), describing your situation. + +Advanced topic: [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker) + +## Checking your installation + +The very first time you use DiViMe, it is a good idea to run a quickstart test, which will be performed using the public files from the ACLEW Starter set (Bergelson et al., 2017): + +1. Open a terminal +2. Navigate inside the DiViMe folder +3. Do +`$ vagrant up` +4. Do +`$ vagrant ssh -c "tools/test.sh"` + +This should produce the output: + +``` +Testing LDC SAD... +LDC SAD passed the test. + +Testing Speech Activity Detection Using Noisemes... +Noisemes passed the test. + +Testing OpenSmile SAD... +OpenSmile SAD passed the test. + +Testing Threshold Optimized Combo SAD... +Threshold Optimized Combo SAD passed the test. + +Testing DiarTK... +DiarTK passed the test. + +Congratulations, everything is OK! + +This is the simple test with a few short files. If you would like to run a test for use with daylong recordings, please run $ vagrant ssh -c "tools/test-daylong.sh". Note that this will download a very large recording. +``` + + +## Checking your installation for daylong files + +Many of our users have very long files that they want to analyze. To check that our tools are working in your environment, we will test them using the one of the public files from the vanDam corpus (vanDam & Tully, 2016): + +1. Open a terminal +2. Navigate inside the DiViMe folder +3. Do +`$ vagrant up` +4. Do +`$ vagrant ssh -c "tools/test-daylong.sh"` + +This test will take quite some time. It will proceed to download that daylong file, and then process it with all of our tools. Afterwards, it should produce the output: + +``` +Downloading the daylong file... +Download complete. + +Processing annotations... +Annotations processed. + +Testing LDC SAD... +LDC SAD passed the test. + +Testing Speech Activity Detection Using Noisemes... +Noisemes passed the test. + +Testing OpenSmile SAD... +OpenSmile SAD passed the test. + +Testing Threshold Optimized Combo SAD... +Threshold Optimized Combo SAD passed the test. + +Testing DiarTK... +DiarTK passed the test. + +Congratulations, everything is OK! + +``` + +## Common installation errors and fixes + +- For LDC SAD, you may get an error "LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include LDC SAD. This error means that you cannot use LDC SAD, but you can use any other SAD/VAD. (For example, noisemes.) +- For LDC SAD, Noisemes, and DiarTK, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. The easiest way to fix it is to install HTK (again). + +If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. + +## Update instructions + +If there is a new version of DiViMe, you'll need to perform the following 3 steps from within the DiViME folder on your terminal: + + +``` +$ vagrant destroy +$ git pull +$ vagrant up +``` + +## Uninstallation instructions + +If you want to get rid of the files completely, you should perform the following 3 steps from within the DiViME folder on your terminal: + +``` +$ vagrant destroy +$ cd .. +$ rm -r -f divime +``` + + diff --git a/docs/source/references.md b/docs/source/references.md new file mode 100644 index 0000000..728a3bc --- /dev/null +++ b/docs/source/references.md @@ -0,0 +1,15 @@ +# References + +Our work builds directly on that of others. The main references for tools currently included and/or data currently used to perform tests are: + +- Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved October 1, 2018 from http://doi.org/10.17910/B7.390. +- Eyben, F. Weninger, F., Gross, F. & B. Schuller. (2013). Recent developments in opensmile, the munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. +- Räsänen, O., Seshadri, S., & Casillas, M. (2018, June). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. In Interspeech 2018. +- Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. +- Sadjadi, S.O. & Hansen, J.H.L. (2013). Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux. IEEE Signal Processing Letters, 20(3), 197-200. +- VanDam, M., & Tully, T. (2016, May). Quantity of mothers’ and fathers’ speech to sons and daughters. Talk presented at the 171st Meeting of the Acoustical Society of America, Salt Lake City, UT. +- Vijayasenan, D. & Valente, F. (2012) Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings. Thirteenth Annual Conference of the International Speech Communication Association, 2012. +- Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) +- Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. +- Ziaei, A. Sangwan, A., & Hansen, J.H.L. (2016). Effective word count estimation for long duration daily naturalistic audio recordings. Speech Communication, 84, 15-23. +- Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. diff --git a/docs/source/troubleshoot.md b/docs/source/troubleshoot.md new file mode 100644 index 0000000..ea71bda --- /dev/null +++ b/docs/source/troubleshoot.md @@ -0,0 +1,55 @@ +# Troubleshooting + +## Installation issues +### Virtual Machine creation +If your computer freezes after `vagrant up`, it may be due to several things. +If your OS is ubuntu 16.04, there's a known incompatibility between VirtualBox and the 4.13 Linux kernel on ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installation_simple), or install the latest version of virtualbox which should fix the problem. +If you are not on ubuntu 16.04, or if the previous fix didn't work, it may also be due to the fact that Vagrant is trying to create a Virtual Machine that asks for too much resources. Please ensure that you have enough space on your computer (you should have at least 15Gb of free space) and check that the memory asked for is okay. If not, you can lower the memory of the VM by changing line 25 of the VagrantFile, +``` +vbox.memory = 3072 +``` +to a lower number, such as +``` +vbox.memory = 2048 +``` +### Resuming the Virtual Machine +If you already used the VM once, shut down your computer, turned it back on and can't seem to be able to do `vagrant up` again, you can simply do +``` +vagrant destroy +``` +and recreate the VM using +``` +vagrant up +``` +If you don't want to destroy it, you can try opening the VirtualBox GUI, go to `File -> Settings or Preferences -> Network `, click on the `Host-only Networks` tab, then click the network card icon with the green plus sign in the right, if there are no networks yet listed. The resulting new default network should appear with the name ‘vboxnet0’. +You can now try again with `vagrant up` + + +## Problems with some of the Tools +### LDC SAD, OpenSmile, DiarTK + +If ldc_sad, OpenSmile, DiarTK don't seem to work after vagrant up, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: +``` +vagrant up --provision +``` +This step will install HTK inside the VM, which is used by several tools including ldc_sad. + +### Noisemes +If you use the noisemes_sad or the noisemes_full tool, one problem you may encounter is that it doesn't treat all of your files and gives you an error that looks like this: +``` +Traceback (most recent call last): + File "SSSF/code/predict/1-confidence-vm5.py", line 59, in + feature = pca(readHtk(os.path.join(INPUT_DIR, filename))).astype('float32') + File "/home/vagrant/G/coconut/fileutils/htk.py", line 16, in readHtk + data = struct.unpack(">%df" % (nSamples * sampSize / 4), f.read(nSamples * sampSize)) +MemoryError +``` +If this happens to you, it's because you are trying to treat more data than the system/your computer can handle. +What you can do is simply put the remaining files that weren't treated in a seperate folder and treat this folder seperately (and do this until all of your files are treated if it happens again on very big datasets). +After that, you can put back all of your data in the same folder. + +### Input Format For Transcriptions +If your transcriptions are in TextGrid format but the conversion doesn't seem to work, it's probably because it isn't in the right TextGrid format. +The input TextGrid the system allows is a TextGrid in which all the tiers have speech segments (so remove tiers with no speech segments) and all the annotated segments for each tiers is indeed speech (so remove segments that are noises or other non-speech type). + + diff --git a/docs/source/usage.md b/docs/source/usage.md new file mode 100644 index 0000000..361cfed --- /dev/null +++ b/docs/source/usage.md @@ -0,0 +1,287 @@ +# Use instructions + + +## Short instructions for all tools + +1. Put the files you want to analyze inside the "data" folder inside the DiViMe folder. If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. + +2. If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. It is probably safer to make a copy (rather than moving them), in case you later decide to delete the whole vagrant folder. + +3. Launch the virtual machine anytime by navigating to your DiViMe folder on your terminal and performing: + +`$ vagrant up` + +4. For the SAD tools, type a command like the one below, being careful to type the SAD tool name instead of SADTOOLNAME: + +`$ vagrant ssh -c "tools/SADTOOLNAME.sh data/"` + +The SAD options are: +- SADTOOLNAME = ldc_sad (coming soon) +- SADTOOLNAME = noisemes_sad +- SADTOOLNAME = noisemes_full +- SADTOOLNAME = opensmile_sad +- SADTOOLNAME = tocombo_sad + +This will create a set of new rttm files, with the name of the tool added at the beginning. For example, imagine you have a file called participant23.wav, and you decide to run both the LDC_SAD and the Noisemes analyses. You will run the following commands: + + +``` +$ vagrant ssh -c "tools/ldc_sad.sh data/" +$ vagrant ssh -c "tools/noisemes_sad.sh data/" +``` + +And this will result in your having the following three files in your /data/ folder: + +- participant23.wav +- ldc_sad_participant23.rttm +- noisemes_sad_participant23.rttm + +If you look inside one of these .rttm's, say the ldc_sad one, it will look as follows: + +``` +SPEAKER participant23 1 0.00 0.77 speech +SPEAKER participant23 1 0.77 0.61 nonspeech +SPEAKER participant23 1 1.38 2.14 speech +SPEAKER participant23 1 3.52 0.82 nonspeech +``` + +This means that LDC_SAD considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. + + +5. For the diarization tools, type a command like the one below, being careful to type the diarization tool name instead of DiarTOOLNAME: + +`$ vagrant ssh -c "tools/DiarTOOLNAME.sh data/ noisemes"` + +The DiarTOOLNAME options are: +- DiarTOOLNAME = diartk +- DiarTOOLNAME = yunitate + +Notice there is one more parameter provided to the system in the call; in the example above "noisemes". This is because the DiarTK tool only does talker diarization (i.e., who speaks) but not speech activity detection (when is someone speaking). Therefore, this system requires some form of SAD. With this last parameter, you are telling the system which annotation to use. At present, you can choose between: + +- ldc_sad: this means you want the system to use the output of the LDC_SAD system. If you have not run LDC_SAD, the system will run it for you. +- noisemes: this means you want the system to use the output of the noisemes system. If you have not run LDC_SAD, the system will run it for you. +- opensmile: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. +- tocombosad: this means you want the system to use the output of the tocombo_sad system. If you have not ran tocombosad, the system will run it for you. +- textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. +- eaf: this means you want the system to use your eaf annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your eaf files before you start. Please note that the system will convert your eafs into .rttm in the process. +- rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. + + +Finally, if no parameter is provided, the system will default to noisemes. + +6. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: + +`$ vagrant ssh -c "tools/eval.sh data/ noisemes"` + +Notice there are 2 parameters provided to the evaluation suite. The first parameter tells the system which folder to analyze (in this case, the whole data/ folder). The second parameter indicates which tool's output to evaluate (in this case, noisemes). The system will use the .rttm annotations if they exist; or the .eaf ones if the former are missing; or the .textgrid of neither .rttm nor .eaf are found. +If you want to evaluate a diarization produced by the diartk tool, you will have to specify a third parameter, to tell the system which SAD was used to compute the diartk outputs you want to evaluate. E.G. : +`$ vagrant ssh -c "tools/eval.sh data/ diartk noisemes_sad` + +7. Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: + +`$ vagrant halt` + +### ACLEW Starter Dataset + +The ACLEW Starter dataset is freely available, and can be downloaded in order to test the tools. +To download it, using your terminal, as explained before, go in the DiViMe folder and do: +`$ ./get_aclewStarter.sh` +This will create a folder called aclewStarter, in which you will find the audio files from the public dataset and their corresponding .rttm annotations. + +You can then use the tools mentioned before, by replacing the "data/" folder in the command given in the previous paragraph by "aclewStarter/", E.G for noisemes: +```$ vagrant ssh -c "tools/noisemes_sad.sh aclewStarter/"``` + +Reference for the ACLEW Starter dataset: + +Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved August 15, 2018 from http://doi.org/10.17910/B7.390. + +## More details for each tool + +### LDC_SAD + +Main reference for this tool: + +Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. + +#### General intro + +LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. + + +Associated references: +Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. +Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. + +### Noisemes_sad + +Main reference for this tool: + +Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) + + +#### General intro + +This system will classify slices of the audio recording into one of 17 noiseme classes: + +- background +- speech +- speech non English +- mumble +- singing alone +- music + singing +- music alone +- human sounds +- cheer +- crowd sounds +- animal sounds +- engine +- noise_ongoing +- noise_pulse +- noise_tone +- noise_nature +- white_noise +- radio + + +#### Instructions for direct use + +You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. + +``` +$ vagrant ssh -c "OpenSAT/runOpenSAT.sh data/<$MYFILE>" +``` + +You can also analyze a group of files as follows: + +``` +$ vagrant ssh -c "OpenSAT/runDiarNoisemes.sh data/" +``` + +This will analyze all .wav's inside the "data" folder. + +Created annotations will be stored inside the same "data" folder. + +#### Some more technical details + +For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": + +``` +$ vagrant ssh +$ cd OpenSAT +``` + +The main script is runOpenSAT.sh and takes one argument: an audio file in .wav format. +Upon successful completion, output will be in the folder (relative to ~/OpenSAT) +`SSSF/data/hyp//confidence.pkl.gz` + +The system will grind first creating features for all the .wav files it found, then will place those features in a subfolder `feature`. Then it will load a model, and process all the features generated, producing output in a subfolder `hyp/` two files per input: `.confidence.mat` and `.confidence.pkl.gz` - a confidence matrix in Matlab v5 mat-file format, and a Python compressed data 'pickle' file. Now, as well, in the `hyp/` folder, `.rttm` with labels found from a config file [noisemeclasses.txt](https://github.com/riebling/OpenSAT/blob/master/noisemeclasses.txt) + +-More details on output format- + +The 18 classes are as follows: +``` +0 background +1 speech +2 speech_ne +3 mumble +4 singing +5 music_sing +6 music +7 human +8 cheer +9 crowd +10 animal +11 engine +12 noise_ongoing +13 noise_pulse +14 noise_tone +15 noise_nature +16 white_noise +17 radio +``` +The frame length is 0.1s. The system also uses a 2-second window, so the i-th frame starts at (0.1 * i - 2) seconds and finishes at (0.1 * i) seconds. That's why 60 seconds become 620 frames. 'speech_ne' means non-English speech + +-Sample RTTM output snippet- +``` +SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 +SPEAKER family 1 4.6 1.2 background 0.327808111906 +SPEAKER family 1 5.8 1.1 speech 0.430758684874 +SPEAKER family 1 6.9 1.2 background 0.401730179787 +SPEAKER family 1 8.1 0.7 speech 0.407463937998 +SPEAKER family 1 8.8 1.1 background 0.37258502841 +SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +``` + +The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the more detailed results as seen above. + +### OpenSmile_SAD + +Main reference for this tool: + +Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. + +#### General intro + +TO BE ADDED + +### TOCombo_SAD + +Main references for this tool: + +A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. +S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. + +#### General intro + +TO BE ADDED + +### DiarTK + +Main reference for this tool: + +D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. + +#### General intro + +TO BE ADDED + + +#### Instructions for direct use + +This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format as generated by one of the tools above. A script to run DiarTK (also known as ib_diarization_toolkit) can be found in `tools/diartk.sh`. Here is its usage: +``` +Usage: diartk.sh +where dirname is the name of the folder +containing the wav files, and transcription +specifies which transcription you want to use. +Choices are: + ldc_sad + noisemes + textgrid + eaf + rttm +``` +To invoke the tool from outside the VM, invoke it with a command like: +``` +vagrant ssh -c 'tools/diartk.sh data noisemes' +``` +where `data/` is in the current working directory, and contains .wav audio as well as speech/nonspeech RTTM files with names based on the tool that generated them, from the set of possible SAD providers `ldc_sad`, `noisemes`, `textgrid`, `eaf`, `rttm` for example `noisemes_sad_myaudio.rttm` or `ldc_sad_myaudio.rttm` + +### LDC Diarization Scoring + +Main references for this tool: + +Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. +Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. + +#### General intro + +For SAD, we employ the evaluation included in the LDC SAD, which returns the false alarm (FA) rate (proportion of frames labeled as speech that were non-speech in the gold annotation) and missed speech rate (proportion of frames labeled as non-speech that were speech in the gold annotation). For TD, we employ the evaluation developed for the DiHARD Challenge, which returns a Diarization error rate (DER), which sums percentage of speaker error (mismatch in speaker IDs), false alarm speech (non-speech segments assigned to a speaker) and missed speech (unassigned speech). + +One important consideration is in order: What to do with files that have no speech to begin with, or where the system does not return any speech at the SAD stage or any labels at the TD stage. This is not a case that is often discussed in the litera- ture because recordings are typically targeted at moments where there is speech. However, in naturalistic recordings, some ex- tracts may not contain any speech activity, and thus one must adopt a coherent framework for the evaluation of such instances. We opted for the following decisions. + +If the gold annotation was empty, and the SAD system returned no speech labels, then the FA = 0 and M = 0; but if the SAD system returned some speech labels, then FA = 100 and M = 0. Also, if the gold annotation was not empty and the sys- tem did not find any speech, then this was treated as FA = 0 and M=100. + +As for the TD evaluation, the same decisions were used above for FA and M, and the following decisions were made for mismatch. If the gold annotation was empty, regardless of what the system returned, the mismatch rate was treated as 0. If the gold annotation was empty but a pipeline returned no TD labels (either because the SAD in that system did not detect any speech, or because the diarization failed), then this was penalized via a miss of 100 (as above), but not further penalized in terms of talker mismatch, which was set at 0. + + From fe0b60ccae3da7912d78ba8e16e2384a1485b017 Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 10 Oct 2018 15:42:02 +0200 Subject: [PATCH 020/299] change theme of doc to read the docs theme --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 852725d..dbf5efd 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -83,7 +83,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the From dea5296ca0c600e9d3d1b90dd22d8aa5903dda37 Mon Sep 17 00:00:00 2001 From: Alex Cristia Date: Mon, 15 Oct 2018 14:32:56 +0200 Subject: [PATCH 021/299] move to readthedocs --- README.md | 548 +----------------------------------------------------- 1 file changed, 2 insertions(+), 546 deletions(-) diff --git a/README.md b/README.md index d7542a9..6f8bf57 100644 --- a/README.md +++ b/README.md @@ -1,549 +1,5 @@ -This repo contains the development version of the ACLEW Diarization Virtual Machine (DiViMe). +This repo contains the development version of the ACLEW Diarization Virtual Machine (DiViMe). The ACLEW DiViMe is a collection of tools allowing users to add annotations onto a long-form raw audio recording. -# Initial questions +Please see the online documentation at https://divime.readthedocs.io/ for instructions on installation and use. -## What is the ACLEW DiViMe? -It is a collection of diarization tools, i.e., it allows users to add annotations onto a raw audio recording. At present, we have tools to do the following types of annotation: - -1) Speech activity detection (answers the question: when is someone talking?) - -2) Talker diarization (answers the question: who is talking?) - -We are hoping to add more tools in the future, including register detection, syllable quantification, and vocal maturity estimation. - -## Who is the ACLEW DiViMe for? - -Our target users have "difficult" recordings, E.G. recorded in natural environment, from sensitive populations, etc. Therefore, we are assuming users who are unable to share their audio recordings. Our primary test case involves language acquisition in children 0-3 years of age. - -We are hoping to make the use of these tools as easy as possible, but some command line programming will be unavoidable. If you are worried when reading this, we can recommend the Software Carpentry programming courses for researchers, and particularly their [unix bash](http://swcarpentry.github.io/shell-novice) and [version control](http://swcarpentry.github.io/git-novice/) bootcamps. - -## What exactly is inside the ACLEW DiViMe? - -A virtual machine is actually a mini-computer that gets set up inside your computer. This creates a virtual environment within which we can be sure that our tools run, and run in the same way across all computers (Windows, Mac, Linux). - -Inside this mini-computer, we have put the following tools: - -1) Speech activity detection (answers the question: when is someone talking?) - - * [LDC Speech Activity Detection](https://github.com/aclew/DiViMe#ldc_sad)(coming soon) - * [Speech Activity Detection Using Noisemes](#noisemes_sad) - * [OpenSmile SAD](#opensmile_sad) - * [Threshold Optimized Combo SAD](#tocombo_sad) - - -2) Talker diarization (answers the question: who is talking?) - - * [DiarTK](#diartk) - -3) Evaluation - -If a user has some annotations, they may want to know how good the ACLEW DiViMe parsed their audio recordings. In that case, you can use one tool we soon paln to provide to evaluate: - - * [LDC Diarization Scoring](https://github.com/aclew/DiViMe#ldc-diarization-scoring) - - -# Installation instructions - -Try the following first: - -1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link and follow the prompted instructions - -1. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. - -2. Clone the present repository: - - - Open a terminal window - - In it, navigate to the directory in which you want the VM to be hosted - - type in: - -`$ git clone https://github.com/aclew/DiViMe` - -3. Change into it by - -`$ cd divime` - -4. Install HTK - -HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. - -- Go to the HTK download page http://htk.eng.cam.ac.uk/download.shtml -- Register by following the instructions on the left (under "Getting HTK": Register) -- Check that you have received your password via email; you will need it for the next step. -- Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). The download is probably called HTK-3.4.1.tar.gz, although the numbers may change if they update their code. -- Move the HTK-*.tar.gz file into the root folder of this repository (alongside Vagrantfile), and rename it HTK.tar.gz - -5. Type - -`$ vagrant up` - -The first time you do this, it will take at least 20 minutes to install all the packages that are needed to build the virtual machine. -Once the virtual machine will be installed, it will stay stuck at "installation finished" for few minutes. However, the tools are not yet installed at this step. -You will need to wait for the tools to be installed, and to take back the control of the terminal to run the tools. - -The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/aclew/DiViMe/issues), describing your situation. - -Advanced topic: [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker) - -# Checking your installation - -The very first time you use DiViMe, it is a good idea to run a quickstart test, which will be performed using the public files from the ACLEW Starter set (Bergelson et al., 2017): - -1. Open a terminal -2. Navigate inside the DiViMe folder -3. Do -`$ vagrant up` -4. Do -`$ vagrant ssh -c "tools/test.sh"` - -This should produce the output: - -``` -Testing LDC SAD... -LDC SAD passed the test. - -Testing Speech Activity Detection Using Noisemes... -Noisemes passed the test. - -Testing OpenSmile SAD... -OpenSmile SAD passed the test. - -Testing Threshold Optimized Combo SAD... -Threshold Optimized Combo SAD passed the test. - -Testing DiarTK... -DiarTK passed the test. - -Congratulations, everything is OK! - -This is the simple test with a few short files. If you would like to run a test for use with daylong recordings, please run $ vagrant ssh -c "tools/test-daylong.sh". Note that this will download a very large recording. -``` - - -# Checking your installation for daylong files - -Many of our users have very long files that they want to analyze. To check that our tools are working in your environment, we will test them using the one of the public files from the vanDam corpus (vanDam & Tully, 2016): - -1. Open a terminal -2. Navigate inside the DiViMe folder -3. Do -`$ vagrant up` -4. Do -`$ vagrant ssh -c "tools/test-daylong.sh"` - -This test will take quite some time. It will proceed to download that daylong file, and then process it with all of our tools. Afterwards, it should produce the output: - -``` -Downloading the daylong file... -Download complete. - -Processing annotations... -Annotations processed. - -Testing LDC SAD... -LDC SAD passed the test. - -Testing Speech Activity Detection Using Noisemes... -Noisemes passed the test. - -Testing OpenSmile SAD... -OpenSmile SAD passed the test. - -Testing Threshold Optimized Combo SAD... -Threshold Optimized Combo SAD passed the test. - -Testing DiarTK... -DiarTK passed the test. - -Congratulations, everything is OK! - -``` - -# Common installation errors and fixes - -- For LDC SAD, you may get an error "LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include LDC SAD. This error means that you cannot use LDC SAD, but you can use any other SAD/VAD. (For example, noisemes.) -- For LDC SAD, Noisemes, and DiarTK, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. The easiest way to fix it is to install HTK (again). - -If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. - -# Update instructions - -If there is a new version of DiViMe, you'll need to perform the following 3 steps from within the DiViME folder on your terminal: - - -``` -$ vagrant destroy -$ git pull -$ vagrant up -``` - -# Uninstallation instructions - -If you want to get rid of the files completely, you should perform the following 3 steps from within the DiViME folder on your terminal: - -``` -$ vagrant destroy -$ cd .. -$ rm -r -f divime -``` - - - - - -# Use instructions - - -## Short instructions for all tools - -1. Put the files you want to analyze inside the "data" folder inside the DiViMe folder. If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. - -2. If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. It is probably safer to make a copy (rather than moving them), in case you later decide to delete the whole vagrant folder. - -3. Launch the virtual machine anytime by navigating to your DiViMe folder on your terminal and performing: - -`$ vagrant up` - -4. For the SAD tools, type a command like the one below, being careful to type the SAD tool name instead of SADTOOLNAME: - -`$ vagrant ssh -c "tools/SADTOOLNAME.sh data/"` - -The SAD options are: -- SADTOOLNAME = ldc_sad (coming soon) -- SADTOOLNAME = noisemes_sad -- SADTOOLNAME = noisemes_full -- SADTOOLNAME = opensmile_sad -- SADTOOLNAME = tocombo_sad - -This will create a set of new rttm files, with the name of the tool added at the beginning. For example, imagine you have a file called participant23.wav, and you decide to run both the LDC_SAD and the Noisemes analyses. You will run the following commands: - - -``` -$ vagrant ssh -c "tools/ldc_sad.sh data/" -$ vagrant ssh -c "tools/noisemes_sad.sh data/" -``` - -And this will result in your having the following three files in your /data/ folder: - -- participant23.wav -- ldc_sad_participant23.rttm -- noisemes_sad_participant23.rttm - -If you look inside one of these .rttm's, say the ldc_sad one, it will look as follows: - -``` -SPEAKER participant23 1 0.00 0.77 speech -SPEAKER participant23 1 0.77 0.61 nonspeech -SPEAKER participant23 1 1.38 2.14 speech -SPEAKER participant23 1 3.52 0.82 nonspeech -``` - -This means that LDC_SAD considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. - - -5. For the diarization tools, type a command like the one below, being careful to type the diarization tool name instead of DiarTOOLNAME: - -`$ vagrant ssh -c "tools/DiarTOOLNAME.sh data/ noisemes"` - -The DiarTOOLNAME options are: -- DiarTOOLNAME = diartk -- DiarTOOLNAME = yunitate - -Notice there is one more parameter provided to the system in the call; in the example above "noisemes". This is because the DiarTK tool only does talker diarization (i.e., who speaks) but not speech activity detection (when is someone speaking). Therefore, this system requires some form of SAD. With this last parameter, you are telling the system which annotation to use. At present, you can choose between: - -- ldc_sad: this means you want the system to use the output of the LDC_SAD system. If you have not run LDC_SAD, the system will run it for you. -- noisemes: this means you want the system to use the output of the noisemes system. If you have not run LDC_SAD, the system will run it for you. -- opensmile: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. -- tocombosad: this means you want the system to use the output of the tocombo_sad system. If you have not ran tocombosad, the system will run it for you. -- textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. -- eaf: this means you want the system to use your eaf annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your eaf files before you start. Please note that the system will convert your eafs into .rttm in the process. -- rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. - - -Finally, if no parameter is provided, the system will default to noisemes. - -6. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: - -`$ vagrant ssh -c "tools/eval.sh data/ noisemes"` - -Notice there are 2 parameters provided to the evaluation suite. The first parameter tells the system which folder to analyze (in this case, the whole data/ folder). The second parameter indicates which tool's output to evaluate (in this case, noisemes). The system will use the .rttm annotations if they exist; or the .eaf ones if the former are missing; or the .textgrid of neither .rttm nor .eaf are found. -If you want to evaluate a diarization produced by the diartk tool, you will have to specify a third parameter, to tell the system which SAD was used to compute the diartk outputs you want to evaluate. E.G. : -`$ vagrant ssh -c "tools/eval.sh data/ diartk noisemes_sad` - -7. Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: - -`$ vagrant halt` - -### ACLEW Starter Dataset - -The ACLEW Starter dataset is freely available, and can be downloaded in order to test the tools. -To download it, using your terminal, as explained before, go in the DiViMe folder and do: -`$ ./get_aclewStarter.sh` -This will create a folder called aclewStarter, in which you will find the audio files from the public dataset and their corresponding .rttm annotations. - -You can then use the tools mentioned before, by replacing the "data/" folder in the command given in the previous paragraph by "aclewStarter/", E.G for noisemes: -```$ vagrant ssh -c "tools/noisemes_sad.sh aclewStarter/"``` - -Reference for the ACLEW Starter dataset: - -Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved August 15, 2018 from http://doi.org/10.17910/B7.390. - -## More details for each tool - -### LDC_SAD - -Main reference for this tool: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. - -#### General intro - -LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. - - -Associated references: -Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. -Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. - -### Noisemes_sad - -Main reference for this tool: - -Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) - - -#### General intro - -This system will classify slices of the audio recording into one of 17 noiseme classes: - -- background -- speech -- speech non English -- mumble -- singing alone -- music + singing -- music alone -- human sounds -- cheer -- crowd sounds -- animal sounds -- engine -- noise_ongoing -- noise_pulse -- noise_tone -- noise_nature -- white_noise -- radio - - -#### Instructions for direct use - -You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. - -``` -$ vagrant ssh -c "OpenSAT/runOpenSAT.sh data/<$MYFILE>" -``` - -You can also analyze a group of files as follows: - -``` -$ vagrant ssh -c "OpenSAT/runDiarNoisemes.sh data/" -``` - -This will analyze all .wav's inside the "data" folder. - -Created annotations will be stored inside the same "data" folder. - -#### Some more technical details - -For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": - -``` -$ vagrant ssh -$ cd OpenSAT -``` - -The main script is runOpenSAT.sh and takes one argument: an audio file in .wav format. -Upon successful completion, output will be in the folder (relative to ~/OpenSAT) -`SSSF/data/hyp//confidence.pkl.gz` - -The system will grind first creating features for all the .wav files it found, then will place those features in a subfolder `feature`. Then it will load a model, and process all the features generated, producing output in a subfolder `hyp/` two files per input: `.confidence.mat` and `.confidence.pkl.gz` - a confidence matrix in Matlab v5 mat-file format, and a Python compressed data 'pickle' file. Now, as well, in the `hyp/` folder, `.rttm` with labels found from a config file [noisemeclasses.txt](https://github.com/riebling/OpenSAT/blob/master/noisemeclasses.txt) - --More details on output format- - -The 18 classes are as follows: -``` -0 background -1 speech -2 speech_ne -3 mumble -4 singing -5 music_sing -6 music -7 human -8 cheer -9 crowd -10 animal -11 engine -12 noise_ongoing -13 noise_pulse -14 noise_tone -15 noise_nature -16 white_noise -17 radio -``` -The frame length is 0.1s. The system also uses a 2-second window, so the i-th frame starts at (0.1 * i - 2) seconds and finishes at (0.1 * i) seconds. That's why 60 seconds become 620 frames. 'speech_ne' means non-English speech - --Sample RTTM output snippet- -``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 -``` - -The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the more detailed results as seen above. - -### OpenSmile_SAD - -Main reference for this tool: - -Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. - -#### General intro - -TO BE ADDED - -### TOCombo_SAD - -Main references for this tool: - -A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. -S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. - -#### General intro - -TO BE ADDED - -### DiarTK - -Main reference for this tool: - -D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. - -#### General intro - -TO BE ADDED - - -#### Instructions for direct use - -This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format as generated by one of the tools above. A script to run DiarTK (also known as ib_diarization_toolkit) can be found in `tools/diartk.sh`. Here is its usage: -``` -Usage: diartk.sh -where dirname is the name of the folder -containing the wav files, and transcription -specifies which transcription you want to use. -Choices are: - ldc_sad - noisemes - textgrid - eaf - rttm -``` -To invoke the tool from outside the VM, invoke it with a command like: -``` -vagrant ssh -c 'tools/diartk.sh data noisemes' -``` -where `data/` is in the current working directory, and contains .wav audio as well as speech/nonspeech RTTM files with names based on the tool that generated them, from the set of possible SAD providers `ldc_sad`, `noisemes`, `textgrid`, `eaf`, `rttm` for example `noisemes_sad_myaudio.rttm` or `ldc_sad_myaudio.rttm` - -### LDC Diarization Scoring - -Main references for this tool: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. -Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. - -#### General intro - -For SAD, we employ the evaluation included in the LDC SAD, which returns the false alarm (FA) rate (proportion of frames labeled as speech that were non-speech in the gold annotation) and missed speech rate (proportion of frames labeled as non-speech that were speech in the gold annotation). For TD, we employ the evaluation developed for the DiHARD Challenge, which returns a Diarization error rate (DER), which sums percentage of speaker error (mismatch in speaker IDs), false alarm speech (non-speech segments assigned to a speaker) and missed speech (unassigned speech). - -One important consideration is in order: What to do with files that have no speech to begin with, or where the system does not return any speech at the SAD stage or any labels at the TD stage. This is not a case that is often discussed in the litera- ture because recordings are typically targeted at moments where there is speech. However, in naturalistic recordings, some ex- tracts may not contain any speech activity, and thus one must adopt a coherent framework for the evaluation of such instances. We opted for the following decisions. - -If the gold annotation was empty, and the SAD system returned no speech labels, then the FA = 0 and M = 0; but if the SAD system returned some speech labels, then FA = 100 and M = 0. Also, if the gold annotation was not empty and the sys- tem did not find any speech, then this was treated as FA = 0 and M=100. - -As for the TD evaluation, the same decisions were used above for FA and M, and the following decisions were made for mismatch. If the gold annotation was empty, regardless of what the system returned, the mismatch rate was treated as 0. If the gold annotation was empty but a pipeline returned no TD labels (either because the SAD in that system did not detect any speech, or because the diarization failed), then this was penalized via a miss of 100 (as above), but not further penalized in terms of talker mismatch, which was set at 0. - -# Troubleshooting - -## Installation issues -### Virtual Machine creation -If your computer freezes after `vagrant up`, it may be due to several things. -If your OS is ubuntu 16.04, there's a known incompatibility between VirtualBox and the 4.13 Linux kernel on ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installation_simple), or install the latest version of virtualbox which should fix the problem. -If you are not on ubuntu 16.04, or if the previous fix didn't work, it may also be due to the fact that Vagrant is trying to create a Virtual Machine that asks for too much resources. Please ensure that you have enough space on your computer (you should have at least 15Gb of free space) and check that the memory asked for is okay. If not, you can lower the memory of the VM by changing line 25 of the VagrantFile, -``` -vbox.memory = 3072 -``` -to a lower number, such as -``` -vbox.memory = 2048 -``` -### Resuming the Virtual Machine -If you already used the VM once, shut down your computer, turned it back on and can't seem to be able to do `vagrant up` again, you can simply do -``` -vagrant destroy -``` -and recreate the VM using -``` -vagrant up -``` -If you don't want to destroy it, you can try opening the VirtualBox GUI, go to `File -> Settings or Preferences -> Network `, click on the `Host-only Networks` tab, then click the network card icon with the green plus sign in the right, if there are no networks yet listed. The resulting new default network should appear with the name ‘vboxnet0’. -You can now try again with `vagrant up` - - -## Problems with some of the Tools -### LDC SAD, OpenSmile, DiarTK - -If ldc_sad, OpenSmile, DiarTK don't seem to work after vagrant up, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: -``` -vagrant up --provision -``` -This step will install HTK inside the VM, which is used by several tools including ldc_sad. - -### Noisemes -If you use the noisemes_sad or the noisemes_full tool, one problem you may encounter is that it doesn't treat all of your files and gives you an error that looks like this: -``` -Traceback (most recent call last): - File "SSSF/code/predict/1-confidence-vm5.py", line 59, in - feature = pca(readHtk(os.path.join(INPUT_DIR, filename))).astype('float32') - File "/home/vagrant/G/coconut/fileutils/htk.py", line 16, in readHtk - data = struct.unpack(">%df" % (nSamples * sampSize / 4), f.read(nSamples * sampSize)) -MemoryError -``` -If this happens to you, it's because you are trying to treat more data than the system/your computer can handle. -What you can do is simply put the remaining files that weren't treated in a seperate folder and treat this folder seperately (and do this until all of your files are treated if it happens again on very big datasets). -After that, you can put back all of your data in the same folder. - -### Input Format For Transcriptions -If your transcriptions are in TextGrid format but the conversion doesn't seem to work, it's probably because it isn't in the right TextGrid format. -The input TextGrid the system allows is a TextGrid in which all the tiers have speech segments (so remove tiers with no speech segments) and all the annotated segments for each tiers is indeed speech (so remove segments that are noises or other non-speech type). - - -# References - -Our work builds directly on that of others. The main references for tools currently included and/or data currently used to perform tests are: - -- Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved October 1, 2018 from http://doi.org/10.17910/B7.390. -- Eyben, F. Weninger, F., Gross, F. & B. Schuller. (2013). Recent developments in opensmile, the munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. -- Räsänen, O., Seshadri, S., & Casillas, M. (2018, June). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. In Interspeech 2018. -- Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. -- Sadjadi, S.O. & Hansen, J.H.L. (2013). Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux. IEEE Signal Processing Letters, 20(3), 197-200. -- VanDam, M., & Tully, T. (2016, May). Quantity of mothers’ and fathers’ speech to sons and daughters. Talk presented at the 171st Meeting of the Acoustical Society of America, Salt Lake City, UT. -- Vijayasenan, D. & Valente, F. (2012) Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings. Thirteenth Annual Conference of the International Speech Communication Association, 2012. -- Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) -- Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. -- Ziaei, A. Sangwan, A., & Hansen, J.H.L. (2016). Effective word count estimation for long duration daily naturalistic audio recordings. Speech Communication, 84, 15-23. -- Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. From 95969a1b23d2708e7ce8940e958cd26d072ce842 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 15 Oct 2018 16:44:33 +0200 Subject: [PATCH 022/299] minor --- docs/source/index.rst | 1 + docs/source/instructions_for_contributors.md | 71 ++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 docs/source/instructions_for_contributors.md diff --git a/docs/source/index.rst b/docs/source/index.rst index 6823ed1..4ad3c50 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -14,6 +14,7 @@ Welcome to DiViMe's documentation! install usage troubleshoot + instructions_for_contributors references diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md new file mode 100644 index 0000000..b3dbd01 --- /dev/null +++ b/docs/source/instructions_for_contributors.md @@ -0,0 +1,71 @@ +# Instructions for contributors + + +## Short instructions + +1. Install DiViMe as per the installation instructions. + +2. Run the test.sh routine and the test-daylong.sh routine. They will each download audio recordings and annotations that you will need to make sure your tool is compatible with the rest of the work flow. + +3. Open Vagrantfile in any text editor and add there what needs to be installed to get your tool to work in this environment. Typically, you'll have something like + +`$ git clone http://github.com/srvk/OpenSAT` + +4. STEPS MISSING HERE -- EXPLAIN HOW TO TEST THAT TOOL WORKS IN ENVIRONMENT + +6. Write a wrapper allowing users to call on your tool. + +- The wrapper should be written in bash, and it should be called TOOLNAME_STAGE.sh. +- You choose your own tool's name. Use anything you want except the other names already in use. +- The fixed stages names are: sad (for both speech activity detection and voice activity detection), diar (for speaker diarization and role assignment), and add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use sad) or the talker role input (then use add type). +- Read on for input/output requirements depending on stage. +- This flowchart may help: https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9 + + +5. All tools should read in all .wav files inside data/ and, optionally, associated annotation files, which are in rttm format. + +6. All tools should write into the data/ folder an annotation file for each .wav file; this annotation file should respect the rttm format. + +7. For all annotations, we are using the following rttm format throughout (From NIST's 2009 eval plan https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf): + +** todo: this example is bad: cells are not intelligible and the example in fact violates rttm recommendations** + +``` +SPEAKER file17 1 0.00 0.77 speech +SPEAKER file17 1 0.77 0.61 nonspeech +SPEAKER file17 1 1.38 2.14 speech +SPEAKER file17 1 3.52 0.82 nonspeech +``` + +The columns are: Type file chnl tbeg tdur ortho stype name conf Slat + +8. If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named toolname_sad_filename.rttm, which will look like this: + +``` +SPEAKER file17 1 0.00 0.77 speech +SPEAKER file17 1 1.38 2.14 speech + +``` + +9. If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the immediately previous step. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then use the default sad/vad (see end of instructions for list of default tools). In both cases, your wrapper should first check these sad/vad exist and if not, execute a command to generate them (see Instructions for use for instructions on how to use DiViMe's included tools). + +10. Your SAD-type tool should return one rttm per audio file, named toolname_diar_filename.rttm, which must look like this: + +** todo: copy-paste the example above, remove all information not present at diar or role stage ** + +10. If your tool is not a VAD/SAD but it is a classifier that assumes only raw acoustic input, then declare it as a sad/vad, and follow the instructions for vad/sad above, except that you'll adapt the rttm output to the classes you typically have. For example, one tool classifies audio into noiseme categories. It returns rttm's like this one: + +** todo: put example here, but make sure that the "type" class is not violated by the contents of the subtype column. For example, this is bad (noise should not be class SPEAKER):** + +``` +SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 +SPEAKER family 1 4.6 1.2 background 0.327808111906 +SPEAKER family 1 5.8 1.1 speech 0.430758684874 +SPEAKER family 1 6.9 1.2 background 0.401730179787 +SPEAKER family 1 8.1 0.7 speech 0.407463937998 +SPEAKER family 1 8.8 1.1 background 0.37258502841 +SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +``` + +11. If your tool is a classifier that works only on a subtype of speaker (e.g., only on children's speech), then assume that each wav is accompanied by an rttm that has this information noted in column XX. + From 353513b4673cff2e59a4d35984250b4a895c132b Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 15 Oct 2018 17:00:12 +0200 Subject: [PATCH 023/299] closed issue #17 --- docs/source/instructions_for_contributors.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index b3dbd01..6c1a6cd 100644 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -1,7 +1,7 @@ # Instructions for contributors -## Short instructions +## Before you start 1. Install DiViMe as per the installation instructions. @@ -11,8 +11,12 @@ `$ git clone http://github.com/srvk/OpenSAT` +## Adapting your tool to the VM environment + 4. STEPS MISSING HERE -- EXPLAIN HOW TO TEST THAT TOOL WORKS IN ENVIRONMENT +## Integrating your tool into the DiViMe workflow + 6. Write a wrapper allowing users to call on your tool. - The wrapper should be written in bash, and it should be called TOOLNAME_STAGE.sh. @@ -26,6 +30,8 @@ 6. All tools should write into the data/ folder an annotation file for each .wav file; this annotation file should respect the rttm format. +6. Your tool may generate two types of ancillary files: Intermediary representation files, such as features extracted from the wav files; and log files, with detailed information of what was done and how. Intermediary representation files should be deleted. Log files may be stored in the temp/ folder, which will only be accessible from within the VM, and should be deleted if they are large (>5MB). As a reminder, our target user may not be technically advanced, and thus including long technical logs may do more to confuse than to help. + 7. For all annotations, we are using the following rttm format throughout (From NIST's 2009 eval plan https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf): ** todo: this example is bad: cells are not intelligible and the example in fact violates rttm recommendations** @@ -69,3 +75,6 @@ SPEAKER family 1 9.9 1.7 noise_ongoing 0.31518515 11. If your tool is a classifier that works only on a subtype of speaker (e.g., only on children's speech), then assume that each wav is accompanied by an rttm that has this information noted in column XX. +** todo: add default tool section** + +** todo: address "process multiple files in parallel, if possible (like using sbatch?)"** From c36e5ab9f93a427744790e72b9eee36634ea59a4 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 15 Oct 2018 18:28:40 +0200 Subject: [PATCH 024/299] minor --- docs/source/references.md | 1 + docs/source/usage.md | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/docs/source/references.md b/docs/source/references.md index 728a3bc..98b6c13 100644 --- a/docs/source/references.md +++ b/docs/source/references.md @@ -4,6 +4,7 @@ Our work builds directly on that of others. The main references for tools curren - Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved October 1, 2018 from http://doi.org/10.17910/B7.390. - Eyben, F. Weninger, F., Gross, F. & B. Schuller. (2013). Recent developments in opensmile, the munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. +- Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013, May). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. - Räsänen, O., Seshadri, S., & Casillas, M. (2018, June). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. In Interspeech 2018. - Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. - Sadjadi, S.O. & Hansen, J.H.L. (2013). Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux. IEEE Signal Processing Letters, 20(3), 197-200. diff --git a/docs/source/usage.md b/docs/source/usage.md index 361cfed..eb3dadf 100644 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -216,13 +216,29 @@ The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the mor ### OpenSmile_SAD -Main reference for this tool: +Main references for this tool: -Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. +Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. + +Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. #### General intro -TO BE ADDED +openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coefficient RASTA-PLP plus first order delta features. It then uses a long short-term memory recurrent neural network (see details in Eyben et al., 2013b) that has been pre-trained on two corpora of read and spontaneous speech by adults recorded in laboratory conditions, augmented with various noise types. + +#### Some more technical details + +By default, these are the parameters that are being used: + +monoMixdown = 1, means "mix down all recorded channels to 1 mono channel" +**todo stopped here** +noHeader = 0 +buffersize_sec = 10 +startIndex = 1 +preSil = 0.1 +postSil = 0.1 +multiOut = 1 +sampleFormat = 16bit ### TOCombo_SAD From 55649bb52f842d039869c92c0c6aa1b9d8bbabb8 Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 17 Oct 2018 16:48:14 +0200 Subject: [PATCH 025/299] minor --- docs/source/usage.md | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index eb3dadf..94f4303 100644 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -228,17 +228,26 @@ openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coeffi #### Some more technical details -By default, these are the parameters that are being used: +These are the parameters that are being used with values that depart from the openSMILE default settings (quoted material comes from either of the openSMILE manuals): monoMixdown = 1, means "mix down all recorded channels to 1 mono channel" -**todo stopped here** -noHeader = 0 -buffersize_sec = 10 -startIndex = 1 -preSil = 0.1 -postSil = 0.1 -multiOut = 1 -sampleFormat = 16bit +noHeader = 0, means read the RIFF header (don't need to specify the parameters ‘sampleRate’, ‘channels’, and possibly ‘sampleSize’) +preSil = 0.1 "Specifies the amount of silence at the turn beginning in seconds, i.e. the lag of the turn +detector. This is the length of the data that will be added to the current segment prior to +the turn start time received in the message from the turn detector component"; we use a tighter criterion than the default (.2) +postSil = 0.1 "Specifies the amount of silence at the turn end in seconds. This is the length of the data +that will be added to the current segment after to the turn end time received in the message +from the turn detector component."; we use a tighter criterion than the default (.3) + +You can change these parameters locally by doing: +``` +$ vagrant ssh +$ nano /vagrant/conf/vad/vad_segmenter_aclew.conf +``` + +openSMILE manuals consulted: +Eyben, F., Woellmer, M., & Schuller, B. (2013). openSMILE: The Munich open Speech and Music Interpretation by Large space Extraction toolkit. Institute for Human-Machine Communication, version 2.0. http://download2.nust.na/pub4/sourceforge/o/project/op/opensmile/openSMILE_book_2.0-rc1.pdf +Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf ### TOCombo_SAD From 07e108031b6831b94bba8cd1cbba5a5717717708 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Wed, 17 Oct 2018 16:55:03 +0200 Subject: [PATCH 026/299] Add script conversion from its format to rttm format --- toolbox/its2rttm.py | 80 +++++++++++++++++++++++++++++++++++++++++++++ toolbox/its2rttm.sh | 23 +++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 toolbox/its2rttm.py create mode 100755 toolbox/its2rttm.sh diff --git a/toolbox/its2rttm.py b/toolbox/its2rttm.py new file mode 100644 index 0000000..240e5a3 --- /dev/null +++ b/toolbox/its2rttm.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# +# author: The ACLEW Team +# +# This script takes as input its file +# and convert it to rttm file. + +import os +import re +import argparse + + +def its_line_2_rttm_line(its_line, rttm_name): + """ + < Segment spkr = "TVF" average_dB = "-49.61" peak_dB = "-38.96" startTime = "PT31819.24S" endTime = "PT31820.61S" / > + to + SPEAKER rttm_name 1 t_beg dur class + """ + its_line = its_line[its_line.find("<"):] + + rttm_line = "" + if its_line[:8] == "\t" +\ + "\t" +\ + spkr + "\t" +\ + "\t" +\ + "\n" + + return rttm_line + + +def its_2_rttm(input_path, output_path): + """Read a RTTM file indicating gold diarization""" + rttm_name = os.path.splitext(os.path.basename(output_path))[0] + + with open(input_path, 'r') as its: + with open(output_path, 'w') as rttm: + for its_line in its: + rttm_line = its_line_2_rttm_line(its_line, rttm_name) + rttm.write(rttm_line) + +def main(): + """Take transcription file in its format as input, and write """ + """it into rttm format.""" + parser = argparse.ArgumentParser( + description='Take transcription file in its format as input, and write ' + 'it into rttm format.', + add_help=True, + usage='%(prog)s [its] [rttm]') + parser.add_argument( + 'its', type=str, metavar='PATH', + help='Path to the its input') + parser.add_argument( + 'rttm', type=str, metavar='PATH', + help='Path to the rttm output') + + args = parser.parse_args() + + its_2_rttm(args.its, args.rttm) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/toolbox/its2rttm.sh b/toolbox/its2rttm.sh new file mode 100755 index 0000000..7f54580 --- /dev/null +++ b/toolbox/its2rttm.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Given a folder, convert all of the its files to rttm + +SCRIPT_PATH=$(dirname "$(readlink -f "$0")") + +folder=$1 + +if [ -z "$folder" ]; then + echo "You must specify a folder containing its files." + exit +fi + +if [ ! -n "$(ls -A $folder/*.its 2>/dev/null)" ] +then + echo "The folder you specified does not contain any its files." + +fi + +for its_file in $folder/*.its +do + rttm_name=${its_file%.its}.rttm + python $SCRIPT_PATH/its2rttm.py $its_file $rttm_name +done From 0d229a1f4360d572067da65f994ea420b0c258fc Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 17 Oct 2018 11:06:22 -0400 Subject: [PATCH 027/299] Clarify diarization command examples --- docs/source/usage.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index 94f4303..69f1fbb 100644 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -47,16 +47,12 @@ SPEAKER participant23 1 3.52 0.82 nonspeech This means that LDC_SAD considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. +5. There are two diarization tools: diartk and yuniSeg. Here are example commands to run each, for the data/ input folder: -5. For the diarization tools, type a command like the one below, being careful to type the diarization tool name instead of DiarTOOLNAME: +`$ vagrant ssh -c "tools/diartk.sh data/ noisemes"` +`$ vagrant ssh -c "tools/yuniSeg.sh data/ noisemes"` -`$ vagrant ssh -c "tools/DiarTOOLNAME.sh data/ noisemes"` - -The DiarTOOLNAME options are: -- DiarTOOLNAME = diartk -- DiarTOOLNAME = yunitate - -Notice there is one more parameter provided to the system in the call; in the example above "noisemes". This is because the DiarTK tool only does talker diarization (i.e., who speaks) but not speech activity detection (when is someone speaking). Therefore, this system requires some form of SAD. With this last parameter, you are telling the system which annotation to use. At present, you can choose between: +Diarization tools only perform talker diarization (i.e., *who* speaks) but not speech activity detection (*when* is someone speaking). Therefore, this system requires some form of SAD. The third parameter ('noisemes') tells the system which SAD annotation to use, from among the list: - ldc_sad: this means you want the system to use the output of the LDC_SAD system. If you have not run LDC_SAD, the system will run it for you. - noisemes: this means you want the system to use the output of the noisemes system. If you have not run LDC_SAD, the system will run it for you. From de7d237f2e96162cb96f1aa065e2801b2b6519c3 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Thu, 18 Oct 2018 10:11:18 -0400 Subject: [PATCH 028/299] Clone v1.0 tool/script/util repositories This prevents new commits in repositories from potentially breaking a working system Unfortunately it also means not automatically getting latest fixes, for commits that are Good :) --- Vagrantfile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 721cd2c..5065399 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -170,17 +170,17 @@ Vagrant.configure("2") do |config| # Install DiarTK, LDC SAD, LDC scoring, Rajat's LENA stuff cd /home/${user} - git clone http://github.com/srvk/OpenSAT - git clone http://github.com/srvk/ib_diarization_toolkit - #git clone http://github.com/srvk/ldc_sad_hmm - git clone http://github.com/srvk/dscore - git clone https://github.com/rajatkuls/lena-clean - git clone https://github.com/srvk/Yunitator - git clone https://github.com/srvk/To-Combo-SAD + git clone http://github.com/srvk/OpenSAT --branch v1.0 + git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 + #git clone http://github.com/srvk/ldc_sad_hmm --branch v1.0 + git clone http://github.com/srvk/dscore --branch v1.0 + git clone https://github.com/srvk/lena-clean --branch v1.0 + git clone https://github.com/srvk/Yunitator --branch v1.0 + git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 # Get the Wrapper scripts - git clone https://github.com/srvk/tools.git + git clone https://github.com/srvk/tools.git --branch v1.0 git clone https://github.com/aclew/varia.git # Festvox Speech Tools From 85237392f4fe4f85cf042d274a71208a7e92e142 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Fri, 19 Oct 2018 19:30:21 +0200 Subject: [PATCH 029/299] Opensmile doesn't write the wav segments now + Change accessing way rttm2scp.py --- conf/vad/output_segment_0001.wav | Bin 301826 -> 0 bytes conf/vad/output_segment_0002.wav | Bin 118976 -> 0 bytes conf/vad/vad_segmenter_aclew.conf | 2 +- toolbox/rttm2scp.py | 3 ++- 4 files changed, 3 insertions(+), 2 deletions(-) delete mode 100644 conf/vad/output_segment_0001.wav delete mode 100644 conf/vad/output_segment_0002.wav mode change 100644 => 100755 conf/vad/vad_segmenter_aclew.conf diff --git a/conf/vad/output_segment_0001.wav b/conf/vad/output_segment_0001.wav deleted file mode 100644 index c85fd4c8c6c32fb2a7760345d3d163e5c04f5261..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 301826 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 diff --git a/conf/vad/output_segment_0002.wav b/conf/vad/output_segment_0002.wav deleted file mode 100644 index 3a1d47a794fa9a1b48e44c51c13df1ac9bb58a2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118976 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 N4BE&2nOrkI^#5ae!qET# diff --git a/conf/vad/vad_segmenter_aclew.conf b/conf/vad/vad_segmenter_aclew.conf old mode 100644 new mode 100755 index 2c81751..35f1636 --- a/conf/vad/vad_segmenter_aclew.conf +++ b/conf/vad/vad_segmenter_aclew.conf @@ -37,7 +37,7 @@ printLevelStats = 0 [waveSinkCut:cWaveSinkCut] reader.dmLevel = frames -fileBase = \cm[waveoutput(W){output_segment_}:prefix of WAV output files] +fileBase = \cm[waveoutput(W){?}:prefix of WAV output files] fileExtension = .wav fileNameFormatString = %s%04d%s startIndex = 1 diff --git a/toolbox/rttm2scp.py b/toolbox/rttm2scp.py index f0ab256..c02bfa4 100755 --- a/toolbox/rttm2scp.py +++ b/toolbox/rttm2scp.py @@ -24,7 +24,8 @@ def read_rttm(input_path): all_intervals = [] fname = "" for line in rttm: - _, fname, _, onset, dur, _, _, _, _ = line.strip('\n').split() + row = line.split('\t') + fname, onset, dur = row[1], row[3], row[4] if float(dur) == 0: # Remove empty intervals continue From ee62cf9bbcd9bf26efd8662482a32e1d7f7e36a9 Mon Sep 17 00:00:00 2001 From: alecristia Date: Tue, 23 Oct 2018 10:59:25 +0200 Subject: [PATCH 030/299] added yunitator, cleaned up --- docs/source/usage.md | 96 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index 69f1fbb..5f89a1e 100644 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -18,7 +18,6 @@ The SAD options are: - SADTOOLNAME = ldc_sad (coming soon) - SADTOOLNAME = noisemes_sad -- SADTOOLNAME = noisemes_full - SADTOOLNAME = opensmile_sad - SADTOOLNAME = tocombo_sad @@ -26,54 +25,65 @@ This will create a set of new rttm files, with the name of the tool added at the ``` -$ vagrant ssh -c "tools/ldc_sad.sh data/" +$ vagrant ssh -c "tools/opensmile_sad.sh data/" $ vagrant ssh -c "tools/noisemes_sad.sh data/" ``` And this will result in your having the following three files in your /data/ folder: - participant23.wav -- ldc_sad_participant23.rttm +- opensmile_sad_participant23.rttm - noisemes_sad_participant23.rttm -If you look inside one of these .rttm's, say the ldc_sad one, it will look as follows: +If you look inside one of these .rttm's, say the opensmile_sad one, it will look as follows: ``` SPEAKER participant23 1 0.00 0.77 speech -SPEAKER participant23 1 0.77 0.61 nonspeech SPEAKER participant23 1 1.38 2.14 speech -SPEAKER participant23 1 3.52 0.82 nonspeech ``` -This means that LDC_SAD considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. +This means that opensmile_sad considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. -5. There are two diarization tools: diartk and yuniSeg. Here are example commands to run each, for the data/ input folder: +5. There is one **pure diarization** tool: diartk. Here is the command to run, for the data/ input folder: -`$ vagrant ssh -c "tools/diartk.sh data/ noisemes"` -`$ vagrant ssh -c "tools/yuniSeg.sh data/ noisemes"` +`$ vagrant ssh -c "tools/diartk.sh data/ noisemes_sad"` -Diarization tools only perform talker diarization (i.e., *who* speaks) but not speech activity detection (*when* is someone speaking). Therefore, this system requires some form of SAD. The third parameter ('noisemes') tells the system which SAD annotation to use, from among the list: +Pure diarization tools only perform talker diarization (i.e., *who* speaks) but not speech activity detection (*when* is someone speaking). Therefore, this system requires some form of SAD. The third parameter ('noisemes') tells the system which SAD annotation to use, from among the list: - ldc_sad: this means you want the system to use the output of the LDC_SAD system. If you have not run LDC_SAD, the system will run it for you. -- noisemes: this means you want the system to use the output of the noisemes system. If you have not run LDC_SAD, the system will run it for you. -- opensmile: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. -- tocombosad: this means you want the system to use the output of the tocombo_sad system. If you have not ran tocombosad, the system will run it for you. +- noisemes_sad: this means you want the system to use the output of the noisemes_sad system. If you have not run LDC_SAD, the system will run it for you. +- opensmile_sad: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. +- tocombo_sad: this means you want the system to use the output of the tocombo_sad system. If you have not ran tocombosad, the system will run it for you. - textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. - eaf: this means you want the system to use your eaf annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your eaf files before you start. Please note that the system will convert your eafs into .rttm in the process. - rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. +Finally, if no parameter is provided, the system will default to noisemes_sad. -Finally, if no parameter is provided, the system will default to noisemes. +6. There is one **role assignment** tool, which classifies spoken turns into three roles: children, female adults, male adults. It exists in two versions. -6. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: +The version we call "yunitator" takes the raw recording as input. To call this one, do -`$ vagrant ssh -c "tools/eval.sh data/ noisemes"` +`$ vagrant ssh -c "tools/yunitator.sh data/"` -Notice there are 2 parameters provided to the evaluation suite. The first parameter tells the system which folder to analyze (in this case, the whole data/ folder). The second parameter indicates which tool's output to evaluate (in this case, noisemes). The system will use the .rttm annotations if they exist; or the .eaf ones if the former are missing; or the .textgrid of neither .rttm nor .eaf are found. + +The version we call "yuniSeg" takes the raw recording as well as a SAD as input. To call this one, do + +`$ vagrant ssh -c "tools/yuniSeg.sh data/ noisemes_sad"` + +Both of them return one rttm per sound file, with an estimation of where there are vocalizations by children, female adults, and male adults. + +For more information on the model underlying them, see the Yunitator section below. + +7. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: + +`$ vagrant ssh -c "tools/eval.sh data/ noisemes_sad"` + +Notice there are 2 parameters provided to the evaluation suite. The first parameter tells the system which folder to analyze (in this case, the whole data/ folder). The second parameter indicates which tool's output to evaluate (in this case, noisemes_sad). The system will use the .rttm annotations if they exist; or the .eaf ones if the former are missing; or the .textgrid of neither .rttm nor .eaf are found. If you want to evaluate a diarization produced by the diartk tool, you will have to specify a third parameter, to tell the system which SAD was used to compute the diartk outputs you want to evaluate. E.G. : `$ vagrant ssh -c "tools/eval.sh data/ diartk noisemes_sad` -7. Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: +8. Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: `$ vagrant halt` @@ -139,7 +149,7 @@ This system will classify slices of the audio recording into one of 17 noiseme c - radio -#### Instructions for direct use +#### Instructions for direct use (ATTENTION, MAY BE OUTDATED) You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. @@ -242,8 +252,11 @@ $ nano /vagrant/conf/vad/vad_segmenter_aclew.conf ``` openSMILE manuals consulted: -Eyben, F., Woellmer, M., & Schuller, B. (2013). openSMILE: The Munich open Speech and Music Interpretation by Large space Extraction toolkit. Institute for Human-Machine Communication, version 2.0. http://download2.nust.na/pub4/sourceforge/o/project/op/opensmile/openSMILE_book_2.0-rc1.pdf -Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf + +- Eyben, F., Woellmer, M., & Schuller, B. (2013). openSMILE: The Munich open Speech and Music Interpretation by Large space Extraction toolkit. Institute for Human-Machine Communication, version 2.0. http://download2.nust.na/pub4/sourceforge/o/project/op/opensmile/openSMILE_book_2.0-rc1.pdf +- Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf + + ### TOCombo_SAD @@ -288,6 +301,45 @@ vagrant ssh -c 'tools/diartk.sh data noisemes' ``` where `data/` is in the current working directory, and contains .wav audio as well as speech/nonspeech RTTM files with names based on the tool that generated them, from the set of possible SAD providers `ldc_sad`, `noisemes`, `textgrid`, `eaf`, `rttm` for example `noisemes_sad_myaudio.rttm` or `ldc_sad_myaudio.rttm` + +### Yunitator + +There is no official reference for this tool. + +#### General intro + +Given that there is no reference for this tool, we provide a more extensive introduction based on a presentation Florian Metze gave on 2018-08-13 in an ACLEW Meeting. + +The data used for training were: + +- ACLEW Starter+ dataset (see Le Franc et al. 2018 Interspeech for explanations and reference) +- Tsimane dataset (idem) +- Data collected from Namibian and Vanuatu children (total of about 24h; recorded, sampled, and annotated like the Tsimane dataset) +- VanDam public 5-min dataset (about 13h; https://homebank.talkbank.org/access/Public/VanDam-5minute.html); noiseme-sad used to detect and remove intraturn silences + +Talker identity annotations collapsed into the following 4 types: + +- children (including both the child wearing the device and other children; class prior: .13) +- female adults (class prior .09) +- male adults (class prior .03) +- non-vocalizations (class prior .75) + +The features were MED (multimedia event detection) feature, extracted with OpenSMILE. They were extracted in 2s windows moving 100ms each step. There were 6,669 dims at first, PCA’ed down to 50 dims + +The model was a RNN, with 1 bidirectional GRU layer and 200 units in each direction. There was a softmax output layer, which therefore doesn’t predict overlaps.. + +The training regime used 5-fold cross-validation, with 5 models trained on 4/5 of the data and tested on the remainder. The outputs are poooled together to measure performance. The final model was trained on all the data. + +The loss function was cross entropy with classes weighted by 1/prior. The batch size was 5 sequences of 625 frames (in order to accommodate the fact that many of the clips were 1 minute long). The optimizer was Adam, the inital LR was .001 and the LR schedule was *=.999 every epoch. + +The resulting F1 for the key classes were: + +- Child .55 (Precision .5, recall .61) +- Female adult .44 (P .41, R .48) +- Male adult .24 (P .22, R .28) + + + ### LDC Diarization Scoring Main references for this tool: From 84a04dc239f47a03dc517ef3d53577411723f578 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Tue, 23 Oct 2018 14:19:08 +0200 Subject: [PATCH 031/299] Change tabulation to space rttm --- toolbox/its2rttm.py | 18 +++++++++--------- toolbox/lab2rttm.sh | 2 +- toolbox/rttm2labels.py | 2 +- toolbox/rttm2scp.py | 2 +- toolbox/tocombo2rttm.py | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/toolbox/its2rttm.py b/toolbox/its2rttm.py index 240e5a3..f3e190a 100644 --- a/toolbox/its2rttm.py +++ b/toolbox/its2rttm.py @@ -33,15 +33,15 @@ def its_line_2_rttm_line(its_line, rttm_name): end_time = float(end_time.group(1)) duration = end_time-start_time - rttm_line = "SPEAKER\t" +\ - rttm_name + "\t" +\ - "1\t" +\ - "%f" % start_time + "\t" +\ - "%f " % duration + "\t" +\ - "\t" +\ - "\t" +\ - spkr + "\t" +\ - "\t" +\ + rttm_line = "SPEAKER " +\ + rttm_name + " " +\ + "1 " +\ + "%f" % start_time + " " +\ + "%f " % duration + " " +\ + " " +\ + " " +\ + spkr + " " +\ + " " +\ "\n" return rttm_line diff --git a/toolbox/lab2rttm.sh b/toolbox/lab2rttm.sh index f2143eb..57f8103 100755 --- a/toolbox/lab2rttm.sh +++ b/toolbox/lab2rttm.sh @@ -26,5 +26,5 @@ do type="" fi subf=`echo $subf | sed "s/_lena//"` - grep ' speech' $j | awk '{print "SPEAKER" "\t" "'$subf'" "\t" 1 "\t" $1 "\t" $2-$1 "\t" "" "\t" "" "\t" $3 "\t" ""}' > $folder/${subf}${type}.rttm + grep ' speech' $j | awk '{print "SPEAKER" " " "'$subf'" " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $folder/${subf}${type}.rttm done diff --git a/toolbox/rttm2labels.py b/toolbox/rttm2labels.py index c1b90bf..0cca5f4 100644 --- a/toolbox/rttm2labels.py +++ b/toolbox/rttm2labels.py @@ -19,7 +19,7 @@ def printbuf (begin, end, text): for l in sys.stdin: - m = re.match("^(.*)\t(.*)\t(.*)\t(\S+)\t(\S+)\t(.*)\t(.*)\t(.*)\t(.*)$", l) + m = re.match("^(.*) (.*) (.*) (\S+) (\S+) (.*) (.*) (.*) (.*)$", l) if m: type, file = m.group(1, 2) channel = int(m.group(3)) diff --git a/toolbox/rttm2scp.py b/toolbox/rttm2scp.py index c02bfa4..f7b0008 100755 --- a/toolbox/rttm2scp.py +++ b/toolbox/rttm2scp.py @@ -24,7 +24,7 @@ def read_rttm(input_path): all_intervals = [] fname = "" for line in rttm: - row = line.split('\t') + row = line.strip('\n').split() fname, onset, dur = row[1], row[3], row[4] if float(dur) == 0: # Remove empty intervals diff --git a/toolbox/tocombo2rttm.py b/toolbox/tocombo2rttm.py index c1e363a..1479bdc 100644 --- a/toolbox/tocombo2rttm.py +++ b/toolbox/tocombo2rttm.py @@ -48,5 +48,5 @@ vad = "speech" else: continue - fout.write(u"SPEAKER\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n".format + fout.write(u"SPEAKER {} {} {} {} {} {} {} {}\n".format (fname, 1, on, off - on, "", "", vad, 1 )) From d8078f5ebf4f110995a198513087a7554eaa9a47 Mon Sep 17 00:00:00 2001 From: alecristia Date: Fri, 26 Oct 2018 13:36:19 +0200 Subject: [PATCH 032/299] reorganizing --- docs/source/index.rst | 1 + docs/source/ldc_sad.md | 14 +++++ docs/source/noisemes_sad.md | 115 ++++++++++++++++++++++++++++++++++ docs/source/usage.md | 120 +----------------------------------- 4 files changed, 131 insertions(+), 119 deletions(-) create mode 100644 docs/source/ldc_sad.md create mode 100644 docs/source/noisemes_sad.md diff --git a/docs/source/index.rst b/docs/source/index.rst index 4ad3c50..33f9d7e 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,6 +13,7 @@ Welcome to DiViMe's documentation! initial_questions install usage + noisemes_sad.md troubleshoot instructions_for_contributors references diff --git a/docs/source/ldc_sad.md b/docs/source/ldc_sad.md new file mode 100644 index 0000000..9849933 --- /dev/null +++ b/docs/source/ldc_sad.md @@ -0,0 +1,14 @@ +# LDC SAD + +## General intro + +LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. + +## Main references: + +Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. + + +## Associated references: +Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. +Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. \ No newline at end of file diff --git a/docs/source/noisemes_sad.md b/docs/source/noisemes_sad.md new file mode 100644 index 0000000..366d427 --- /dev/null +++ b/docs/source/noisemes_sad.md @@ -0,0 +1,115 @@ +# Noisemes_sad + +## General intro + +Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. + + + + + +## Instructions for direct use (ATTENTION, MAY BE OUTDATED) + +You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. + +``` +$ vagrant ssh -c "OpenSAT/runOpenSAT.sh data/<$MYFILE>" +``` + +You can also analyze a group of files as follows: + +``` +$ vagrant ssh -c "OpenSAT/runDiarNoisemes.sh data/" +``` + +This will analyze all .wav's inside the "data" folder. + +Created annotations will be stored inside the same "data" folder. + +This system will classify slices of the audio recording into one of 17 noiseme classes: + +- background +- speech +- speech non English +- mumble +- singing alone +- music + singing +- music alone +- human sounds +- cheer +- crowd sounds +- animal sounds +- engine +- noise_ongoing +- noise_pulse +- noise_tone +- noise_nature +- white_noise +- radio + +#### Some more technical details + +For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": + +``` +$ vagrant ssh +$ cd OpenSAT +``` + +The main script is runOpenSAT.sh and takes one argument: an audio file in .wav format. +Upon successful completion, output will be in the folder (relative to ~/OpenSAT) +`SSSF/data/hyp//confidence.pkl.gz` + +The system will grind first creating features for all the .wav files it found, then will place those features in a subfolder `feature`. Then it will load a model, and process all the features generated, producing output in a subfolder `hyp/` two files per input: `.confidence.mat` and `.confidence.pkl.gz` - a confidence matrix in Matlab v5 mat-file format, and a Python compressed data 'pickle' file. Now, as well, in the `hyp/` folder, `.rttm` with labels found from a config file [noisemeclasses.txt](https://github.com/riebling/OpenSAT/blob/master/noisemeclasses.txt) + +-More details on output format- + +The 18 classes are as follows: +``` +0 background +1 speech +2 speech_ne +3 mumble +4 singing +5 music_sing +6 music +7 human +8 cheer +9 crowd +10 animal +11 engine +12 noise_ongoing +13 noise_pulse +14 noise_tone +15 noise_nature +16 white_noise +17 radio +``` +The frame length is 0.1s. The system also uses a 2-second window, so the i-th frame starts at (0.1 * i - 2) seconds and finishes at (0.1 * i) seconds. That's why 60 seconds become 620 frames. 'speech_ne' means non-English speech + +-Sample RTTM output snippet- +``` +SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 +SPEAKER family 1 4.6 1.2 background 0.327808111906 +SPEAKER family 1 5.8 1.1 speech 0.430758684874 +SPEAKER family 1 6.9 1.2 background 0.401730179787 +SPEAKER family 1 8.1 0.7 speech 0.407463937998 +SPEAKER family 1 8.8 1.1 background 0.37258502841 +SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +``` + +The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the more detailed results as seen above. + + + +## Main references: + +Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) + + +## Associated references: + +S.Burger,Q.Jin,P.F.Schulam,andF.Metze,“Noisemes:Man- ual annotation of environmental noise in audio streams,” Carnegie Mellon University, Pittsburgh, PA; U.S.A., Tech. Rep. CMU-LTI- 12-07, 2012. +S.Strassel,A.Morris,J.G.Fiscus,C.Caruso,H.Lee,P.D.Over, J. Fiumara, B. L. Shaw, B. Antonishek, and M. Michel, “Creating havic: Heterogeneous audio visual internet collection,” in Proc. +LREC. Istanbul, Turkey: ELRA, May 2012. +F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia fea- ture extractor,” in Proceedings of the 21st ACM international con- ference on Multimedia. ACM, 2013, pp. 835–838. \ No newline at end of file diff --git a/docs/source/usage.md b/docs/source/usage.md index 5f89a1e..3e86ff3 100644 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -101,126 +101,8 @@ Reference for the ACLEW Starter dataset: Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved August 15, 2018 from http://doi.org/10.17910/B7.390. -## More details for each tool -### LDC_SAD - -Main reference for this tool: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. - -#### General intro - -LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. - - -Associated references: -Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. -Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. - -### Noisemes_sad - -Main reference for this tool: - -Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) - - -#### General intro - -This system will classify slices of the audio recording into one of 17 noiseme classes: - -- background -- speech -- speech non English -- mumble -- singing alone -- music + singing -- music alone -- human sounds -- cheer -- crowd sounds -- animal sounds -- engine -- noise_ongoing -- noise_pulse -- noise_tone -- noise_nature -- white_noise -- radio - - -#### Instructions for direct use (ATTENTION, MAY BE OUTDATED) - -You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. - -``` -$ vagrant ssh -c "OpenSAT/runOpenSAT.sh data/<$MYFILE>" -``` - -You can also analyze a group of files as follows: - -``` -$ vagrant ssh -c "OpenSAT/runDiarNoisemes.sh data/" -``` - -This will analyze all .wav's inside the "data" folder. - -Created annotations will be stored inside the same "data" folder. - -#### Some more technical details - -For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": - -``` -$ vagrant ssh -$ cd OpenSAT -``` - -The main script is runOpenSAT.sh and takes one argument: an audio file in .wav format. -Upon successful completion, output will be in the folder (relative to ~/OpenSAT) -`SSSF/data/hyp//confidence.pkl.gz` - -The system will grind first creating features for all the .wav files it found, then will place those features in a subfolder `feature`. Then it will load a model, and process all the features generated, producing output in a subfolder `hyp/` two files per input: `.confidence.mat` and `.confidence.pkl.gz` - a confidence matrix in Matlab v5 mat-file format, and a Python compressed data 'pickle' file. Now, as well, in the `hyp/` folder, `.rttm` with labels found from a config file [noisemeclasses.txt](https://github.com/riebling/OpenSAT/blob/master/noisemeclasses.txt) - --More details on output format- - -The 18 classes are as follows: -``` -0 background -1 speech -2 speech_ne -3 mumble -4 singing -5 music_sing -6 music -7 human -8 cheer -9 crowd -10 animal -11 engine -12 noise_ongoing -13 noise_pulse -14 noise_tone -15 noise_nature -16 white_noise -17 radio -``` -The frame length is 0.1s. The system also uses a 2-second window, so the i-th frame starts at (0.1 * i - 2) seconds and finishes at (0.1 * i) seconds. That's why 60 seconds become 620 frames. 'speech_ne' means non-English speech - --Sample RTTM output snippet- -``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 -``` - -The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the more detailed results as seen above. - -### OpenSmile_SAD +##### OpenSmile_SAD Main references for this tool: From 0053590b6749cc77f573fe599b254c40bdb71556 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Fri, 26 Oct 2018 18:46:04 +0200 Subject: [PATCH 033/299] Add dependency phonemizer tool --- Vagrantfile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Vagrantfile b/Vagrantfile index 5065399..fb6a6d1 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -258,6 +258,16 @@ Vagrant.configure("2") do |config| # Some cleanup sudo apt-get autoremove -y + # Phonemizer installation + + sudo apt-get install festival espeak + + git clone https://github.com/bootphon/phonemizer + cd phonemizer + python setup.py build + sudo apt-get install python-setuptools + sudo python setup.py install + # Silence error message from missing file touch /home/${user}/.Xauthority From 8eb67fbdd30aa14de0a1673f7f86cacfa246032b Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Mon, 29 Oct 2018 17:55:21 +0100 Subject: [PATCH 034/299] Correct phonemizer installation --- Vagrantfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index fb6a6d1..a0cc7c5 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -259,14 +259,14 @@ Vagrant.configure("2") do |config| sudo apt-get autoremove -y # Phonemizer installation - - sudo apt-get install festival espeak - + sudo apt-get install -y festival espeak + cd /home/${user} git clone https://github.com/bootphon/phonemizer cd phonemizer python setup.py build - sudo apt-get install python-setuptools + sudo apt-get install -y python-setuptools sudo python setup.py install + cd .. # Silence error message from missing file touch /home/${user}/.Xauthority From a94446a5846771179de1843ae7cb6afdf7dfc1f6 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Mon, 29 Oct 2018 17:58:03 +0100 Subject: [PATCH 035/299] Fix warning provided when running phonemizer by modifying the rights on python-eggs --- Vagrantfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Vagrantfile b/Vagrantfile index a0cc7c5..cb286ca 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -268,6 +268,9 @@ Vagrant.configure("2") do |config| sudo python setup.py install cd .. + #Fix warning provided when running phonemizer by modifying the rights on python-eggs + chmod g-wx,o-wx /home/vagrant/.python-eggs + # Silence error message from missing file touch /home/${user}/.Xauthority From 0683550e7d67fd6b8a908e6030a473b458402a90 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 29 Oct 2018 18:13:17 +0100 Subject: [PATCH 036/299] finished factoring out tool intro from usage --- docs/source/usage.md | 189 ++++++------------------------------------- 1 file changed, 23 insertions(+), 166 deletions(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index 3e86ff3..6038751 100644 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -1,27 +1,33 @@ # Use instructions +## Overview + +This is an overview of the full tool presentation found in the next stage, recapping the main steps: + +1. Put your data in /data/ +2. Do `$ vagrant up` to "wake the machine up" +3. Choose between: running a speech activity detection system followed by a diarization system (steps 3 and 4 below), or a tool that directly segments recordings into 3 main roles, namely child, male adult, female adult (step 5 below) +4. If you have some annotations, you can evaluate how the tools did (step 6 below) +5. Finally, remember to put the machine back to sleep with `$ vagrant halt` + +Next we provide instructions for all tools. More detailed information about each tool can be found in separate readme's. ## Short instructions for all tools -1. Put the files you want to analyze inside the "data" folder inside the DiViMe folder. If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. +1. Put sound files (and annotations, if you have any) inside the "data" folder inside the DiViMe folder. If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. -2. If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. It is probably safer to make a copy (rather than moving them), in case you later decide to delete the whole vagrant folder. + If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. It is probably safer to make a copy (rather than moving them), in case you later decide to delete the whole vagrant folder. -3. Launch the virtual machine anytime by navigating to your DiViMe folder on your terminal and performing: +2. Launch the virtual machine anytime by navigating to your DiViMe folder on your terminal and performing: `$ vagrant up` -4. For the SAD tools, type a command like the one below, being careful to type the SAD tool name instead of SADTOOLNAME: +3. For the SAD tools, type a command like this one: -`$ vagrant ssh -c "tools/SADTOOLNAME.sh data/"` +`$ vagrant ssh -c "tools/noisemes_sad.sh data/"` -The SAD options are: -- SADTOOLNAME = ldc_sad (coming soon) -- SADTOOLNAME = noisemes_sad -- SADTOOLNAME = opensmile_sad -- SADTOOLNAME = tocombo_sad -This will create a set of new rttm files, with the name of the tool added at the beginning. For example, imagine you have a file called participant23.wav, and you decide to run both the LDC_SAD and the Noisemes analyses. You will run the following commands: +This will create a set of new rttm files, with the name of the tool added at the beginning. For example, imagine you have a file called participant23.wav, and you decide to run two SADs: ``` @@ -29,7 +35,7 @@ $ vagrant ssh -c "tools/opensmile_sad.sh data/" $ vagrant ssh -c "tools/noisemes_sad.sh data/" ``` -And this will result in your having the following three files in your /data/ folder: +This will result in your having the following three files in your /data/ folder: - participant23.wav - opensmile_sad_participant23.rttm @@ -44,7 +50,7 @@ SPEAKER participant23 1 1.38 2.14 speech This means that opensmile_sad considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. -5. There is one **pure diarization** tool: diartk. Here is the command to run, for the data/ input folder: +4. There is one **pure diarization** tool: diartk. Here is the command to run, for the data/ input folder: `$ vagrant ssh -c "tools/diartk.sh data/ noisemes_sad"` @@ -58,9 +64,9 @@ Pure diarization tools only perform talker diarization (i.e., *who* speaks) but - eaf: this means you want the system to use your eaf annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your eaf files before you start. Please note that the system will convert your eafs into .rttm in the process. - rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. -Finally, if no parameter is provided, the system will default to noisemes_sad. +Finally, if no parameter is provided, the system will give an error. -6. There is one **role assignment** tool, which classifies spoken turns into three roles: children, female adults, male adults. It exists in two versions. +5. There is one **role assignment** tool, which classifies spoken turns into three roles: children, female adults, male adults. It exists in two versions. The version we call "yunitator" takes the raw recording as input. To call this one, do @@ -75,7 +81,7 @@ Both of them return one rttm per sound file, with an estimation of where there a For more information on the model underlying them, see the Yunitator section below. -7. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: +6. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: `$ vagrant ssh -c "tools/eval.sh data/ noisemes_sad"` @@ -83,160 +89,11 @@ Notice there are 2 parameters provided to the evaluation suite. The first parame If you want to evaluate a diarization produced by the diartk tool, you will have to specify a third parameter, to tell the system which SAD was used to compute the diartk outputs you want to evaluate. E.G. : `$ vagrant ssh -c "tools/eval.sh data/ diartk noisemes_sad` -8. Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: +7. Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: `$ vagrant halt` -### ACLEW Starter Dataset - -The ACLEW Starter dataset is freely available, and can be downloaded in order to test the tools. -To download it, using your terminal, as explained before, go in the DiViMe folder and do: -`$ ./get_aclewStarter.sh` -This will create a folder called aclewStarter, in which you will find the audio files from the public dataset and their corresponding .rttm annotations. - -You can then use the tools mentioned before, by replacing the "data/" folder in the command given in the previous paragraph by "aclewStarter/", E.G for noisemes: -```$ vagrant ssh -c "tools/noisemes_sad.sh aclewStarter/"``` - -Reference for the ACLEW Starter dataset: - -Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved August 15, 2018 from http://doi.org/10.17910/B7.390. - - -##### OpenSmile_SAD - -Main references for this tool: - -Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. - -Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. - -#### General intro - -openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coefficient RASTA-PLP plus first order delta features. It then uses a long short-term memory recurrent neural network (see details in Eyben et al., 2013b) that has been pre-trained on two corpora of read and spontaneous speech by adults recorded in laboratory conditions, augmented with various noise types. - -#### Some more technical details - -These are the parameters that are being used with values that depart from the openSMILE default settings (quoted material comes from either of the openSMILE manuals): - -monoMixdown = 1, means "mix down all recorded channels to 1 mono channel" -noHeader = 0, means read the RIFF header (don't need to specify the parameters ‘sampleRate’, ‘channels’, and possibly ‘sampleSize’) -preSil = 0.1 "Specifies the amount of silence at the turn beginning in seconds, i.e. the lag of the turn -detector. This is the length of the data that will be added to the current segment prior to -the turn start time received in the message from the turn detector component"; we use a tighter criterion than the default (.2) -postSil = 0.1 "Specifies the amount of silence at the turn end in seconds. This is the length of the data -that will be added to the current segment after to the turn end time received in the message -from the turn detector component."; we use a tighter criterion than the default (.3) - -You can change these parameters locally by doing: -``` -$ vagrant ssh -$ nano /vagrant/conf/vad/vad_segmenter_aclew.conf -``` - -openSMILE manuals consulted: - -- Eyben, F., Woellmer, M., & Schuller, B. (2013). openSMILE: The Munich open Speech and Music Interpretation by Large space Extraction toolkit. Institute for Human-Machine Communication, version 2.0. http://download2.nust.na/pub4/sourceforge/o/project/op/opensmile/openSMILE_book_2.0-rc1.pdf -- Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf - - - -### TOCombo_SAD - -Main references for this tool: - -A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. -S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. - -#### General intro - -TO BE ADDED - -### DiarTK - -Main reference for this tool: - -D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. - -#### General intro - -TO BE ADDED - - -#### Instructions for direct use - -This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format as generated by one of the tools above. A script to run DiarTK (also known as ib_diarization_toolkit) can be found in `tools/diartk.sh`. Here is its usage: -``` -Usage: diartk.sh -where dirname is the name of the folder -containing the wav files, and transcription -specifies which transcription you want to use. -Choices are: - ldc_sad - noisemes - textgrid - eaf - rttm -``` -To invoke the tool from outside the VM, invoke it with a command like: -``` -vagrant ssh -c 'tools/diartk.sh data noisemes' -``` -where `data/` is in the current working directory, and contains .wav audio as well as speech/nonspeech RTTM files with names based on the tool that generated them, from the set of possible SAD providers `ldc_sad`, `noisemes`, `textgrid`, `eaf`, `rttm` for example `noisemes_sad_myaudio.rttm` or `ldc_sad_myaudio.rttm` - - -### Yunitator - -There is no official reference for this tool. - -#### General intro - -Given that there is no reference for this tool, we provide a more extensive introduction based on a presentation Florian Metze gave on 2018-08-13 in an ACLEW Meeting. - -The data used for training were: - -- ACLEW Starter+ dataset (see Le Franc et al. 2018 Interspeech for explanations and reference) -- Tsimane dataset (idem) -- Data collected from Namibian and Vanuatu children (total of about 24h; recorded, sampled, and annotated like the Tsimane dataset) -- VanDam public 5-min dataset (about 13h; https://homebank.talkbank.org/access/Public/VanDam-5minute.html); noiseme-sad used to detect and remove intraturn silences - -Talker identity annotations collapsed into the following 4 types: - -- children (including both the child wearing the device and other children; class prior: .13) -- female adults (class prior .09) -- male adults (class prior .03) -- non-vocalizations (class prior .75) - -The features were MED (multimedia event detection) feature, extracted with OpenSMILE. They were extracted in 2s windows moving 100ms each step. There were 6,669 dims at first, PCA’ed down to 50 dims - -The model was a RNN, with 1 bidirectional GRU layer and 200 units in each direction. There was a softmax output layer, which therefore doesn’t predict overlaps.. - -The training regime used 5-fold cross-validation, with 5 models trained on 4/5 of the data and tested on the remainder. The outputs are poooled together to measure performance. The final model was trained on all the data. - -The loss function was cross entropy with classes weighted by 1/prior. The batch size was 5 sequences of 625 frames (in order to accommodate the fact that many of the clips were 1 minute long). The optimizer was Adam, the inital LR was .001 and the LR schedule was *=.999 every epoch. - -The resulting F1 for the key classes were: - -- Child .55 (Precision .5, recall .61) -- Female adult .44 (P .41, R .48) -- Male adult .24 (P .22, R .28) - - - -### LDC Diarization Scoring - -Main references for this tool: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. -Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. - -#### General intro - -For SAD, we employ the evaluation included in the LDC SAD, which returns the false alarm (FA) rate (proportion of frames labeled as speech that were non-speech in the gold annotation) and missed speech rate (proportion of frames labeled as non-speech that were speech in the gold annotation). For TD, we employ the evaluation developed for the DiHARD Challenge, which returns a Diarization error rate (DER), which sums percentage of speaker error (mismatch in speaker IDs), false alarm speech (non-speech segments assigned to a speaker) and missed speech (unassigned speech). - -One important consideration is in order: What to do with files that have no speech to begin with, or where the system does not return any speech at the SAD stage or any labels at the TD stage. This is not a case that is often discussed in the litera- ture because recordings are typically targeted at moments where there is speech. However, in naturalistic recordings, some ex- tracts may not contain any speech activity, and thus one must adopt a coherent framework for the evaluation of such instances. We opted for the following decisions. -If the gold annotation was empty, and the SAD system returned no speech labels, then the FA = 0 and M = 0; but if the SAD system returned some speech labels, then FA = 100 and M = 0. Also, if the gold annotation was not empty and the sys- tem did not find any speech, then this was treated as FA = 0 and M=100. -As for the TD evaluation, the same decisions were used above for FA and M, and the following decisions were made for mismatch. If the gold annotation was empty, regardless of what the system returned, the mismatch rate was treated as 0. If the gold annotation was empty but a pipeline returned no TD labels (either because the SAD in that system did not detect any speech, or because the diarization failed), then this was penalized via a miss of 100 (as above), but not further penalized in terms of talker mismatch, which was set at 0. From c3554fa8cc66ae42f2028d85264b8a6ee2d1148d Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 30 Oct 2018 13:32:37 -0400 Subject: [PATCH 037/299] add recommonmark python package to fix 'make html' in docs/ --- Vagrantfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index cb286ca..238163d 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -240,7 +240,8 @@ Vagrant.configure("2") do |config| # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) # and intervaltree (needed for rttm2scp.py) - su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree" + # and recommonmark (needed to make html in docs/) + su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" # assume 'conda' is installed now (get path) su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" From 877cc45c0254606a1429f38630fbe865e32b6dcc Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 31 Oct 2018 13:41:55 +0100 Subject: [PATCH 038/299] reorganization --- docs/source/diartk.md | 21 +++++++++++++++++++ docs/source/eval.md | 19 ++++++++++++++++++ docs/source/extra-tools.md | 20 ++++++++++++++++++ docs/source/index.rst | 2 +- docs/source/opensmile_sad.md | 37 ++++++++++++++++++++++++++++++++++ docs/source/tocombo_sad.md | 13 ++++++++++++ docs/source/yunitator.md | 39 ++++++++++++++++++++++++++++++++++++ 7 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 docs/source/diartk.md create mode 100644 docs/source/eval.md create mode 100644 docs/source/extra-tools.md create mode 100644 docs/source/opensmile_sad.md create mode 100644 docs/source/tocombo_sad.md create mode 100644 docs/source/yunitator.md diff --git a/docs/source/diartk.md b/docs/source/diartk.md new file mode 100644 index 0000000..ed94fdc --- /dev/null +++ b/docs/source/diartk.md @@ -0,0 +1,21 @@ +# DiarTK + +## General intro + +This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format, from human annotation, or potentially from one of the SAD or VAD tools included in this VM. + +The DiarTK model imported in the VM is a C++ open source toolkit by Vijayasenan & Valente (2012). The algorithm first extracts MFCC features, then performs non-parametric clustering of the frames using agglomerative information bottleneck clustering. At the end of the process, the resulting clusters correspond to a set of speakers. The most likely Diarization sequence between those speakers is computed by Viterbi realignement. + +We use this tool with the following parameter values: + +- weight MFCC = 1 (default) +- Maximum Segment Duration 250 (default) +- Maximum number of clusters possible: 10 (default) +- Normalized Mutual Information threshold: 0.5 (default) +- Beta value: 10 (passed as parameter) +- Number of threads: 3 (passed as parameter) + + +## Main references: + +D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. https://pdfs.semanticscholar.org/71e3/9d42aadd9ec44a42aa5cd21202fedb5eaec5.pdf \ No newline at end of file diff --git a/docs/source/eval.md b/docs/source/eval.md new file mode 100644 index 0000000..418f967 --- /dev/null +++ b/docs/source/eval.md @@ -0,0 +1,19 @@ +# LDC Diarization Scoring + +## General intro + +For SAD, we employ the evaluation included in the LDC SAD, which returns the false alarm (FA) rate (proportion of frames labeled as speech that were non-speech in the gold annotation) and missed speech rate (proportion of frames labeled as non-speech that were speech in the gold annotation). For TD, we employ the evaluation developed for the DiHARD Challenge, which returns a Diarization error rate (DER), which sums percentage of speaker error (mismatch in speaker IDs), false alarm speech (non-speech segments assigned to a speaker) and missed speech (unassigned speech). + +One important consideration is in order: What to do with files that have no speech to begin with, or where the system does not return any speech at the SAD stage or any labels at the TD stage. This is not a case that is often discussed in the litera- ture because recordings are typically targeted at moments where there is speech. However, in naturalistic recordings, some ex- tracts may not contain any speech activity, and thus one must adopt a coherent framework for the evaluation of such instances. We opted for the following decisions. + +If the gold annotation was empty, and the SAD system returned no speech labels, then the FA = 0 and M = 0; but if the SAD system returned some speech labels, then FA = 100 and M = 0. Also, if the gold annotation was not empty and the sys- tem did not find any speech, then this was treated as FA = 0 and M=100. + +As for the TD evaluation, the same decisions were used above for FA and M, and the following decisions were made for mismatch. If the gold annotation was empty, regardless of what the system returned, the mismatch rate was treated as 0. If the gold annotation was empty but a pipeline returned no TD labels (either because the SAD in that system did not detect any speech, or because the diarization failed), then this was penalized via a miss of 100 (as above), but not further penalized in terms of talker mismatch, which was set at 0. + +## Main references: + +Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. +Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. + + + diff --git a/docs/source/extra-tools.md b/docs/source/extra-tools.md new file mode 100644 index 0000000..73f0a21 --- /dev/null +++ b/docs/source/extra-tools.md @@ -0,0 +1,20 @@ +# Extra tools + +## Getting sample data + +### ACLEW Starter Dataset + +The ACLEW Starter dataset is freely available, and can be downloaded in order to test the tools. +To download it, using your terminal, as explained before, go in the DiViMe folder and do: +```$ vagrant ssh -c "tools/get_aclewStarter.sh data/aclewStarter/"``` + +This will create a folder called aclewStarter inside data, in which you will find the audio files from the public dataset and their corresponding .rttm annotations. At the present time, there are only two matched annotation-wav files, totalling 10 minutes of running recordings + +You can then use the tools mentioned before, by replacing the "data/" folder in the command given in the previous paragraph by "aclewStarter/", E.G for noisemes: + +```$ vagrant ssh -c "tools/noisemes_sad.sh /"``` + +#### Reference for the ACLEW Starter dataset: + +Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved August 15, 2018 from http://doi.org/10.17910/B7.390. + diff --git a/docs/source/index.rst b/docs/source/index.rst index 33f9d7e..95d1d50 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,7 +13,7 @@ Welcome to DiViMe's documentation! initial_questions install usage - noisemes_sad.md + tool_doc troubleshoot instructions_for_contributors references diff --git a/docs/source/opensmile_sad.md b/docs/source/opensmile_sad.md new file mode 100644 index 0000000..3d106d8 --- /dev/null +++ b/docs/source/opensmile_sad.md @@ -0,0 +1,37 @@ +# OpenSmile SAD + + +## General intro + +openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coefficient RASTA-PLP plus first order delta features. It then uses a long short-term memory recurrent neural network (see details in Eyben et al., 2013b) that has been pre-trained on two corpora of read and spontaneous speech by adults recorded in laboratory conditions, augmented with various noise types. + +## Some more technical details + +These are the parameters that are being used with values that depart from the openSMILE default settings (quoted material comes from either of the openSMILE manuals): + +monoMixdown = 1, means "mix down all recorded channels to 1 mono channel" +noHeader = 0, means read the RIFF header (don't need to specify the parameters ‘sampleRate’, ‘channels’, and possibly ‘sampleSize’) +preSil = 0.1 "Specifies the amount of silence at the turn beginning in seconds, i.e. the lag of the turn +detector. This is the length of the data that will be added to the current segment prior to +the turn start time received in the message from the turn detector component"; we use a tighter criterion than the default (.2) +postSil = 0.1 "Specifies the amount of silence at the turn end in seconds. This is the length of the data +that will be added to the current segment after to the turn end time received in the message +from the turn detector component."; we use a tighter criterion than the default (.3) + +You can change these parameters locally by doing: +``` +$ vagrant ssh +$ nano /vagrant/conf/vad/vad_segmenter_aclew.conf +``` + +openSMILE manuals consulted: + +- Eyben, F., Woellmer, M., & Schuller, B. (2013). openSMILE: The Munich open Speech and Music Interpretation by Large space Extraction toolkit. Institute for Human-Machine Communication, version 2.0. http://download2.nust.na/pub4/sourceforge/o/project/op/opensmile/openSMILE_book_2.0-rc1.pdf +- Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf + + +## Main references for this tool: + +Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. + +Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. \ No newline at end of file diff --git a/docs/source/tocombo_sad.md b/docs/source/tocombo_sad.md new file mode 100644 index 0000000..34fa830 --- /dev/null +++ b/docs/source/tocombo_sad.md @@ -0,0 +1,13 @@ +# TOCombo SAD + +## General intro + +This tool's name stands for "Threshold-Optimized" "combo" SAD; we explain each part in turn. It is a SAD because the goal is to extract speech activity. It is called "combo" because it combines linearly 4 different aspects of voicing (harmonicity , clarity, prediction gain, periodicity) in addition to one perceptual spectral flux feature (see details in Sadjadi & Hansen, 2013). These are extracted in 32-ms frames (with a 10 ms stride). The specific version included here corresponds to the Combo SAD introduced in Ziaei et al. (2014) and used further in Ziaei et al (2016). In this work, a threshold was optimized for daylong recordings, which typically have long silent periods, in order to avoid the usual overly large false alarm rates found in typical SAD systems provided with these data. + +## Main references: + +Ziaei, A., Sangwan, A., & Hansen, J. H. (2014). A speech system for estimating daily word counts. In Fifteenth Annual Conference of the International Speech Communication Association. http://193.6.4.39/~czap/letoltes/IS14/IS2014/PDF/AUTHOR/IS141028.PDF +A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. +S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. + + diff --git a/docs/source/yunitator.md b/docs/source/yunitator.md new file mode 100644 index 0000000..764ee9b --- /dev/null +++ b/docs/source/yunitator.md @@ -0,0 +1,39 @@ +# Yunitator + +## General intro + + +Given that there is no reference for this tool, we provide a more extensive introduction based on a presentation Florian Metze gave on 2018-08-13 in an ACLEW Meeting. + +The data used for training were: + +- ACLEW Starter+ dataset (see Le Franc et al. 2018 Interspeech for explanations and reference) +- Tsimane dataset (idem) +- Data collected from Namibian and Vanuatu children (total of about 24h; recorded, sampled, and annotated like the Tsimane dataset) +- VanDam public 5-min dataset (about 13h; https://homebank.talkbank.org/access/Public/VanDam-5minute.html); noiseme-sad used to detect and remove intraturn silences + +Talker identity annotations collapsed into the following 4 types: + +- children (including both the child wearing the device and other children; class prior: .13) +- female adults (class prior .09) +- male adults (class prior .03) +- non-vocalizations (class prior .75) + +The features were MED (multimedia event detection) feature, extracted with OpenSMILE. They were extracted in 2s windows moving 100ms each step. There were 6,669 dims at first, PCA?ed down to 50 dims + +The model was a RNN, with 1 bidirectional GRU layer and 200 units in each direction. There was a softmax output layer, which therefore doesn?t predict overlaps.. + +The training regime used 5-fold cross-validation, with 5 models trained on 4/5 of the data and tested on the remainder. The outputs are poooled together to measure performance. The final model was trained on all the data. + +The loss function was cross entropy with classes weighted by 1/prior. The batch size was 5 sequences of 625 frames (in order to accommodate the fact that many of the clips were 1 minute long). The optimizer was Adam, the inital LR was .001 and the LR schedule was *=.999 every epoch. + +The resulting F1 for the key classes were: + +- Child .55 (Precision .5, recall .61) +- Female adult .44 (P .41, R .48) +- Male adult .24 (P .22, R .28) + + +## Main references: + +There is no official reference for this tool. From 31e97cdaa589b61cb6402f98921ef30295cead7a Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Wed, 7 Nov 2018 13:06:45 +0100 Subject: [PATCH 039/299] Fix python-eggs not found error --- Vagrantfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 238163d..5d390f6 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -269,9 +269,6 @@ Vagrant.configure("2") do |config| sudo python setup.py install cd .. - #Fix warning provided when running phonemizer by modifying the rights on python-eggs - chmod g-wx,o-wx /home/vagrant/.python-eggs - # Silence error message from missing file touch /home/${user}/.Xauthority From 64640be6e7904b5f15c1e8bb9e9e502575e1faf2 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 8 Nov 2018 19:37:23 +0100 Subject: [PATCH 040/299] first pass - NOT TESTED --- MED_2s_100ms_htk.conf | 318 ----------- Vagrantfile | 131 ++--- conf/reconf-slurm.sh | 3 - conf/slurm.conf | 172 ------ conf/slurm.sv.conf | 14 - conf/supervisor.conf | 7 - conf/vad/README.txt | 55 -- conf/vad/lstmvad_rplp18d_12.net | 57 -- conf/vad/rplp18d_norm.dat | Bin 576 -> 0 bytes conf/vad/turnDetector.conf.inc | 37 -- conf/vad/vad_opensource.conf.inc | 189 ------- conf/vad/vad_segmenter.conf | 62 --- launcher/.DS_Store | Bin 0 -> 6148 bytes launcher/537classify.sh | 48 ++ launcher/diartk.sh | 117 ++++ launcher/eval.sh | 59 ++ launcher/ldcSad.sh | 47 ++ launcher/noisemesSad.sh | 80 +++ launcher/opensmileSad.sh | 60 ++ launcher/test.sh | 249 +++++++++ launcher/tocomboSad.sh | 78 +++ launcher/yunitate.sh | 57 ++ toolbox/README.md | 13 - utils/.DS_Store | Bin 0 -> 6148 bytes utils/README.md | 105 ++++ utils/adjust_timestamps.py | 308 ++++++++++ utils/catspa-syllabify-corpus.pl | 93 ++++ utils/change_tsi_lena_names.py | 43 ++ utils/chat2stm.sh | 53 ++ utils/check_folder.sh | 35 ++ utils/chunk.sh | 61 ++ utils/create_ref_sys.sh | 75 +++ diarization.sh => utils/diarization.sh | 0 utils/eaf2enriched_txt.sh | 37 ++ utils/eaf2txt.py | 89 +++ utils/elan2rttm.py | 75 +++ utils/empty_transcription.sh | 15 + utils/evalDiar.sh | 123 ++++ utils/evalSAD.sh | 83 +++ utils/extract_stats_chi.py | 124 +++++ utils/frame_cutter.py | 220 ++++++++ utils/generate_html.py | 44 ++ .../get_aclewStarter.sh | 0 utils/high_volubility.py | 526 ++++++++++++++++++ utils/html_python/__init__.py | 0 utils/html_python/files_page.py | 179 ++++++ utils/html_python/models_page.py | 103 ++++ utils/html_python/page.py | 30 + utils/html_python/style_css.py | 33 ++ utils/html_python/utils.py | 164 ++++++ {toolbox => utils}/its2rttm.py | 0 {toolbox => utils}/its2rttm.sh | 0 {toolbox => utils}/lab2rttm.sh | 0 utils/make_big_corpus.sh | 101 ++++ utils/noisemes_full.sh | 80 +++ utils/parse_cha_xml.py | 191 +++++++ {toolbox => utils}/rttm2labels.py | 0 {toolbox => utils}/rttm2scp.py | 0 {toolbox => utils}/rttm2scp.sh | 0 utils/runTALNet.sh | 47 ++ utils/selcha2clean.sh | 169 ++++++ utils/sum-rttm.sh | 19 + utils/syllabify.sh | 77 +++ utils/textgrid2rttm.py | 103 ++++ {toolbox => utils}/tocombo2rttm.py | 0 utils/train_test_split.py | 146 +++++ utils/txt2rttm.py | 140 +++++ .../vad_segmenter_aclew.conf.txt | 0 utils/yuniSeg.sh | 121 ++++ 69 files changed, 4646 insertions(+), 1019 deletions(-) delete mode 100644 MED_2s_100ms_htk.conf delete mode 100644 conf/reconf-slurm.sh delete mode 100644 conf/slurm.conf delete mode 100644 conf/slurm.sv.conf delete mode 100644 conf/supervisor.conf delete mode 100644 conf/vad/README.txt delete mode 100644 conf/vad/lstmvad_rplp18d_12.net delete mode 100644 conf/vad/rplp18d_norm.dat delete mode 100644 conf/vad/turnDetector.conf.inc delete mode 100644 conf/vad/vad_opensource.conf.inc delete mode 100644 conf/vad/vad_segmenter.conf create mode 100644 launcher/.DS_Store create mode 100644 launcher/537classify.sh create mode 100644 launcher/diartk.sh create mode 100644 launcher/eval.sh create mode 100644 launcher/ldcSad.sh create mode 100644 launcher/noisemesSad.sh create mode 100644 launcher/opensmileSad.sh create mode 100644 launcher/test.sh create mode 100644 launcher/tocomboSad.sh create mode 100644 launcher/yunitate.sh delete mode 100644 toolbox/README.md create mode 100644 utils/.DS_Store create mode 100755 utils/README.md create mode 100755 utils/adjust_timestamps.py create mode 100755 utils/catspa-syllabify-corpus.pl create mode 100755 utils/change_tsi_lena_names.py create mode 100755 utils/chat2stm.sh create mode 100755 utils/check_folder.sh create mode 100755 utils/chunk.sh create mode 100755 utils/create_ref_sys.sh rename diarization.sh => utils/diarization.sh (100%) create mode 100755 utils/eaf2enriched_txt.sh create mode 100755 utils/eaf2txt.py create mode 100755 utils/elan2rttm.py create mode 100755 utils/empty_transcription.sh create mode 100644 utils/evalDiar.sh create mode 100644 utils/evalSAD.sh create mode 100755 utils/extract_stats_chi.py create mode 100755 utils/frame_cutter.py create mode 100755 utils/generate_html.py rename get_aclewStarter.sh => utils/get_aclewStarter.sh (100%) create mode 100755 utils/high_volubility.py create mode 100755 utils/html_python/__init__.py create mode 100755 utils/html_python/files_page.py create mode 100755 utils/html_python/models_page.py create mode 100755 utils/html_python/page.py create mode 100755 utils/html_python/style_css.py create mode 100755 utils/html_python/utils.py rename {toolbox => utils}/its2rttm.py (100%) rename {toolbox => utils}/its2rttm.sh (100%) rename {toolbox => utils}/lab2rttm.sh (100%) create mode 100755 utils/make_big_corpus.sh create mode 100644 utils/noisemes_full.sh create mode 100755 utils/parse_cha_xml.py rename {toolbox => utils}/rttm2labels.py (100%) rename {toolbox => utils}/rttm2scp.py (100%) rename {toolbox => utils}/rttm2scp.sh (100%) create mode 100755 utils/runTALNet.sh create mode 100755 utils/selcha2clean.sh create mode 100755 utils/sum-rttm.sh create mode 100755 utils/syllabify.sh create mode 100755 utils/textgrid2rttm.py rename {toolbox => utils}/tocombo2rttm.py (100%) create mode 100755 utils/train_test_split.py create mode 100755 utils/txt2rttm.py rename conf/vad/vad_segmenter_aclew.conf => utils/vad_segmenter_aclew.conf.txt (100%) mode change 100755 => 100644 create mode 100644 utils/yuniSeg.sh diff --git a/MED_2s_100ms_htk.conf b/MED_2s_100ms_htk.conf deleted file mode 100644 index edaa202..0000000 --- a/MED_2s_100ms_htk.conf +++ /dev/null @@ -1,318 +0,0 @@ -// OpenSMILE configuration for Large Scale Feature Extraction for Multimedia Event Detection// -// Low Level Descriptors: MFCC, Pitch, Loudness, PLP, LSP ... // - -/////////////////////////////////////////////////////////////////////////////////////// -; -; This section is always required in openSMILE configuration files -; it configures the componentManager and gives a list of all components which are to be loaded -; The order in which the components are listed should match -; the order of the data flow for most efficient processing -; -/////////////////////////////////////////////////////////////////////////////////////// -[componentInstances:cComponentManager] -instance[dataMemory].type=cDataMemory -instance[waveIn].type=cWaveSource -instance[fr1].type=cFramer -instance[pe2].type=cVectorPreemphasis -instance[w1].type=cWindower -instance[fft1].type=cTransformFFT -instance[fftmp1].type=cFFTmagphase -instance[mspec].type=cMelspec -instance[mfcc].type=cMfcc -instance[mzcr].type=cMZcr -instance[acf].type=cAcf -instance[cepstrum].type=cAcf -instance[pitchACF].type=cPitchACF -instance[energy].type=cEnergy -instance[spectral].type=cSpectral -instance[lld].type=cContourSmoother -instance[delta1].type=cDeltaRegression -instance[delta2].type=cDeltaRegression -instance[functL1].type=cFunctionals -instance[htksink].type=cHtkSink -printLevelStats=0 -nThreads=1 - - -///////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////// component configuration //////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////// -; the following sections configure the components listed above -; a help on configuration parameters can be obtained with -; SMILExtract -H -; or -; SMILExtract -H configTypeName (= componentTypeName) -///////////////////////////////////////////////////////////////////////////////////////////// -[waveIn:cWaveSource] -writer.dmLevel=wave -filename=\cm[inputfile(I){test.wav}:name of input file] -monoMixdown=1 - -[fr1:cFramer] -reader.dmLevel=wave -writer.dmLevel=frames -noPostEOIprocessing = 1 -copyInputName = 1 -frameSize = 0.0250 -frameStep = 0.010 -frameMode = fixed -frameCenterSpecial = right -buffersize = 1000 - -[pe2:cVectorPreemphasis] -reader.dmLevel=frames -writer.dmLevel=framespe -k = 0.97 -de = 0 - -[w1:cWindower] -reader.dmLevel=framespe -writer.dmLevel=winframe -copyInputName = 1 -processArrayFields = 1 -winFunc = ham -gain = 1.0 -offset = 0 - - // ---- LLD ----- - -[fft1:cTransformFFT] -reader.dmLevel=winframe -writer.dmLevel=fftc -copyInputName = 1 -processArrayFields = 1 -inverse = 0 - -[fftmp1:cFFTmagphase] -reader.dmLevel=fftc -writer.dmLevel=fftmag -copyInputName = 1 -processArrayFields = 1 -inverse = 0 -magnitude = 1 -phase = 0 - -[mspec:cMelspec] -nameAppend=melspec -reader.dmLevel=fftmag -writer.dmLevel=mspec1 -copyInputName = 1 -processArrayFields = 1 -htkcompatible = 1 -usePower = 0 -nBands = 26 -lofreq = 0 -hifreq = 8000 -usePower = 0 -inverse = 0 -specScale = mel - -[mfcc:cMfcc] -reader.dmLevel=mspec1 -writer.dmLevel=mfcc1 -copyInputName = 1 -processArrayFields = 1 -firstMfcc = 0 -lastMfcc = 12 -cepLifter = 22.0 -htkcompatible = 1 - - -[acf:cAcf] -reader.dmLevel=fftmag -writer.dmLevel=acf -nameAppend = acf -copyInputName = 1 -processArrayFields = 1 -usePower = 1 -cepstrum = 0 - -[cepstrum:cAcf] -reader.dmLevel=fftmag -writer.dmLevel=cepstrum -nameAppend = acf -copyInputName = 1 -processArrayFields = 1 -usePower = 1 -cepstrum = 1 - -[pitchACF:cPitchACF] - ; the pitchACF component must ALWAYS read from acf AND cepstrum in the given order! -reader.dmLevel=acf;cepstrum -writer.dmLevel=pitch -copyInputName = 1 -processArrayFields = 0 -maxPitch = 500 -voiceProb = 1 -voiceQual = 0 -HNR = 0 -F0 = 1 -F0raw = 0 -F0env = 1 -voicingCutoff = 0.550000 - -[energy:cEnergy] -reader.dmLevel=winframe -writer.dmLevel=energy -nameAppend=energy -copyInputName = 1 -processArrayFields = 0 -htkcompatible = 0 -rms=0 -log=1 - -[mzcr:cMZcr] -reader.dmLevel=frames -writer.dmLevel=mzcr -copyInputName = 1 -processArrayFields = 1 -zcr = 1 -amax = 0 -mcr = 0 -maxmin = 0 -dc = 0 - -[spectral:cSpectral] -reader.dmLevel=fftmag -writer.dmLevel=spectral -copyInputName = 1 -processArrayFields = 1 -squareInput = 1 -bands[0]=0-250 -bands[1]=0-650 -bands[2]=250-650 -bands[3]=1000-4000 -bands[4]=3010-9123 -rollOff[0] = 0.25 -rollOff[1] = 0.50 -rollOff[2] = 0.75 -rollOff[3] = 0.90 -flux = 1 -centroid = 1 -maxPos = 1 -minPos = 1 -entropy = 0 - -[lld:cContourSmoother] -reader.dmLevel=energy;mfcc1;mspec1;mzcr;pitch;spectral -writer.dmLevel=lld -writer.levelconf.nT=10 -;writer.levelconf.noHang=2 -writer.levelconf.isRb=0 -writer.levelconf.growDyn=1 -;processArrayFields=0 -nameAppend = sma -copyInputName = 1 -noPostEOIprocessing = 0 -smaWin = 3 - - // ---- delta regression of LLD ---- - -[delta1:cDeltaRegression] -reader.dmLevel=lld -writer.dmLevel=lld_de -writer.levelconf.isRb=0 -writer.levelconf.growDyn=1 -nameAppend = de -copyInputName = 1 -noPostEOIprocessing = 0 -deltawin=2 -blocksize=1 - -[delta2:cDeltaRegression] -reader.dmLevel=lld_de -writer.dmLevel=lld_dede -writer.levelconf.isRb=0 -writer.levelconf.growDyn=1 -nameAppend = de -copyInputName = 1 -noPostEOIprocessing = 0 -deltawin=2 -blocksize=1 - - -[functL1:cFunctionals] -reader.dmLevel=lld;lld_de;lld_dede -writer.dmLevel=func -copyInputName = 1 -frameMode = fixed - ; frameSize and frameStep = 0 => functionals over complete input - ; (NOTE: buffersize of lld and lld_de levels must be large enough!!) - ; 2 Sec frames with 100 millisec shift -frameSize=2 -frameStep=0.10 -frameCenterSpecial = right -noPostEOIprocessing = 0 -functionalsEnabled=Extremes;Regression;Moments;Percentiles;Crossings;Peaks;Means -Extremes.max = 0 -Extremes.min = 0 -Extremes.range = 1 -Extremes.maxpos = 1 -Extremes.minpos = 1 -Extremes.amean = 0 -Extremes.maxameandist = 1 -Extremes.minameandist = 1 -Extremes.norm = frame -Regression.linregc1 = 1 -Regression.linregc2 = 1 -Regression.linregerrA = 1 -Regression.linregerrQ = 1 -Regression.qregc1 = 1 -Regression.qregc2 = 1 -Regression.qregc3 = 1 -Regression.qregerrA = 1 -Regression.qregerrQ = 1 -Regression.centroid = 1 -Moments.variance = 1 -Moments.stddev = 1 -Moments.skewness = 1 -Moments.kurtosis = 1 -Moments.amean = 0 -Percentiles.quartiles = 1 -Percentiles.quartile1 = 0 -Percentiles.quartile2 = 0 -Percentiles.quartile3 = 0 -Percentiles.iqr = 1 -Percentiles.iqr12 = 0 -Percentiles.iqr23 = 0 -Percentiles.iqr13 = 0 -Percentiles.interp = 1 -Percentiles.percentile[0] = 0.95 -Percentiles.percentile[1] = 0.98 -Crossings.zcr = 1 -Crossings.mcr = 0 -Crossings.amean = 0 -Peaks.numPeaks = 1 -Peaks.meanPeakDist = 1 -Peaks.peakMean = 1 -Peaks.peakMeanMeanDist = 1 -Peaks.overlapFlag = 1 -Means.amean = 1 -Means.absmean = 1 -Means.qmean = 1 -Means.nzamean = 0 -Means.nzabsmean = 1 -Means.nzqmean = 1 -Means.nzgmean = 1 -Means.nnz = 1 - - - - - ////////////////////////////////////////////////////////////////////// - /////////////////// data output configuration ////////////////////// -////////////////////////////////////////////////////////////////////// - -; the HTK sink writes data in HTK parameter format -[htksink:cHtkSink] - ; data from the following dataMemory levels in concattenated - ; to form the output vectors -reader.dmLevel=func - ; this again defines a commandline option for the output file (see waveIn) -filename=\cm[output(O):name of output filename (HTK format)] -append=0 -parmKind=9 - -//////---------------------- END -------------------------/////// - - diff --git a/Vagrantfile b/Vagrantfile index 5d390f6..bd67238 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -112,16 +112,7 @@ Vagrant.configure("2") do |config| sudo apt-get install -y openjdk-6-jre || sudo apt-get install -y icedtea-netx-common icedtea-netx # sudo apt-get install -y libtool-bin apache2 - # If you wish to train EESEN with a GPU machine, uncomment this section to install CUDA - # also uncomment the line that mentions cudatk-dir in the EESEN install section below - #cd /home/${user} - #wget -nv http://speechkitchen.org/vms/Data/cuda-repo-ubuntu1404-7-5-local_7.5-18_amd64.deb - #dpkg -i cuda-repo-ubuntu1404-7-5-local_7.5-18_amd64.deb - #rm cuda-repo-ubuntu1404-7-5-local_7.5-18_amd64.deb - #apt-get update - #apt-get remove --purge xserver-xorg-video-nouveau - #apt-get install -y cuda - + # Kaldi and others want bash - otherwise the build process fails [ $(readlink /bin/sh) == "dash" ] && sudo ln -s -f bash /bin/sh @@ -135,6 +126,8 @@ Vagrant.configure("2") do |config| if ! grep -q -i anaconda .bashrc; then echo "export PATH=/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc fi + # assume 'conda' is installed now (get path) + su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" # install Matlab runtime environment cd /tmp @@ -147,7 +140,8 @@ Vagrant.configure("2") do |config| # Install OpenSMILE echo "Installing OpenSMILE" - cd /home/${user} + mkdir -p repos/ + cd /home/${user}/repos/ wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz tar zxvf OpenSMILE-2.1.tar.gz rm OpenSMILE-2.1.tar.gz @@ -157,7 +151,7 @@ Vagrant.configure("2") do |config| # we cannot redistribute if [ -f /vagrant/HTK.tar.gz ] then - cd /home/${user} + cd /home/${user}/repos/ su ${user} -c "tar zxf /vagrant/HTK.tar.gz" cd htk ./configure --without-x --disable-hslab @@ -166,102 +160,45 @@ Vagrant.configure("2") do |config| make install fi - # Get OpenSAT and all the tools - # Install DiarTK, LDC SAD, LDC scoring, Rajat's LENA stuff + - cd /home/${user} + # POPOULATE THE REPOSITORY SECTION + cd /home/${user}/repos/ + + # Get OpenSAT=noisemes and dependencies git clone http://github.com/srvk/OpenSAT --branch v1.0 - git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 - #git clone http://github.com/srvk/ldc_sad_hmm --branch v1.0 - git clone http://github.com/srvk/dscore --branch v1.0 - git clone https://github.com/srvk/lena-clean --branch v1.0 - git clone https://github.com/srvk/Yunitator --branch v1.0 - git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 - - # Get the Wrapper scripts - - git clone https://github.com/srvk/tools.git --branch v1.0 - git clone https://github.com/aclew/varia.git - - # Festvox Speech Tools -# wget -nv http://festvox.org/packed/festival/2.4/speech_tools-2.4-release.tar.gz -# tar zxvf speech_tools-2.4-release.tar.gz && rm speech_tools-2.4-release.tar.gz -# cd speech_tools -# ./configure -# make -# cd .. - - # Festvox 2.7.0 -# wget -nv http://festvox.org/festvox-2.7/festvox-2.7.0-release.tar.gz -# tar zxvf festvox-2.7.0-release.tar.gz && rm festvox-2.7.0-release.tar.gz -# cd festvox -# ./configure -# make -j 4 -# cd .. - - # Festival 2.4 -# wget -nv http://festvox.org/packed/festival/2.4/festival-2.4-release.tar.gz -# tar zxvf festival-2.4-release.tar.gz -# wget -nv http://festvox.org/packed/festival/2.4/festlex_CMU.tar.gz -# tar zxvf festlex_CMU.tar.gz -# wget -nv http://festvox.org/packed/festival/2.4/festlex_OALD.tar.gz -# tar zxvf festlex_OALD.tar.gz -# wget -nv http://festvox.org/packed/festival/2.4/festlex_POSLEX.tar.gz -# tar zxvf festlex_POSLEX.tar.gz -# wget -nv http://festvox.org/packed/festival/2.4/voices/festvox_cmu_us_awb_cg.tar.gz -# tar zxvf festvox_cmu_us_awb_cg.tar.gz -# cd festival -# ./configure -# make - - # LIUM Diarization system http://www-lium.univ-fr/diarization -# cd /home/${user} -# mkdir LIUM -# cd LIUM -# wget -nv http://www-lium.univ-lemans.fr/diarization/lib/exe/fetch.php/lium_spkdiarization-8.4.1.jar.gz -# gunzip lium_spkdiarization-8.4.1.jar.gz -# cp /vagrant/diarization.sh . -# ln -s /home/vagrant/tools/eesen-offline-transcriber/models . - - # Get tools: PDNN, coconut, ldc_sad_hmm - cd /home/${user} - mkdir G - cd G - git clone http://github.com/yajiemiao/pdnn - git clone http://github.com/srvk/coconut + git clone http://github.com/yajiemiao/pdnn + git clone http://github.com/srvk/coconut + su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" - # get theanorc! cp /vagrant/.theanorc /home/${user}/ - export PATH=/home/${user}/anaconda/bin:$PATH - - # install theano su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" - # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) - # and intervaltree (needed for rttm2scp.py) - # and recommonmark (needed to make html in docs/) - su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" - # assume 'conda' is installed now (get path) - su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" + # Install ldc-sad + #git clone http://github.com/srvk/ldc_sad_hmm --branch v1.0 + - # now dependencies for Yunitator + # Install Yunitator and dependencies + git clone https://github.com/srvk/Yunitator --branch v1.0 su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" - # now dependencies for noisemes_full - su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" - # Get some packages for tocombo_sad (matlab runtime environnement) - sudo apt-get install -y libxt-dev libx11-xcb1 + #Install to-combo sad and dependencies (matlab runtime environnement) + git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 + sudo apt-get install -y libxt-dev libx11-xcb1 - # Some cleanup - sudo apt-get autoremove -y + # Install DiarTK + git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 - # Phonemizer installation + + # Install eval + git clone http://github.com/srvk/dscore --branch v1.0 + + # Phonemizer installation sudo apt-get install -y festival espeak - cd /home/${user} git clone https://github.com/bootphon/phonemizer cd phonemizer python setup.py build @@ -269,6 +206,16 @@ Vagrant.configure("2") do |config| sudo python setup.py install cd .. + + # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) + # and intervaltree (needed for rttm2scp.py) + # and recommonmark (needed to make html in docs/) + su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" + + + # Some cleanup + sudo apt-get autoremove -y + # Silence error message from missing file touch /home/${user}/.Xauthority diff --git a/conf/reconf-slurm.sh b/conf/reconf-slurm.sh deleted file mode 100644 index 68d9208..0000000 --- a/conf/reconf-slurm.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -sed -i `lscpu -p|grep -v '#'|wc -l|awk '{printf ("s/Procs=DYN/Procs=%d/",$0)}'` /etc/slurm-llnl/slurm.conf diff --git a/conf/slurm.conf b/conf/slurm.conf deleted file mode 100644 index f1ad0c8..0000000 --- a/conf/slurm.conf +++ /dev/null @@ -1,172 +0,0 @@ -############################################################################### -# Sample configuration file for SLURM 2 -############################################################################### -# -# This file holds the system-wide SLURM configuration. It is read -# by SLURM clients, daemons, and the SLURM API to determine where -# and how to contact the SLURM controller, what other nodes reside -# in the current cluster, and various other configuration information. -# -# SLURM configuration parameters take the form Keyword=Value, where -# at this time, no spacing is allowed to surround the equals (=) sign. -# Many of the config values are not mandatory, and so may be left -# out of the config file. We will attempt to list the default -# values for those parameters in this file. -# -# This simple configuration provides a control machine named "laptop" -# to run the Slurm's central management daemon and a single node -# named "server" which execute jobs. Both machine should have Slurm -# installed and use this configuration file. If you have a similar -# configuration just change the values of ControlMachine, for the -# control machine and PartitionName and NodeName for job execution -# -############################################################################### -# -ControlMachine=localhost -#ControlAddr= -#BackupController= -#BackupAddr= -# -AuthType=auth/munge -#AuthType=auth/none -CacheGroups=0 -#CheckpointType=checkpoint/none -CryptoType=crypto/munge -#CryptoType=none -#DisableRootJobs=NO -#EnforcePartLimits=NO -#Epilog= -#PrologSlurmctld= -#FirstJobId=1 -JobCheckpointDir=/var/lib/slurm-llnl/checkpoint -#JobCredentialPrivateKey= -#JobCredentialPublicCertificate= -#JobFileAppend=0 -#JobRequeue=1 -#KillOnBadExit=0 -#Licenses=foo*4,bar -#MailProg=/usr/bin/mail -#MaxJobCount=5000 -MpiDefault=none -#MpiParams=ports:#-# -#PluginDir= -#PlugStackConfig= -#PrivateData=jobs -ProctrackType=proctrack/pgid -#Prolog= -#PrologSlurmctld= -#PropagatePrioProcess=0 -#PropagateResourceLimits= -#PropagateResourceLimitsExcept= -ReturnToService=1 -#SallocDefaultCommand= -SlurmctldPidFile=/var/run/slurm-llnl/slurmctld.pid -SlurmctldPort=6817 -SlurmdPidFile=/var/run/slurm-llnl/slurmd.pid -SlurmdPort=6818 -SlurmdSpoolDir=/var/lib/slurm-llnl/slurmd -SlurmUser=slurm -#SrunEpilog= -#SrunProlog= -StateSaveLocation=/var/lib/slurm-llnl/slurmctld -SwitchType=switch/none -#TaskEpilog= -TaskPlugin=task/none -#TaskPluginParam= -#TaskProlog= -#TopologyPlugin=topology/tree -#TmpFs=/tmp -#TrackWCKey=no -#TreeWidth= -#UnkillableStepProgram= -#UnkillableStepTimeout= -#UsePAM=0 -# -# -# TIMERS -#BatchStartTimeout=10 -#CompleteWait=0 -#EpilogMsgTime=2000 -#GetEnvTimeout=2 -#HealthCheckInterval=0 -#HealthCheckProgram= -InactiveLimit=0 -KillWait=30 -#MessageTimeout=10 -#ResvOverRun=0 -MinJobAge=300 -#OverTimeLimit=0 -SlurmctldTimeout=300 -SlurmdTimeout=300 -#UnkillableStepProgram= -#UnkillableStepTimeout=60 -Waittime=0 -# -# -# SCHEDULING -#DefMemPerCPU=0 -FastSchedule=0 -#MaxMemPerCPU=0 -#SchedulerRootFilter=1 -#SchedulerTimeSlice=30 -SchedulerType=sched/backfill -SchedulerPort=7321 -SelectType=select/cons_res -SelectTypeParameters=CR_Core_Memory -#SelectType=select/linear -#SelectTypeParameters= -# -# -# JOB PRIORITY -#PriorityType=priority/basic -#PriorityDecayHalfLife= -#PriorityFavorSmall= -#PriorityMaxAge= -#PriorityUsageResetPeriod= -#PriorityWeightAge= -#PriorityWeightFairshare= -#PriorityWeightJobSize= -#PriorityWeightPartition= -#PriorityWeightQOS= -# -# -# LOGGING AND ACCOUNTING -#AccountingStorageEnforce=0 -#AccountingStorageHost= -#AccountingStorageLoc= -#AccountingStoragePass= -#AccountingStoragePort= -AccountingStorageType=accounting_storage/none -#AccountingStorageUser= -ClusterName=cluster -#DebugFlags= -#JobCompHost= -#JobCompLoc= -#JobCompPass= -#JobCompPort= -JobCompType=jobcomp/none -#JobCompUser= -JobAcctGatherFrequency=30 -JobAcctGatherType=jobacct_gather/none -SlurmctldDebug=3 -SlurmctldLogFile=/var/log/slurm-llnl/slurmctld.log -SlurmdDebug=3 -SlurmdLogFile=/var/log/slurm-llnl/slurmd.log -# -# -# POWER SAVE SUPPORT FOR IDLE NODES (optional) -#SuspendProgram= -#ResumeProgram= -#SuspendTimeout= -#ResumeTimeout= -#ResumeRate= -#SuspendExcNodes= -#SuspendExcParts= -#SuspendRate= -#SuspendTime= -# -# -# COMPUTE NODES -NodeName=localhost Procs=1 State=UNKNOWN -PartitionName=standard Nodes=localhost Default=YES MaxTime=INFINITE State=UP -# Shared=Yes diff --git a/conf/slurm.sv.conf b/conf/slurm.sv.conf deleted file mode 100644 index c80d806..0000000 --- a/conf/slurm.sv.conf +++ /dev/null @@ -1,14 +0,0 @@ -[program:munge] -startsecs=0 -command=/usr/sbin/munged -f - -[program:slurmconfig] -startsecs=0 -priority=100 -command=/root/reconf-slurm.sh - -[program:slurmctl] -command=/usr/sbin/slurmctld -D - -[program:slurmd] -command=/usr/sbin/slurmd -D diff --git a/conf/supervisor.conf b/conf/supervisor.conf deleted file mode 100644 index 95242cd..0000000 --- a/conf/supervisor.conf +++ /dev/null @@ -1,7 +0,0 @@ -[supervisord] -nodaemon=true -logfile=/var/log/supervisor/supervisord.log -pidfile=/var/log/supervisor/supervisord.pid - -[include] -files = /etc/supervisor/conf.d/*.conf diff --git a/conf/vad/README.txt b/conf/vad/README.txt deleted file mode 100644 index 4b1672a..0000000 --- a/conf/vad/README.txt +++ /dev/null @@ -1,55 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -///////// > openSMILE LSTM-RNN voice activity detector< ////////////////// -///////// ////////////////// -///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// -///////// All rights reserverd. ////////////////// -/////////////////////////////////////////////////////////////////////////////////////// - - -This folder contains configuration files and models for a -prototype LSTM-RNN Voice Activity Detector. -This is meant as an example to show how to implement such -a VAD in openSMILE with the RNN components and to provide -a simple VAD for prototype development. The noise-robustness -of this VAD is *not* state-of-the-art, it has been built on -a small-scale research data-set, mainly for clean speech. - - -This config implements a voice activity detector as described in: - - Eyben, F.; Weninger, F.; Squartini, S.; Schuller, B.: - "Real-life voice activity detection with LSTM Recurrent Neural - Networks and an application to Hollywood movies," - Proc. of ICASSP 2013, pp. 483-487, 26-31 May 2013. - doi: 10.1109/ICASSP.2013.6637694 - -The models are not the same models as used in the paper, but a -preliminary version of the data presented in the paper. - -If you need a more accurate and noise-robust VAD, -contact audEERING at info@audeering.com for a demo of -our latest commercial VAD technology. -We have extremely robust detectors, which are even capable -of reliably detecting sung speech (vocals) in single channel -polyphonic music recordings. - - -There are two main config files to start from here: - vad_opensource.conf : Dumps vad activations per frame to CSV - vad_segmenter.conf : Creates wave files with voice segments - and optionally writes activations to CSV - -Run - SMILExtract -ccmdHelp -C -to see the commandline options supported by these config files. - -If you want to include the VAD as a module in your own -configuration files, you can use: - vad_opensource.conf.inc - turnDetector.conf.inc - -See the comments in these config files for level input/output -naming requirements. See the main config files for examples -of how to use the module includes. - - diff --git a/conf/vad/lstmvad_rplp18d_12.net b/conf/vad/lstmvad_rplp18d_12.net deleted file mode 100644 index be23ad2..0000000 --- a/conf/vad/lstmvad_rplp18d_12.net +++ /dev/null @@ -1,57 +0,0 @@ -autosave true -batchLearn false -bidirectional false -dataFileNum 0 -dataFraction 1.0 -dataset train -display false -displayAll false -errorTest false -gradCheck false -hiddenSize 50 -hiddenType lstm -initWeightRange 0.1 -inputNoiseDev 0.3 -inputSize 36 -labelDelimiter , -learnRate 1e-5 -loadWeights true -maxTestsNoBest 10 -momentum 0.9 -netUseImportanceWeight false -optimiser steepest -randSeed 2 -recurrent true -saveFileBase trained_nets/net4_proto.vad_rplp18d.seed2 -saveFileNoTimestamp true -seqsPerWeightUpdate 1 -sequence 0 -subsampleBias false -subsampleType tanh -targetLabels sil -task regression -testDistortions false -totalEpochs 40 -trainFile /home/iaa1/data/eyb/vad2012/ncout/train_timit_part0.vad_RASTA_PLP_18_new_D_std.nc,/home/iaa1/data/eyb/vad2012/ncout/train_buckeye_part0.vad_RASTA_PLP_18_new_D_std.nc,/home/iaa1/data/eyb/vad2012/ncout/train_timit_part1.vad_RASTA_PLP_18_new_D_std.nc,/home/iaa1/data/eyb/vad2012/ncout/train_buckeye_part1.vad_RASTA_PLP_18_new_D_std.nc,/home/iaa1/data/eyb/vad2012/ncout/train_timit_part2.vad_RASTA_PLP_18_new_D_std.nc,/home/iaa1/data/eyb/vad2012/ncout/train_buckeye_part2.vad_RASTA_PLP_18_new_D_std.nc -valFile /home/iaa1/data/eyb/vad2012/ncout/val_timit_part0.vad_RASTA_PLP_18_new_D_std.nc,/home/iaa1/data/eyb/vad2012/ncout/val_buckeye_part0.vad_RASTA_PLP_18_new_D_std.nc -verbose false -weightDistortion 0 -trainer_epoch 14 -weightContainer_bias_to_hidden_0_0_deltas 200 -1.99516e-05 4.48064e-05 -0.000767233 -9.14626e-05 3.74249e-05 2.83748e-05 0.000239365 5.80469e-05 0.000106838 -7.50933e-05 0.000263419 -0.000377648 -7.56347e-06 2.09836e-05 -0.000531158 1.4857e-05 5.43028e-05 1.542e-05 0.000486663 9.75604e-05 -0.000319651 -0.000530647 0.00103749 -0.00058428 -0.000363198 -0.000306504 -0.0011169 -0.000272457 7.83875e-05 -2.92362e-05 0.000232784 -9.7805e-06 8.09087e-05 -9.22712e-06 -0.000851507 1.8463e-05 0.000321361 0.000466429 0.000689636 0.000476001 -0.000241884 -0.00020066 0.00130061 -0.000387487 0.000143066 4.96411e-05 -0.000678754 -0.000194493 -0.000160726 -3.38491e-05 0.000875098 1.37522e-05 -0.000422412 -0.00120165 0.0019546 -0.000525643 -9.80324e-05 -7.38454e-05 0.000354641 -0.000138335 1.98706e-05 -1.1247e-05 0.000553439 -0.000105229 -1.13617e-06 0.000146241 -0.000219821 0.000174662 2.03272e-05 8.01116e-05 -0.00019477 3.58812e-05 -4.60032e-05 -0.000121285 -5.2363e-05 -0.000118773 1.79847e-05 5.54962e-05 -2.60865e-05 -0.000109219 -4.1655e-05 4.6459e-05 0.000474449 -5.49482e-05 2.76839e-05 -5.76082e-05 -0.000994326 -1.92571e-05 0.000432874 0.000484373 -0.0008782 -0.000871781 -6.53445e-05 -3.21839e-05 0.000553109 -9.96264e-05 0.000319616 0.000309716 -0.000334632 -0.000347932 -0.000979236 -0.000812577 -0.000876466 -0.000890904 -5.21071e-05 4.8518e-05 8.01847e-05 -0.000118949 0.000108098 -3.97319e-05 -0.00105208 -0.000259927 -8.61183e-05 -0.000107296 -6.64512e-08 -0.000300323 8.51064e-05 3.94476e-05 0.00100217 0.000120243 -1.27632e-05 -4.05727e-05 0.000692619 -6.77036e-05 3.11682e-06 1.6617e-05 0.000468729 6.43445e-06 3.17259e-05 -8.52122e-05 0.000292063 7.87395e-05 0.00011371 8.72672e-05 -0.000138786 0.000202463 -2.25759e-05 2.75158e-06 -0.00017917 -2.66222e-05 -0.000140109 -0.000141946 0.000748189 7.36507e-05 -7.15315e-05 -6.30679e-05 0.000388028 -0.000121339 -0.000140405 -4.99484e-05 -0.000574873 -1.82134e-05 -5.38926e-05 -5.30809e-05 -0.000743596 -2.80434e-05 -0.000177643 -4.81274e-05 -0.0010356 4.04676e-05 -0.000390048 -0.00038756 -0.00164338 -0.000158854 4.49241e-05 6.29954e-05 -0.000184927 -0.000141718 -0.000190526 -2.93841e-05 -0.00145176 -0.000106099 -8.71121e-06 -0.000102073 -0.00079582 -6.19339e-05 -0.000526148 -0.000367158 0.00121479 -0.000159713 -2.25399e-05 -0.000181648 0.000959452 -0.000123745 9.12361e-05 7.98257e-05 -0.000864942 0.000197508 -4.94676e-05 -3.40292e-05 0.000398959 -4.26745e-05 0.000136126 9.7843e-05 0.000619172 0.000107907 -0.000293325 -0.00024008 0.000312882 -0.000497748 -weightContainer_bias_to_hidden_0_0_plasticities 200 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -weightContainer_bias_to_hidden_0_0_weights 200 -0.090787 -0.025611 0.0686484 0.020715 -0.183305 -0.0514311 0.0240362 -0.0729901 -0.390663 0.265635 0.147228 -0.0208399 -0.104589 -0.0774166 0.00367128 -0.112317 -0.382623 0.43732 0.0701977 -0.0761555 -1.47089 1.09143 0.306384 -1.07971 -0.320082 0.0492079 0.371177 -0.198651 -0.322556 0.380218 0.0745057 -0.052245 -0.709443 0.311318 0.156893 -0.347423 -0.199716 0.449041 0.123378 -0.170316 -1.29131 0.299952 0.626696 -0.610752 -0.257146 0.258258 -0.0389681 -0.157554 -0.474364 0.69823 0.696208 0.274842 -1.68515 0.336885 1.06218 -0.198632 -0.0779467 0.11479 0.0894735 -0.139754 -0.413006 -0.00663865 -0.00642319 -0.454224 -0.0887571 0.240199 -0.178207 0.0293636 -0.368747 0.0635344 0.0634651 -0.221994 0.029159 0.229145 0.176904 0.0404112 -0.435518 0.218746 0.00239275 -0.45835 -0.177709 0.355238 0.317109 -0.164265 -0.417683 0.0156948 -0.470475 -0.320418 -1.36279 -0.0576207 -0.161182 -0.167941 0.192863 0.29193 -0.0282057 0.332661 -0.970847 0.636299 -0.117287 -0.722274 -3.58219 3.70157 -0.553343 -0.232276 -0.484217 0.262557 0.111359 -0.261932 -0.896064 0.583479 -0.0377573 -1.51472 -0.9334 0.547024 -0.0857952 -0.529523 -0.418695 0.0684181 0.383063 -0.205841 -0.700579 0.241562 0.360554 -0.446364 -0.119864 -0.186761 0.0189661 -0.20437 -1.0613 -0.535632 0.842101 -1.20872 -0.504905 0.24774 -0.19909 -0.251614 -0.213142 0.150525 -0.139476 -0.22194 -0.670078 -0.0341599 0.934486 -0.931747 -0.0982499 0.1526 0.146562 0.0856425 -0.301729 -0.0441415 -0.406311 -0.366714 -0.449713 0.0877422 -0.416363 -0.50319 -0.746189 0.113834 -0.717596 -0.723134 -0.966897 0.446275 -0.843039 -0.666983 -0.0690042 0.130759 -0.316706 -0.138208 -0.106739 0.15283 -0.217087 -0.119201 -0.364857 -0.0164419 -0.104133 -0.199913 -0.919475 0.533006 0.815641 -1.04558 -0.329349 -0.00601929 0.35322 -0.444459 -0.64087 -0.00986712 -0.614327 -0.309639 -0.27331 0.233924 0.179557 -0.225245 0.0749919 0.0358092 0.210549 0.0710572 -0.710864 -0.170808 0.156876 -0.499669 -weightContainer_bias_to_output_deltas 1 -0.0109575 -weightContainer_bias_to_output_plasticities 1 1 -weightContainer_bias_to_output_weights 1 -0.328142 -weightContainer_hidden_0_0_peepholes_deltas 150 -0.000112187 -0.000244427 -0.00021885 1.75543e-05 2.50924e-05 2.29404e-05 6.61633e-05 0.000358873 0.00119757 -4.18712e-05 -5.71147e-05 -6.09577e-05 -0.00013112 -0.000290922 -8.78166e-05 0.000549743 0.000951048 0.000969859 -0.000185397 -0.000289085 -0.00024156 -2.70176e-05 -0.000269407 -0.000192937 -0.000112449 -0.000215352 -0.000316033 0.000111647 0.000233694 0.000278182 6.61912e-05 0.000110838 0.000774643 -3.43196e-05 -0.000350854 -0.000756087 -1.10083e-05 5.84782e-05 -4.77198e-05 0.00106901 0.00209617 0.00134481 7.02118e-05 9.84524e-05 7.91491e-05 0.000122763 0.000174457 0.00059346 -0.0001406 -0.000229524 -0.000386738 -9.32881e-06 -4.83042e-05 -2.68122e-05 9.18725e-05 0.000341081 0.000254954 -5.6036e-05 -7.80558e-05 -0.000552087 6.98788e-05 0.00012723 4.61353e-05 -6.96291e-05 -0.000232799 -0.000270754 0.000189004 0.000435921 -0.00143788 0.000103942 0.000180976 0.000249714 0.000571498 0.000576632 -0.00106981 -0.000721738 -0.000473225 -0.00160571 -0.000168268 -0.000481436 -0.000732335 0.0010804 3.0342e-05 0.00206562 -0.000102236 -0.000356633 -0.000691144 7.84877e-05 4.0262e-05 8.86107e-05 0.000116718 0.000246179 0.000379068 2.1169e-05 3.03008e-05 2.56518e-05 0.000107357 0.000324508 -2.81076e-06 -3.3767e-06 -0.000263808 0.000486333 -8.76665e-06 -4.03935e-06 4.62405e-05 6.55661e-05 8.33292e-05 0.000169196 1.80206e-05 3.23031e-05 6.21876e-05 -6.2074e-05 -0.000265925 -0.000341123 -0.000177546 -0.000209964 -0.000363467 -0.000172605 -0.000506149 -0.000363223 -0.000289094 -0.000430273 -0.000385714 0.000227443 6.90163e-05 -0.000440788 -4.21301e-05 -6.44139e-05 -7.04012e-05 8.51443e-05 -0.000628853 -0.000178066 0.000282033 0.000344361 0.000328462 0.000251825 0.000475821 0.000637635 -7.01862e-05 -9.18049e-05 0.000260791 5.41986e-07 -1.161e-05 -0.000104373 0.000209972 0.000514648 0.000562167 0.000131159 0.000129938 0.000427909 -weightContainer_hidden_0_0_peepholes_plasticities 150 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -weightContainer_hidden_0_0_peepholes_weights 150 -0.0582822 -0.0717567 -0.116709 0.0466333 0.00334405 0.0845384 -0.113949 -0.17412 0.324185 0.110866 -0.0725225 -0.422003 0.0723734 0.319526 0.329959 0.255159 -0.267925 -0.168246 0.063671 -0.0658368 0.187477 -0.0116592 0.163734 0.0643249 -0.0366798 0.145704 -0.0137499 -0.0216675 0.0425596 -0.0531198 0.117976 -0.327671 0.428641 0.0769959 0.121258 -0.314721 -0.265012 -2.51086 1.26959 0.837684 -0.336179 -0.0949343 -0.0293589 -0.0357165 -0.095552 -0.10349 -0.159679 0.412354 -0.066949 0.0370586 0.0335873 -0.0821785 -0.0319935 -0.0978408 -0.350031 -0.109881 -0.124293 0.162458 0.14267 -0.339189 -0.00708674 0.213557 -0.494643 -0.0030318 0.277255 0.276072 0.145391 -0.220638 -0.831469 0.0426866 -0.136254 0.0571479 -0.88166 0.7944 -0.474567 -2.03633 0.485977 0.633773 0.0280737 0.0415605 -0.0762735 0.080465 1.54812 0.228326 -0.0685759 0.145195 -0.217159 -0.0820535 -0.119761 -0.288874 -0.235261 0.0691181 0.0458398 0.013801 0.0471015 -0.0220044 -0.365381 -0.230267 -0.24482 0.303266 0.63298 0.115404 -0.0319068 0.283463 0.254602 1.30492 -0.0681746 -1.13219 -0.0882439 0.0724224 -0.0836222 0.130289 0.0401118 0.414498 -0.0985429 0.077117 0.377402 0.403568 0.176716 0.149658 -0.468978 0.496285 0.156111 0.168802 0.763113 -0.156811 0.0114554 0.280087 0.263341 0.100036 0.323918 -0.0260952 -0.0588127 0.126123 -1.31442 0.0649711 -0.0525275 0.0131568 0.712538 0.468058 -0.265749 -0.249805 -0.254891 -0.0415938 0.0245014 -0.0105911 -0.0284155 -0.0847691 -0.00358457 0.0589205 -weightContainer_hidden_0_0_to_hidden_0_0_delay_-1_deltas 10000 -4.99328e-05 -2.3538e-06 -3.76554e-06 -2.06321e-06 2.80715e-06 -1.86809e-05 -1.92886e-05 3.65167e-05 -1.4427e-06 -2.23034e-05 5.63673e-07 4.96743e-06 1.45407e-06 3.2181e-05 2.93589e-05 -1.1332e-05 -3.70308e-05 9.11944e-06 -1.84956e-05 -4.74611e-06 -2.0961e-05 1.80714e-05 -3.35373e-06 -6.47834e-05 1.28395e-06 -1.80926e-05 -3.526e-05 1.10187e-05 -4.76832e-06 -2.58417e-05 -2.32132e-06 9.90098e-06 -1.1652e-05 -1.95239e-06 -1.70876e-06 1.31975e-05 -2.29914e-05 -5.11554e-06 -5.4532e-06 7.16438e-06 -1.25207e-05 -6.95006e-06 -8.34835e-06 -1.41391e-05 4.1699e-06 -5.39459e-06 2.7832e-06 1.59893e-05 2.75331e-05 -3.47684e-06 -0.000118121 -3.87207e-06 -2.27575e-05 4.35665e-06 -2.18276e-06 -4.32189e-05 -9.11469e-06 2.28745e-05 -1.9537e-05 -2.87632e-05 7.74951e-06 1.85712e-05 -6.97985e-06 2.71858e-05 3.45437e-05 -3.32677e-05 -6.05143e-05 -8.67418e-06 -3.00249e-05 -1.19274e-05 -2.04504e-05 2.40273e-05 -3.57333e-07 -8.27858e-05 2.77915e-06 -1.59562e-07 -5.38258e-05 1.58037e-05 1.0448e-05 -5.27879e-05 -6.61756e-06 1.51103e-05 -2.58531e-05 -1.47202e-05 -1.27387e-05 2.16094e-05 -3.81517e-05 5.15653e-06 -1.07562e-05 -3.60245e-06 5.68396e-07 -2.25761e-05 -2.82357e-05 -1.6111e-05 3.48488e-06 3.65014e-06 1.05616e-05 2.08194e-05 4.82637e-06 -1.41101e-05 7.7842e-05 7.3403e-05 0.000171386 -5.63292e-05 -0.000108357 0.000140028 -0.000153524 1.26028e-05 6.79961e-06 -8.86961e-05 0.000109954 -7.71545e-05 -1.25297e-05 0.000255036 -5.42219e-05 0.000112651 0.000170922 5.18989e-05 -1.79969e-05 1.72772e-05 0.000175236 -7.7131e-05 -9.93596e-05 0.000222672 -6.77626e-05 -0.000126647 2.75228e-05 3.33644e-05 -6.02193e-05 4.69633e-05 1.89296e-05 -8.45527e-05 1.35943e-05 -0.000101008 -6.32956e-05 3.26478e-06 -3.24881e-05 -2.25973e-05 -4.86575e-05 -4.36039e-05 -7.81563e-05 -5.21061e-05 -1.45208e-05 -3.34207e-05 3.91743e-05 8.84929e-05 -2.72578e-05 8.67601e-05 -1.86194e-05 0.000113595 -8.72315e-05 5.70881e-06 -5.63576e-06 -8.50637e-07 -3.93501e-06 -2.4918e-05 -2.59177e-05 5.6394e-05 -4.48511e-06 -3.21614e-05 1.22796e-05 -2.93322e-07 -7.24244e-07 5.98927e-05 3.8202e-05 -7.49567e-06 -4.53494e-05 8.76546e-06 -2.76428e-05 -1.03883e-05 -1.33811e-05 1.72831e-05 -1.45852e-05 -6.43232e-05 -5.34654e-06 -3.7468e-05 -4.55613e-05 1.58983e-05 -7.26842e-06 -3.6587e-05 -2.54749e-06 1.27385e-05 -2.29186e-05 -7.04974e-06 -5.97491e-06 2.65226e-05 -3.19084e-05 -4.82405e-06 -1.3909e-05 1.92849e-06 -2.03343e-05 -2.1178e-05 -1.68672e-05 -1.40637e-05 7.05945e-06 2.89056e-06 4.64606e-06 3.38018e-05 2.6214e-05 6.65882e-06 -1.07586e-06 6.80005e-06 -1.6678e-06 -5.09822e-08 2.97892e-06 -1.19727e-05 3.49928e-07 6.32526e-06 -2.04572e-06 4.19098e-06 -8.38306e-06 9.99934e-06 -9.67196e-07 -3.6197e-06 2.31119e-06 -4.2788e-06 -9.85043e-06 5.67182e-06 -1.16731e-05 4.5687e-06 -8.60446e-07 5.97551e-06 2.39805e-06 -1.89438e-06 -1.17429e-07 5.27606e-06 -5.77552e-07 1.86807e-06 3.07297e-06 -2.92956e-06 -9.17297e-06 4.19388e-06 -7.16915e-06 8.38744e-06 2.04969e-06 -4.61513e-06 -6.45902e-06 -5.20072e-06 9.10248e-06 1.32297e-05 -7.2331e-06 7.88439e-07 7.86134e-06 7.48911e-07 -7.05364e-06 -4.3352e-06 2.74105e-06 1.19211e-05 3.23504e-06 -5.67254e-06 -6.86989e-06 1.00571e-05 4.55306e-06 6.50232e-07 3.91938e-06 -7.80746e-06 -2.73259e-07 4.24593e-06 3.27894e-06 -4.82861e-06 -9.64548e-06 1.02104e-05 -5.93751e-07 -8.28899e-07 2.57235e-06 -4.16824e-06 -1.90381e-05 7.58644e-06 -1.0022e-05 2.47342e-06 -5.67682e-06 4.84439e-06 1.28037e-06 -5.99652e-06 -5.95411e-07 1.70959e-06 -1.32416e-06 2.11332e-06 3.9694e-06 -1.44774e-05 -3.09258e-06 1.57296e-06 -5.26716e-06 8.12957e-06 1.30328e-06 -1.65988e-06 -9.25372e-07 -1.07329e-05 6.51483e-06 1.73162e-05 -6.02452e-06 -1.59795e-06 5.73308e-06 -1.07663e-06 -8.75749e-06 -1.52963e-06 1.57577e-06 1.10445e-05 4.22285e-06 -7.98219e-06 2.09398e-06 8.16606e-06 1.02461e-05 -1.35718e-05 4.39354e-05 2.95584e-05 6.98869e-05 -4.01185e-05 5.72656e-06 3.04022e-05 -1.26699e-05 -1.67841e-05 2.48681e-05 -0.000127465 -2.10473e-05 3.70404e-06 -4.67697e-05 -1.01514e-06 9.01e-05 -1.12887e-05 -5.45576e-05 -6.83096e-08 5.6145e-06 -7.10955e-06 3.37513e-06 -2.38693e-05 2.29824e-05 -3.04306e-05 -6.72879e-06 6.35896e-06 5.99971e-05 -2.40922e-05 3.59982e-05 1.24509e-06 7.19444e-05 -3.89478e-05 4.26136e-05 3.97791e-05 6.04745e-06 -1.20146e-05 4.99076e-05 4.44825e-05 3.20961e-05 8.43361e-06 3.40912e-06 -5.20934e-07 2.50126e-06 -8.40414e-05 -1.38129e-05 -8.03558e-06 -7.44198e-06 7.61347e-06 -1.69793e-06 -2.36917e-06 7.72848e-06 -1.36173e-05 3.91154e-06 7.83918e-06 3.70269e-06 -3.53951e-06 -1.59437e-05 1.38151e-05 1.95658e-06 -1.1025e-05 3.52853e-06 -6.6766e-06 -1.88823e-05 9.49016e-06 -1.40465e-05 6.43787e-06 -8.87142e-06 8.23354e-06 3.51332e-06 -2.70031e-06 1.59512e-06 8.72758e-06 1.82562e-06 3.49403e-06 5.60351e-06 -1.43496e-05 -7.86883e-06 5.26604e-06 -8.53834e-06 1.37572e-05 2.32609e-06 -5.72118e-06 -5.3154e-06 -1.30616e-05 1.25152e-05 2.74805e-05 -4.72714e-06 -1.27947e-06 1.12368e-05 3.73364e-06 -1.16362e-05 -8.25607e-06 2.15012e-06 1.0398e-05 2.57666e-06 -1.19162e-05 -2.23687e-05 5.84395e-06 5.78834e-05 -4.51468e-06 4.83688e-05 7.24149e-06 1.13868e-05 1.79593e-05 1.88292e-05 6.16002e-05 -9.11955e-05 -4.06412e-05 -1.10835e-05 -6.39978e-05 1.25662e-05 -4.4e-05 -2.04764e-05 2.49789e-06 -5.79917e-06 1.29191e-05 2.4192e-05 2.86927e-06 1.33576e-05 1.62823e-06 1.49284e-05 1.88457e-05 1.11522e-05 -2.62432e-05 2.37257e-05 6.48437e-05 -6.53304e-06 -9.56842e-06 5.88411e-06 5.52229e-05 6.60624e-06 2.37899e-05 2.38819e-05 -1.2877e-05 5.47614e-05 2.26529e-05 5.13009e-05 3.47486e-05 3.76736e-05 -9.19018e-06 -2.54157e-05 -1.49453e-05 1.61592e-05 1.44587e-05 5.69965e-05 -3.38874e-05 -3.4689e-05 2.1042e-05 0.000146887 9.16483e-06 2.54023e-05 4.55562e-05 -2.27862e-05 5.6525e-05 -1.07087e-05 4.59039e-05 -1.59964e-05 -2.97551e-05 -5.90604e-06 5.31155e-05 4.29002e-05 -8.90925e-06 -3.86533e-05 -5.01523e-06 -1.39853e-05 1.22519e-05 6.68484e-05 -2.39185e-05 -1.65767e-05 -4.00721e-05 -1.021e-05 -5.31009e-05 -2.41936e-05 5.61225e-06 -8.8141e-07 3.732e-05 5.08599e-07 5.75627e-06 -1.2042e-06 2.61799e-05 1.47932e-05 5.31976e-05 3.85867e-05 -2.57723e-05 2.10592e-05 -2.35193e-05 3.61365e-06 1.81702e-07 -2.07491e-05 -4.04446e-05 -7.99132e-06 6.08975e-05 5.52525e-06 4.7333e-05 3.25183e-05 3.4878e-06 3.10508e-06 -4.27096e-05 1.87561e-05 3.18699e-05 0.000149746 -8.08383e-05 0.000149689 -2.81083e-05 -2.90929e-05 0.000134672 -8.8292e-05 0.00012026 1.36053e-05 -0.000231587 1.05648e-05 -4.93995e-05 -0.000166102 -0.000107028 0.000157076 -2.48558e-05 -0.000215708 8.01498e-05 5.19667e-05 -0.000180796 2.3653e-05 -2.89742e-05 -3.02554e-05 -6.50157e-05 4.48935e-05 -0.000109906 1.16358e-05 8.35959e-06 -1.08652e-05 0.000157736 9.02083e-05 -1.66594e-05 4.7405e-05 -2.28841e-05 4.85276e-05 2.56141e-05 1.84969e-05 0.000138423 -6.02781e-05 -5.27062e-05 -7.53482e-05 -8.08613e-05 3.34745e-05 -3.52669e-05 6.91268e-05 -8.03092e-05 4.23939e-05 9.27609e-05 0.000243616 -5.72403e-06 -4.94219e-05 0.00014628 -7.1405e-05 8.55356e-05 1.22034e-05 6.09298e-05 -3.11367e-05 -6.42697e-06 -2.72292e-05 0.000123779 2.35275e-05 -3.37284e-06 -5.36361e-05 3.52767e-05 5.3187e-05 3.20156e-06 6.04017e-05 -2.94335e-05 -3.94785e-05 0.000112019 -9.1722e-06 -8.42986e-05 1.64426e-05 -9.00643e-06 -7.45903e-06 6.17616e-05 6.97362e-05 -3.65963e-05 5.57499e-05 1.87062e-06 -3.11042e-05 5.157e-05 1.9499e-05 -6.91118e-05 4.56296e-05 -2.07362e-05 -1.38113e-05 1.30188e-05 1.13867e-05 -4.52371e-05 -8.49825e-06 6.13237e-05 1.36188e-06 5.9257e-05 5.32698e-05 3.32162e-05 5.07256e-06 -1.52598e-06 -1.20192e-05 -1.82018e-05 -3.4651e-06 -7.70076e-06 1.1044e-06 -1.06257e-05 -8.44123e-08 -8.52916e-06 -1.18237e-05 1.12727e-05 5.78922e-06 -7.17268e-06 -8.12353e-06 5.39965e-06 -7.41538e-06 2.05352e-06 -6.95571e-06 -5.76792e-08 -1.70276e-05 1.31653e-06 6.96089e-07 -7.43662e-07 6.5198e-07 -5.64783e-07 -1.01671e-05 6.75817e-06 -4.86036e-06 -4.69863e-06 -3.57041e-06 5.14888e-06 -2.85673e-06 1.37869e-05 -8.99302e-06 -1.10713e-06 -9.13772e-06 -1.88431e-05 4.57604e-06 1.36124e-05 -2.33311e-06 1.501e-05 6.8505e-06 3.76536e-06 -5.13682e-06 -1.23968e-05 -4.64573e-06 -3.04101e-07 4.59979e-06 6.87389e-06 3.45299e-06 -2.07875e-06 1.04093e-05 -2.60769e-05 -1.61338e-05 1.78724e-06 -5.05066e-06 -7.17102e-06 8.15302e-09 1.61919e-07 -3.59476e-06 1.67502e-06 5.9172e-06 -6.21921e-06 -8.39489e-06 -2.57269e-06 -1.14693e-06 2.75086e-06 -3.2756e-06 3.80879e-06 -9.01963e-06 4.61727e-06 -2.59724e-07 1.53726e-05 1.01088e-06 3.65336e-06 -6.18828e-06 2.52677e-06 -4.93218e-06 5.18474e-06 1.0143e-06 1.48265e-06 2.78554e-06 9.22643e-07 -1.23679e-05 1.79795e-06 -3.70614e-06 -1.88653e-05 7.22519e-06 1.21691e-05 -3.26793e-06 7.15673e-06 2.21735e-06 2.52272e-06 -5.65431e-06 6.43203e-07 -3.90653e-06 1.85468e-06 5.75262e-06 1.03955e-06 3.41344e-06 -1.55343e-05 2.34788e-05 5.13728e-06 3.31936e-05 -1.87615e-05 -5.79205e-05 2.0059e-05 -2.87411e-05 -5.12646e-06 -7.51597e-06 -1.37033e-05 -1.32578e-05 7.6243e-05 6.96256e-06 1.59454e-05 2.11469e-05 -5.78938e-05 -6.62637e-05 1.27126e-05 3.13268e-05 5.05484e-05 -3.02072e-05 -3.3453e-05 -9.42815e-06 -8.75902e-05 -7.99705e-05 1.95609e-05 1.08814e-05 -5.58438e-05 -2.91278e-05 -1.33686e-05 -1.83168e-05 2.52114e-05 -3.35458e-05 -8.82401e-06 -5.34932e-05 -1.61401e-05 3.60083e-05 1.5994e-06 -2.6759e-05 1.57155e-05 -4.13969e-05 -1.77825e-05 -1.53957e-05 -2.865e-07 -1.8054e-05 4.69404e-05 2.77627e-05 -1.93707e-05 -8.16045e-06 -3.76991e-06 -4.85158e-06 -2.11359e-05 -4.81174e-07 -9.88896e-06 -2.64309e-07 1.0837e-06 6.86278e-06 -1.19919e-05 -5.95992e-06 1.00639e-05 5.79067e-06 -1.42488e-05 -5.08395e-06 1.69085e-06 -3.97592e-06 6.58058e-06 -6.82074e-06 7.97439e-06 -2.54215e-05 5.29213e-06 1.33791e-06 7.80304e-06 1.09708e-06 1.17962e-05 -3.1557e-06 7.34815e-06 -1.89637e-06 -1.08169e-05 -4.1686e-06 5.39317e-06 -9.45482e-06 8.40408e-06 -8.78103e-06 -1.59268e-06 -1.43402e-05 -1.85358e-05 4.05876e-06 1.09186e-05 2.11844e-06 1.43917e-05 5.06249e-06 3.80079e-06 -5.69867e-06 -1.02161e-05 -5.12971e-06 2.04599e-06 1.38607e-06 -1.10182e-07 1.40781e-05 -4.59143e-06 1.82242e-06 -3.4795e-05 -9.19392e-06 9.79989e-06 3.11181e-05 -6.91471e-05 -2.27454e-05 -1.50005e-05 -2.36278e-05 1.05368e-05 -9.98941e-06 -1.98157e-05 -3.33668e-05 2.38551e-06 2.75232e-05 -8.5847e-06 4.03422e-05 4.42651e-07 -2.61197e-05 7.24063e-06 3.08105e-05 3.08037e-05 2.55093e-05 4.29059e-05 4.84362e-05 -2.87845e-05 -3.18912e-05 1.45087e-05 3.67462e-05 -1.35726e-05 7.41126e-06 -3.24535e-05 -2.99213e-05 1.81816e-05 -8.7426e-07 -3.45731e-05 -8.21245e-06 -9.00336e-06 1.26439e-05 3.69787e-05 -2.54198e-06 -1.628e-06 3.92847e-06 5.27371e-06 2.74833e-05 2.90054e-06 -3.89956e-06 1.51272e-06 2.00043e-05 1.6921e-06 -2.05368e-06 -4.70864e-05 -2.94496e-05 5.21358e-05 7.09199e-05 -0.000116681 -5.04327e-05 1.1636e-05 -5.21527e-05 -1.19357e-05 -6.0659e-06 -2.86945e-05 -7.10924e-05 3.1734e-05 1.22704e-05 7.90623e-06 0.000103029 -7.5223e-06 -7.37422e-05 -1.15491e-05 3.80077e-05 1.96922e-05 2.77709e-05 -6.69583e-06 0.000106412 -4.52606e-05 -4.9873e-05 2.62439e-05 0.000109892 -2.1458e-05 5.80023e-05 -1.58447e-05 -3.15744e-05 3.80341e-05 6.17063e-05 -5.59379e-05 6.6647e-06 2.11459e-05 6.33819e-06 6.09569e-05 2.98517e-05 2.96423e-05 2.61911e-05 -2.03229e-05 2.99021e-05 -3.48735e-05 1.65806e-05 -3.49786e-06 0.000216398 5.25979e-06 -9.62103e-06 5.47338e-06 7.33975e-05 0.000131849 0.000261034 -0.000217365 4.52275e-06 0.000280279 -0.00017378 1.69918e-06 7.54309e-05 -0.000374795 -0.000165984 8.37356e-05 -0.000117258 -2.74528e-05 0.00025326 4.91786e-05 -0.000195951 2.29919e-05 9.13771e-05 7.32005e-05 9.10761e-05 1.36716e-05 0.000210679 -7.93853e-05 -1.34719e-05 -2.81524e-05 0.000239009 -4.40374e-05 0.000173872 6.20022e-05 0.000114397 -6.89595e-05 0.000329208 9.97827e-05 9.04354e-05 3.14237e-05 0.000189601 0.000260228 0.000135513 6.67551e-05 -3.11253e-05 -4.3751e-05 2.35592e-05 -0.000273779 -6.12615e-05 -0.00013983 6.80913e-06 9.82477e-06 9.65534e-06 -1.02511e-05 -5.7597e-06 4.00084e-06 4.77202e-05 -6.09034e-05 -2.27967e-05 -5.51397e-05 -4.80037e-05 2.08618e-05 -2.29627e-05 -7.02524e-05 -5.71129e-05 -1.34869e-05 2.40835e-05 1.49954e-06 6.2408e-05 1.6997e-06 -3.08616e-05 -1.07235e-05 4.27821e-05 5.0828e-05 3.6113e-05 5.6104e-05 8.14098e-05 -3.81541e-05 -1.51208e-05 1.70862e-05 4.47038e-05 -3.02674e-05 1.77103e-05 -3.292e-05 3.45733e-06 2.04995e-05 5.54089e-05 -1.04626e-05 7.05685e-06 1.15101e-05 6.24618e-05 5.95116e-05 1.24579e-05 3.05088e-05 -4.78506e-06 -1.55545e-06 2.6898e-05 1.98847e-06 1.48071e-05 -9.62982e-06 9.33338e-05 0.000100674 0.000176695 1.97244e-05 -0.000159873 0.000100278 -0.000120028 2.89633e-05 7.98647e-05 1.95243e-05 -1.26184e-05 1.18583e-05 1.28639e-05 0.000153389 -1.57133e-05 3.60554e-05 5.00019e-05 2.94773e-05 1.93312e-05 -2.30165e-05 6.7483e-05 -2.31849e-05 -6.48022e-05 0.00015204 1.09169e-05 -2.96022e-05 -1.46304e-05 1.26072e-05 -2.11586e-05 3.55291e-05 -8.07712e-06 6.70445e-06 4.34575e-05 -3.26122e-05 -0.000163418 3.13565e-05 -7.42355e-05 -3.73713e-05 7.47373e-05 -4.40339e-05 3.98955e-06 1.80719e-06 3.01624e-05 3.35228e-05 3.43536e-05 3.1036e-05 4.64403e-05 2.80027e-05 5.20341e-05 7.56933e-05 0.000101558 9.33273e-05 0.000183531 -5.35295e-05 -0.000192854 0.000179776 -0.000156213 0.000139687 7.21992e-05 3.58402e-05 4.82033e-05 -3.10666e-05 1.74122e-05 0.00027477 2.84198e-06 5.58688e-05 -1.3742e-05 2.49937e-06 6.11006e-05 -3.35026e-05 6.04613e-05 -3.19528e-05 -9.54647e-05 0.000126991 -2.67506e-05 -0.000135381 -5.62157e-07 -6.86818e-06 7.30796e-06 5.68964e-05 -2.52418e-05 -4.14553e-05 7.75672e-05 -1.33289e-05 -0.000206169 6.92347e-05 -0.000148582 -0.00011771 2.08503e-05 -4.09e-05 -6.58738e-05 -2.72709e-05 3.72725e-05 -2.42271e-05 3.0967e-05 7.13177e-05 2.40754e-05 1.36753e-05 6.18334e-05 7.30508e-05 2.96859e-05 -6.29479e-05 -7.00706e-05 0.000153283 0.00029863 -0.00011077 0.000114601 0.000112785 1.55991e-05 0.000232317 -5.94456e-06 0.000253585 6.4963e-06 -0.00013133 0.00011045 -2.16919e-05 -0.000283074 -7.6508e-05 0.000124285 -2.52578e-05 -0.000152346 8.32205e-07 6.68656e-05 -0.000191514 3.68832e-05 -4.54617e-05 1.16937e-05 -9.95625e-05 0.00011234 6.29224e-05 -0.000164665 9.5303e-06 -9.8433e-05 -4.88851e-05 8.66535e-05 7.89355e-05 0.000104931 5.90616e-05 1.80122e-05 5.84389e-05 5.32577e-05 0.000203909 -0.000104119 3.30529e-06 -7.07071e-06 -5.10252e-05 3.96255e-05 3.45711e-05 6.75295e-05 -0.000100579 0.000127391 8.67977e-05 0.00020868 -5.64702e-05 -0.000135725 0.000180105 -0.000222065 7.93947e-05 2.17239e-05 1.01444e-05 0.000101527 -1.42869e-05 4.0912e-05 0.000398787 -1.65457e-05 7.13342e-05 3.23318e-05 4.1081e-05 -2.97138e-06 -6.99383e-06 6.81134e-05 -6.49652e-05 -0.000119366 0.000279661 -5.03089e-05 -9.45815e-05 -6.45333e-05 4.94698e-05 -6.84186e-05 4.02908e-05 -9.33445e-06 -2.22755e-05 2.27483e-05 -6.7897e-06 -0.000269185 9.9063e-05 -0.000166052 -0.000179387 1.06757e-05 -4.68955e-05 -0.000160844 -6.0999e-05 5.24165e-06 -5.69591e-05 6.75961e-05 5.78106e-05 1.43006e-05 7.57501e-05 6.16538e-05 7.62352e-05 1.24257e-05 3.5783e-06 5.55159e-05 -3.92738e-05 -0.000103554 4.54416e-05 -9.80411e-05 5.1606e-05 -1.15854e-05 -1.14988e-05 5.44631e-05 -4.63838e-05 4.40288e-06 0.000147125 -7.71603e-06 1.99954e-05 5.81757e-05 5.57794e-06 -2.84387e-05 -3.74627e-06 6.10782e-05 -6.51829e-06 -5.50135e-05 4.30552e-05 -2.65139e-05 -0.000100843 -1.89774e-05 3.07883e-05 -3.61757e-05 3.73746e-05 4.2284e-07 7.50424e-07 1.49913e-06 -3.90693e-05 -6.95982e-05 4.37438e-05 -5.17089e-05 -3.65365e-05 -1.17064e-05 1.43686e-05 -3.03739e-05 -3.30513e-05 -7.35313e-06 -2.38817e-05 2.00228e-05 6.20927e-05 -3.13229e-06 3.15138e-05 1.18076e-05 5.88768e-05 5.47613e-07 -7.51064e-06 4.96689e-05 -1.92724e-05 -6.77786e-05 3.9044e-05 -0.000137878 5.38971e-05 -2.86401e-05 -3.81688e-08 6.39798e-05 -3.37212e-05 -1.28839e-06 0.000130226 1.32718e-05 8.01883e-06 4.46046e-05 3.15338e-06 -2.47068e-05 -1.4718e-05 5.83961e-05 2.01152e-06 -4.92216e-05 4.38927e-05 -2.57642e-05 -8.73588e-05 -2.53231e-05 2.26196e-05 -3.46568e-05 3.04974e-05 1.10609e-05 4.94571e-06 2.10916e-06 -2.76425e-05 -4.1379e-05 3.65369e-05 -3.67895e-05 -7.19165e-06 -8.49033e-06 9.59409e-06 -2.73986e-05 -4.6571e-05 9.3307e-07 -3.2089e-05 2.5926e-05 5.67123e-05 1.05141e-06 4.27268e-05 1.62901e-05 3.9647e-05 -2.76414e-05 1.4953e-05 0.000199951 -0.000111931 -0.000210153 0.000159972 -0.000163509 -2.8812e-06 -0.000131135 -9.6034e-05 0.000252509 -7.95101e-05 3.38683e-05 0.000512511 1.1116e-05 1.20747e-05 0.000135151 -4.94485e-06 -0.000100134 -1.20678e-05 0.000191133 -3.68343e-05 -0.00016342 0.000191542 -0.000113391 -0.00025338 -0.00013585 0.000103281 -0.000125826 8.89049e-05 6.95276e-05 -8.72891e-06 2.06121e-05 -8.89228e-05 -0.000178519 5.08742e-05 -0.000204937 -0.000133648 1.16164e-06 -0.000102937 -0.000190312 -0.000128679 -0.000126445 -0.000102402 0.000127968 0.000170367 -6.35486e-05 0.00013728 1.24869e-05 0.000175817 -6.09533e-06 6.52588e-06 4.17084e-05 -2.27008e-05 -7.83921e-05 3.55541e-05 -0.000107883 4.14931e-05 -1.64182e-05 -6.07178e-06 5.57851e-05 -3.65376e-05 -7.11173e-07 0.000115059 3.384e-06 1.09983e-05 5.23708e-05 6.07448e-06 -8.28776e-06 -7.96395e-06 4.85815e-05 3.1052e-06 -4.60403e-05 3.34817e-05 -2.32896e-05 -8.10271e-05 -2.64896e-05 2.28416e-05 -3.53818e-05 1.58648e-05 3.27498e-06 5.99412e-06 4.20345e-07 -4.49415e-05 -4.47286e-05 3.36793e-05 -3.97069e-05 -1.81085e-05 -1.23375e-05 1.18955e-05 -1.93831e-05 -3.46125e-05 9.14714e-06 -2.45875e-05 1.90235e-05 5.1102e-05 -1.51054e-06 3.49356e-05 1.83838e-05 4.46337e-05 1.48523e-05 -1.17968e-05 -3.48045e-05 7.21848e-07 -3.58043e-05 -6.65854e-05 3.90157e-05 7.12896e-06 1.41954e-05 3.35273e-05 -2.28884e-05 1.11455e-05 2.33274e-06 -6.26595e-05 -2.51346e-05 -2.08989e-05 2.25361e-06 -4.23413e-05 -8.32659e-06 1.05797e-05 1.47198e-05 2.12421e-06 1.72451e-05 -2.12462e-05 2.94691e-05 8.82174e-05 -2.6366e-05 -4.44183e-06 -4.1419e-06 1.90114e-05 -5.32533e-05 2.70417e-05 -4.0545e-05 -1.32049e-05 -1.91131e-05 -1.77945e-05 -4.18611e-05 2.13443e-05 -4.56898e-06 1.09551e-07 2.23408e-05 -2.59338e-06 -2.64822e-05 -4.96165e-06 -2.8344e-05 -2.29488e-05 1.01616e-05 1.79879e-05 3.69848e-06 1.94523e-05 3.85246e-05 2.11555e-05 1.70729e-05 -1.41378e-05 -4.06856e-05 3.73554e-05 4.22395e-05 -8.29176e-05 -1.51986e-05 4.46336e-05 -3.28187e-05 2.66645e-05 5.68284e-07 -5.06582e-05 -2.76369e-05 -4.08289e-06 1.64134e-05 -4.49917e-05 1.06591e-05 -3.29758e-06 2.42772e-05 -2.48654e-05 1.44081e-05 3.6956e-05 3.5112e-05 6.41249e-05 7.70733e-06 -1.96851e-05 5.05004e-06 6.5675e-05 3.05242e-05 -6.85713e-06 3.83804e-05 -2.20458e-05 -2.12779e-05 -7.30133e-07 2.7008e-05 2.42532e-05 -2.68528e-06 -1.97239e-05 1.61619e-05 5.19182e-06 -8.32876e-06 -5.60097e-06 -1.29997e-05 9.11383e-06 1.43414e-05 9.97879e-07 2.57413e-05 1.25628e-05 0.000126095 0.000124551 7.36123e-05 1.7617e-05 -0.000249364 0.000234928 -4.01619e-05 3.47467e-05 8.34839e-05 4.06513e-05 3.10739e-06 3.76815e-05 -4.33972e-05 0.000151956 -3.34803e-05 -3.82935e-05 0.000108271 4.84137e-05 5.47907e-05 -8.80972e-06 0.000165624 -6.63166e-05 -8.16366e-06 0.000193708 5.41182e-06 0.000150073 9.3816e-05 5.10708e-05 -1.07744e-05 0.000132059 7.92597e-05 -2.95799e-05 0.000132369 -4.21583e-05 -0.000144539 5.04768e-05 -2.78354e-05 4.09306e-05 -3.74768e-06 -9.55149e-05 -1.67741e-05 -0.000151075 5.79362e-05 2.91038e-05 6.09208e-05 7.07587e-05 -9.11364e-06 6.20646e-05 1.38956e-05 9.5337e-05 4.49814e-05 5.7117e-06 -4.98066e-06 -7.17431e-06 -2.26645e-05 -1.57844e-05 2.5318e-05 -6.21352e-05 9.56491e-09 2.25071e-05 -3.37024e-05 1.70412e-05 6.70106e-07 -6.28794e-05 -3.80865e-05 9.99898e-07 2.15153e-05 -2.84716e-05 1.34793e-05 3.28897e-06 4.22383e-06 -1.22409e-05 1.81906e-05 2.29698e-05 3.27809e-05 7.43936e-05 -2.61041e-06 -1.18461e-05 3.48032e-06 2.80533e-05 -5.4435e-06 -9.28056e-07 -5.32567e-06 -2.63625e-05 -3.17064e-05 -4.67965e-06 -8.40531e-06 9.29849e-06 -4.83252e-07 2.31116e-06 2.79709e-05 1.23544e-05 -3.98603e-06 -2.28845e-06 -2.71661e-05 -4.3118e-06 4.93856e-06 -4.41863e-07 2.26985e-05 1.17216e-05 -2.03144e-05 -5.48637e-05 -2.63718e-06 8.54537e-06 -5.52145e-05 -3.47672e-05 -2.62712e-05 -3.07363e-06 -4.70921e-05 5.57087e-06 1.36513e-05 1.40849e-05 -1.6302e-05 -2.58077e-06 1.25502e-05 -2.96628e-05 4.15987e-05 -4.8126e-05 -5.65288e-06 -3.24228e-06 6.2822e-05 -1.00493e-05 1.26329e-05 -4.89963e-05 1.81714e-05 5.9266e-05 7.94485e-07 -1.87659e-05 2.78943e-05 4.33529e-05 -2.34335e-05 9.91012e-07 -1.61338e-05 -3.91089e-05 -3.34545e-05 1.32245e-05 -4.41453e-05 5.80724e-05 2.50421e-05 7.71285e-06 3.15084e-05 -6.87248e-06 -6.32529e-05 1.95532e-06 1.80374e-06 4.40273e-05 1.69986e-05 2.02113e-05 -1.21866e-05 1.85167e-05 1.71908e-05 -1.93517e-05 6.00807e-06 2.55811e-06 -3.69483e-05 -1.78254e-05 -2.7028e-05 3.44066e-05 -8.48641e-05 9.21306e-06 2.8029e-05 2.5615e-05 -5.59709e-06 2.66798e-05 3.66591e-05 -1.06745e-05 -2.43327e-06 -2.90973e-05 -1.61203e-05 3.5388e-06 0.000107885 2.59863e-07 1.41587e-06 -1.09073e-05 1.70909e-05 5.11709e-05 1.59122e-06 -3.12941e-05 4.59817e-05 5.90189e-05 -4.18786e-05 5.42443e-06 -9.61583e-06 -1.90467e-05 -1.58155e-05 1.58338e-05 -3.30799e-05 3.25301e-05 5.75436e-06 4.59292e-06 -1.3704e-05 -7.68313e-06 -5.51662e-05 -7.80809e-06 -1.32304e-05 5.09439e-05 1.31594e-05 6.26953e-05 -2.34528e-06 3.17827e-05 7.27213e-05 0.000105792 0.000142587 -0.000109259 -0.00024685 0.000222842 -0.000191572 2.92409e-05 -4.65029e-05 -0.000153447 0.00015186 -6.08388e-05 -3.07176e-05 0.000397498 -6.32601e-05 4.97454e-05 0.000210238 9.4011e-05 -7.65771e-05 5.1323e-05 0.000224211 -7.30416e-05 -0.000107715 0.000250217 -7.9665e-05 -0.000161176 -5.36017e-05 7.03339e-05 -9.67696e-05 0.000176897 6.26152e-05 -2.84363e-05 6.38557e-05 -0.000107777 -0.00017285 3.11229e-05 -3.19546e-05 -0.000123233 -3.56525e-05 -3.5917e-05 -0.000129563 -4.02573e-05 3.31796e-05 -6.67213e-06 8.13477e-05 0.000137978 -2.87953e-05 8.40398e-05 1.59059e-07 0.000110855 1.66231e-05 -4.01899e-05 -4.96271e-06 -4.25623e-06 -3.39583e-05 -1.97105e-05 -5.64328e-05 1.34841e-05 -0.000103105 8.88335e-06 3.59263e-05 2.62261e-05 -1.14876e-05 3.93275e-05 3.30649e-05 -1.94542e-05 -1.4317e-06 -3.95728e-05 -2.62842e-05 -8.98773e-06 0.000109852 -1.98491e-05 4.19408e-06 -6.3495e-06 1.636e-05 5.8991e-05 -3.1958e-06 -3.69852e-05 5.74247e-05 8.04583e-05 -3.31969e-05 1.99877e-07 -7.14778e-06 -2.6062e-05 -1.43559e-05 2.8585e-05 -4.19977e-05 2.96344e-05 3.5733e-06 1.90352e-06 -2.50843e-05 -2.18958e-05 -6.88427e-05 -2.19638e-05 -7.59462e-06 6.90437e-05 1.58801e-05 7.06384e-05 -1.02266e-07 3.002e-05 1.19226e-05 -1.35636e-05 -1.14899e-05 2.6749e-05 -3.46852e-06 -1.87058e-05 3.42487e-05 -1.66187e-05 3.85652e-05 3.74624e-05 -3.34045e-05 3.6006e-07 -7.07401e-07 -8.64579e-05 -8.314e-07 -5.31963e-06 4.61701e-05 -5.96754e-06 4.55238e-05 2.47142e-06 2.76202e-05 -1.37655e-06 3.87293e-05 1.19167e-05 2.10399e-05 0.000111295 4.78912e-05 -1.12449e-05 1.92177e-05 1.43114e-05 -2.26045e-05 3.33742e-06 9.96606e-07 -1.68023e-05 -6.20009e-06 -2.26212e-06 3.48323e-05 2.67969e-05 4.66023e-07 -1.03077e-05 4.74841e-05 4.15018e-06 5.99703e-06 3.5919e-05 -7.10443e-06 -8.47229e-06 -1.3315e-05 -4.09158e-06 -3.91853e-05 1.51959e-05 2.75837e-05 -4.27759e-05 1.6577e-05 2.71795e-05 -4.11366e-05 -2.44913e-05 2.01375e-06 -3.86179e-05 1.85443e-05 8.04294e-05 -1.60834e-05 2.12614e-05 -2.0094e-07 -5.19209e-05 -1.71766e-05 -2.52758e-05 7.53455e-05 -7.63529e-07 5.21783e-05 -6.44482e-06 4.72902e-05 3.19893e-06 3.12113e-05 2.06665e-05 8.63535e-06 0.000125848 3.36116e-05 -7.9746e-07 -2.84535e-06 2.09455e-05 -1.70786e-05 8.16413e-06 4.04309e-06 -3.31148e-05 -3.13916e-05 1.63126e-05 2.72125e-05 1.86886e-05 2.1866e-05 -7.70659e-06 2.95892e-05 -1.5482e-05 4.46916e-05 7.93856e-06 2.35696e-06 -2.88995e-05 -9.78345e-06 -1.24845e-05 -3.09384e-05 4.00254e-06 8.90802e-05 -2.45464e-05 -6.34962e-05 9.83545e-05 9.53812e-05 -9.78957e-05 0.000170331 -2.38931e-05 2.21453e-06 0.000333508 -0.00019257 9.0218e-05 3.03122e-05 -0.000318646 -9.07259e-05 -2.82813e-06 4.11551e-05 -0.000103149 6.00056e-07 -1.18165e-05 -6.00985e-05 5.33864e-05 6.02048e-05 -6.81857e-05 7.84782e-05 4.0544e-06 2.86159e-05 -2.41439e-05 5.00905e-05 -6.13765e-05 -5.40225e-05 6.02488e-05 -2.87376e-05 2.81242e-05 1.94781e-05 -3.28688e-05 0.000153699 0.000108619 0.000127467 2.97234e-05 0.000166775 0.000157282 9.67215e-05 4.89724e-05 -7.19139e-05 -0.000137399 6.42523e-05 -9.07916e-05 1.15452e-05 -0.000162138 4.14574e-05 -2.7202e-05 3.75394e-06 2.46531e-05 -3.96214e-05 -2.52097e-05 3.84513e-05 -4.34095e-05 5.11833e-05 8.53394e-05 -5.68886e-05 1.86738e-05 2.64619e-06 -0.000123745 -3.52318e-05 -2.53626e-05 5.92696e-05 9.8507e-06 6.15296e-05 6.88924e-06 3.40065e-05 7.4818e-07 5.83372e-05 2.10501e-05 1.82354e-05 0.000165144 7.90681e-05 -3.09604e-05 2.34989e-05 5.67418e-05 -2.63677e-05 -6.00239e-07 1.05126e-05 -4.64977e-05 -7.05405e-06 -1.13726e-05 6.61946e-05 3.49849e-05 2.20814e-05 -9.10228e-06 7.02177e-05 4.45522e-06 5.39306e-05 4.16926e-05 -3.5915e-06 -3.78722e-05 -1.50205e-05 -2.33072e-05 -4.89771e-05 -3.76265e-06 -5.85749e-05 2.62182e-05 6.91935e-05 -4.45847e-05 -8.87095e-05 5.58358e-05 -6.92092e-05 3.81507e-05 -2.54727e-05 -1.77286e-05 8.94271e-05 -6.56715e-05 7.16736e-06 0.000142437 2.11638e-05 7.11086e-05 1.62685e-05 -2.02609e-05 -2.3729e-05 -1.59099e-05 7.0917e-05 1.52431e-05 -6.77152e-05 -1.89558e-05 -4.87528e-05 -0.000166034 1.85095e-05 1.06466e-05 -7.5518e-06 -2.10031e-05 -1.19754e-05 -7.78306e-06 7.15942e-08 -2.50059e-05 -2.82661e-05 -3.9258e-08 -7.45995e-05 -4.22076e-05 2.74186e-05 -3.08992e-05 -1.73977e-05 5.32072e-06 -3.8145e-06 -3.29134e-05 6.07739e-05 9.98373e-05 1.93355e-05 2.90653e-05 -3.62267e-05 6.22226e-05 -4.67307e-05 3.09924e-05 -8.55273e-07 -1.70079e-05 -5.11057e-05 3.53701e-05 -5.03374e-05 8.42714e-05 1.85425e-06 -2.64402e-05 0.000124476 -7.33703e-05 3.31e-06 0.000127345 4.6446e-05 3.37368e-05 1.85504e-05 -2.26687e-06 -3.86324e-05 -1.78368e-05 8.26603e-05 2.44198e-05 -5.84713e-05 2.73182e-05 -4.22584e-05 -0.000129249 2.03173e-06 1.21319e-05 -1.45796e-05 5.21006e-06 -1.71204e-05 2.14501e-06 -6.54721e-06 -2.68528e-05 3.53003e-06 1.46372e-05 -3.18156e-05 1.55522e-06 -2.20106e-05 -1.48449e-05 -3.1676e-05 -4.51599e-05 1.90115e-05 3.34201e-05 3.17594e-05 8.76106e-05 1.09245e-05 4.33606e-05 -3.96955e-05 5.94497e-05 4.48063e-05 -0.000100751 -0.000147442 0.000109112 0.000262213 -8.39109e-05 0.000182442 -0.000127013 -6.22489e-05 0.00014097 -0.000123938 8.85964e-05 4.89606e-05 -0.000341949 -9.15053e-08 -5.92509e-05 -0.000167883 -5.76568e-05 0.000103116 -7.81229e-06 -0.000190331 -1.47489e-05 0.000141949 -0.000204014 9.51656e-05 0.000165343 -1.63354e-05 -7.48621e-05 0.000128713 -4.13101e-05 4.49103e-05 2.05415e-05 2.58638e-05 0.000204008 0.00010863 2.3735e-05 0.000192451 3.49245e-06 3.73917e-05 8.37318e-05 0.000106203 0.000209696 -6.86846e-05 4.24019e-05 -3.85772e-05 -5.80973e-05 5.24685e-05 -0.000168388 7.71789e-06 -0.000201165 3.6299e-05 -2.01721e-05 -2.68781e-05 -6.55861e-06 -0.00014811 3.62465e-05 -0.00014051 0.000112258 -7.03534e-05 4.88633e-06 0.000209019 -6.1671e-05 1.84834e-05 0.000290625 8.27162e-05 5.19755e-05 0.000103223 -4.02995e-05 -5.86815e-05 -2.25485e-05 0.00019149 1.864e-05 -9.97329e-05 -1.30353e-05 -4.24276e-05 -0.000190897 -3.18931e-05 5.38897e-05 -1.78939e-05 8.75937e-05 -7.09602e-05 6.22794e-05 -1.79536e-05 -6.17297e-05 -9.7104e-05 4.89366e-05 -0.000147938 2.75154e-05 -6.43793e-05 -2.38044e-05 -8.472e-05 -9.70926e-05 -0.000118876 -1.59502e-05 7.45083e-05 0.000144579 2.2962e-05 8.63948e-05 -7.43734e-05 0.000134471 -6.27786e-06 5.74297e-06 -1.4614e-05 -7.84033e-06 -3.71172e-05 -5.03172e-06 5.02049e-08 -3.78366e-06 1.4393e-05 2.1779e-06 -1.65262e-05 -2.53373e-05 -1.22242e-05 -6.29295e-05 -2.28126e-05 1.45141e-05 -1.1948e-05 1.29434e-05 -2.41946e-05 7.44255e-06 5.30596e-06 -4.56572e-06 1.27634e-05 -3.91377e-05 1.60679e-05 1.73435e-05 -1.05308e-05 -3.25945e-06 3.82891e-05 -1.62845e-05 -2.96119e-05 4.49986e-06 -9.58734e-06 7.86482e-06 -5.11678e-06 -5.60475e-06 -1.41539e-05 3.1782e-06 2.74115e-05 1.51195e-05 4.615e-05 -7.90432e-06 2.06865e-05 1.38734e-05 -1.26961e-05 3.15105e-05 8.02468e-06 -2.68614e-05 -2.51825e-09 1.38904e-05 -5.23642e-06 -2.36963e-05 1.81782e-06 -2.14034e-05 -4.91499e-05 -3.31698e-05 -6.18949e-05 1.36132e-05 2.04145e-05 -1.09208e-05 -1.52281e-06 -0.000123713 -1.79578e-05 -1.19459e-05 -1.88148e-06 -7.44331e-06 6.10472e-05 6.97687e-06 -3.94864e-05 1.61488e-05 5.9783e-05 -2.5978e-05 -3.35136e-06 -3.24606e-05 -6.6562e-06 9.9769e-06 -1.13352e-05 4.48737e-07 2.82736e-05 7.10304e-06 -7.02273e-05 -1.0448e-05 -3.40306e-05 -6.46147e-05 -2.15329e-05 1.80845e-05 -3.48969e-05 2.61814e-05 -4.77455e-06 1.13336e-05 2.83662e-05 -2.1916e-05 3.07647e-06 2.9576e-05 -1.50034e-05 3.33702e-05 -3.2724e-06 -1.40911e-05 4.84942e-06 2.96908e-05 0.000117218 0.000105216 4.05887e-05 -7.97062e-05 -0.000168911 0.000156728 -0.000138167 -7.44922e-06 5.69555e-05 -0.000118838 8.49242e-05 1.5982e-05 -4.67753e-05 0.000187397 -4.8241e-05 9.7355e-05 0.00016475 0.000158577 4.2865e-07 4.08674e-05 9.09707e-05 -7.10984e-05 -3.64193e-05 0.000276702 -1.43575e-05 5.74757e-05 9.79664e-05 2.10306e-05 -8.78242e-05 -3.43535e-06 7.64417e-05 -9.20605e-06 6.05503e-05 -0.000165376 -0.000133443 -7.2655e-06 -3.23494e-05 -8.84361e-05 -1.15582e-05 2.32058e-05 -5.4564e-05 -0.000143923 8.1175e-05 4.22802e-05 4.19671e-05 1.09676e-05 -3.24599e-05 6.71136e-05 -9.12825e-05 0.00013762 3.84374e-05 1.98116e-06 4.33991e-05 -2.88645e-05 -0.000122643 2.89101e-05 -8.18002e-05 8.22479e-05 -9.17718e-07 -1.24126e-05 6.25372e-05 -0.00014348 -1.70773e-05 7.67086e-05 2.22649e-07 1.45786e-05 5.12921e-05 2.09967e-05 -3.76435e-05 4.18937e-06 0.000118578 2.28896e-06 -3.16005e-05 1.77569e-05 -1.73273e-05 -4.85768e-05 -1.82491e-05 2.34253e-06 1.62585e-05 2.14908e-05 -4.42594e-05 -1.21196e-05 -1.28058e-05 -6.32613e-05 -4.41654e-05 1.21901e-05 -4.76825e-05 -1.28985e-05 -3.14787e-06 -9.45475e-06 -6.11709e-06 -3.5635e-05 6.51572e-06 2.69119e-05 2.42834e-06 0.000107583 3.27995e-06 5.38913e-06 -3.07707e-05 8.35981e-05 -8.87348e-05 -3.44789e-05 2.04353e-05 -1.84051e-05 8.3581e-07 -3.4296e-05 -2.39082e-05 -1.33445e-05 -5.87289e-05 -7.07939e-05 5.43798e-05 -8.0362e-05 2.64273e-05 6.56733e-05 1.89332e-05 -5.14459e-05 3.71681e-05 -2.71885e-05 -7.91493e-06 5.18882e-07 4.52576e-05 7.09087e-05 -2.01565e-05 3.20228e-05 -2.47342e-05 -2.26934e-05 -5.98855e-05 -6.35057e-06 1.41794e-05 -4.58772e-05 3.59052e-06 -3.59867e-06 -4.70588e-05 -2.19918e-05 5.85389e-05 -2.83469e-05 -5.03096e-05 -5.18938e-06 -5.44367e-05 -5.82229e-05 -3.2631e-05 4.19827e-05 -4.98873e-05 -7.66556e-05 -1.05564e-06 2.93313e-05 1.16516e-05 -6.05345e-07 3.13947e-05 -2.14328e-06 -6.64379e-06 -1.2414e-05 -8.35188e-06 1.30968e-06 2.52785e-07 -6.93143e-06 -1.64372e-05 -1.20271e-05 -2.26048e-05 -1.94317e-05 1.59187e-05 -9.62168e-06 1.65428e-05 3.02457e-05 3.53529e-06 -1.17791e-05 1.98933e-05 -1.34506e-05 -2.27593e-05 -1.0354e-05 7.43441e-06 1.20448e-05 -1.03362e-05 -1.4824e-05 -7.95698e-06 -2.14964e-06 -2.93382e-05 5.9994e-06 -6.77268e-07 -7.57437e-07 -8.15211e-06 -1.43204e-07 -1.3662e-05 4.67866e-07 -7.42858e-06 2.74734e-07 -2.46359e-05 -1.6762e-05 -3.99637e-05 -3.47126e-05 -2.80402e-05 -7.47533e-06 -3.44986e-05 -3.44765e-05 -2.38128e-06 1.51832e-05 3.51591e-06 1.34505e-05 -5.49907e-07 -1.288e-06 7.2782e-06 -6.32226e-05 -0.000103259 -1.41586e-05 -0.000145363 -0.000164705 6.76553e-05 3.97963e-05 8.84954e-06 1.96685e-05 -0.000131328 4.40024e-05 -0.000121378 -0.000310869 1.38363e-05 -8.47151e-05 -3.43734e-05 3.12597e-05 2.66294e-06 9.7702e-05 5.22473e-05 -1.00773e-05 0.000133844 -4.86127e-05 0.000118897 0.000365704 0.000196478 -0.000136689 0.000146843 0.000104369 -0.000125789 4.3947e-06 -4.91177e-05 -0.000147233 -1.72718e-05 9.5837e-06 5.02542e-05 4.44805e-05 0.000113898 0.000112522 0.000155185 7.02821e-06 0.000150574 8.41202e-05 -8.38603e-05 -4.73342e-05 0.000113695 1.06819e-05 6.14015e-05 -3.24137e-05 2.37706e-06 3.13977e-06 3.65051e-06 1.10762e-05 -1.08852e-05 2.74137e-05 -8.10078e-06 4.92991e-06 9.32648e-06 -1.1453e-05 3.76091e-06 2.63683e-05 -1.08352e-05 1.70168e-05 -1.28715e-05 -2.50875e-05 1.74632e-05 5.19551e-06 6.19295e-07 -3.27709e-06 -1.063e-05 -2.16579e-05 1.392e-05 1.83643e-05 2.05212e-05 5.62467e-05 2.39504e-05 -1.4701e-06 4.51745e-06 1.8253e-05 1.3277e-05 -8.26465e-06 2.61093e-05 -5.13121e-06 -2.16234e-05 9.59305e-06 1.1425e-05 -7.67681e-06 -2.11199e-05 -3.68922e-06 6.59764e-06 -2.29442e-05 -2.11838e-05 -1.525e-06 -3.4749e-06 5.44263e-06 -4.56095e-06 2.86556e-05 2.52914e-05 2.97481e-06 -0.000104568 8.89248e-05 0.000254234 4.05859e-05 -0.000114807 0.000160402 -9.27706e-05 0.00021736 -3.39431e-05 -3.35814e-05 0.000115475 -2.02752e-05 3.4401e-05 0.000421609 8.1849e-05 0.000195575 -4.64754e-05 9.83428e-05 7.48076e-05 -7.8917e-05 4.35894e-05 -0.000167868 -0.00012794 9.90636e-05 -0.000112062 -0.000335505 0.000121054 -8.92962e-06 -0.000132714 0.000155668 5.49295e-05 -2.25705e-05 4.26142e-05 -6.57877e-05 -3.83077e-05 0.000160458 1.69366e-06 1.16985e-06 4.08311e-05 -8.39986e-06 -0.000117802 -5.82996e-06 3.00754e-05 4.1449e-05 0.000161833 5.57096e-05 1.92128e-05 1.80082e-05 0.000142681 0.000134775 -5.38133e-05 0.000121252 0.000216339 -7.75394e-06 -0.000239123 0.000251054 -0.000278723 0.000417404 -8.73019e-05 -0.000112215 0.000268111 -0.000107376 3.17252e-05 0.000927675 0.000164201 0.000214676 9.83819e-05 0.00013298 -8.7621e-05 -6.53695e-05 0.000191633 -9.45892e-05 -0.000270839 0.000129042 -0.000163836 -0.000518891 1.02531e-05 0.000124507 -0.000152599 0.000146163 -3.15017e-05 1.21508e-05 2.62789e-06 -0.000194439 -0.000217493 0.000124987 -0.00021289 -0.000131684 9.23757e-06 -6.48928e-05 -0.000196118 -9.95475e-05 3.73112e-05 4.77825e-05 0.00018451 0.000179786 1.39578e-05 7.88989e-05 -7.81937e-05 0.000243385 4.07206e-05 -0.000112182 -0.000308142 0.000112201 0.000297859 -0.000194861 0.00037485 -0.000188972 -1.01252e-06 0.000366985 -0.000289493 0.000145387 2.36133e-05 -0.000565259 -0.000102549 -0.000132955 -0.000197733 -0.000104916 0.000148851 -1.4295e-05 -0.000253242 0.000115705 0.000281071 -0.000323514 0.000119788 0.000339911 6.70902e-05 -9.60494e-05 0.000191239 -6.09074e-05 -4.67717e-07 0.000126721 4.69333e-06 0.00016333 0.000155456 2.21848e-05 0.000302343 4.75221e-05 3.81953e-06 6.77362e-05 0.000150022 0.000305607 1.36125e-05 6.92265e-05 -9.52279e-05 -0.000193106 5.20692e-05 -0.000151565 -2.93475e-05 -0.000307847 -2.84696e-05 3.60469e-05 0.000138543 -2.97481e-05 -0.000130065 5.49716e-05 -0.000235598 0.000248974 -5.28427e-05 2.88494e-05 0.000136371 1.57511e-05 3.25085e-05 0.00062939 9.71813e-05 4.66175e-05 7.1015e-05 1.3075e-05 -0.000123276 -4.4256e-05 0.000138498 -0.000107837 -0.000139573 0.000190489 -9.60144e-05 -0.000181556 -8.45096e-05 6.58131e-05 -3.77299e-05 0.000170034 -0.000157966 1.61259e-05 -3.99276e-05 -1.00674e-05 -0.000257025 0.000216965 -0.000231027 -0.000176698 -2.15574e-05 -8.4972e-05 -0.000233416 -7.23187e-05 -5.92887e-05 -4.07216e-05 9.13944e-05 8.71993e-05 3.41528e-05 0.000205262 9.69457e-05 8.80717e-05 -7.56066e-06 2.21596e-06 2.96934e-05 -1.39663e-05 -1.2466e-05 1.13761e-05 -1.32619e-05 3.77904e-05 -1.00428e-05 -1.85954e-05 1.40231e-05 -2.08037e-06 5.19445e-06 4.45671e-05 2.67781e-05 1.35645e-05 -4.32877e-06 1.18297e-05 -1.68542e-05 3.99038e-06 1.00419e-05 4.35144e-06 -1.11651e-05 -7.15393e-06 -4.7932e-06 -1.70433e-05 1.76106e-05 -2.72885e-06 -4.36513e-06 3.21488e-05 3.99366e-06 4.37435e-06 6.9253e-06 -2.58142e-05 3.85537e-06 2.11081e-06 -5.69445e-06 -2.09039e-05 -1.69669e-05 1.8177e-05 -2.23063e-05 -6.22617e-06 -1.046e-05 7.66291e-06 2.82157e-06 1.01581e-05 4.54432e-07 3.60878e-05 -3.92712e-06 1.70753e-05 -1.05485e-05 6.23194e-06 1.42155e-05 -5.58855e-06 -3.24156e-05 7.37717e-06 -6.47168e-06 2.97806e-05 -9.74731e-06 -2.55791e-05 2.49766e-05 1.45904e-07 1.27643e-05 4.04027e-05 3.73913e-05 5.09886e-06 5.58096e-07 -4.04047e-06 -5.36773e-06 -1.13602e-05 4.97715e-06 1.05949e-05 -7.82041e-06 -1.87443e-05 -1.36171e-07 -1.07798e-05 2.27745e-05 2.33151e-06 -3.1298e-06 2.15172e-05 1.07169e-05 1.45446e-05 7.97712e-06 -4.26928e-05 1.21754e-05 5.48101e-06 -1.76805e-05 5.15023e-06 -2.13651e-05 1.30555e-05 -7.52993e-06 -1.19476e-05 -3.75083e-07 4.44023e-06 7.44312e-06 1.19232e-05 5.98647e-06 1.77029e-05 -1.42144e-05 2.37407e-05 8.73735e-05 8.26889e-06 -6.78171e-05 3.33369e-05 6.70504e-05 -1.40235e-05 0.000125158 5.16113e-07 9.74807e-05 0.000189258 -0.000149392 1.90996e-05 -2.3057e-05 -0.000219817 -2.32318e-05 3.51092e-06 -0.000120896 1.66153e-05 9.00668e-05 2.71556e-05 -6.57413e-05 6.84972e-08 8.07396e-05 -0.000109086 6.05428e-05 0.000114411 4.89915e-05 -6.23838e-05 5.78407e-05 1.07791e-05 3.12626e-05 3.03068e-05 3.4407e-05 1.78772e-05 3.72185e-05 1.11905e-05 0.000133117 4.0517e-05 5.28625e-05 7.08996e-06 8.15447e-05 4.5551e-05 3.46385e-05 1.02205e-05 -5.51569e-05 -6.34017e-05 7.4094e-06 -6.35512e-05 -1.27754e-05 -7.38352e-05 -1.45718e-05 8.07823e-06 3.33008e-05 -1.45204e-05 -2.78704e-05 1.90595e-05 -1.48817e-05 5.34152e-05 -9.03922e-06 -3.57982e-05 2.07431e-05 7.90495e-07 1.10284e-05 5.70382e-05 2.87754e-05 2.87865e-06 -6.11661e-06 1.46542e-05 -1.83751e-05 -3.93155e-06 4.37847e-06 -9.34774e-07 -1.15271e-05 -1.05867e-05 -3.2762e-06 -2.1748e-05 1.74201e-05 2.43202e-07 -5.29128e-06 3.79675e-05 1.65057e-05 8.55421e-06 1.33707e-05 -4.62235e-05 4.69465e-06 1.35733e-05 -5.40935e-06 -1.52346e-05 -2.61411e-05 1.45458e-05 -2.26644e-05 -1.12505e-05 -1.40171e-05 2.267e-06 6.09769e-06 8.54275e-06 4.22387e-06 3.55759e-05 7.69203e-06 1.96499e-05 6.7886e-05 1.68512e-05 -5.15103e-05 1.05731e-05 -4.36525e-05 1.41347e-05 -2.96645e-06 5.45837e-07 1.05567e-05 -9.04761e-08 9.6066e-06 3.21731e-05 -1.39148e-05 3.20752e-05 -2.18643e-05 6.29241e-05 2.08343e-05 1.4703e-05 -4.32769e-06 -2.17273e-05 -2.83294e-05 -2.9593e-05 -1.1838e-05 1.38325e-05 -1.4673e-05 -1.40994e-06 -2.26236e-06 1.17771e-05 -2.43947e-05 2.03882e-05 -2.00445e-05 6.06585e-06 -1.59928e-05 -5.68315e-06 -4.68756e-05 3.96387e-06 -1.72688e-05 -8.72249e-06 -8.62953e-06 -2.49162e-05 -2.50437e-05 -2.80086e-05 6.49653e-05 5.2843e-06 2.80069e-05 -1.24777e-05 1.32412e-05 2.30776e-05 -4.90116e-06 3.25363e-05 4.92861e-05 1.02744e-05 -5.89308e-05 -1.14968e-05 -3.4727e-05 1.32715e-05 -1.41215e-05 2.26208e-05 1.8092e-05 -1.23106e-05 1.83574e-05 -4.20258e-07 -8.92444e-06 5.36171e-05 -2.89914e-06 8.95506e-05 1.26133e-05 2.95741e-05 -1.60681e-05 -1.45207e-05 -1.31102e-05 -3.34399e-05 -1.45655e-05 3.40911e-05 -1.6089e-05 -8.17951e-06 3.33806e-05 1.00401e-05 -1.10736e-05 1.1873e-05 -1.52075e-05 2.80034e-06 -1.1066e-05 -5.14324e-06 -3.80105e-05 8.11913e-06 -3.57958e-05 -4.2122e-05 -1.82444e-05 -1.93942e-05 -2.83151e-05 -3.80373e-05 5.17961e-05 1.14792e-05 3.20731e-05 -3.3821e-06 5.81507e-06 1.06539e-05 -3.51214e-05 5.06751e-05 3.25284e-05 -4.94378e-05 -0.000125204 4.52272e-05 0.000217475 -6.51668e-05 0.000133473 -0.000130036 2.71842e-05 0.000141067 -0.000117842 3.91286e-06 3.04604e-05 -0.00023796 -1.84507e-05 -2.82519e-05 -5.60539e-05 -8.30138e-05 0.000105442 -1.5532e-05 -0.000190568 2.26608e-05 6.92686e-05 -0.000116195 4.64625e-05 2.6238e-05 -5.24707e-05 -1.5047e-05 1.69954e-05 -6.48645e-05 1.79161e-05 3.23694e-05 1.09244e-05 0.000126192 9.33479e-05 4.04635e-05 9.48028e-05 7.15039e-05 2.28758e-05 -3.84394e-05 8.43814e-05 0.00013177 2.27181e-05 -8.11572e-06 -3.22526e-05 -0.00010676 1.14538e-05 -0.000133375 5.85626e-05 -0.000159125 6.8504e-05 3.73375e-05 -3.85647e-05 -2.0706e-05 -2.61765e-05 8.54933e-05 -1.14173e-05 7.21418e-05 -2.35155e-06 -2.78904e-05 4.00651e-05 2.88585e-06 -1.19358e-05 0.000141717 3.12315e-05 0.00013031 2.50998e-05 4.98317e-05 1.61977e-05 -1.65766e-05 -1.39647e-05 -6.98522e-05 -1.694e-05 7.58093e-05 -2.49518e-05 -3.01387e-05 0.000102431 2.76844e-06 -1.02119e-05 1.99909e-05 1.9453e-05 -1.71181e-06 3.88728e-05 -3.56463e-05 -4.19464e-05 8.01814e-05 6.00773e-06 -4.33401e-05 -2.86222e-05 -3.31306e-05 -5.42247e-05 -1.99354e-05 6.38378e-05 3.00224e-05 4.04644e-05 1.71241e-05 -4.48829e-06 -1.29272e-06 -1.55113e-05 7.60788e-05 -3.63177e-05 4.05781e-05 3.53582e-06 -2.91904e-06 1.79579e-05 7.3595e-06 2.50198e-05 6.73802e-06 -1.88059e-05 -3.62788e-05 -5.11856e-06 3.01529e-05 -1.9757e-05 2.28163e-05 1.68138e-05 -7.39101e-06 -4.92619e-05 1.74678e-05 -2.29513e-05 -1.06222e-05 -3.75801e-05 -4.50849e-06 2.76965e-06 2.60617e-05 4.38554e-07 8.34424e-06 -1.93817e-06 -6.08034e-06 9.33222e-06 -3.19241e-06 8.92444e-06 -4.66992e-06 1.06031e-05 2.21411e-05 1.98206e-05 -1.36659e-05 -1.84843e-05 -2.83672e-05 -2.27037e-05 -7.15402e-06 -1.63176e-05 1.11174e-05 4.57244e-06 -1.72573e-05 2.50921e-06 -2.63542e-05 5.09153e-06 1.69539e-05 4.69641e-05 -8.32098e-06 -5.33196e-05 2.91829e-05 1.92338e-05 9.03521e-06 -1.6882e-05 -1.07422e-05 3.1468e-05 -2.68983e-06 -5.79767e-06 -5.9198e-05 -1.09208e-05 2.01354e-05 -1.663e-05 -3.43767e-05 6.22103e-06 -6.57898e-06 -7.00273e-05 2.11196e-05 -6.95915e-06 -4.73339e-06 -2.72954e-06 -3.3893e-05 1.99129e-05 2.59697e-05 1.56401e-05 5.6634e-05 3.08911e-05 -1.56997e-05 2.19922e-05 -1.49149e-06 3.41373e-06 -6.54525e-06 2.35443e-06 -1.91427e-05 3.44605e-05 -2.71064e-05 -7.06711e-06 -2.6773e-06 1.4664e-05 8.99562e-06 4.05318e-05 3.58846e-05 4.30935e-07 2.89089e-05 -4.4636e-06 -2.74712e-06 1.94754e-05 1.15166e-05 -1.22737e-06 8.48813e-06 -4.726e-05 5.00863e-06 7.98797e-05 -1.22464e-05 -0.000180352 4.43415e-05 -0.000105442 3.03143e-05 -2.1461e-05 -0.000159617 5.47154e-05 2.32133e-05 -6.02161e-05 0.000228009 3.07451e-06 5.6607e-06 0.000122251 4.68534e-05 -4.09896e-05 -1.49387e-05 8.98942e-05 -0.000112952 -1.75908e-05 6.6314e-05 -1.27286e-05 7.59224e-05 6.14078e-05 3.08408e-05 -3.74796e-05 4.68773e-05 -1.0582e-05 -1.9722e-05 -1.15434e-06 -0.000137142 -9.83876e-05 9.27816e-05 -3.10709e-05 -8.38307e-05 -3.28775e-05 5.40477e-06 -2.29372e-05 -8.16579e-05 -4.56509e-07 -1.26095e-05 4.90526e-05 4.24426e-05 5.82354e-06 0.000159485 5.88853e-05 0.000117034 -6.39222e-05 5.23693e-05 1.34507e-05 -1.2887e-06 7.62771e-06 -5.74355e-06 5.03278e-05 7.01114e-06 -9.3367e-06 -5.25854e-05 -3.7083e-05 3.92092e-05 -1.77981e-05 -4.16537e-05 1.76773e-05 -5.52874e-06 -0.000112543 3.04805e-05 -1.70205e-06 -1.73938e-05 -5.82288e-05 -1.27381e-05 2.02666e-05 3.84052e-05 1.25299e-05 4.76724e-05 3.99717e-05 -1.76844e-05 2.64004e-05 -4.85078e-06 1.24937e-05 -1.05842e-05 4.42702e-06 -1.90212e-06 5.35502e-05 -2.65037e-05 -9.81187e-06 -5.54112e-06 1.08143e-05 1.37238e-05 2.70075e-05 4.28703e-05 2.55495e-05 1.14614e-05 -1.19224e-05 -3.95966e-05 2.99588e-05 1.87216e-05 3.96016e-05 -6.09755e-06 1.40511e-07 2.93868e-06 1.30816e-05 1.06108e-05 -1.32606e-05 -2.5404e-06 2.30901e-05 4.3657e-06 1.63949e-05 -9.36688e-06 -1.61781e-05 9.90627e-06 1.97879e-06 -1.54668e-05 -1.08231e-05 -3.26268e-06 1.111e-05 8.21089e-07 2.42264e-05 -5.82671e-06 1.06345e-05 -1.4704e-05 1.19426e-05 -6.71094e-06 9.50247e-06 2.26482e-05 1.36737e-05 1.04178e-06 -2.66888e-06 1.29973e-05 1.15014e-06 7.72742e-06 7.37866e-06 -2.15365e-05 -6.15273e-06 9.45672e-06 1.67858e-05 1.62957e-05 -4.46606e-07 -6.02375e-06 2.70618e-05 -1.87339e-06 -1.66511e-05 1.37195e-05 2.2279e-07 6.3021e-06 3.1476e-06 -6.6153e-06 -2.39251e-06 -1.96712e-07 4.70833e-06 -5.39575e-06 -1.25585e-05 6.5786e-06 -9.59742e-06 -2.07444e-05 9.95844e-06 1.80811e-05 1.80218e-05 -2.5435e-06 -9.6097e-06 6.14275e-06 -5.03572e-06 -2.33858e-05 -6.91341e-08 -3.23839e-06 1.30119e-05 -1.06413e-05 2.24376e-06 2.91714e-06 1.68253e-05 -9.93408e-06 1.2525e-05 -5.44264e-06 1.54257e-05 4.45663e-05 8.25523e-06 3.14183e-06 7.27012e-06 6.16337e-06 -2.29728e-05 1.41779e-05 -9.94982e-06 -2.17647e-06 -8.46935e-06 8.94627e-06 9.62482e-07 9.93153e-06 -3.98748e-06 -1.04199e-05 2.70112e-05 -9.04875e-06 -1.51102e-05 3.11198e-06 -1.03575e-05 2.95505e-06 2.60767e-06 1.57603e-07 -5.71512e-06 -1.28029e-06 -9.63117e-05 -2.0497e-05 9.3792e-05 -1.37801e-05 5.08766e-05 9.16527e-05 -6.22516e-05 1.68564e-05 -9.50673e-05 -6.57695e-05 0.000138265 -4.16543e-05 4.86841e-05 0.000170267 1.83646e-05 3.96751e-05 1.27171e-05 2.85717e-05 4.49074e-05 -3.29321e-05 -6.09785e-05 5.83739e-06 -7.47482e-05 2.75748e-05 -9.49698e-05 -0.000242649 -3.5394e-05 8.76341e-06 -6.12939e-05 -6.74256e-05 0.000102712 -5.98561e-05 4.89653e-05 -1.57046e-05 5.84376e-05 8.62003e-06 4.72355e-05 1.51269e-05 7.8553e-06 -1.69456e-05 -9.86866e-05 -1.39578e-05 2.55459e-05 -5.99286e-05 0.000102127 3.88685e-05 -1.8957e-05 -3.34133e-05 -3.35978e-06 3.20172e-06 7.79295e-06 1.557e-06 8.48562e-06 7.35959e-06 -1.83363e-05 -6.15713e-06 2.5617e-05 1.86902e-06 1.52223e-05 -5.03921e-06 -1.41721e-05 1.99585e-05 -1.19018e-06 -3.01314e-05 -7.95458e-06 -8.53289e-06 1.18504e-05 -4.37501e-06 1.81151e-05 1.37387e-06 1.19262e-05 -1.54223e-05 1.30097e-05 -6.19652e-06 1.43389e-05 2.95652e-05 1.17313e-05 3.55679e-06 5.0757e-06 1.41676e-05 -7.49502e-06 8.92932e-06 4.18421e-06 -2.80676e-05 -1.4038e-05 4.49549e-06 1.52421e-05 7.67386e-06 -7.92242e-07 -7.45882e-06 2.99299e-05 4.24251e-06 -2.07161e-05 3.71331e-06 -6.56597e-06 7.08013e-06 5.83329e-06 -8.62536e-06 8.5472e-07 -1.84015e-06 5.23738e-05 2.29427e-05 4.00562e-05 -4.5461e-06 -2.92071e-05 3.71275e-05 6.01334e-06 -2.14337e-05 6.18173e-07 2.41418e-05 -2.47083e-05 2.44461e-05 6.51447e-06 2.82069e-06 -1.10303e-05 4.36708e-06 -2.59983e-06 -3.24915e-06 2.52333e-05 7.38365e-07 -1.98722e-05 -2.66702e-06 3.97406e-06 2.2111e-05 1.3899e-05 1.69354e-05 1.48698e-05 5.12738e-06 -1.44391e-05 1.72616e-05 4.29772e-05 -6.34944e-06 3.45528e-05 7.09403e-06 -9.32851e-06 2.04285e-06 2.89561e-05 -4.65305e-06 6.74172e-06 -6.21593e-06 5.06661e-06 2.41045e-05 1.78046e-06 -1.22402e-06 -4.41063e-06 -5.62827e-06 -1.3171e-06 9.02279e-07 2.80898e-05 8.88516e-06 4.60877e-05 1.80481e-05 3.94917e-05 3.27787e-06 -5.37976e-05 4.08792e-05 9.16635e-06 -2.0336e-05 2.14993e-06 2.88435e-05 -9.22566e-06 3.47382e-05 -1.31909e-06 3.22824e-06 1.34337e-05 2.88501e-05 -1.30349e-06 -5.34511e-06 7.96846e-05 -7.78898e-06 -1.46991e-05 1.16024e-05 -7.41115e-06 3.28134e-05 1.21096e-05 -1.59459e-06 3.71503e-05 5.36416e-07 -3.35672e-05 7.72624e-06 4.54567e-05 -1.30931e-05 1.96795e-05 7.57395e-06 -1.10745e-05 -6.16921e-06 -1.31329e-06 -5.09564e-06 2.85947e-05 -1.06204e-05 -8.30666e-06 1.57127e-05 1.20647e-05 -1.36949e-06 -2.90708e-06 -1.23435e-05 -1.43877e-06 -1.47724e-06 -9.04465e-06 2.96338e-05 -9.44254e-05 -4.27315e-05 5.58222e-06 2.54881e-05 0.000144207 -2.96181e-05 -1.13963e-05 7.54769e-05 -2.8608e-05 1.60482e-05 5.195e-05 -3.12666e-05 5.95581e-05 8.07308e-05 6.84906e-05 7.85842e-07 -2.01351e-05 -3.51586e-05 -2.6644e-05 -2.91829e-05 -2.12477e-05 2.91205e-05 -5.6667e-05 -8.31546e-05 -7.05315e-05 -0.000213535 -8.22271e-05 3.3803e-05 -3.23203e-05 -3.37965e-05 -4.27454e-05 1.25825e-05 -4.10779e-05 8.20185e-05 2.63669e-05 2.29985e-05 -6.13309e-06 -1.24074e-05 2.2908e-05 3.67205e-06 -4.79922e-05 7.26136e-05 -6.635e-05 -4.43019e-05 1.19893e-05 -2.02393e-05 -5.25493e-06 -3.00074e-06 4.20288e-05 -2.81248e-05 6.44532e-05 2.38013e-05 6.36681e-05 -3.99083e-06 -4.3074e-05 6.81487e-05 5.03022e-08 -1.19746e-06 6.13657e-06 1.91162e-05 -9.72863e-06 2.6954e-05 1.6957e-06 2.74059e-05 9.5502e-06 2.99455e-05 -9.52724e-06 8.58034e-06 6.45081e-05 7.54723e-08 -1.45129e-05 -8.32853e-06 -4.48762e-06 4.84461e-05 1.14828e-05 -3.17066e-06 4.05578e-05 7.79767e-06 -2.58471e-05 2.35967e-05 6.37661e-05 -1.94284e-05 4.10989e-05 1.35729e-05 -5.66379e-06 9.30439e-06 1.33522e-05 -1.61092e-05 1.60803e-05 -6.11459e-06 -8.56076e-06 1.54178e-05 1.3566e-05 6.89984e-06 2.1364e-06 -3.41715e-06 -7.27692e-06 -5.75339e-06 2.47404e-05 3.02766e-05 -1.6435e-05 4.92935e-06 4.30034e-06 1.37539e-05 -1.15591e-05 6.62311e-06 3.51069e-06 1.66932e-05 -3.83737e-06 -4.17254e-05 2.17804e-05 3.21115e-05 1.16629e-05 -5.60343e-06 5.11482e-06 2.64857e-06 -1.08454e-05 1.67737e-05 5.91535e-06 -2.6892e-05 3.09182e-05 -1.20414e-05 1.42955e-07 3.39674e-05 8.04925e-06 2.89287e-05 3.03133e-05 -4.33069e-06 -6.09992e-06 -1.06423e-05 3.94079e-06 -9.83901e-06 4.28341e-06 -9.98763e-06 -9.72704e-06 -4.57787e-06 -1.42739e-05 2.59811e-05 2.80897e-05 1.76741e-05 -9.08371e-07 -1.69465e-05 2.11873e-05 3.25983e-05 7.73516e-06 -7.24083e-06 3.33022e-06 1.25644e-05 -2.03079e-05 2.4048e-05 7.49072e-06 3.11345e-06 -6.80413e-06 8.17138e-06 -1.10604e-05 7.68079e-06 -4.78771e-06 3.98797e-05 9.24603e-06 -1.50979e-06 -4.47365e-06 1.52106e-05 9.03028e-06 -1.09399e-05 -1.12924e-05 7.991e-06 -2.61557e-05 1.96453e-05 2.25319e-06 -3.89184e-05 1.13577e-05 -2.22587e-05 -6.31627e-07 1.09746e-05 -1.61786e-06 2.23191e-05 2.62007e-05 -5.64151e-06 -1.24719e-05 1.17796e-05 -4.42513e-06 -4.95189e-06 -5.31182e-07 -1.9894e-05 -2.23525e-05 3.90576e-06 2.8774e-06 2.78774e-05 3.3057e-05 2.76555e-05 1.29141e-05 -1.93019e-05 5.30539e-05 3.19465e-05 1.32904e-05 -4.43046e-06 -3.69581e-06 1.06876e-05 -1.12389e-05 2.29529e-05 3.72381e-05 3.84752e-05 7.60459e-05 -5.50146e-05 -0.000150301 3.62851e-05 -9.67166e-05 8.03477e-05 2.34031e-05 -0.000213838 5.16448e-05 -9.23583e-06 -2.65938e-05 7.45991e-05 -1.26246e-05 -2.70805e-05 6.48936e-05 7.70434e-05 -4.82366e-05 4.39519e-05 0.000127916 -6.60122e-05 9.54234e-06 8.44737e-05 1.75536e-05 0.000142528 9.07197e-05 5.90273e-06 5.62713e-06 4.96246e-05 -4.02564e-06 -2.23988e-05 1.93662e-05 -0.000110358 -5.54461e-05 2.84305e-05 -3.35774e-05 -5.57723e-05 -4.40639e-05 5.14741e-05 -6.8653e-06 -0.000106383 1.56594e-05 5.84908e-05 -2.24833e-05 8.24243e-05 -3.81347e-05 9.90241e-05 -7.03429e-06 0.000120864 -4.97893e-05 -5.35413e-06 2.02674e-05 2.78668e-05 -3.21433e-05 2.5493e-05 7.67935e-07 3.97485e-05 -3.06279e-05 -1.08055e-06 5.42566e-05 1.8379e-05 1.78681e-06 0.000114111 3.17906e-05 2.00011e-05 -8.08493e-06 1.02615e-05 4.68447e-05 -9.37544e-05 6.54466e-05 -3.72265e-05 -1.96486e-05 -1.14444e-05 -1.7354e-05 -3.3423e-05 3.75303e-05 7.9539e-06 -3.93121e-05 2.44273e-05 1.25879e-05 -7.88313e-06 4.47212e-06 -3.79434e-05 -4.76196e-05 4.20988e-05 -3.0369e-05 6.09982e-05 2.47497e-05 -2.38682e-05 -1.86354e-05 -4.35425e-05 -1.83138e-05 3.65355e-05 4.97735e-05 2.16715e-05 2.42944e-06 4.88959e-06 -4.44766e-05 6.05764e-05 1.2063e-05 3.16268e-06 2.57533e-05 6.55784e-06 -3.19104e-06 1.17636e-05 6.89501e-06 -1.54998e-05 1.73239e-05 -2.90511e-05 1.12928e-05 6.2106e-06 1.39756e-06 9.8355e-07 -1.95428e-05 -2.10572e-05 4.16913e-06 6.10404e-06 1.75236e-05 1.4303e-05 2.60259e-05 2.89666e-06 6.18681e-06 1.73728e-05 7.8476e-06 1.07716e-05 2.11295e-05 -4.01035e-06 1.04205e-06 -7.93158e-06 5.72164e-06 -4.39117e-06 1.09755e-05 -2.27771e-05 2.98849e-06 6.13055e-06 1.13626e-05 1.52518e-05 -7.2379e-06 -2.56089e-06 1.43304e-05 -1.51948e-05 -1.79281e-05 9.54539e-06 8.64111e-06 1.17235e-05 2.12374e-06 5.78295e-06 -1.02692e-06 9.3463e-06 4.17238e-06 -1.14689e-05 -9.00549e-06 1.49129e-05 -2.61841e-06 -2.52013e-05 2.35012e-05 3.90699e-06 2.95524e-05 -4.44447e-05 1.35724e-05 1.99932e-05 -2.80165e-06 -1.3183e-05 5.46276e-06 -2.06579e-05 1.37406e-05 7.11149e-06 -1.03173e-06 1.31435e-05 3.10751e-05 -2.89046e-06 1.46178e-05 4.94289e-06 1.40053e-05 5.66771e-05 1.43279e-05 1.50943e-07 -1.90995e-06 -1.83515e-05 -1.54386e-05 -4.08714e-06 -1.62531e-05 -1.68513e-05 -1.1457e-05 -6.06614e-06 -1.12552e-05 2.50641e-05 2.78694e-06 -6.22318e-06 1.73889e-05 -6.24311e-06 -5.41641e-05 2.42783e-05 -9.20712e-06 -5.20103e-06 -1.95706e-06 1.49333e-05 -2.47459e-05 1.81703e-05 3.21857e-05 2.62286e-05 -3.93337e-05 -1.70433e-05 -2.36944e-05 3.73243e-05 -5.41202e-05 -4.83097e-05 1.11355e-05 -0.000106527 -4.90234e-05 4.32268e-05 -5.86432e-05 -7.57767e-05 -8.66746e-05 -6.09102e-06 2.84515e-05 0.000107214 2.96535e-05 5.35051e-05 3.92774e-05 -2.65762e-05 7.79242e-05 0.000109075 4.37251e-05 0.000280698 7.52003e-05 -3.97717e-05 2.22814e-05 1.42911e-05 0.000116508 -1.37339e-05 5.96691e-05 -9.53356e-06 -1.93752e-05 7.62164e-06 0.000128907 -8.71196e-05 -8.83106e-05 1.84068e-05 -2.56971e-05 -2.58098e-05 0.000111471 1.93047e-05 -3.99134e-06 1.84479e-05 1.36655e-05 3.28652e-05 7.93418e-06 -9.16947e-06 2.39903e-05 2.96002e-06 3.46658e-05 -1.29125e-05 -4.0932e-05 4.62901e-05 2.95269e-06 -1.59531e-05 1.60176e-05 -4.31834e-05 1.87433e-05 2.58211e-05 -1.07689e-05 -4.0308e-06 -2.6308e-05 -2.46649e-05 1.27233e-05 1.99744e-05 2.32131e-05 1.06815e-06 2.97985e-05 -9.80795e-06 1.52691e-05 6.31084e-05 2.19417e-05 6.65188e-05 2.01457e-05 -2.16741e-05 6.06434e-06 6.89878e-06 4.36456e-05 -3.04101e-05 3.82668e-05 -1.68511e-05 -2.15819e-05 -6.4215e-06 1.5749e-05 -3.19493e-06 2.33125e-07 -2.05071e-05 1.69409e-05 -2.17558e-05 -2.16497e-05 6.51027e-06 1.56173e-06 3.56789e-05 1.28958e-06 1.04866e-05 -9.51259e-06 1.82309e-05 -5.46031e-06 -9.31966e-06 3.84567e-05 2.89318e-05 3.98963e-05 -3.43111e-06 -1.35437e-05 -3.18122e-05 -9.17343e-06 1.79402e-05 -3.47103e-05 1.36189e-05 -2.03394e-06 -1.30201e-05 -9.21574e-06 1.54973e-06 -2.74255e-05 -6.73399e-06 -4.32614e-06 -3.0227e-05 -6.90619e-06 -3.6254e-05 6.24229e-06 -5.67229e-07 1.2344e-05 3.90379e-05 -1.67347e-05 4.26303e-06 5.6019e-06 -3.16021e-05 1.44414e-05 -5.07404e-06 9.74556e-06 7.45145e-05 -5.86114e-06 1.34932e-05 1.09961e-05 1.02402e-05 1.63681e-05 -1.44906e-05 -9.76324e-06 -6.48236e-06 -1.17976e-05 -2.65137e-05 -7.08475e-06 -2.12173e-05 -2.47871e-06 1.20463e-07 2.25185e-05 -2.36292e-06 1.98697e-05 -1.4524e-05 8.89202e-06 1.47854e-05 2.72475e-05 2.93715e-05 -1.06123e-05 -9.09279e-07 -1.23239e-05 9.30041e-06 -1.51194e-05 -1.66891e-05 -2.14019e-06 4.85659e-05 -1.70348e-05 4.52682e-05 -2.80495e-05 -5.71485e-06 -3.00726e-05 -3.96294e-05 -2.33098e-05 -0.000108661 -2.02582e-05 -3.63353e-07 -1.29742e-05 -3.31488e-05 -9.64843e-06 2.69708e-06 -2.06404e-05 -1.96537e-05 6.30456e-06 -1.45188e-05 1.91479e-05 7.64866e-05 -4.52166e-07 1.0222e-05 -3.32159e-06 -9.2581e-06 2.40431e-06 -3.91011e-05 -1.81674e-05 -1.25716e-05 -1.02937e-05 -1.16252e-06 2.02425e-05 -1.33356e-05 -2.14893e-05 -4.46831e-05 1.89283e-05 8.85737e-06 -7.94949e-06 4.52071e-05 0.000119409 -1.73034e-05 -7.19848e-05 3.5193e-05 -0.000137945 0.000111826 -3.09164e-05 -0.000234168 7.10289e-05 -4.76558e-05 -3.52233e-05 0.000258843 7.82458e-05 6.30516e-05 0.000112259 7.00171e-06 -0.000114235 8.77385e-06 0.000156035 -7.86121e-05 -7.42846e-05 8.86594e-05 -3.57039e-05 -4.07877e-05 -3.45735e-05 1.74365e-05 -6.88193e-05 1.64156e-05 -4.25171e-05 -2.05579e-05 -3.24435e-05 8.83369e-05 -5.9419e-05 2.27321e-05 -0.000101169 -1.29934e-05 1.25594e-05 -2.96895e-05 -8.34287e-05 -0.00010116 -8.45827e-05 -1.39767e-05 1.14596e-05 8.48149e-05 -4.06802e-05 0.00011166 -3.33873e-05 0.000115374 1.06846e-05 -2.05317e-05 8.02951e-06 2.94895e-05 5.48862e-05 6.93425e-06 8.85085e-06 -3.83289e-05 -9.60311e-06 1.23876e-05 -3.03159e-05 4.61027e-06 -4.90378e-06 1.95503e-05 -1.59415e-05 2.61953e-05 -3.99008e-05 -1.14378e-05 -1.65974e-06 -4.63651e-05 -1.84076e-05 -9.95713e-05 -2.39341e-06 3.11017e-06 -1.16825e-06 1.78451e-05 -2.51366e-05 2.77448e-06 -2.07991e-05 -1.9187e-05 1.55057e-05 -1.17286e-05 1.40564e-05 8.96083e-05 -8.61419e-06 1.76134e-05 6.2387e-06 -3.21068e-06 1.19115e-05 -3.06531e-05 -1.85962e-05 -1.33185e-06 -3.2268e-05 -2.2839e-05 1.00425e-05 -2.20615e-05 -1.94596e-05 -2.2815e-05 2.97801e-05 -5.20724e-06 1.2359e-05 -1.28739e-05 3.6263e-05 -1.45765e-06 -7.36593e-05 -2.25891e-05 -5.41071e-05 4.46765e-05 6.25157e-05 9.91196e-06 2.19749e-06 -6.19224e-05 4.75223e-05 -9.53858e-05 3.01461e-06 2.55993e-06 9.18505e-06 1.10404e-05 6.33019e-05 3.55967e-06 5.30735e-05 1.02367e-05 -1.48958e-05 5.46e-05 -9.31522e-06 9.80013e-05 3.45148e-05 1.15977e-05 -1.2497e-06 -0.000105086 -4.17137e-05 -2.87266e-05 -1.15597e-05 -3.67217e-05 -3.77358e-05 -1.60771e-05 -5.026e-05 6.02637e-05 4.28027e-05 1.17828e-05 5.94127e-05 -6.30617e-05 4.12826e-05 -4.89978e-05 -4.39177e-05 -4.43635e-06 1.70303e-05 -5.23041e-05 -2.14142e-05 4.34467e-05 3.3143e-05 -2.15702e-05 -7.8414e-06 3.53647e-05 -4.46125e-05 -5.74254e-05 -3.21027e-05 3.10817e-05 6.21708e-05 -1.88062e-05 -5.54824e-05 -2.25518e-05 1.29429e-05 -0.00021557 -3.25724e-05 -3.683e-05 4.48974e-05 -3.70634e-06 4.36498e-05 1.64035e-05 4.70241e-05 4.86072e-05 1.51143e-05 6.92942e-06 1.38156e-05 0.000133632 4.29187e-05 2.20211e-06 3.19577e-05 -0.000142491 -6.81787e-05 -3.2664e-05 -2.09196e-05 -9.26782e-05 -3.38052e-06 -8.20016e-05 -2.21184e-05 0.000106436 6.33587e-05 3.25115e-05 0.00015546 -1.77944e-05 2.55872e-05 4.7696e-06 -7.82506e-05 -3.38192e-05 8.47933e-07 -5.49525e-05 -5.96523e-05 1.17754e-05 2.10196e-05 -9.38675e-06 7.95415e-06 -6.38086e-05 -3.15521e-05 -6.16162e-05 -0.000146164 -1.64853e-05 4.74403e-05 -0.000200701 -6.18774e-05 -5.6489e-05 -7.60248e-05 -8.51885e-05 -3.65951e-05 -5.90727e-05 0.000164733 -4.04293e-05 -0.000123822 0.000102447 0.000113648 0.000114526 2.16261e-05 5.33799e-05 3.53274e-05 0.000178268 -2.045e-05 5.29135e-05 6.74327e-06 -9.15339e-05 -7.09505e-05 -6.2638e-05 -2.51672e-05 -1.27829e-05 -2.87945e-05 -0.000124667 -9.93527e-05 6.76354e-05 5.93194e-06 7.60412e-05 8.10934e-05 -0.000113712 -5.48141e-05 4.92242e-06 -9.36806e-05 -4.46958e-05 -5.34659e-05 8.93311e-05 8.32186e-06 3.02925e-05 -6.96273e-05 8.65391e-06 0.000153453 -5.08553e-05 -9.42547e-05 -9.94001e-07 -0.000414283 0.000239748 -6.70426e-06 -0.000104646 0.00030311 2.39897e-06 5.22452e-05 0.000908309 0.000196152 5.86327e-05 -4.60483e-06 9.00759e-05 -0.000293405 -5.81151e-05 0.000207071 -0.000104196 -0.000219711 0.000269395 -0.0001602 -0.000132468 -0.000215781 0.000150408 -0.000121024 9.77945e-05 -0.000164367 5.91754e-05 -8.91332e-05 0.000126556 -0.000306473 0.000267695 -0.00040919 -0.000302526 -0.00018857 -0.000125584 -0.000532802 -0.000307615 -4.87859e-05 -0.000218432 0.000118858 5.41863e-05 -1.06289e-05 0.000325373 0.000176299 0.000137226 2.74079e-05 5.2491e-06 7.23337e-06 6.03697e-06 -4.95555e-05 1.19614e-05 -2.9219e-05 -3.44312e-05 -1.24401e-05 -1.49306e-05 6.61263e-06 2.3893e-05 -6.42903e-06 1.88048e-05 -1.39317e-05 5.12668e-06 2.08212e-05 -8.65223e-06 2.71693e-05 -1.02441e-05 5.272e-05 -1.44194e-05 7.67366e-06 5.58338e-05 -9.75115e-07 3.44681e-05 1.28416e-05 -1.22672e-05 2.73347e-06 3.75121e-05 1.6967e-05 -7.29779e-06 2.44477e-05 -3.67486e-05 -2.00495e-05 1.99218e-06 4.62436e-06 9.55466e-06 5.5078e-07 -2.319e-05 9.95325e-06 -5.6003e-07 -8.2523e-06 2.10567e-06 1.38304e-05 2.98317e-05 4.67771e-06 1.52675e-05 -3.45158e-05 2.1577e-05 2.79519e-05 1.49483e-05 2.8083e-06 1.23009e-05 -3.43535e-05 6.22377e-06 -2.90534e-05 -7.9332e-06 9.04726e-06 1.09139e-05 -2.58329e-05 2.60559e-05 -1.72809e-05 1.54108e-06 -7.33986e-06 -5.53658e-06 -1.18853e-06 1.21414e-05 1.89593e-05 3.36487e-06 6.46827e-05 -3.35922e-05 7.80982e-06 8.88532e-05 2.63036e-06 4.41262e-05 6.02464e-06 -2.34325e-05 -7.09778e-06 3.36367e-05 -1.64182e-06 -1.29288e-05 1.55651e-05 3.02917e-06 -2.30463e-05 2.08167e-05 1.99462e-06 4.10184e-06 1.40465e-05 -3.77306e-06 4.93558e-06 9.95525e-06 -2.35769e-06 -2.73529e-06 -1.65914e-06 1.45018e-05 5.62699e-06 3.20738e-05 7.04811e-06 2.35558e-05 -9.77469e-05 3.6926e-06 -7.59744e-05 -3.09923e-05 0.000205643 -6.82179e-05 6.98722e-05 -0.000136158 5.08476e-06 -0.000173315 -0.00012148 0.000105198 -2.45522e-05 -0.000275525 -1.08175e-05 -8.4789e-05 -0.000108468 4.06333e-05 -2.10163e-06 -7.77821e-07 -0.000226302 2.0734e-05 0.000129061 -4.75823e-05 4.78163e-05 0.000239469 5.00764e-05 -0.000120069 7.11293e-05 -8.35756e-05 7.59592e-05 -2.79286e-05 2.6898e-05 0.000153598 0.000176198 2.03646e-05 0.000104844 -0.000121054 -7.74619e-05 5.39444e-05 -2.10775e-05 8.20833e-05 8.84815e-05 -5.88015e-05 -4.3156e-05 -0.000123068 1.72854e-05 -7.9772e-06 0.000155408 -0.000115193 5.81976e-05 3.32351e-05 1.8093e-05 9.34247e-06 -4.61464e-05 4.53306e-05 -1.98506e-05 -2.54768e-05 2.46589e-06 -3.09316e-06 -1.69884e-05 5.72524e-05 -9.54789e-06 1.30627e-05 -1.93705e-05 5.45278e-06 2.53806e-06 7.27093e-06 3.51205e-05 -7.1478e-06 3.77752e-05 -2.64516e-05 6.68698e-06 8.93206e-05 1.54747e-07 3.01646e-05 1.76127e-05 -1.16204e-05 -1.01444e-05 4.87592e-05 2.91515e-05 -1.08686e-05 3.71405e-05 -2.45559e-05 -3.9595e-05 2.0134e-05 1.27287e-05 -1.50158e-05 1.05576e-05 -1.71176e-05 3.55644e-06 8.38751e-06 2.3053e-06 -5.26371e-06 1.08413e-05 1.96945e-05 7.06838e-06 3.97141e-05 1.72498e-05 3.06995e-05 5.23741e-05 -2.10732e-05 -2.49516e-06 1.44569e-05 5.25931e-06 -2.74433e-05 4.26781e-06 5.01403e-05 2.49023e-05 -1.10242e-05 -2.93776e-05 -2.10056e-05 -2.50195e-05 -0.000150864 -1.32722e-05 -1.23306e-05 2.70977e-05 -1.7354e-05 2.64625e-05 2.33312e-05 9.63594e-06 4.59503e-06 2.68517e-05 -1.42022e-05 7.8454e-06 5.78814e-05 6.66e-05 -8.18724e-06 5.17655e-05 -3.97829e-05 -4.73307e-05 -4.2981e-05 -1.37453e-05 -3.38119e-05 4.31378e-05 -5.50973e-05 8.11279e-06 0.000109861 1.40521e-05 1.72278e-05 0.000122218 -2.07683e-05 1.34467e-05 3.21908e-05 -3.60851e-05 7.91713e-06 8.85934e-06 -2.33196e-05 -3.76779e-05 -4.09417e-06 4.31554e-05 -9.58515e-06 -4.83176e-05 1.94e-06 1.34684e-05 -7.00435e-05 -1.79809e-05 0.000110163 6.08517e-05 -2.05203e-05 -2.82082e-05 -1.18509e-05 -2.73762e-05 -0.000128447 -7.70548e-06 -1.95691e-05 -1.47526e-06 2.77083e-05 -7.04279e-05 2.49674e-05 5.20595e-06 4.13891e-06 1.68872e-05 -2.89735e-06 6.1346e-06 8.13103e-05 3.71039e-05 -5.40029e-06 6.85848e-05 -8.38355e-06 -9.79436e-05 -2.49467e-05 -4.52974e-05 -2.67441e-05 2.50243e-05 -6.14435e-05 -3.68443e-05 3.91586e-05 -6.62193e-06 1.50138e-05 9.37839e-05 -1.72286e-05 2.76463e-06 3.13261e-05 -7.22835e-05 1.79751e-05 1.22917e-06 1.87524e-05 -3.35712e-05 -5.20853e-07 7.19834e-05 2.82068e-05 7.98674e-05 -6.17831e-05 -7.95561e-05 0.000115152 -5.08746e-05 -8.53775e-05 1.99605e-05 -9.83236e-05 -6.87032e-06 -3.61151e-05 1.23389e-05 2.04161e-05 -6.82355e-05 2.69236e-05 5.79136e-05 5.23536e-05 -3.22592e-06 1.55304e-05 2.02145e-05 -2.80378e-05 1.33276e-05 0.000207967 4.03103e-05 0.000145987 1.38808e-05 2.00491e-05 -5.75716e-05 -1.57303e-05 0.000144446 -4.11823e-05 0.000101055 3.3349e-05 -1.72796e-05 -4.03464e-05 4.25322e-05 -1.2333e-05 1.94449e-05 -9.0236e-06 2.81173e-05 -8.81521e-05 5.97606e-05 -1.13167e-05 1.2091e-05 3.15892e-05 -1.78714e-05 -2.10453e-05 -1.3438e-05 5.42227e-05 3.0258e-05 1.88607e-05 5.40192e-05 -1.20399e-05 -0.000111084 5.88277e-05 -0.000161111 0.000214885 1.92094e-05 -2.2146e-06 7.83201e-05 -2.80909e-05 -3.08519e-05 0.000295508 6.64421e-05 3.35855e-05 5.61868e-05 2.58183e-05 -4.82706e-05 -2.93216e-05 0.000142099 -4.80631e-05 -7.68098e-05 4.79254e-05 -6.95835e-05 -0.000118332 3.22607e-05 2.93009e-05 -8.10082e-06 0.000119313 -8.95149e-05 -1.0423e-05 -1.95781e-05 -7.12065e-05 -0.000134878 0.000102266 -0.000131021 -3.28682e-05 -4.46095e-05 -5.63202e-05 -0.000105903 -0.000124172 -1.26513e-05 -2.99259e-05 5.01639e-05 7.47964e-05 2.05245e-05 0.000113992 1.65541e-05 9.65546e-05 0.000149545 0.000123178 0.000210142 -5.71518e-05 -0.000237576 0.000373842 -2.37417e-05 7.695e-05 -9.57149e-06 0.000176132 -3.40539e-05 9.30696e-05 -8.63867e-06 0.000217691 -8.41297e-05 -1.19744e-05 0.000107848 -2.99524e-05 0.000130543 1.62519e-05 0.000150354 -0.000161815 -1.05777e-05 0.000167817 6.88754e-05 -0.000192703 6.66214e-06 3.56378e-06 -1.02448e-05 0.000464756 0.000174291 5.97952e-06 0.000246133 -0.000193386 -0.000243177 0.00016083 0.000212147 -0.000184893 -3.85201e-05 -3.33265e-05 7.46037e-05 0.00011472 -6.67228e-05 6.05591e-05 8.16873e-05 0.000279017 8.04839e-05 0.000168656 0.000136297 8.85549e-05 4.74567e-05 -5.87126e-05 0.000289146 -3.83189e-05 -0.000405583 0.000487239 -0.000529979 0.000308481 -3.58688e-05 -0.000394531 0.000412025 -4.23074e-05 4.80058e-06 0.00101561 5.7959e-05 0.000106479 0.000242854 0.000293943 8.90724e-05 -8.96073e-05 0.000541178 -0.000191221 -0.000137515 0.000327364 -0.000164154 -0.000133788 0.000101122 0.000115705 -7.13192e-05 0.000287575 0.00019169 -0.00016536 0.000187232 -0.00029929 -0.000447881 0.000388703 -2.06545e-06 -0.000276002 -0.000301982 -0.000268932 -0.000378114 -0.000407679 1.49204e-05 -3.00228e-05 0.000282972 0.000441508 -7.10704e-05 0.000207468 1.69634e-05 0.000339928 0.000308414 8.15941e-05 0.000184488 -4.87077e-05 -0.000223328 0.000275496 -0.000165112 9.70424e-05 -2.3284e-05 -5.99753e-05 6.2702e-05 -3.7379e-05 -5.73884e-05 0.000366806 -0.000200112 6.05738e-05 0.000213583 0.000189098 5.85288e-05 2.54686e-05 0.000112418 -0.000127647 -9.0016e-05 0.000463739 -3.60479e-05 -8.47989e-05 0.000184921 -0.000106252 -5.49974e-05 0.000141765 0.00017885 -0.000115209 0.000151081 -0.00014171 -0.000105767 7.86447e-05 0.00010189 -0.000154762 -5.30353e-05 -1.61196e-06 -4.3168e-05 -3.65757e-05 5.73357e-05 -7.35515e-05 7.07818e-05 0.000113617 -2.90726e-05 0.000153539 6.33857e-05 7.5961e-05 -6.08849e-05 4.22292e-05 0.000159931 -4.8155e-05 -0.000208667 0.00017606 -0.00031742 0.000228687 -1.80182e-05 -0.000278408 0.000305149 -0.000112141 1.86328e-05 0.000804286 6.07128e-05 0.000100519 0.000125608 0.000178916 -8.03725e-05 -8.49662e-05 0.000186588 -7.22167e-05 -0.000189362 0.000261919 -0.000173103 -0.000254103 -1.22697e-05 2.89666e-05 -0.000177521 -1.69446e-05 -1.57e-05 -4.94268e-05 4.65046e-06 -4.92632e-05 -0.000257339 0.000150924 -0.000202673 -0.00015902 -0.000115913 -0.000138994 -0.000318693 -0.000284442 7.97747e-05 -8.3241e-05 0.000181076 0.000144202 -2.36395e-05 0.000181441 1.63399e-05 0.000186412 -1.18727e-05 -4.50063e-05 -1.32383e-05 4.59183e-05 -0.000150695 -5.95323e-05 -3.94399e-05 4.70414e-05 2.53136e-05 -3.57075e-05 6.35889e-05 -8.36813e-06 -1.28013e-05 0.000146633 7.5844e-06 -2.72175e-05 0.000121894 -3.46029e-05 5.87101e-05 -4.04095e-05 0.000109061 -2.45925e-05 -6.06285e-06 6.5323e-05 1.81864e-05 4.85618e-05 -5.45312e-05 2.62856e-05 -4.2711e-05 -7.05857e-06 -1.55592e-05 4.94598e-05 -6.59845e-05 -3.74292e-05 -0.000123752 2.46409e-05 -0.000112665 3.88892e-05 -2.4458e-05 -5.53329e-05 2.32677e-05 -6.98833e-05 -3.46969e-05 5.52928e-05 6.78804e-05 0.000107454 2.86139e-05 6.14778e-05 -6.60376e-05 7.29521e-05 -3.23887e-05 -1.08176e-05 -1.88525e-06 -6.08849e-05 -0.000153453 -1.37912e-05 -1.96137e-05 -3.5357e-05 -2.1052e-05 -2.49795e-05 -1.60653e-05 -2.97656e-05 -9.46857e-06 4.88885e-06 -7.18335e-05 -5.10022e-05 0.000129047 -4.30006e-05 -7.5628e-06 3.61682e-05 9.1471e-05 -3.26718e-05 1.38183e-05 2.19314e-05 3.13616e-05 5.24262e-05 -0.000127247 8.78369e-06 9.05467e-07 4.66047e-05 -3.58246e-05 1.82589e-05 -1.65002e-05 -1.43221e-05 -9.63079e-05 1.18503e-05 -2.55323e-05 -2.17091e-05 1.34957e-05 4.6329e-05 5.5346e-05 1.68713e-07 -4.20727e-05 6.68876e-05 8.82496e-06 8.8543e-05 3.03062e-05 6.84476e-05 4.35416e-06 1.19827e-05 4.45673e-05 3.67298e-05 0.000123203 -0.000105976 -0.000183328 0.000126103 -0.00019713 0.000125102 4.56937e-05 -0.000144745 0.000104845 1.78184e-05 -2.53821e-06 0.00023253 2.09186e-05 1.65426e-05 9.24111e-05 8.56081e-05 -9.50708e-05 7.50411e-05 0.000199879 -0.000121031 -9.75776e-06 0.000229003 -1.91738e-05 0.000164477 0.000120233 5.92654e-05 4.60638e-05 0.000145652 -1.73907e-05 -3.78503e-05 5.91092e-05 -0.000195807 -0.000148295 0.000157079 -2.11605e-05 -0.000138854 -5.07278e-05 7.32478e-06 -9.99346e-05 -0.000128409 -2.11179e-05 3.62509e-05 1.76362e-05 0.000161346 -3.60888e-05 0.000154016 4.63279e-05 0.000147819 -6.83408e-05 -8.09774e-06 -6.43629e-06 -3.28884e-05 -0.000157508 -2.75299e-05 -2.13867e-05 -1.72826e-05 -8.35434e-06 -8.75702e-05 4.76922e-05 -2.683e-05 -3.29352e-05 0.000104886 -3.79081e-05 -8.45583e-05 0.000125276 -1.86964e-05 -4.90379e-05 1.10308e-05 0.000120033 -4.12475e-05 -1.70949e-05 7.52361e-05 1.66296e-05 3.30667e-05 -0.000133285 2.36711e-05 -2.16258e-05 3.93205e-05 -2.19082e-05 1.73454e-05 -4.5686e-05 -6.23169e-06 -0.000115794 1.90251e-05 -7.42312e-05 -3.41356e-06 2.93813e-06 -7.21113e-06 6.17049e-06 -4.35635e-05 -5.37839e-05 1.81469e-05 9.13956e-06 6.89723e-05 3.19352e-05 0.000110895 1.37278e-05 1.90356e-05 3.2511e-05 -1.18127e-05 4.88987e-05 1.8796e-05 4.31584e-05 4.45493e-06 4.97113e-06 4.06208e-05 -3.22696e-05 1.20964e-05 2.48781e-05 1.66859e-07 -2.55833e-05 0.00010645 3.02488e-05 3.51536e-05 -8.52674e-05 -5.41286e-05 8.5163e-05 -1.4489e-05 -3.33851e-05 7.38572e-05 -1.70445e-05 -2.57357e-05 1.72023e-05 -4.41416e-05 4.0305e-05 9.59521e-05 -2.12194e-07 -6.68911e-05 -8.38142e-05 -2.25814e-05 -5.25987e-05 3.98323e-05 -5.09606e-05 1.98299e-05 -2.02573e-05 4.6759e-05 2.99141e-05 3.27989e-05 -8.36657e-07 -2.34989e-05 -4.99916e-05 2.05913e-05 1.06604e-05 9.73946e-05 1.88488e-05 1.57152e-05 -5.29779e-05 5.75507e-05 7.65559e-06 7.97001e-06 1.92368e-05 4.11076e-06 -3.30742e-05 4.95729e-06 -1.16749e-05 1.45985e-05 -5.32758e-07 4.23059e-05 2.19505e-05 -1.34972e-05 4.28002e-06 5.82922e-05 7.0775e-06 -1.01072e-05 3.13051e-05 -9.68795e-06 1.60257e-05 -1.31289e-05 -7.12297e-07 3.23504e-05 -1.26747e-05 3.72696e-05 -6.76613e-06 -6.60023e-06 1.91151e-07 2.57493e-05 -3.02527e-05 -4.74968e-05 -1.81607e-05 9.23048e-06 -3.77973e-05 3.42112e-05 -4.98822e-05 1.19408e-05 -5.31116e-05 -8.15189e-06 3.81122e-05 -7.5883e-06 -1.22893e-05 -1.0137e-06 9.49807e-06 -1.75336e-05 1.51798e-05 -5.2446e-06 1.52774e-05 1.93832e-05 6.24931e-06 2.04302e-05 5.64479e-05 -6.54584e-05 -4.57329e-05 4.57968e-05 5.8739e-05 -0.000227089 0.000177841 -1.20835e-05 6.88347e-05 0.000165544 -0.000142745 2.16421e-05 -9.92355e-05 -0.000229905 -9.72533e-05 -1.20359e-05 1.89443e-05 -0.00010391 0.000108796 2.05224e-05 -0.000147978 0.000144777 0.000137946 2.18665e-05 0.000181734 0.000159516 0.000109423 -0.000484685 1.19145e-05 -0.000281948 -3.85824e-05 -1.00523e-05 -0.000170716 0.00020526 -1.42402e-05 -3.62215e-05 5.44692e-05 -3.32728e-05 8.9729e-05 0.000123472 6.59194e-05 0.000133138 3.93353e-05 -4.43916e-05 -0.000129596 -5.74626e-05 0.000255896 3.80629e-05 -3.25094e-05 -6.4992e-05 -7.5777e-05 5.45523e-05 4.53965e-05 -4.74374e-05 -0.000132437 0.000136148 -0.000107113 5.92866e-05 1.75649e-05 -5.58939e-05 0.000149933 -5.35423e-06 4.38909e-05 0.000372635 3.95043e-05 5.10038e-05 7.16516e-05 0.000111563 -5.35187e-05 -3.71259e-05 8.56363e-05 -5.04429e-05 -9.79477e-05 2.58929e-05 -8.00305e-05 -0.000172718 -9.84076e-05 0.00015469 -0.000110711 2.73397e-05 4.26243e-05 4.49549e-05 5.98641e-05 -3.0086e-05 -0.000150853 9.49735e-05 -7.31932e-05 -0.000124056 -7.46206e-05 -1.82314e-05 -0.000195467 -0.000118268 4.74059e-05 -4.99923e-05 0.000102767 5.55236e-05 -5.15087e-05 3.34794e-05 3.56491e-05 6.69822e-05 4.18684e-05 5.39782e-05 -1.80363e-05 5.10421e-05 -1.15356e-05 -1.29667e-06 5.34718e-05 3.05692e-05 0.000104281 1.73644e-06 -2.59148e-05 6.41102e-05 3.54336e-05 4.61311e-05 2.63371e-05 1.10495e-05 -3.50161e-05 4.49198e-05 5.84151e-05 -2.75461e-05 -7.16273e-05 -2.46705e-05 3.30047e-06 6.7371e-05 2.95783e-05 5.17788e-05 4.16618e-05 2.77329e-05 -6.98285e-05 -4.00057e-05 3.2701e-05 2.64626e-05 -1.52126e-05 -2.95573e-06 -2.33745e-05 -3.30455e-07 -1.2734e-05 5.36449e-05 1.76858e-05 -7.56693e-06 2.4696e-05 -1.69089e-05 1.57827e-05 5.61473e-05 5.03828e-06 -2.83964e-05 1.47509e-05 -2.35038e-05 -4.25604e-05 6.13175e-05 2.34461e-05 4.96215e-05 -1.09567e-05 -3.52918e-05 -4.4671e-05 1.99182e-05 -1.22898e-05 2.89061e-05 4.78975e-05 1.98945e-05 -1.87747e-05 4.42076e-05 -3.25895e-06 9.86093e-05 1.04269e-05 -5.2709e-06 -7.98209e-06 3.17008e-05 -2.71268e-06 -8.89626e-06 -5.08401e-06 -2.21482e-05 -1.10945e-05 8.233e-05 2.32167e-05 5.02573e-05 1.50116e-05 3.01708e-05 -3.78677e-05 1.85566e-05 -8.9498e-06 5.9028e-06 -2.21539e-05 1.72928e-05 -0.000101746 3.42282e-05 -7.08081e-05 -1.22862e-05 4.89565e-06 8.22152e-06 -2.5305e-05 -2.20154e-05 7.74875e-06 -1.65378e-05 -5.03617e-06 -1.08733e-05 5.79486e-06 3.08272e-05 1.45915e-05 4.82554e-05 8.87941e-05 4.16093e-05 -4.36936e-05 -4.63524e-05 -0.000164262 6.17676e-05 -0.000114955 4.75515e-05 7.43762e-05 -0.000118141 2.45128e-06 -2.06326e-05 -6.1173e-05 4.19797e-05 1.88146e-05 1.8336e-06 9.48203e-05 8.15405e-05 -6.85581e-05 5.23745e-05 0.000136106 -7.19732e-05 3.17321e-05 0.000116518 2.59383e-05 0.000229138 0.000125191 1.51521e-06 3.69452e-05 0.000100384 4.14542e-07 -5.80938e-05 9.99005e-05 -9.54967e-06 -3.02356e-05 1.37224e-05 -3.08289e-05 1.09112e-05 -3.66039e-05 -4.52834e-05 3.74264e-06 -0.000103117 0.000130262 8.78739e-05 3.33981e-06 -9.28725e-07 -3.29515e-05 2.36037e-05 -2.86707e-05 8.13425e-05 2.822e-05 2.81819e-05 3.13988e-05 3.41684e-05 -7.98744e-05 7.60606e-06 -4.90646e-05 8.51598e-05 8.59014e-05 1.16447e-06 5.57946e-06 3.73136e-05 -2.66042e-06 0.000227405 2.55205e-05 1.32721e-05 6.69367e-05 2.61803e-05 -9.84186e-06 -4.22571e-05 6.69322e-05 -5.18631e-05 -3.86576e-05 0.000102035 7.68932e-06 4.88248e-05 -2.28807e-05 6.21881e-05 -7.41015e-05 3.38387e-05 -5.47902e-05 3.47761e-05 -5.99132e-05 -1.97624e-05 -0.000190806 6.87449e-05 -0.000122418 -1.45137e-05 5.49491e-06 -2.80096e-05 -6.42466e-05 -0.00011061 -3.22999e-06 5.14803e-06 3.69375e-05 2.20557e-08 8.37023e-06 6.52009e-05 -3.13807e-05 8.53695e-05 3.90179e-05 -1.88571e-05 1.88458e-06 7.58577e-06 3.62047e-05 -1.87869e-05 3.83374e-05 -1.41278e-05 1.53798e-05 4.12608e-05 -3.08201e-05 3.74509e-06 -5.82935e-06 -5.13461e-05 -6.33205e-07 -8.51335e-06 5.38369e-06 -1.7802e-05 2.69636e-05 9.37872e-06 -2.39759e-05 1.60953e-06 1.70778e-05 -1.63352e-05 4.99362e-06 2.70494e-05 5.10529e-05 -9.75259e-06 1.84476e-05 3.56143e-05 -9.83091e-06 -9.51433e-06 5.16385e-06 -7.18825e-07 2.17028e-07 7.38293e-06 3.54677e-05 5.64018e-06 -2.49955e-06 1.21464e-05 2.33211e-05 2.84897e-05 -1.22076e-05 1.88048e-05 -8.13106e-06 -1.94214e-05 -8.41683e-06 -4.49612e-06 -1.1817e-06 -1.462e-05 3.45576e-05 -2.35667e-05 -8.5924e-06 1.83975e-05 4.13055e-05 -3.7036e-05 4.10851e-05 -9.13407e-06 1.45307e-05 3.53946e-05 -1.37567e-05 -7.14746e-06 1.34559e-06 -1.94424e-05 2.6407e-05 -1.38793e-05 9.74228e-06 -2.14848e-05 5.89758e-06 -1.04352e-05 1.07708e-05 1.47316e-05 1.17212e-05 -4.48775e-05 9.53328e-06 2.59297e-05 2.05924e-05 -8.21962e-06 1.93012e-06 2.99409e-05 -3.92188e-05 3.23319e-05 -1.6868e-05 1.01183e-05 -1.00616e-05 5.11547e-06 -1.05528e-05 2.44526e-05 -1.24627e-05 -2.59363e-05 1.06765e-05 -8.11461e-07 -4.21634e-05 -1.91008e-05 -2.62658e-05 -2.04358e-05 -1.09974e-05 1.23359e-06 1.08428e-05 6.12114e-06 -5.55186e-05 -1.00125e-05 1.75439e-05 4.89286e-05 -5.20396e-06 -1.35875e-05 2.84811e-05 -3.09286e-05 -5.09821e-06 0.000143064 -4.22764e-05 0.000121144 1.3112e-05 -0.000145654 -7.12933e-06 -0.000117314 -8.66401e-05 -2.3456e-05 9.10654e-05 -6.69288e-05 -1.71358e-05 5.31579e-05 7.88238e-05 -7.23239e-05 4.53513e-05 0.000153568 5.69696e-05 -3.24107e-05 7.77851e-05 3.7917e-06 4.54791e-05 -4.67084e-06 4.9074e-05 -8.71633e-05 -2.00274e-07 3.88461e-05 6.82122e-05 -9.14257e-06 3.7088e-05 -3.82403e-05 2.86649e-05 -1.28733e-05 5.59792e-05 -5.70591e-05 9.06701e-06 -1.58531e-05 0.000105102 1.20238e-06 2.49069e-06 -4.89617e-05 3.94281e-05 -1.78461e-05 -1.80152e-05 2.21698e-05 5.56305e-05 -3.24995e-05 4.43547e-05 -6.56651e-07 2.94517e-05 4.82351e-05 -3.35695e-05 -6.81119e-06 -6.70881e-06 -3.30597e-05 2.07783e-05 -7.75268e-06 4.19304e-06 -3.21821e-05 2.18553e-05 4.32536e-06 -7.64039e-06 6.14265e-06 2.06873e-05 -3.40251e-05 5.70892e-06 3.5019e-05 3.09475e-05 -1.73707e-05 1.50159e-05 3.15994e-05 -3.32316e-05 1.61028e-05 -5.81272e-06 2.64231e-05 3.23338e-06 9.12609e-06 1.9776e-05 2.08887e-05 -1.33518e-05 -1.12629e-05 2.25306e-06 9.73494e-06 -2.23521e-05 -2.11678e-06 -1.6606e-05 -1.51563e-05 -1.62363e-05 -9.37255e-06 1.29153e-05 -8.05153e-06 2.6932e-05 1.80583e-05 2.06058e-05 -3.61828e-05 -3.44208e-05 3.74574e-05 8.55516e-06 -3.12017e-05 7.86515e-06 3.24411e-05 -2.26397e-05 1.51876e-05 1.44738e-05 -5.92148e-05 -4.67281e-05 -1.01245e-06 -1.43658e-05 -1.23922e-05 2.47739e-05 1.11274e-05 -1.95948e-05 1.00711e-06 1.56054e-05 2.7185e-05 3.29763e-05 2.60424e-05 -1.35886e-05 -1.57691e-05 1.6759e-05 3.54183e-05 6.57932e-05 8.91284e-06 4.42899e-05 3.14396e-05 7.50357e-06 -3.47983e-05 1.87367e-05 -2.01865e-05 1.93088e-05 4.31003e-05 1.02381e-05 3.49396e-05 4.289e-05 3.1229e-05 -1.13693e-05 -1.97789e-05 7.19242e-06 -2.85964e-05 3.93308e-05 -3.8428e-05 5.99833e-06 3.74947e-05 3.95334e-05 -1.40741e-05 -4.05198e-05 5.76096e-05 -4.30932e-06 2.33065e-05 1.86174e-05 -4.05446e-07 -2.78294e-05 6.64948e-05 -3.29238e-06 -3.16258e-05 7.30449e-06 -1.92712e-05 -3.97283e-05 -1.02038e-06 7.53831e-05 1.31966e-05 -5.25504e-06 1.36958e-05 1.49952e-05 6.73957e-05 3.80424e-05 5.66847e-05 -4.91613e-06 -2.22498e-06 3.02682e-05 -1.13282e-05 0.000100012 -2.09126e-05 1.65912e-05 2.37207e-05 -3.48936e-05 1.98173e-05 -3.43388e-06 4.88046e-06 1.56249e-05 2.62621e-05 2.9864e-05 2.58733e-05 2.76139e-05 1.84208e-05 -3.59848e-05 6.82386e-06 -6.78234e-07 1.7651e-05 4.69213e-05 -4.21938e-06 -5.58739e-05 -0.000108803 -0.000175758 0.000100701 0.00020421 -0.000274331 0.000153914 -0.000104187 -4.19658e-05 0.00012391 -6.55471e-05 7.79264e-05 5.38825e-05 -0.000376554 3.87034e-05 -5.55613e-05 -0.000121088 -0.000145368 6.29781e-06 -1.41688e-05 -9.901e-05 0.000112636 0.000104948 -0.000264898 8.12961e-05 0.000143414 1.33842e-05 -7.79015e-05 0.000105084 -6.04953e-05 -9.82453e-05 7.19599e-05 -5.71476e-05 6.73751e-05 0.000164086 -0.000107693 4.9524e-07 0.000110134 2.49507e-05 4.89859e-05 0.000114175 0.000116588 -8.90218e-05 -2.16278e-05 -7.53877e-05 -0.000108774 5.60577e-05 -0.000111533 8.79567e-07 -0.000105878 3.09442e-06 6.25783e-05 4.05069e-05 -1.61836e-05 -9.47444e-06 5.90564e-05 7.05396e-06 -6.74876e-06 4.87218e-05 -9.33745e-07 -3.92647e-05 9.23349e-05 4.74705e-06 -2.51882e-05 6.79182e-06 1.11246e-06 -5.03906e-05 5.89301e-06 5.01337e-05 -8.19145e-06 -2.8978e-05 -1.57621e-05 2.21034e-05 0.000104102 5.70934e-05 8.60576e-05 7.61645e-06 6.27188e-06 8.18207e-06 -2.31211e-05 9.72455e-05 -9.01404e-06 4.09518e-05 1.98021e-05 -2.59779e-05 6.31971e-06 -3.95051e-06 -2.3648e-05 1.24446e-05 2.65833e-05 3.16889e-05 1.28428e-05 2.04401e-05 2.38253e-05 -2.93163e-05 -1.8592e-05 9.15605e-07 -1.67104e-05 6.52815e-05 3.42224e-06 -1.35566e-06 -3.82391e-06 -3.227e-06 3.73769e-06 -8.3655e-06 -7.18494e-06 -2.6831e-06 1.41252e-05 8.29889e-08 1.02352e-06 4.51022e-06 8.00707e-06 5.05369e-06 1.69931e-05 1.62785e-05 6.86028e-06 4.79155e-06 2.42475e-06 5.66431e-06 -2.29497e-06 2.848e-06 5.57007e-06 -1.38391e-06 -1.51407e-05 -8.19395e-08 4.07675e-06 3.72148e-06 6.83145e-06 -4.80879e-06 1.2699e-06 -3.55246e-06 1.14161e-05 -3.84282e-06 -1.01007e-05 -8.93382e-06 4.76894e-06 -9.16478e-06 -4.50237e-06 -3.32655e-06 -1.00014e-06 -1.08178e-05 -1.01229e-05 1.7336e-06 -1.84066e-06 6.34429e-07 -2.651e-06 2.07168e-06 3.88726e-06 -6.85686e-06 1.32113e-05 -2.54594e-06 -1.302e-06 -5.71139e-06 1.93778e-06 -1.64178e-05 -9.90496e-06 5.19415e-08 5.18924e-06 9.27619e-07 3.17366e-06 7.80314e-06 4.11786e-06 3.95485e-06 9.29227e-06 9.31314e-06 -8.38783e-07 7.49861e-06 -3.5941e-06 2.74982e-06 8.04647e-07 5.38421e-06 1.02625e-05 6.52987e-07 -9.54307e-06 1.71569e-06 1.28494e-05 -5.90154e-07 4.90589e-06 -3.49752e-06 -2.57214e-07 -7.49278e-06 1.69871e-05 -4.09856e-06 -1.14882e-05 -1.25706e-05 2.11087e-07 -1.21291e-05 -6.88574e-07 -2.14541e-06 5.53299e-07 -8.14775e-06 -1.1796e-05 1.89075e-06 -3.58669e-06 -3.20853e-07 -2.38747e-06 2.70581e-06 3.51e-06 -4.84782e-06 8.27597e-06 4.29573e-05 -6.39873e-05 -0.000108638 5.19193e-05 0.000100209 -0.000119527 0.000105474 -0.000131606 3.17275e-05 9.03103e-05 -9.3727e-05 6.56384e-05 1.265e-06 -0.00023099 -2.88159e-05 -4.70174e-05 -3.91143e-05 -5.43046e-05 1.6934e-05 2.75976e-05 -5.4198e-05 4.83231e-05 8.18414e-05 -4.67625e-05 6.23493e-05 0.000187994 -9.25604e-06 -4.92364e-05 4.1937e-05 -0.000102338 -1.68599e-05 1.81141e-05 -2.88674e-05 7.59237e-05 2.26721e-05 -4.63401e-05 2.67781e-05 4.65102e-05 4.5634e-05 6.14429e-06 4.62862e-05 4.83132e-05 -1.20191e-05 -1.46625e-06 -5.03268e-05 -0.000103062 1.78963e-05 -8.23498e-05 -3.32922e-05 -0.000107145 -2.62779e-07 -3.58253e-06 -2.39126e-06 3.05067e-06 -1.62371e-05 -5.6191e-06 -3.96313e-06 9.19464e-06 6.34527e-07 1.95928e-06 5.08039e-06 6.03178e-06 5.70567e-06 1.37223e-05 1.16042e-05 5.08325e-06 8.56539e-06 5.65927e-07 6.08539e-06 -5.29886e-07 4.47712e-06 7.7964e-06 -9.01683e-07 -1.32443e-05 3.60544e-07 6.37318e-06 2.4602e-06 7.77733e-06 -4.59685e-06 -1.25036e-06 -2.14071e-06 1.22596e-05 -3.15134e-06 -1.23594e-05 -1.16688e-05 3.92413e-06 -1.05536e-05 -5.62485e-08 -1.70782e-06 9.96394e-07 -8.7142e-06 -1.29544e-05 1.4445e-06 -3.16448e-06 9.25478e-07 -3.12577e-06 2.46163e-06 9.87424e-07 -4.15107e-06 1.11029e-05 3.713e-05 3.50225e-05 1.93721e-05 1.26643e-05 -1.8672e-05 3.29976e-05 -1.1553e-05 1.53868e-06 2.16779e-05 2.29613e-05 -2.07156e-05 2.18681e-05 9.31295e-06 -1.06096e-06 -1.14654e-05 1.69551e-05 -6.41089e-06 -1.51765e-05 3.76884e-05 -5.35011e-07 -1.71787e-05 -2.56324e-05 4.04116e-06 3.73482e-05 4.62491e-06 3.57765e-05 1.48705e-05 7.06219e-06 7.02394e-06 9.42352e-06 2.46245e-05 6.45961e-06 3.52927e-05 2.43687e-05 -7.87454e-06 2.70337e-06 6.02698e-07 -5.20586e-06 9.01577e-06 -9.09084e-06 1.35677e-05 1.48261e-05 1.28428e-05 5.95378e-07 -5.16034e-06 -1.3278e-06 -2.54842e-06 -3.03594e-05 1.14029e-05 7.89508e-07 8.72841e-05 5.55264e-05 3.42268e-05 3.32261e-06 -1.17499e-05 9.24214e-05 -1.62945e-05 -1.80159e-07 2.88498e-05 1.39933e-05 -1.27411e-05 4.29922e-05 1.20637e-05 1.46643e-06 -2.78836e-05 2.00166e-05 -1.74227e-05 -1.54269e-05 4.37187e-05 1.02459e-05 -1.39322e-05 -2.06773e-05 2.38903e-06 8.63325e-05 7.76249e-06 3.71785e-05 3.83927e-05 -1.26242e-05 1.07196e-05 1.48483e-05 6.42912e-05 -1.37657e-05 8.35874e-05 2.17814e-05 -1.72226e-07 -1.13452e-05 2.72875e-05 -1.82348e-05 1.91562e-05 -7.34469e-07 1.45744e-05 3.03336e-05 2.71052e-05 2.98212e-06 -7.23432e-06 -2.42931e-06 -1.33065e-05 -3.05417e-05 7.21467e-06 -9.19928e-06 -8.86737e-05 -7.7716e-05 -7.21013e-05 -4.45934e-06 5.07565e-05 -0.000108412 3.41455e-05 5.61025e-05 -3.88379e-05 4.54034e-05 5.76309e-05 -5.709e-05 2.57404e-07 1.15946e-05 6.49812e-05 -1.89645e-05 6.98908e-06 -2.79827e-05 -7.64857e-05 -2.18876e-05 1.46011e-05 4.16484e-05 -2.09246e-05 -0.000123253 -3.26605e-05 -7.21446e-05 -1.90125e-05 -1.41619e-07 6.28686e-06 1.164e-05 -0.000127138 3.75757e-05 -0.000114264 -2.6167e-05 8.31537e-06 2.18955e-05 -4.15692e-05 1.26102e-05 -2.76522e-05 1.27793e-05 -4.28385e-05 -4.23584e-05 -5.09113e-05 -3.75595e-05 1.57025e-05 2.61495e-05 6.55825e-06 3.51733e-05 -2.94887e-05 1.34967e-05 7.26482e-05 3.64896e-05 2.88134e-05 2.68067e-06 -1.98247e-05 2.86453e-05 -2.65067e-05 -1.96159e-06 2.42195e-05 2.61765e-05 -1.25757e-05 3.14457e-05 1.71927e-05 -3.39549e-06 -1.87731e-05 1.04368e-05 -1.41632e-05 -1.41728e-05 1.7509e-05 9.52148e-06 1.44198e-05 -2.20053e-05 5.22325e-06 7.27533e-05 1.48567e-05 8.30599e-05 1.11125e-06 8.60466e-06 2.13752e-05 7.39074e-06 2.58196e-06 1.12837e-05 3.18079e-05 2.33377e-05 -3.1021e-05 -5.22575e-06 -3.19074e-05 -1.87297e-05 1.91124e-05 -5.7541e-06 4.71292e-06 2.88935e-05 7.94973e-06 -3.69591e-06 -1.86121e-05 -4.01625e-06 -1.14565e-05 -1.20408e-05 1.35774e-05 -2.46096e-06 1.12052e-05 -5.59679e-05 -8.56084e-05 3.46687e-05 -5.7873e-05 -6.37578e-05 1.43986e-05 -3.8157e-05 2.43509e-05 -9.89374e-06 -5.71645e-06 0.000128486 -4.628e-06 -7.26485e-05 1.54478e-05 -6.21538e-05 6.94458e-06 1.57785e-05 -1.65262e-05 -3.23091e-05 3.17703e-05 9.86829e-06 4.67123e-05 -2.35546e-05 1.97192e-05 0.000112717 -1.18986e-05 4.85724e-06 -3.66983e-06 -7.68235e-07 -9.89131e-06 2.56804e-05 -1.62242e-05 -1.12379e-05 -7.30334e-05 1.4557e-05 -4.51129e-05 3.06158e-05 4.35215e-05 3.30802e-05 -2.07237e-06 -2.90098e-06 -1.84022e-05 2.71679e-05 4.80655e-06 -1.13957e-05 1.82359e-05 2.42628e-05 -1.09584e-05 1.33089e-05 -2.01593e-05 -1.60947e-05 5.38951e-06 -1.08817e-05 -4.26801e-05 -3.40761e-05 2.40725e-05 1.40216e-05 7.10707e-06 -4.88787e-05 -1.6588e-05 2.99931e-05 2.29093e-06 -5.73252e-05 1.93624e-06 -2.49183e-05 -8.92398e-06 2.66307e-05 7.31693e-06 1.58216e-05 -4.7883e-06 -4.04071e-05 4.05711e-05 2.12607e-06 2.56391e-05 0.00011173 5.50903e-06 2.45102e-06 2.18146e-05 3.91044e-06 5.37887e-07 -3.28696e-06 -3.53723e-06 1.95149e-05 -3.05324e-05 3.14006e-06 -2.23847e-05 -3.54255e-05 3.66174e-05 1.85902e-05 1.08997e-05 -2.26696e-06 -7.61185e-06 4.08017e-05 -2.02326e-07 -1.72337e-05 2.09278e-05 1.16063e-05 2.34264e-05 1.57369e-05 0.000118531 -8.79587e-06 -0.000100381 -2.17878e-05 3.44932e-05 -6.50846e-05 6.24662e-05 9.31616e-05 0.000140938 0.00011745 -9.79617e-05 1.78964e-05 8.67368e-06 -0.000153861 2.27907e-06 5.10729e-05 -8.77339e-05 2.71371e-06 3.21089e-05 5.59494e-05 7.39175e-06 3.85094e-06 6.30738e-05 -0.000118403 5.84837e-05 6.06903e-05 1.29075e-06 -9.55517e-05 6.25948e-05 2.26335e-05 -5.1278e-05 1.60881e-05 2.62566e-05 -0.000275802 -0.000124859 -8.08472e-06 9.5608e-06 -0.000100123 1.07523e-05 4.29545e-05 1.85534e-06 -1.57722e-05 6.20596e-05 3.73881e-05 -5.27067e-05 -1.87466e-05 5.30465e-05 3.06042e-05 3.06651e-05 -6.57757e-06 -2.03919e-05 -1.37822e-05 -3.00867e-05 -1.06739e-05 -1.87051e-05 -2.09836e-05 2.49616e-05 -5.32367e-05 -8.33329e-06 -6.39924e-05 -2.34475e-05 4.061e-05 -1.81579e-05 -4.59566e-05 -3.30619e-05 -1.32089e-05 7.31851e-06 1.84799e-05 -2.13574e-05 8.74521e-06 -1.07075e-05 -2.58531e-05 2.64909e-05 5.03713e-05 2.53636e-05 8.65905e-05 -1.84135e-06 5.11098e-06 1.17552e-07 -1.14204e-05 6.68666e-06 -2.54862e-06 -5.71275e-06 0.000100982 -1.42079e-05 1.45589e-05 -2.36023e-06 -5.21002e-05 2.38821e-05 6.19487e-06 -7.5677e-06 1.51858e-05 5.10034e-06 7.66526e-06 8.22056e-06 -1.29865e-05 1.16225e-05 1.8597e-05 2.05602e-05 -1.18625e-05 -7.75717e-06 1.5852e-05 1.79948e-05 -1.09526e-05 -2.46475e-05 4.38589e-06 -1.27813e-05 3.82639e-06 3.48242e-06 -3.46136e-05 6.378e-07 5.26059e-06 1.53038e-06 2.31671e-06 -1.67892e-05 -1.52041e-07 -2.30892e-05 2.65024e-05 -1.55211e-05 3.39087e-06 -8.47381e-06 4.12627e-06 2.51634e-06 7.62487e-06 -1.92446e-06 4.61043e-06 -1.81026e-05 3.41874e-06 -8.09793e-06 -2.85611e-06 1.5571e-05 -9.05253e-06 3.74421e-06 -1.03581e-05 -2.92741e-06 -1.9242e-06 1.34889e-05 -2.28151e-05 -7.12837e-07 2.26639e-05 1.16407e-06 -2.90493e-06 3.50148e-05 9.24732e-06 5.58309e-06 5.83059e-06 5.24397e-06 -3.63933e-06 3.98671e-06 -2.58689e-07 -1.34371e-06 8.42938e-06 1.68616e-05 -4.39811e-06 -2.40444e-05 -1.21296e-05 -1.89374e-05 2.47596e-05 9.43437e-06 -3.21523e-05 -9.5907e-06 3.36064e-06 -5.40486e-07 9.06304e-06 5.21337e-06 -2.69776e-06 -3.11419e-05 2.67201e-05 -2.92745e-06 5.43802e-07 -1.30895e-05 -3.44733e-06 6.05665e-06 -2.43272e-06 1.90755e-06 1.91883e-05 -8.79195e-06 2.44135e-06 -8.82964e-06 -2.9606e-06 6.03212e-06 -1.8952e-06 9.30162e-07 -1.3223e-05 -3.16731e-06 1.39678e-05 5.46819e-06 -8.90992e-06 -4.9415e-06 1.47237e-05 1.5182e-06 -6.86669e-06 2.43489e-05 9.71288e-06 -2.46401e-06 -1.08185e-06 2.63395e-06 -1.58839e-06 6.69907e-06 9.09262e-06 2.71983e-05 3.23381e-05 -1.34355e-05 2.87954e-05 8.79694e-05 -6.71959e-05 9.21746e-05 -1.5956e-05 5.1161e-05 0.000148034 -0.000122131 -1.87256e-06 3.91787e-05 -0.000168009 3.04599e-05 5.36985e-05 -4.67295e-05 -9.55234e-05 -2.8442e-05 2.60521e-05 -6.4426e-05 3.14119e-05 -9.19194e-06 -0.000115267 2.52895e-05 -9.15284e-05 -2.51838e-05 2.67625e-05 1.89395e-05 9.70089e-06 -7.5877e-05 5.14525e-05 -1.81575e-05 6.03229e-05 2.97333e-05 -5.77424e-05 -1.61469e-05 8.16402e-05 7.62772e-05 3.45516e-05 0.000120999 0.000102586 -5.59916e-05 3.60811e-05 -7.36867e-05 -6.46581e-05 9.62485e-06 -6.40383e-05 2.63247e-05 -4.57589e-05 -7.84201e-06 1.28005e-05 3.47665e-05 -1.48922e-05 -2.14616e-05 1.99841e-05 -1.99286e-05 5.65809e-06 -9.40575e-06 -3.97737e-05 5.37444e-06 5.51765e-06 -9.96706e-07 1.61949e-05 -1.74126e-05 4.15446e-06 -2.46337e-05 3.891e-05 -2.60526e-07 1.62083e-07 -1.87327e-05 -6.53799e-06 1.51438e-06 2.25217e-05 -4.66509e-06 -3.62502e-06 -1.15314e-05 -2.38707e-07 -1.55829e-05 1.51163e-07 3.93822e-05 -1.41547e-05 1.97789e-05 -1.90054e-05 7.94894e-06 7.57054e-06 3.60295e-05 -3.23339e-05 -6.60412e-06 2.22121e-05 -8.26272e-06 -3.94678e-06 3.82597e-05 6.75205e-06 1.25804e-05 1.66263e-05 5.04491e-07 -6.26847e-06 7.62875e-06 4.16918e-06 -3.39956e-05 -1.27507e-05 4.96613e-05 -6.37024e-06 1.11711e-05 5.61058e-06 -2.36563e-05 4.69668e-05 -7.70679e-06 -1.1649e-05 1.14634e-05 -1.72849e-05 1.43642e-06 7.91008e-05 2.054e-05 1.42156e-06 9.00864e-06 2.95822e-07 -1.90822e-05 -1.60452e-05 2.14889e-05 -2.74812e-05 -1.19292e-05 -1.31169e-05 -1.04015e-05 -2.57818e-05 -1.1513e-05 4.18375e-06 -1.33196e-05 1.83421e-05 -7.3632e-06 3.30876e-06 -7.78498e-06 2.01983e-05 1.09656e-05 4.73718e-05 -1.61672e-05 -1.57867e-05 -2.17079e-05 4.51599e-06 -3.21324e-05 -1.06913e-05 -5.43835e-05 -1.68716e-05 1.0069e-05 1.01189e-06 -2.38487e-06 -2.68757e-06 2.4723e-05 8.80475e-06 -5.70085e-05 -8.2589e-06 3.67295e-05 4.06166e-06 3.48462e-05 1.02118e-05 -2.94282e-05 4.47192e-05 -8.58556e-06 -1.94903e-05 8.45454e-06 -2.42156e-06 -2.10703e-07 0.000119421 2.25239e-05 1.68247e-05 3.16465e-06 5.52272e-07 -2.80634e-05 -1.95559e-05 3.21655e-06 -2.84863e-05 -2.09116e-05 5.36294e-06 -1.36625e-05 -3.9727e-05 -2.42152e-05 1.08933e-05 -1.08067e-05 1.41149e-05 -7.88271e-06 9.28373e-06 -4.31955e-06 5.5715e-05 3.0772e-06 6.53465e-05 -1.47749e-05 -2.69823e-05 -2.47176e-05 3.42182e-06 -5.57014e-05 -2.45229e-05 -3.94074e-05 -3.77955e-05 1.6094e-05 -8.70223e-06 -1.13962e-05 1.34806e-05 4.00967e-05 1.6277e-06 9.60824e-05 -4.49462e-05 -0.000176983 3.52759e-05 7.32979e-05 -9.45218e-05 0.000160319 -0.000163664 1.9942e-05 0.000101991 -7.34923e-05 5.53032e-05 -3.4073e-05 -0.000356222 -6.58406e-05 -3.52978e-05 -3.51048e-05 -7.6294e-05 7.93792e-05 3.26892e-05 -7.01854e-05 5.30486e-05 0.000117609 -9.92521e-05 6.88735e-05 0.000214106 8.00872e-05 -5.38913e-05 9.74113e-05 -8.24069e-05 -2.35652e-05 -6.07706e-06 -1.56676e-05 5.11072e-05 6.23952e-05 -8.08056e-05 0.000121827 8.48979e-05 3.17059e-06 7.75447e-06 0.000119102 7.74695e-05 4.01104e-05 1.27425e-05 -4.87327e-05 -4.82469e-05 1.976e-05 -7.47608e-05 -0.000149652 -6.92329e-05 -3.30895e-05 -2.9215e-05 9.53358e-06 8.1011e-06 2.0137e-05 -7.8841e-06 -1.18832e-05 1.68937e-05 5.44395e-06 2.28337e-05 -4.4863e-06 3.19088e-06 8.90057e-06 3.049e-05 -1.37069e-06 8.9715e-06 2.54713e-05 -1.11472e-05 8.73637e-06 -4.73046e-06 -8.09385e-06 -1.89701e-05 4.27651e-06 -2.53074e-06 3.94722e-07 1.20072e-06 -1.11813e-05 1.08265e-06 -1.22727e-06 2.67834e-05 -1.75349e-05 8.4058e-06 -8.73919e-06 1.03078e-05 8.45853e-07 4.6455e-05 1.38728e-05 -6.9497e-06 -1.78111e-05 -2.89731e-06 -1.61199e-05 4.30232e-06 -1.98297e-05 8.3854e-06 1.04874e-05 5.24127e-06 3.80393e-06 -5.96078e-06 1.5239e-05 -1.48863e-05 -1.53761e-06 6.90133e-06 2.60038e-05 -8.27262e-07 -4.40431e-05 1.98372e-05 -1.67396e-05 -1.759e-06 -5.40181e-07 -5.38054e-06 1.51603e-05 -1.02609e-06 7.70499e-06 2.31323e-05 -1.47112e-05 1.10335e-05 1.28191e-05 1.10925e-05 5.08424e-06 8.07248e-07 3.14563e-05 -7.55938e-06 -7.49208e-06 3.22295e-05 1.95453e-06 -9.64003e-07 1.8692e-05 1.08722e-05 -7.4985e-06 1.16384e-05 2.52881e-05 3.33676e-06 1.56108e-05 -1.67292e-05 -1.73167e-05 -3.18653e-06 3.7541e-06 1.01733e-06 8.7598e-06 -7.93903e-06 1.03616e-05 -2.69598e-06 8.4947e-06 1.37646e-05 1.25588e-05 1.80439e-05 -3.96151e-07 -5.21598e-06 -1.46313e-05 1.96651e-05 4.50379e-06 1.34647e-05 1.52922e-05 9.94767e-06 -2.66935e-05 2.10128e-05 -9.35751e-06 1.2584e-05 1.62797e-05 -4.50505e-06 1.22952e-05 4.58312e-06 7.60129e-06 1.71573e-05 -1.15316e-05 1.30836e-05 4.92803e-06 8.35782e-06 1.25102e-05 2.55137e-06 1.87375e-05 -1.56692e-05 -5.47356e-06 1.00334e-05 7.87833e-06 6.89627e-06 1.65615e-05 9.16302e-06 -9.44699e-06 3.66691e-06 1.98197e-05 8.7524e-06 1.41181e-05 -8.12805e-06 -1.63012e-05 -1.82174e-06 5.59305e-06 1.05268e-06 -1.26329e-06 -4.15328e-06 1.23533e-05 -1.00085e-05 1.52481e-06 2.25126e-05 7.9605e-06 1.2654e-05 -1.12462e-06 -1.01017e-05 -8.9446e-06 2.13229e-05 -1.54198e-05 -1.89547e-05 4.37644e-05 1.65569e-05 -4.93947e-05 3.39402e-05 -5.04765e-06 2.80104e-05 -4.21605e-05 5.47395e-05 9.57726e-05 -3.43413e-05 6.74979e-05 0.000124335 4.0176e-05 2.24516e-05 5.1039e-05 -2.57809e-05 1.25006e-06 -1.28341e-05 5.9882e-05 -2.87493e-06 -6.55134e-05 -6.01952e-05 -6.21437e-05 -0.000145643 -1.93322e-05 0.000127788 -3.27545e-05 1.05126e-05 6.08013e-06 1.50661e-05 1.15406e-05 -9.0088e-05 -4.3311e-05 3.86464e-05 -1.62182e-05 1.4995e-05 -8.13941e-06 -8.77775e-06 -1.92471e-05 5.39326e-06 -7.73836e-05 1.31204e-05 6.27019e-05 8.64942e-05 -3.25558e-05 -1.43866e-05 -2.55469e-05 5.93773e-05 2.74922e-05 1.20685e-05 3.64366e-05 9.14148e-06 -3.01599e-05 3.4619e-05 -2.36395e-05 1.00042e-06 9.26299e-06 -8.72447e-06 1.53426e-05 1.21154e-05 9.9589e-06 2.77204e-05 -2.06733e-05 1.65431e-05 1.69045e-05 9.24175e-06 2.18128e-05 -2.12312e-06 2.31059e-05 -1.72524e-05 -8.15199e-06 4.47385e-05 6.31497e-06 4.5963e-06 1.62266e-05 9.66484e-06 -7.74617e-06 8.57955e-06 4.36471e-05 -1.31764e-06 2.59342e-05 -2.02494e-05 -2.07676e-05 -5.29849e-06 1.47007e-05 3.51275e-07 6.76859e-06 -1.3801e-05 9.56029e-06 -8.05641e-06 1.02569e-05 2.00944e-05 1.11711e-05 1.67081e-05 -3.53275e-06 -5.68778e-06 -1.99312e-05 2.09448e-05 -2.58192e-05 3.11818e-05 4.16801e-05 -1.77121e-05 -6.3345e-05 5.18791e-05 1.41265e-05 -4.02057e-06 5.52764e-06 -9.40625e-06 -7.78333e-06 -1.5435e-05 9.15815e-07 6.53975e-05 -2.57283e-05 4.81337e-05 9.23019e-06 1.94104e-05 -4.82072e-07 6.53086e-06 -4.02607e-06 -8.97602e-05 -2.19758e-05 7.733e-05 -2.99391e-06 -3.50521e-05 2.56306e-05 2.39038e-05 -3.54756e-05 7.72704e-05 3.25897e-05 1.39442e-05 2.59377e-05 -1.80167e-07 -3.92049e-05 3.75338e-06 -6.55279e-06 -3.35551e-05 2.18651e-05 -1.60603e-06 9.30585e-07 -2.89769e-05 2.52504e-05 4.12437e-05 4.43528e-05 1.04281e-05 3.03979e-05 -1.64841e-05 2.73299e-05 1.82484e-05 8.17176e-06 3.02222e-05 3.10429e-05 -1.22386e-05 -1.79786e-05 3.38047e-05 -1.41385e-05 6.12744e-05 6.45428e-05 1.29125e-05 -4.29094e-05 -1.89718e-05 -2.02811e-06 2.65454e-05 -1.89984e-05 1.12348e-05 2.62591e-05 4.76181e-06 -5.92912e-06 3.66113e-05 -3.65855e-05 -4.89853e-05 -1.05056e-05 5.3793e-05 1.74856e-05 -2.5251e-05 3.03637e-05 1.40035e-05 8.99418e-06 5.89714e-05 -1.2476e-05 1.18191e-05 2.1925e-05 7.38165e-06 -3.90607e-05 1.30752e-05 -5.35479e-07 -9.87169e-05 1.45864e-05 1.94566e-05 4.82723e-05 -3.21144e-05 2.60271e-05 2.22161e-05 -5.17973e-06 1.55223e-05 2.34491e-05 1.94191e-05 5.0561e-05 4.91013e-06 3.59568e-05 5.08548e-05 9.2015e-05 -4.25497e-05 -0.000232645 0.0001668 -0.000124773 1.46921e-05 4.36617e-05 -0.000136027 8.92301e-05 2.61252e-05 -5.64547e-05 0.00033906 -1.78422e-05 1.75021e-05 0.000154829 9.65974e-05 -4.86736e-05 6.2692e-06 0.00010818 -0.000132351 -5.737e-05 0.000308739 -2.0568e-06 5.28886e-05 6.69061e-07 8.26962e-05 -0.000120424 6.02385e-05 7.48725e-05 1.84615e-05 3.68194e-05 -5.48373e-05 -0.000210701 0.00010622 -3.81701e-05 -0.000151352 -5.13403e-06 -5.10394e-05 -2.23406e-05 -8.814e-05 -6.0773e-05 -3.90375e-05 9.11458e-05 3.72345e-05 -3.75049e-05 0.000130959 3.3763e-06 0.000152073 -2.42132e-05 2.66778e-05 3.03254e-05 -1.60441e-05 1.06652e-05 3.96388e-05 2.86022e-05 1.67559e-05 3.44621e-05 -4.74137e-06 -3.08301e-05 1.70548e-05 -1.00504e-06 1.01601e-05 -2.53314e-05 2.42549e-05 -1.95784e-05 2.30252e-05 3.05095e-06 1.65036e-05 -7.63494e-05 -5.38071e-05 -2.21356e-06 3.12805e-05 1.43845e-05 -2.65294e-05 2.28968e-05 8.36878e-06 -1.66316e-06 4.43259e-05 1.54461e-05 8.8701e-06 2.39133e-05 -3.66333e-06 -1.79197e-05 1.51301e-05 2.11987e-05 -9.76858e-05 1.85828e-05 3.45666e-05 1.95735e-05 1.84077e-05 2.54738e-05 1.44715e-05 6.88382e-06 -3.70886e-05 2.74172e-05 6.1381e-06 5.07134e-05 -1.16878e-05 -5.21876e-06 -1.19895e-06 -2.519e-05 -3.01986e-05 -5.66317e-05 5.90263e-06 -1.25494e-05 4.95843e-05 7.1881e-07 -3.33626e-05 3.58676e-05 -2.20458e-05 2.51718e-05 4.70043e-05 5.2318e-05 2.50106e-05 2.51629e-05 -3.02254e-05 1.22302e-07 2.43218e-05 -4.78492e-06 1.00588e-05 -1.36499e-05 -3.3095e-05 -4.64132e-06 -3.95981e-05 1.28246e-06 1.54191e-05 -6.49257e-06 3.00348e-05 -2.6903e-05 2.29033e-05 -7.94114e-06 -4.29506e-05 -7.23198e-06 1.01407e-05 -1.8981e-05 -4.88013e-06 -5.9941e-05 9.3448e-06 -1.71271e-05 3.80577e-06 -3.28153e-05 1.2202e-05 4.71328e-06 5.37541e-05 3.52211e-06 2.54583e-05 -1.72141e-05 2.53961e-05 -8.57742e-06 -9.79339e-06 -3.49488e-05 -1.89569e-05 -3.82991e-05 -8.10698e-06 -1.89446e-05 2.78667e-05 1.5907e-05 -3.42863e-05 3.92657e-05 -6.38364e-06 2.21104e-05 4.9862e-05 4.74419e-05 2.33765e-05 2.50034e-05 -2.10536e-05 3.0193e-06 2.42642e-05 1.54205e-05 8.74978e-06 -1.35079e-05 -4.06989e-05 -8.21487e-06 -3.99569e-05 5.3776e-06 1.41676e-05 4.23114e-06 3.37925e-05 -1.7251e-05 2.08241e-05 -1.10575e-05 -6.18011e-05 -6.44184e-06 1.48396e-05 -2.4779e-05 1.04807e-05 -6.80999e-05 -2.34985e-06 -1.33633e-05 -1.21616e-05 -4.04336e-05 3.38516e-05 9.81582e-06 3.56859e-05 6.55318e-06 1.24671e-05 -3.08863e-05 2.10862e-05 -1.21496e-05 -4.66414e-06 2.60097e-05 -6.95305e-05 -0.000154164 -2.23488e-05 -0.000121259 9.5098e-05 -4.73261e-07 -0.000155105 5.95416e-05 -6.83475e-06 1.44318e-05 0.00014715 6.6499e-05 -4.8749e-06 0.000152763 -3.88158e-05 -0.000123567 5.38715e-05 0.000158425 -1.16857e-05 -5.26082e-05 1.13944e-05 -1.56157e-05 -3.87564e-05 8.56097e-07 4.18181e-05 -2.48379e-05 3.76027e-05 -9.25201e-05 1.26346e-05 -3.34707e-05 -0.000110871 -7.66718e-05 -1.69419e-06 -0.000143626 -1.92925e-05 -2.74747e-05 1.54932e-06 -4.70757e-05 -0.000108899 -8.50581e-05 2.33008e-07 -1.95136e-06 7.90878e-05 -3.5403e-05 0.000102875 5.34205e-06 9.82213e-05 -1.57304e-05 -5.53152e-06 -4.10786e-05 -3.81548e-05 -3.37475e-05 -1.08221e-05 -4.65546e-06 2.66205e-05 1.75707e-05 -3.74377e-05 5.3083e-05 -6.41227e-06 2.49983e-05 4.49196e-05 5.98572e-05 2.55664e-05 3.64547e-05 -1.65639e-05 -1.11081e-06 3.4218e-05 -7.63948e-07 8.2666e-06 -5.22959e-06 -3.60858e-05 -6.87897e-06 -2.7221e-05 1.02954e-05 4.85682e-06 3.7037e-06 3.39951e-05 -2.26024e-05 1.69741e-05 -1.33562e-05 -5.60844e-05 7.01664e-06 3.08862e-05 -1.05669e-05 2.70408e-06 -0.000100676 3.83087e-06 -2.30741e-05 -4.97662e-07 -3.81436e-05 1.98195e-05 1.4632e-06 4.05248e-05 1.37626e-05 3.02704e-05 -1.65269e-05 1.51635e-05 -4.15673e-05 3.30617e-05 8.44222e-06 5.16224e-05 1.74116e-05 1.60595e-05 1.13136e-05 9.2725e-08 6.56977e-06 -3.23492e-05 1.78961e-05 2.57467e-05 1.89741e-05 9.72654e-05 1.13282e-05 2.3068e-05 -1.38617e-05 -2.65649e-05 8.82551e-05 -3.33124e-05 -1.05545e-05 -2.87036e-05 -1.72938e-05 1.84885e-06 -2.57153e-05 -9.99526e-05 1.54265e-05 -3.8163e-06 -3.01486e-05 2.00176e-05 2.7425e-05 -3.12446e-05 1.012e-05 -5.11378e-05 1.47141e-05 2.84949e-05 5.00064e-05 3.68121e-05 -2.3125e-05 -8.54469e-05 -7.09587e-07 -3.83979e-05 -6.41459e-06 2.43236e-05 4.68807e-05 2.86963e-05 -6.38798e-06 -6.95983e-06 -1.22136e-05 1.19253e-05 8.35107e-06 -1.10947e-05 -2.39646e-06 3.28918e-05 2.46941e-06 1.09856e-06 4.00134e-05 -4.51982e-05 5.39503e-06 9.00566e-06 2.38486e-05 3.0523e-06 5.77444e-06 3.83473e-05 -3.6345e-05 1.79528e-05 2.55829e-05 -4.75653e-05 7.5577e-05 -1.10063e-05 1.70933e-05 -3.01807e-05 -7.50322e-06 1.20307e-05 -1.77203e-05 -4.43142e-05 1.65992e-05 -1.54625e-05 1.19258e-05 5.08883e-05 -1.23295e-05 -2.94084e-05 3.24749e-06 -2.05513e-05 1.58465e-05 1.25986e-05 6.89597e-07 4.57462e-05 -2.15939e-05 -0.000161934 2.01709e-06 -4.47717e-05 -5.08931e-05 9.02126e-06 4.37943e-05 2.88629e-05 -9.41186e-06 -4.65909e-05 -1.00854e-05 5.71164e-06 -0.000112354 1.40034e-05 7.56734e-05 -7.77141e-05 -0.000119244 8.07275e-05 -0.000193236 8.88539e-05 -2.61397e-05 -0.000148716 0.000276047 -3.31315e-05 2.75829e-05 0.000442164 6.82605e-05 3.64592e-06 7.16317e-05 4.03353e-05 -7.00489e-05 -4.35894e-05 0.000134083 1.35952e-05 -0.000146088 5.96679e-05 -9.96715e-05 -0.000223497 -0.000112954 0.000102358 -0.000111375 4.77044e-05 2.16132e-05 7.11686e-06 -9.91362e-06 -0.000152623 -0.00010511 6.74552e-05 -0.000193017 -2.91316e-05 -5.59458e-05 -6.91059e-05 -0.000252506 -0.000245551 -7.12425e-05 -4.47688e-05 9.47591e-05 8.32866e-05 -5.8238e-05 0.000141119 1.14811e-05 0.000135211 -6.4054e-06 9.29424e-06 1.74414e-06 3.38731e-05 6.61433e-06 -5.08707e-06 3.1847e-05 -2.65704e-05 2.27263e-05 8.25113e-06 3.55565e-06 1.61336e-05 -7.16863e-06 3.05072e-05 -9.93641e-06 1.20499e-05 -1.00956e-05 -9.75669e-06 5.96076e-05 -5.7588e-06 1.1366e-05 -1.68245e-05 1.14575e-05 9.52319e-06 -6.01037e-07 -4.06882e-06 1.41727e-05 -1.88268e-05 6.66046e-06 3.52784e-05 2.93774e-06 -1.17022e-05 2.92492e-06 -2.28661e-05 7.97819e-07 2.40533e-05 3.59159e-05 3.67911e-05 4.26043e-06 -7.41023e-05 3.09774e-06 -3.15393e-05 -1.02896e-05 2.87995e-05 3.09064e-05 1.02272e-05 2.8428e-06 -5.2579e-06 -2.01739e-05 2.35354e-06 1.59259e-06 -1.52536e-05 9.47427e-05 -2.6877e-06 -0.000222337 4.75983e-05 -0.000111474 9.15868e-05 -0.000129571 -4.38028e-05 0.000147768 1.80459e-05 2.87089e-05 0.000347679 4.08405e-05 9.91385e-05 6.20936e-05 5.94189e-05 -5.74283e-05 -5.68694e-05 8.23364e-05 -4.30124e-05 -0.000107819 -4.61925e-05 -9.21082e-05 -0.000227949 1.57018e-05 5.32798e-05 -0.000124736 0.000160895 1.39885e-05 5.04781e-05 6.32014e-07 -0.000124201 -2.98838e-05 7.75256e-05 -7.40179e-05 1.59176e-05 -9.44545e-05 5.98688e-06 -0.000145135 -4.57284e-05 -1.65208e-05 -1.93953e-05 0.000118234 -8.9265e-06 1.93603e-05 2.58945e-05 -1.44088e-05 0.000110568 -5.60726e-05 -3.33222e-05 5.53423e-05 -1.83709e-05 -0.00013313 3.94473e-05 -0.000102626 0.000118621 -9.00745e-05 -9.24926e-06 0.000161531 3.50101e-05 1.11984e-05 0.00046598 9.0641e-05 6.56197e-05 8.45811e-05 -7.63232e-06 -7.61325e-05 -5.14004e-05 0.000100533 -2.31399e-05 -0.00011162 -2.76028e-05 -7.09057e-05 -0.000165721 -8.0421e-06 6.3444e-05 -9.76467e-05 0.00015103 -3.7661e-05 8.59608e-05 -2.10182e-05 -9.36355e-05 -0.00014479 0.000140622 -0.000162105 -6.28354e-05 -3.1519e-05 1.31751e-05 -0.000297626 -0.000173691 -1.79802e-05 -5.88169e-05 0.000149806 1.77262e-05 4.79797e-05 0.000121517 -6.05966e-05 0.000118005 -7.0124e-05 8.07095e-05 0.000134418 -0.000105989 -0.000245701 0.000136781 -0.000288431 0.000179472 -1.09204e-05 -0.00027432 0.000150326 -9.49041e-05 -4.66451e-05 0.000541386 1.19729e-05 4.96398e-05 0.000165371 0.000107049 -0.000208482 -2.72626e-05 0.000252398 -0.000181361 -0.000176159 0.000267428 -6.24992e-05 -0.000224603 -9.62312e-05 0.00011008 -0.00017483 0.000147827 -6.99763e-05 -4.85806e-05 -1.08165e-05 -4.0173e-05 -0.000239924 0.000104923 -0.000279473 -0.00013474 5.74311e-06 -9.58611e-06 -9.61624e-05 -0.00022532 6.21226e-05 -3.22767e-05 7.07509e-05 6.50519e-05 -5.40266e-05 0.000188071 0.000108752 0.000236604 -2.86989e-06 -2.29237e-05 -1.51011e-05 1.09902e-05 -9.56914e-05 -2.16712e-05 -8.81022e-05 0.000118716 -1.9933e-05 4.49976e-05 0.000101224 3.10957e-05 -4.36121e-06 0.000311502 9.35939e-05 8.28399e-05 9.17436e-05 -5.93525e-05 -3.46606e-05 -4.30664e-05 0.000129219 -5.98008e-05 -7.43632e-05 -2.25527e-05 -3.61235e-05 -0.000130588 5.11629e-05 2.75728e-05 -4.20903e-05 0.000202299 -0.000108745 8.45352e-05 -2.96374e-05 -8.79957e-05 -0.00010402 0.000118809 -0.000111877 5.04361e-05 -7.36683e-05 -6.00676e-05 -0.000182463 -0.000113241 -5.84536e-05 -1.71419e-05 9.83997e-05 5.35097e-05 0.000101124 0.00011991 -1.28517e-05 0.000107488 -1.6966e-06 8.26894e-06 -2.6134e-05 -6.80089e-06 4.37918e-05 6.484e-06 2.58743e-05 -2.92068e-05 7.22509e-06 -1.28384e-05 -2.19279e-05 2.59381e-05 9.16958e-06 -4.24264e-05 -4.56351e-06 6.15838e-06 -2.39611e-05 -2.34229e-05 2.72571e-05 5.46914e-06 -2.19671e-05 1.2684e-06 1.45878e-05 3.56142e-05 1.20913e-05 4.34491e-05 2.1245e-05 -1.83019e-05 -6.90851e-06 2.75837e-05 2.3708e-05 7.31685e-07 3.16802e-05 3.73807e-05 1.95289e-05 9.51148e-06 2.7192e-05 -9.47135e-07 3.25171e-06 -5.98404e-07 -4.54802e-06 3.93841e-06 3.06981e-05 1.09133e-06 2.4555e-06 -2.35634e-05 6.41303e-06 -9.33121e-06 2.13099e-05 -7.40223e-06 2.88987e-06 2.85453e-06 6.91568e-06 6.22504e-06 4.9723e-05 1.97893e-05 1.9337e-05 -2.04404e-06 9.4513e-06 1.88534e-05 -2.98507e-06 1.62506e-05 -7.05382e-06 1.38681e-05 -1.0433e-05 -1.07442e-05 -1.61e-05 -1.86826e-05 1.75943e-05 -4.14392e-06 4.34012e-06 -5.84946e-06 -2.7727e-07 3.07544e-05 9.08002e-06 1.51646e-05 5.5502e-06 -4.3378e-06 2.11687e-06 2.15908e-05 1.34353e-05 -7.44155e-06 1.68498e-05 3.06375e-05 -8.86955e-07 2.18265e-05 4.44959e-06 8.24521e-06 8.3528e-06 -3.83792e-05 -2.90831e-05 -2.00291e-05 2.44643e-06 -2.94945e-05 1.98022e-05 1.4927e-05 -3.72694e-06 -3.81921e-06 1.22103e-05 -1.09504e-05 -0.000117976 -6.04653e-05 0.000205378 -2.82838e-05 0.000164224 4.90828e-05 -4.10714e-05 1.14092e-05 -0.000111596 2.67992e-06 5.60284e-05 -0.000126452 5.02427e-05 0.000246893 6.02113e-06 2.98794e-05 -6.12623e-05 -4.63545e-05 3.64807e-05 -3.82811e-05 -2.07361e-05 -9.3138e-06 -7.93579e-05 5.30225e-06 -4.64479e-05 -0.000182421 -4.64758e-05 1.45144e-05 -5.85038e-05 3.0865e-05 2.6336e-05 -7.1951e-05 -3.84947e-06 0.000264927 3.17226e-05 0.000122505 -5.20085e-05 -4.49311e-05 1.60508e-05 -4.18035e-05 -0.000132538 0.000101012 -6.90579e-05 -9.57624e-05 7.65674e-05 3.55717e-05 -6.68504e-05 3.80239e-05 7.27085e-05 2.25849e-05 2.79034e-07 1.71053e-05 5.64114e-06 -1.18161e-05 -3.20449e-05 2.73573e-05 -3.95424e-05 3.23414e-05 -3.41126e-07 -2.14557e-05 4.83331e-05 4.38354e-05 -1.18582e-05 6.99386e-05 1.32675e-05 5.12964e-06 4.06303e-06 3.86062e-06 -1.16724e-05 -7.98197e-06 2.06364e-05 -4.05762e-06 -1.78964e-05 4.23845e-05 2.78227e-06 -1.0815e-05 -7.68022e-06 2.46688e-05 -2.15848e-05 -9.00234e-07 2.31986e-05 1.22017e-05 2.44259e-05 -3.50509e-05 -2.75188e-05 1.84926e-05 -2.4381e-05 8.84915e-06 -2.13414e-05 -2.2512e-05 -5.44982e-05 -9.83661e-05 2.78046e-05 -1.316e-05 2.61215e-05 2.36004e-05 1.25753e-05 1.24038e-05 4.02281e-07 3.14677e-05 -2.5436e-05 6.78864e-06 6.38241e-05 -1.19437e-05 -3.56575e-06 1.16658e-05 -1.88041e-05 8.3727e-06 2.65949e-06 -6.01056e-05 8.99428e-06 -2.20387e-05 3.29806e-06 1.54957e-05 6.13334e-06 -1.50142e-05 2.1523e-05 1.18637e-05 -1.6473e-05 3.03758e-05 4.97986e-05 -2.49591e-05 -4.40785e-06 -2.79016e-06 -3.88707e-06 -2.08857e-05 4.66192e-06 -9.14263e-06 1.25372e-05 2.41072e-05 2.65172e-06 -1.73537e-05 8.40472e-06 -1.24702e-05 1.64319e-05 -2.98538e-07 -6.59134e-07 -2.70584e-06 -2.02339e-05 9.07837e-06 -2.31512e-06 8.39381e-06 -3.88961e-05 -2.55214e-06 1.12701e-06 2.59386e-05 -3.62595e-06 1.11141e-05 6.94212e-06 -1.56121e-05 -1.29494e-05 -8.5746e-06 3.22629e-05 -1.59137e-05 -9.05909e-06 1.79557e-06 2.24378e-05 -1.89578e-05 1.17528e-05 -4.68006e-05 -1.28889e-05 -1.79913e-05 6.36165e-06 -4.45776e-05 -8.56254e-07 -3.13582e-05 2.1985e-05 -2.26509e-05 6.70247e-06 3.8514e-05 2.88243e-05 -3.4176e-06 1.39682e-05 -1.86039e-05 1.65754e-05 2.63607e-05 1.05344e-05 -1.8199e-05 1.8812e-05 3.27748e-05 -9.48496e-07 -1.68744e-05 1.35023e-05 3.03287e-06 4.72107e-06 -9.74024e-07 6.28144e-06 2.03878e-05 -1.67369e-06 2.15771e-05 2.65168e-05 3.60476e-05 -6.39918e-05 7.93909e-06 -2.19839e-05 3.42976e-06 -1.33746e-06 7.52416e-06 2.18699e-06 -2.73426e-05 -0.000223025 3.7587e-05 0.000187522 -2.45356e-05 3.4243e-05 6.81608e-05 -0.000215051 0.000120433 -8.93918e-05 -0.000258805 0.000232972 -0.000170392 3.69808e-05 0.000400833 5.55096e-05 -7.22377e-06 0.00014113 4.73522e-05 -9.41312e-05 -7.4841e-05 5.25564e-05 7.5337e-06 -0.000161908 0.000122877 -0.000136342 -0.000414289 -0.000161261 3.95611e-05 -9.93623e-05 5.75609e-05 3.86904e-05 -5.47701e-05 -2.15859e-05 -5.09366e-05 8.91392e-05 2.54195e-05 -8.8735e-05 -1.63404e-05 -8.22975e-05 -0.00011026 -9.32376e-05 -4.77214e-05 -0.000123028 -5.53736e-05 9.97002e-05 0.000100489 -4.57128e-05 0.000135909 6.61865e-05 3.48125e-05 -5.4996e-06 4.53494e-06 5.24227e-05 -8.19469e-06 -2.70938e-05 4.04419e-05 3.02703e-05 -2.4273e-05 -9.14795e-06 -4.75571e-05 -1.25168e-05 2.21271e-06 7.22623e-07 -3.02344e-05 -1.50973e-05 -2.56542e-05 2.73595e-05 -1.21322e-05 2.3625e-05 1.67132e-05 3.55427e-05 -1.01034e-05 1.24705e-05 -9.24022e-06 1.10619e-05 1.57228e-05 1.99941e-05 -2.64336e-05 1.33302e-05 4.57069e-05 4.27071e-05 -2.05085e-05 4.2379e-05 -1.19577e-05 1.40928e-05 1.97874e-06 4.6078e-05 2.59732e-05 -1.90993e-05 -5.38186e-06 2.14557e-05 2.33948e-05 -4.87479e-05 -1.02796e-05 -6.25205e-06 1.51256e-05 2.73864e-07 -4.94056e-06 2.23268e-05 -3.07815e-05 1.59869e-05 -6.04732e-06 3.99152e-05 -1.55797e-05 -6.11015e-05 9.05866e-07 -2.7515e-05 -2.03383e-05 -4.88643e-06 1.16721e-05 -1.3802e-05 3.56008e-05 -3.59968e-06 4.2727e-06 -6.95858e-06 -1.20346e-05 4.20441e-05 -5.66374e-06 -1.6426e-05 1.49118e-05 3.2176e-05 1.78109e-05 -2.70378e-07 -2.77845e-06 2.76346e-06 1.013e-06 2.33707e-05 1.04177e-05 -4.08372e-06 4.63215e-05 -6.61142e-06 1.20437e-05 -7.7775e-06 -5.12797e-05 -4.72679e-05 1.14173e-05 -3.30812e-05 -9.8931e-06 1.55792e-05 2.27995e-05 -4.15939e-06 -2.67904e-06 -1.68401e-05 -3.74061e-05 -1.02299e-05 -9.22304e-06 1.31683e-05 -1.3088e-05 4.18784e-05 -3.95815e-06 -1.00536e-05 -6.5866e-06 3.9046e-05 -7.67858e-06 -7.16985e-05 1.10594e-05 -6.27415e-05 -7.83984e-06 -2.53164e-05 2.21624e-05 3.34526e-05 3.40847e-05 7.02768e-06 6.77491e-05 1.28831e-05 6.33527e-06 4.42738e-05 7.67359e-07 -3.93256e-05 1.13455e-05 6.99231e-05 -3.66212e-06 -1.56528e-05 2.4092e-05 -1.68912e-06 -1.07527e-05 -5.61686e-06 1.09166e-05 -1.45984e-05 6.05021e-05 -1.08425e-05 2.00991e-05 -7.77497e-06 -5.42837e-05 -5.30997e-05 1.41142e-05 -3.03017e-05 -1.79757e-05 1.00837e-05 1.61158e-05 -3.93429e-05 -1.77631e-05 -3.56792e-05 -6.7774e-05 2.56469e-05 3.12348e-05 1.0568e-05 2.66245e-05 2.66411e-05 1.64184e-05 -0.00011738 3.08181e-05 0.000120648 -2.30396e-05 -0.000156238 0.000123546 -0.000263173 6.51483e-05 -2.16131e-05 -0.000217508 0.000275605 3.09472e-05 4.31807e-05 0.000661758 0.000129008 -3.13138e-05 8.39088e-05 8.43966e-05 -7.37397e-05 -6.84706e-05 0.000229171 -5.61418e-05 -0.000159064 0.000159356 -0.000114782 -0.00020877 -0.000103875 0.000137281 -0.000120928 9.44448e-05 4.19885e-05 -4.19635e-06 1.82976e-05 -0.000171901 -0.000136465 0.000113505 -0.000200648 -7.38198e-05 -9.61548e-05 -6.94754e-05 -0.000265715 -0.000209684 -0.000167911 -0.000148645 0.000142955 0.000110439 -4.80632e-05 0.000184091 3.25422e-05 0.000166398 -2.8238e-06 6.08316e-06 4.64095e-05 -3.92502e-05 -8.78244e-05 1.13267e-05 -5.74827e-05 -3.76418e-05 -8.97458e-06 -1.56181e-05 2.45435e-05 4.89032e-05 -1.87736e-06 8.40356e-06 -3.07783e-05 -2.367e-05 6.82054e-05 8.76763e-06 -3.51748e-05 4.25973e-05 5.67012e-05 -7.44662e-06 -9.42966e-06 4.38699e-05 2.48743e-06 -2.45674e-06 2.53989e-05 1.77957e-05 -4.69352e-06 6.16755e-05 -9.08519e-07 5.05964e-06 -1.61641e-06 -7.46239e-05 -6.51289e-05 2.36786e-05 -1.67883e-05 -4.95401e-05 2.64106e-05 4.62971e-05 -2.43242e-05 -1.05995e-05 -1.27803e-05 -5.20895e-05 -3.8926e-06 -2.11248e-06 1.07094e-05 3.98868e-05 3.12777e-05 4.89007e-07 -5.10857e-05 2.70545e-05 5.89663e-05 4.57519e-05 1.20582e-05 4.74585e-05 -0.000103385 6.2782e-05 -3.16369e-05 2.17196e-06 9.82579e-05 6.68229e-06 5.95472e-06 0.00035968 7.20575e-05 9.53784e-05 -7.88814e-06 -2.48051e-06 2.15967e-05 -0.000101991 5.61381e-05 -5.78967e-05 -7.3311e-05 2.61157e-05 -5.71931e-05 -0.00018874 -9.55234e-06 5.19649e-05 -7.78389e-05 1.47746e-05 3.38729e-05 1.10917e-06 1.01936e-05 2.75669e-05 -4.127e-05 8.59623e-05 -6.96114e-05 1.25205e-06 -2.96549e-05 -7.39985e-05 -0.000144641 -0.000112726 -9.13317e-07 -8.65228e-07 0.000133183 4.65392e-05 4.97421e-06 3.60915e-05 -3.56053e-05 6.91534e-05 -2.45628e-05 1.16627e-05 1.93184e-05 2.22008e-05 2.19114e-05 4.08498e-05 -6.96948e-05 6.64312e-05 -1.64676e-05 1.25516e-05 8.16707e-05 4.15992e-06 1.00802e-05 0.000287728 5.12236e-05 4.42128e-05 -1.65999e-05 -6.26445e-06 -1.25339e-05 -5.83689e-05 3.99041e-05 -4.05856e-05 -6.05962e-05 6.84548e-05 -4.66436e-05 -0.000127731 -1.42387e-05 4.00284e-05 -4.90148e-05 9.44562e-06 2.16111e-05 -1.20579e-05 2.47526e-06 7.27445e-05 -3.21737e-05 6.41318e-05 -9.09073e-05 -9.81416e-06 -1.0365e-05 -8.46648e-05 -0.000119837 -9.04985e-05 -3.22255e-06 5.97208e-06 0.000145756 4.3947e-05 -8.04808e-06 -1.07113e-06 -1.88227e-05 3.78457e-05 -4.48329e-05 -6.92182e-05 -0.000163708 2.88037e-05 0.000239214 -0.000192803 0.000238756 -0.000121635 8.11939e-05 0.000166944 -0.000247132 5.94698e-05 -9.73635e-06 -0.000559268 -4.69e-06 -8.80317e-05 -0.000113146 -8.5737e-05 6.16496e-05 7.24042e-05 -0.000205385 4.07933e-05 0.000178441 -0.00015185 9.58434e-05 0.000326649 7.77087e-05 -9.65167e-05 0.000136202 -2.19181e-05 -4.97124e-05 3.11434e-05 -2.92698e-05 0.00011832 0.000184601 -4.24796e-05 0.00016325 6.29832e-05 1.20953e-05 2.58383e-05 0.000159436 0.000160215 6.74638e-06 1.26725e-05 -0.000121874 -0.000119184 3.76187e-05 -0.000121616 5.73547e-05 -0.000173072 -1.12003e-05 3.06251e-06 1.96512e-05 3.43699e-05 2.05422e-05 1.84687e-05 -2.23432e-05 3.98392e-05 -1.36425e-05 4.26523e-05 6.61598e-05 3.18855e-05 2.21414e-05 0.000217925 3.17755e-05 3.63316e-05 -2.50413e-05 -1.55973e-05 2.34403e-05 -5.02113e-05 1.44508e-05 -1.92666e-05 -3.956e-05 2.73548e-05 -2.6008e-05 -0.000104847 -2.52831e-06 1.42924e-05 -4.30523e-05 1.24319e-05 9.78088e-06 -2.99178e-06 -8.9237e-07 1.86932e-05 -4.34043e-05 4.90157e-05 -6.03917e-05 -1.78402e-05 -9.42164e-07 -4.90475e-05 -9.20652e-05 -2.79108e-05 9.04127e-06 9.57987e-06 0.000111375 -5.15795e-07 2.08579e-05 -2.41402e-06 -1.60956e-05 1.3388e-05 -5.76418e-06 2.07299e-06 2.63664e-05 -7.23028e-06 -4.3077e-05 9.75183e-07 7.21813e-06 -1.49082e-05 -1.95936e-05 -1.39544e-05 2.94426e-05 -2.90495e-05 4.90068e-06 6.4829e-06 -6.97767e-06 -3.13462e-05 6.61941e-06 -2.42729e-05 2.83129e-05 4.7474e-06 3.36122e-05 3.67033e-05 1.20554e-06 7.26502e-06 -2.90992e-06 -1.89548e-05 -2.59191e-05 -1.03824e-05 1.19576e-05 -7.04297e-06 1.22311e-05 -1.77601e-05 -1.21143e-05 5.79225e-06 -2.59414e-07 -2.77582e-06 -1.91746e-05 3.48847e-05 6.87715e-06 -9.08798e-06 2.59426e-05 2.65254e-06 -1.22062e-05 1.19267e-05 -4.65566e-06 8.84271e-05 2.61542e-06 2.76663e-06 -2.00184e-05 2.22999e-05 7.9627e-06 7.34147e-06 6.42026e-05 6.23215e-06 -4.90808e-05 2.62056e-05 -3.25286e-05 1.85196e-05 -3.03373e-05 -1.84669e-05 6.92902e-05 -5.50691e-05 9.79206e-06 7.40328e-05 8.17756e-06 -1.24525e-05 4.01797e-05 -2.85671e-05 3.7661e-05 -7.35497e-07 7.88432e-05 1.79635e-05 -1.46385e-05 1.27655e-05 -1.71634e-05 -7.20867e-05 -2.02541e-05 -1.17553e-06 1.07568e-05 -1.1779e-05 2.17174e-06 -2.43488e-05 -4.06055e-06 -3.72783e-06 1.48239e-05 5.0876e-06 -2.86021e-07 6.11886e-05 -1.83536e-05 -2.43922e-05 1.42025e-05 -3.47621e-06 -4.20073e-05 -2.73446e-06 -4.13894e-06 0.000160414 -2.85871e-07 2.15748e-05 -3.80635e-05 3.93185e-05 4.56543e-05 -1.98753e-05 -0.000125687 8.08582e-05 0.000164615 -9.53746e-05 0.000144465 -5.99639e-05 7.41056e-06 0.000125688 -0.000105789 0.000131577 -2.07662e-05 -0.000265476 -2.82317e-05 -4.04691e-05 -0.000137863 -4.20137e-05 8.68134e-05 1.88548e-06 -9.64667e-05 2.03771e-05 0.000100641 -0.000141294 5.2506e-05 0.000132362 2.33787e-05 -2.6909e-05 8.10244e-05 -3.69281e-06 -2.26821e-05 2.68346e-05 -3.62672e-06 9.29464e-05 9.7187e-05 -2.94004e-05 0.000109211 0.000102349 1.12173e-05 -1.24591e-05 7.45989e-05 7.28205e-05 2.72734e-05 4.67976e-06 -2.66089e-05 -6.25114e-05 3.10142e-05 -7.51325e-05 3.26444e-05 -0.000119544 1.55926e-05 -1.46541e-05 4.92311e-05 7.44068e-06 -7.12039e-05 1.08459e-05 -4.4296e-05 6.13861e-06 -5.35581e-05 -2.75427e-05 8.69343e-05 -5.60123e-05 1.02981e-05 7.83433e-05 1.04281e-05 -2.82437e-05 3.43721e-05 -4.4404e-05 1.44319e-05 4.35217e-06 0.000111095 3.15761e-05 -1.23064e-05 1.40308e-05 -1.06879e-05 -6.42583e-05 -4.97153e-05 1.21154e-06 2.09743e-05 -1.25966e-05 -8.03043e-06 -2.23217e-05 -1.30197e-05 6.67276e-06 8.95399e-07 4.34284e-06 -2.92095e-05 6.45069e-05 -3.33319e-05 -3.3536e-05 2.90108e-05 4.40293e-07 -5.72519e-05 9.31311e-06 5.105e-06 0.000196616 2.85996e-06 8.27747e-06 -5.1996e-05 4.3201e-05 -3.38948e-06 -5.91933e-06 -3.28303e-08 -5.92332e-06 2.14468e-05 2.50333e-05 -8.18355e-07 -8.2905e-06 -2.13532e-05 -1.4859e-05 1.13335e-05 -6.08815e-07 -1.04352e-05 8.55806e-06 5.90775e-06 -9.13401e-07 -7.62703e-06 -4.9272e-06 -8.52976e-06 1.21978e-05 6.60515e-06 -5.50662e-06 -2.20232e-06 -9.93161e-06 -9.75692e-06 -2.40989e-06 -9.96887e-06 1.47539e-05 -1.39129e-06 6.66096e-06 7.47041e-06 4.42533e-06 7.4397e-06 2.87854e-05 2.37615e-05 -3.96682e-06 1.37322e-05 -1.18871e-05 -7.27734e-06 -8.98552e-06 -1.19348e-05 8.50512e-06 -1.06235e-05 7.50061e-06 1.31853e-05 8.07861e-06 -1.84644e-05 -1.26453e-05 -5.24262e-06 -5.16394e-06 1.99986e-06 -2.93251e-06 9.68317e-06 5.7667e-06 1.25841e-05 1.2535e-05 1.16505e-05 -1.23547e-05 -1.32885e-05 7.38389e-07 -8.76418e-06 1.09111e-06 7.17766e-07 -1.65282e-05 -1.37751e-05 4.20512e-06 2.72397e-06 1.07512e-05 -1.12193e-05 5.3653e-06 -4.36812e-08 -5.86464e-06 2.87355e-06 -1.81214e-05 -5.72591e-06 -6.30262e-06 2.49362e-06 1.16356e-05 -3.64715e-06 -4.13094e-06 1.25271e-05 6.33496e-06 2.21441e-06 1.74721e-05 8.44509e-06 5.9304e-07 2.96487e-05 -2.41432e-05 1.27577e-05 -1.4034e-06 5.66239e-06 2.44577e-05 -1.05075e-05 2.69211e-05 4.86827e-06 -2.69405e-06 -1.20516e-05 -1.59502e-05 2.1045e-05 -6.80388e-06 6.7392e-05 7.16738e-05 6.45255e-06 -5.80867e-05 -0.000130358 5.15289e-05 5.19188e-05 -7.68505e-05 -1.39604e-05 -7.73681e-05 -4.75399e-06 1.0789e-05 6.01123e-05 3.92335e-05 -3.66925e-05 0.000144234 1.07306e-05 5.46095e-05 -1.16192e-05 5.68223e-06 -7.21595e-06 -4.43063e-05 -3.36168e-06 1.02195e-06 -5.49671e-06 -6.57781e-05 4.2981e-05 -8.76237e-05 -7.49822e-05 -3.35496e-05 9.24632e-05 1.95165e-05 2.94777e-05 6.29126e-06 -6.78949e-05 -2.00569e-06 8.1061e-05 -0.000111727 -3.01099e-05 6.04828e-07 -2.33262e-05 2.804e-05 7.28439e-05 1.40097e-05 -1.63936e-06 2.53242e-05 5.31673e-06 -2.06444e-05 2.30473e-05 4.60583e-05 -2.36425e-06 -8.51445e-06 -7.7364e-06 3.30687e-06 1.38736e-05 4.45231e-06 2.04747e-05 1.00483e-05 1.88844e-05 5.6446e-06 -2.94038e-05 1.78342e-05 -2.36548e-05 -6.04679e-05 1.0703e-05 -1.94592e-05 1.9869e-05 -1.00661e-05 2.36861e-06 1.46912e-05 1.62577e-05 -2.8242e-05 1.81043e-05 -3.01627e-05 1.52664e-05 2.97765e-05 3.87725e-05 1.85911e-06 1.81453e-05 4.25422e-05 -8.03129e-06 4.12031e-06 8.5755e-06 -1.86893e-05 7.18194e-06 -8.10625e-08 3.42258e-05 1.77247e-05 2.23011e-06 1.4997e-05 6.37939e-05 -4.72096e-06 -3.36819e-05 2.1906e-05 -8.25615e-06 1.5087e-05 2.24451e-05 1.04527e-05 1.34815e-05 -7.59873e-06 5.39119e-06 4.97834e-06 1.99306e-05 2.82991e-06 -1.86573e-06 2.12993e-05 -7.02807e-06 1.34502e-05 6.27208e-06 4.70902e-07 -3.00074e-06 1.03679e-07 3.10241e-06 6.54096e-06 -2.31224e-07 -9.97784e-07 1.76675e-06 4.89713e-06 2.36301e-05 -7.75952e-06 -2.34063e-06 -4.50496e-06 2.9414e-06 2.82959e-05 1.13571e-05 1.23171e-05 9.70567e-06 -8.89918e-06 -1.04429e-06 1.10531e-05 1.86975e-05 -7.02238e-06 1.93846e-05 5.75387e-06 4.09295e-06 4.78738e-08 1.66727e-05 5.20343e-06 4.88673e-06 -9.94252e-06 8.11777e-06 -4.53514e-06 7.13e-06 -3.3865e-06 7.13649e-07 1.32302e-06 -2.28916e-06 -3.08503e-06 1.23489e-05 1.53968e-06 -1.31298e-05 7.36357e-06 -1.79991e-06 1.3464e-06 9.11249e-06 3.86417e-06 -7.07033e-07 1.62075e-05 2.10997e-06 -1.1156e-05 -2.67125e-06 5.78216e-06 -1.55408e-06 7.44468e-06 5.17486e-06 4.47949e-06 -9.5696e-06 -3.05716e-06 6.67912e-06 -5.02929e-06 -1.37206e-05 -3.1197e-06 2.06856e-06 1.1781e-05 1.11042e-05 1.2855e-05 -6.18683e-06 1.15636e-06 6.61819e-06 -1.04749e-05 1.07246e-05 -2.91366e-06 1.15081e-05 1.59874e-05 6.20999e-06 -2.78264e-06 5.64062e-06 9.48581e-07 -9.25802e-06 -7.46624e-06 9.45184e-07 -1.34413e-05 -1.11247e-06 5.05953e-07 -4.16014e-06 -6.22322e-06 -6.80742e-07 1.36505e-05 7.68073e-06 1.26873e-06 7.15505e-05 1.09327e-05 9.83152e-06 3.51707e-05 -1.82064e-05 2.81166e-05 1.1196e-05 -4.58184e-05 -6.53761e-05 2.69344e-05 -1.40441e-05 8.24468e-05 -4.13479e-05 -9.18939e-05 -5.33299e-05 -2.22345e-06 -1.62858e-05 5.95543e-06 5.07254e-05 -3.47811e-06 1.83879e-06 -3.03914e-05 3.19926e-05 7.30947e-05 2.29949e-05 9.08843e-05 0.000112192 -7.68215e-05 3.59459e-05 5.01004e-05 5.23754e-05 -8.16176e-06 4.92609e-05 -4.06915e-05 1.74613e-05 -4.88639e-06 5.91807e-05 1.53528e-05 1.15884e-05 2.2034e-05 5.47588e-05 3.69838e-05 4.71198e-05 -4.07021e-06 1.36154e-05 3.3203e-06 6.03053e-05 -2.11869e-05 4.90385e-07 -2.26718e-05 -9.37939e-06 -3.90272e-06 1.09272e-06 3.88633e-07 5.69924e-06 4.19399e-06 -1.76858e-05 2.91747e-05 2.32989e-06 -9.35596e-06 3.07944e-06 -5.1009e-06 -1.0345e-06 1.94785e-05 1.29389e-05 -2.0577e-06 -7.92244e-06 1.89066e-06 1.66758e-05 -8.22246e-06 -9.26375e-07 -8.13125e-07 1.73986e-06 2.42424e-05 1.23498e-05 1.88407e-05 -1.05591e-05 9.07179e-07 7.63593e-06 4.54962e-06 3.09307e-06 -3.27969e-06 8.23455e-06 2.31102e-05 4.45174e-06 4.70684e-06 3.05771e-06 6.30089e-06 -6.76799e-06 -1.67948e-05 -2.64567e-06 -2.24741e-05 -6.50547e-07 -5.62666e-07 -2.43672e-06 2.3356e-06 1.57284e-06 6.36078e-06 1.52345e-05 4.69885e-06 2.43186e-05 -9.31299e-06 1.31443e-05 -2.6886e-05 -1.2901e-07 -1.98156e-06 -1.64647e-05 -5.13017e-05 2.29534e-05 -4.35738e-06 -5.58442e-05 1.46483e-05 1.02958e-05 -0.00013597 -5.43855e-05 -3.43483e-05 6.07826e-06 2.29432e-05 -4.28106e-06 2.14676e-05 -4.11414e-05 -1.19681e-05 2.42628e-05 6.7975e-05 1.75227e-05 6.49854e-05 -1.19061e-05 -9.88108e-06 5.90839e-06 2.47514e-05 2.19172e-05 -8.03848e-06 5.34092e-06 4.0664e-05 1.03885e-05 -1.5776e-05 3.41034e-05 -2.38671e-05 2.96651e-05 1.7118e-05 2.59236e-05 3.70474e-05 6.33959e-06 1.67723e-05 -1.89554e-05 -5.83254e-05 9.4134e-07 2.51429e-06 9.11769e-05 -6.24426e-05 -2.04116e-05 2.08186e-05 3.55591e-05 -3.92002e-05 1.40184e-05 1.87569e-05 1.03046e-05 -4.7101e-05 1.20117e-05 -1.12054e-05 -8.6151e-05 2.3751e-05 1.01161e-05 -0.00010483 -4.88092e-05 -1.81995e-05 -3.41632e-05 3.27129e-05 -1.44607e-05 3.38994e-05 -5.58772e-05 1.19634e-05 1.4555e-05 4.10089e-05 1.07642e-05 1.21787e-05 -5.11344e-06 -4.75379e-06 2.32793e-05 2.91416e-05 3.49549e-05 -2.82033e-05 1.49651e-05 4.29532e-05 1.72674e-05 8.87936e-06 3.61802e-05 -4.8061e-05 5.09019e-05 3.07171e-05 2.71594e-05 6.02252e-05 1.75983e-05 -5.89128e-06 -3.7443e-05 -3.72859e-05 -7.28083e-06 3.74091e-05 0.000203321 -6.10744e-05 9.32069e-05 -1.24432e-05 -0.0001688 4.69742e-05 0.000202213 -0.000126877 0.000214685 -0.000166393 3.05696e-05 0.000224651 -0.000167074 0.00010326 -1.93135e-05 -0.000416086 -9.79984e-06 -1.96661e-05 -0.000195216 -8.16368e-05 5.77453e-05 -1.01759e-05 -0.000229626 2.56069e-05 0.000120334 -0.000140969 9.8985e-05 0.00015443 2.47908e-05 -0.000115995 8.47979e-05 -7.8543e-05 -6.78303e-06 -1.37591e-05 -6.56959e-06 0.000186674 0.000152392 -6.30235e-05 7.0167e-05 6.26926e-05 1.23577e-05 3.8462e-05 0.000134855 0.000161784 1.00482e-05 -2.98192e-05 -0.000103668 -0.000105412 7.29053e-05 -0.000133161 4.27418e-05 -0.000131819 -4.52862e-07 1.43458e-05 4.55281e-05 -3.19554e-05 1.22887e-05 9.30785e-06 -9.47303e-06 -1.26881e-05 1.5568e-05 -5.4642e-06 -7.79913e-05 1.88249e-05 6.58338e-06 -9.77254e-05 -3.90681e-05 -1.90633e-05 -2.74117e-05 3.22579e-05 -2.18482e-05 3.43055e-05 -4.12514e-05 -2.13519e-05 1.4911e-05 7.55326e-05 1.38363e-05 2.84379e-05 -1.31521e-05 -4.95271e-06 1.77647e-05 7.29107e-05 2.29531e-05 -6.8458e-06 3.00805e-06 5.40982e-05 2.77197e-05 1.00146e-05 4.91111e-05 -4.7945e-05 4.81472e-05 3.94846e-05 2.49539e-05 5.98522e-05 1.81493e-05 9.2683e-06 -2.30273e-05 -6.10614e-05 -1.07233e-05 3.78269e-05 0.000197303 -6.55638e-05 -9.92508e-06 7.96148e-06 2.19909e-05 7.53883e-06 -1.73481e-05 2.52566e-05 -1.77009e-05 9.70199e-06 -2.14681e-05 7.96665e-06 5.46924e-05 -1.13436e-05 3.12284e-06 0.000131504 2.38948e-05 4.34059e-05 -7.37173e-06 3.02843e-05 5.08298e-06 -3.03121e-05 -1.39785e-05 -1.01364e-05 -4.28384e-05 2.46153e-05 -2.81611e-05 -8.38479e-05 -1.5111e-05 1.78353e-05 -4.09139e-05 -2.5997e-06 8.36288e-06 2.38132e-06 -1.28145e-05 1.24376e-05 -1.54093e-05 1.24417e-05 -3.8482e-05 -1.45101e-05 -1.12116e-05 -2.82753e-05 -5.57504e-05 -2.39054e-05 -2.01245e-05 -1.06515e-05 2.43056e-05 2.41971e-05 1.23355e-06 7.89871e-06 -3.94892e-05 4.57994e-05 1.51772e-05 8.4279e-08 2.94183e-05 2.1185e-06 -1.88971e-05 3.35163e-05 -2.32576e-05 2.33143e-05 -2.32875e-05 8.8921e-06 5.70959e-05 -3.29906e-05 6.23005e-06 9.42623e-05 1.48398e-05 2.63019e-05 1.8846e-05 3.22583e-06 -6.59272e-06 -1.93258e-05 3.10174e-06 -1.6264e-05 -3.95717e-05 1.92431e-05 -2.28621e-05 -7.38062e-05 3.42448e-06 1.94408e-05 -2.7988e-05 8.34486e-06 7.01353e-06 7.26668e-06 2.66862e-06 -9.09246e-06 -6.18759e-06 3.16014e-07 -1.30687e-05 -3.29794e-06 -2.357e-05 -1.45049e-05 -3.76577e-05 -2.31198e-05 -1.47678e-05 -1.12243e-05 2.34917e-05 4.39814e-05 -6.03628e-06 2.43525e-06 -3.69885e-05 5.20451e-05 -6.95304e-05 -1.42735e-05 -5.80406e-05 1.08826e-05 0.000102246 -1.35751e-05 0.000103777 -0.000101269 -1.33186e-05 0.000126705 -4.16768e-05 4.92067e-05 2.37915e-05 -0.000139018 -1.97575e-05 4.09772e-07 -4.7597e-05 -3.73911e-05 0.000133344 -6.85746e-06 -0.00014983 3.75108e-05 2.73465e-05 -7.09974e-05 4.11366e-05 -4.92423e-05 -1.70613e-05 -3.33589e-05 -2.73779e-05 -5.31966e-05 9.53332e-05 3.78442e-05 1.99138e-05 3.95718e-05 7.51968e-05 -1.20984e-05 0.000111436 1.83315e-05 -2.15253e-05 -1.437e-05 1.82671e-05 4.12187e-05 6.01066e-05 -3.45522e-05 1.07099e-05 -4.19894e-05 4.32045e-05 -6.81508e-05 -1.24756e-05 -6.56949e-05 1.46074e-05 1.01973e-05 5.30898e-05 -7.71149e-06 -2.75384e-05 6.16261e-05 -5.92153e-05 1.60843e-05 -5.38694e-05 -1.53373e-05 0.000128556 -4.13292e-05 9.07065e-06 0.000223028 2.85516e-05 6.78282e-05 -5.35509e-06 3.09465e-05 -1.05483e-05 -5.47015e-05 1.22826e-05 -1.95995e-05 -7.12969e-05 6.05471e-05 -4.14995e-05 -0.000142017 -1.71811e-05 2.4287e-05 -6.17919e-05 7.90332e-07 3.56435e-05 3.50259e-06 1.00788e-05 2.22437e-06 -1.3577e-05 1.15724e-05 -4.52137e-05 -2.55489e-05 -4.43251e-05 -5.9304e-05 -9.29627e-05 -5.88081e-05 -4.28141e-06 -2.67734e-05 5.40994e-05 9.06922e-05 -5.29528e-06 1.98062e-05 -5.89032e-05 0.000100016 -weightContainer_hidden_0_0_to_hidden_0_0_delay_-1_plasticities 10000 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -weightContainer_hidden_0_0_to_hidden_0_0_delay_-1_weights 10000 0.0225559 -0.0834278 0.074425 -0.0665444 0.0390622 -0.0930986 -0.0312984 0.0716682 0.0652826 -0.0432128 -0.032084 -0.00340282 -0.0233996 0.059465 0.0672438 0.0699626 0.0371355 -0.0848568 -0.0245627 0.0953146 0.0620708 -0.0326974 -0.0181711 0.0200607 0.0428656 -0.0417634 -0.128443 -0.087839 -0.0873404 0.0525392 0.0814224 -0.00250657 -0.102991 0.000692845 0.0310506 0.0847679 -0.0646384 -0.0836361 -0.0978995 -0.117981 -0.00650177 0.01632 0.0664051 0.000841302 0.026553 0.0904983 0.0819325 -0.0225098 0.0761695 0.0723762 -0.0192743 0.00246078 0.00631449 0.0699602 -0.0501134 0.0573235 -0.115921 -0.00907862 -0.0487564 -0.0282942 -0.0385174 -0.0268694 0.0551461 -0.0155797 0.031022 0.0354184 0.0616295 0.0152533 0.0693255 0.040828 0.0885757 -0.0427651 0.0723907 -0.0168034 -0.0713851 -0.0151962 -0.0591876 -0.0977424 -0.0226203 -0.090572 0.0486771 -0.0703777 0.0489453 0.10739 -0.0262975 -0.0404792 -0.00925907 -0.0706976 0.054167 -0.0874241 0.0853732 -0.0327167 -0.0411694 0.040436 0.0477533 -0.0213643 0.0607821 0.0198868 -0.0245706 -0.056593 -0.00144621 0.0955856 -0.0106349 0.0226632 -0.0669201 -0.0905972 0.0664112 0.17334 0.117812 -0.0683726 0.0391128 0.108911 0.144903 -0.0519203 -0.054049 -0.0493519 0.0405721 0.0351337 -0.0860544 -0.0147049 0.0692322 -0.00247423 0.0143611 -0.0173101 -0.0540886 -0.0839737 -0.0146833 -0.244227 0.08607 -0.0778768 -0.108025 -0.0536126 -0.00874333 0.0433998 -0.0301507 -0.0150074 -0.00812568 0.0737225 -0.0699318 -0.0753749 0.054189 -0.0504824 0.155667 -0.000312775 -0.144185 -0.00602161 -0.150663 0.133544 0.0264197 0.0357808 -0.0972003 -0.0456422 0.0853743 -0.085524 0.00129838 0.0528964 -0.0889704 -0.0310013 -0.0476066 -0.00839949 -0.0695024 -0.00241046 -0.0755877 0.0878534 -0.0554496 -0.0787673 -0.0817862 -0.1018 -0.0171671 -0.0185931 0.0175022 0.0501383 -0.0805675 0.0174483 0.0401557 -0.0698294 -0.125563 -0.041307 -0.0551775 -0.0597102 0.00820667 -0.036304 0.0599352 -0.0330933 0.10822 -0.0686297 -0.00021418 0.0306932 -0.00100445 0.057433 -0.038437 -0.0473987 0.000607897 0.027513 -0.053085 -0.039354 0.0112729 0.0325228 0.0680105 -0.0886059 0.0896943 -0.0461663 -0.0404637 0.0288543 0.0874247 0.0229529 0.0923994 -0.0847482 0.0110882 0.112793 0.0127307 -0.00255769 0.0682825 0.0336826 0.0928361 -0.068105 0.0951481 -0.0553415 0.0803153 0.0293406 0.0620497 -0.10151 -0.0778398 -0.0534229 0.0243996 -0.121396 -0.0499124 -0.115897 -0.110849 0.0124666 0.0733544 -0.0679067 0.0915499 -0.0343285 -0.00623861 0.0611073 -0.0726365 -0.0259196 0.0117636 -0.102775 -0.0836776 0.0322497 -0.0280555 -0.0653978 0.0388702 -0.0846668 -0.0911762 -0.055396 0.0479972 0.0951833 -0.0542703 -0.063538 -0.0167043 0.0326976 -0.111045 -0.0471415 -0.0816848 -0.0041394 0.0528552 -0.0334747 -0.0912348 -0.0608362 0.0368161 -0.0431438 -0.0988422 -0.086645 -0.0351745 0.0678832 0.0853085 -0.0243032 0.0659037 -0.0750022 -0.0296681 0.0832162 0.0979451 -0.0631905 0.0432224 0.0407943 -0.00590802 -0.0706283 -0.0200653 -0.0476 -0.0152914 0.0881371 0.0863316 0.0706511 0.042855 0.0136767 0.0337803 0.0636804 -0.0533139 -0.00663536 -0.0591874 -0.0996075 0.0825125 -0.00950726 0.0222521 -0.0376535 -0.0715288 0.0511697 -0.0515156 -0.0179974 -0.0957016 -0.117857 -0.0420829 0.0666225 0.00197125 -0.0301522 -0.0315318 -0.00711852 -0.0927452 -0.00360615 0.00511427 0.0131701 -0.0755343 0.107903 0.152196 -0.0379494 -0.221199 -0.0240562 0.0459175 0.0415356 -0.169429 -0.0146591 -0.0804656 -0.0487458 -0.0881813 -0.0373449 -0.180076 0.0345995 -0.0932572 0.0550739 0.00312234 0.0798554 -0.107625 -0.0440581 -0.182602 0.0318425 0.0565794 0.0752204 -0.0383331 -0.0758832 -0.00472496 0.0505995 -0.0589545 0.0352904 -0.0176178 0.149355 0.0496379 0.0183766 0.0477121 -0.0381241 -0.0420753 0.0414008 0.0548123 -0.137254 0.0323832 -0.113038 0.022986 -0.0883728 0.0338721 0.049683 -0.111895 0.0861598 0.0103317 0.00847486 0.0672484 0.061383 -0.0525601 -0.0476424 -0.0407407 0.0683191 0.0045812 -0.00349195 0.0469951 0.0187869 -0.0621464 -0.00774324 -0.0679422 -0.0972243 0.034835 -0.135087 -0.0828717 0.0712822 0.0479155 0.0604312 -0.0657241 0.170918 0.0442724 -0.0813633 0.0867228 -0.0637734 -0.118138 0.0260605 0.113952 0.0188158 0.0803886 -0.0415656 -0.109229 0.0333877 -0.0551596 -0.0344247 -0.122201 0.0224667 0.0938467 0.0117199 -0.0374013 0.16671 0.155006 0.100832 -0.106742 0.0090645 -0.17326 -0.071016 0.0760887 0.0996136 0.101035 -0.0505442 -0.116349 -0.0281245 0.087401 -0.0430033 0.0293739 -0.104939 -0.0273954 -0.148078 -0.0688562 -0.0682807 0.14922 0.291358 -0.182828 0.0523283 -0.0134317 0.223801 0.0668564 0.0383693 -0.133664 0.149402 -0.0386767 -0.242649 0.0718326 -0.154678 0.108826 -0.0503838 -0.0355565 0.057873 -0.0554315 -0.101681 -0.0661704 -0.0624139 -0.0637751 0.0374887 -0.0814188 0.0962322 0.13636 -0.206978 -0.0888249 0.206944 0.0921264 0.153668 -0.0463519 0.0782229 -0.208512 -0.134557 0.181684 -0.237157 0.00423228 -0.125516 -0.00696799 -0.0679303 -0.0407429 0.141795 -0.125846 0.0689487 0.140001 0.0832676 -0.0371733 -0.101374 0.124865 0.00781553 -0.239967 -0.0388628 -0.102467 0.133505 0.111898 -0.129352 -0.139731 0.0640514 0.031486 -0.160425 0.0288676 -0.0758886 0.0459359 -0.161279 -0.0353332 -0.00558501 0.100305 -0.0305539 0.0766795 -0.0585858 -0.0307512 0.0269536 0.0161426 0.0574823 -0.142476 0.232828 -0.0773038 -0.256514 -0.0613669 -0.0266868 0.158829 -0.196261 0.243027 0.0889655 -0.410823 0.105787 -0.0392743 -0.0247819 0.305263 -0.0689563 -0.196513 0.015182 0.0527517 0.315433 -0.0988594 -0.0999348 -0.073497 -0.0204339 -0.209181 -0.0125981 0.283755 -0.126382 0.0201421 0.00374731 -0.0722963 -0.0748289 0.0979533 -0.304587 0.0218755 0.140393 -0.219376 0.0112896 -0.0248639 0.0813686 0.0519464 0.0765595 0.107289 -0.166626 0.153474 -0.223888 -0.0559903 0.0915512 -0.0835337 0.148642 0.134682 -0.0756729 0.0438894 0.0892607 0.0137364 0.0359545 0.000109005 0.0698972 -0.222031 -0.0456165 0.0201275 0.0842448 -0.101295 -0.146429 0.171509 -0.0533956 -0.0384996 -0.0457724 0.0525022 -0.0207979 0.0926667 -0.157874 0.0289664 -0.0377934 -0.0456519 0.181707 0.039754 0.0710901 0.0667784 0.178874 -0.066584 -0.0714827 -0.123404 -0.0217982 -0.11251 -0.2304 0.0216472 -0.135976 -0.0140503 -0.1361 0.0825956 -0.102648 0.0952593 0.0622051 0.108821 -0.117802 0.0414339 -0.132686 0.04561 0.0956872 -0.01848 0.112791 0.0500763 -0.0943362 0.167875 -0.103801 0.0494839 -0.119537 0.0993541 -0.0889589 0.0170325 -0.000695475 -0.0355416 0.0428184 0.0309751 -0.0494222 0.0634932 -0.185283 0.0405514 0.0235994 0.0344139 0.121177 0.0502695 0.0914826 0.0142998 0.00260332 0.0365394 0.0875643 -0.176546 -0.145116 0.0629972 -0.0492806 -0.0376404 0.0402906 0.0162241 0.0916654 -0.120773 -0.0697554 0.00382228 0.0375895 0.113725 0.10503 -0.0418801 0.0663869 0.0102507 0.0213373 0.0631052 0.0169462 -0.00673753 -0.00682506 -0.033714 -0.0802541 0.0552409 0.107695 0.105124 -0.0292883 -0.0699177 0.110428 0.045032 -0.114503 0.0283493 -0.0102115 -0.0460593 -0.0535283 0.0756041 0.0629215 -0.0398346 -0.0965432 0.118406 -0.0164436 -2.17103e-05 0.134217 0.109096 -0.117105 -0.154383 -0.102808 0.0665562 0.0356235 -0.102096 0.00367701 -0.0790902 0.0745591 0.0572153 0.192001 0.0930538 0.010363 -0.0090896 -0.0522286 0.0141689 -0.0279156 -0.0997941 -0.0742814 0.15954 0.0486407 0.00531171 0.0259459 0.0210692 0.0538037 -0.000942563 -0.262646 0.122613 -0.138612 -0.215146 0.266424 0.0216659 0.0844176 0.0281371 0.0728627 -0.149924 0.0212907 0.149599 -0.0865264 -0.365446 -0.114167 -0.0273151 -0.0927532 0.0157149 0.0984064 0.0545818 -0.0207693 0.0430084 0.0987858 -0.0587363 0.090881 0.460215 0.0109917 -0.080789 0.0293679 -0.394209 0.0339463 0.178517 -0.0259172 0.0594595 -0.111778 0.0348441 -0.251182 0.124681 -0.0192038 -0.0266 0.00664767 0.111203 0.0157075 -0.0881086 -0.215244 0.0883453 -0.0601349 -0.0760366 -0.0769217 0.0124876 0.0655715 -0.0363111 0.0101537 -0.151028 0.0546058 0.0515461 -0.0697585 -0.0477335 -0.0112409 0.0926283 0.00998641 0.0734658 -0.0379235 0.0286179 -0.0100413 0.0336184 -0.031437 -0.0494182 -0.0925607 0.0755105 0.0376272 -0.0162302 0.0600381 0.00741478 -0.0271921 -0.238643 -0.0960489 0.0447607 0.0318979 -0.0656715 -0.00332372 -0.000527756 -0.0323549 0.129081 0.0687356 -0.0547247 -0.0316321 0.022404 -0.00184703 0.0628296 0.0964838 0.0399955 0.0168549 -0.0384122 0.0183099 0.0198439 0.0701291 -0.0663372 -0.00946628 0.153248 -0.0803005 -0.0161353 -0.138037 -0.0806587 -0.0849793 -0.111583 -0.0590482 -0.0159801 0.027477 0.0826132 0.16945 -0.108779 -0.0704421 -0.0243743 0.117535 0.0569838 0.015461 0.184541 0.056398 0.110965 0.23908 0.0389221 0.00357745 -0.022593 -0.114845 0.0747135 0.0327388 -0.0225259 -0.0454644 0.0931793 -0.160058 0.059292 -0.0651308 0.138859 0.0810553 -0.131213 0.033089 0.00794119 0.037553 0.0332789 -0.0309187 0.0167584 0.102805 -0.00551495 0.158089 -0.0423091 -0.0302643 -0.0710645 -0.0757942 -0.0511589 -0.114908 0.151156 0.114487 -0.171808 0.0198058 -0.0198176 -0.220074 0.0480179 -0.000307668 -0.0743223 0.267207 0.073492 -0.0430634 0.103564 0.168485 -0.116063 0.0821628 0.134912 0.0474068 0.0677532 0.296471 0.1047 0.0568023 0.107236 -0.0619522 0.0412599 0.168605 -0.0974431 -0.0222112 0.0692466 -0.215993 0.033214 0.203632 -0.0219112 -0.192686 -0.0547422 -0.0319674 -0.0839585 0.0820985 0.0902876 0.0863166 -0.00261925 0.11111 -0.1276 0.128865 0.00327978 -0.0299774 -0.229476 -0.0746146 0.0938986 -0.00601632 0.268962 0.10968 0.0285828 -0.141574 -0.00554248 0.176466 -0.151229 -0.0195917 -0.181274 0.0180406 -0.0500427 -0.0129466 -0.159055 -0.183823 -0.149747 -0.00118917 -0.259298 0.0699463 0.108305 -0.120453 0.226347 -0.456246 0.0249588 0.222162 0.180395 0.0439628 -0.0283877 0.190332 -0.082147 0.0623309 0.375195 0.0237049 0.248243 0.144943 -0.0254376 -0.0273415 0.0783653 0.0318528 -0.199098 -0.0466393 0.151248 -0.00480484 0.107006 -0.166243 0.0706829 -0.428421 -0.0285147 -0.0852053 0.0848495 -0.0541942 -0.0610098 0.00582213 -0.131287 -0.100738 -0.052288 -0.218755 0.127877 0.0722714 -0.0412132 0.102117 -0.11046 -0.15404 0.0431363 -0.01969 -0.136115 0.065429 0.212519 0.126728 -0.0407296 0.308748 0.0168266 0.141193 0.0424618 0.00869889 0.0123388 0.119093 -5.17082e-05 -0.071438 -0.0015355 -0.255008 -0.0863692 0.111821 0.0230629 -0.0384772 -0.0915264 0.0233537 0.0839539 0.0443871 0.0575737 0.0880874 0.132984 -0.0210701 -0.00224915 0.0638907 0.00934875 -0.0123486 0.0608242 0.123704 0.021731 -0.284657 0.0461343 0.0898078 -0.014752 -0.163654 0.0960011 0.0436185 -0.232335 -0.0764332 0.145291 0.0364674 0.138827 0.128576 0.130732 -0.180847 -0.0663263 0.0212074 0.0626746 0.0831375 -0.149592 -0.0826684 0.0789937 -0.338194 0.0593712 0.0918723 0.114596 -0.28993 0.222493 -0.0871773 0.0129937 0.117361 0.146577 -0.0640117 -0.0304068 0.292708 0.0949907 -0.265053 0.35367 -0.178519 -0.0547755 -0.0330856 0.161677 0.0729662 0.092226 -0.0270949 -0.0423384 -0.271642 -0.121046 0.113762 -0.172637 0.0378492 0.387603 -0.16393 -0.378288 0.312177 0.211481 0.0966079 0.0147554 -0.111043 -0.300007 0.354339 -0.0242722 0.00581122 -0.261791 -0.100939 -0.0626664 0.043094 0.152686 0.0368626 -0.121973 0.0139292 0.287902 -0.00626178 -0.0371036 0.174512 0.451781 0.131574 -0.390478 -0.19975 -0.249386 0.31769 0.360486 0.0400791 -0.0470985 -0.134178 -0.0267013 -0.352182 -0.161211 0.147505 -0.0482762 0.0176707 0.130421 -0.126298 0.124415 0.139938 0.21575 -0.120872 -0.227038 -0.000221393 0.440876 0.0557476 -0.0985377 0.184579 -0.131449 -0.382474 -0.47894 0.126341 0.795666 -0.50071 0.294733 0.666437 0.119083 0.276591 -0.200589 0.206846 0.225127 -0.253542 -0.341272 -0.469657 -0.316138 0.376408 -0.39762 -0.957246 -0.300206 0.0722174 -0.658568 0.553233 0.386965 0.116291 0.293966 -0.111295 0.134951 0.350213 0.0703597 -0.487298 -0.48262 -0.227083 -0.572245 0.152783 0.0356146 -0.194354 0.659588 0.601235 -0.216895 0.290698 0.210585 0.222588 0.17881 -0.0644158 0.0190038 0.251437 0.155572 -0.250527 0.162068 -0.00983851 0.06523 0.143702 -0.177142 -0.181307 0.052931 0.53403 0.104133 -0.0675727 -0.0656783 -0.139921 -0.139719 0.0128851 0.0171275 -0.137403 0.393946 -0.135657 0.158236 -0.174072 -0.130811 0.0337868 0.153276 0.014793 -0.344288 0.0561006 -0.696717 0.363872 0.222811 0.155725 -0.360842 0.00786254 0.0327737 -0.161416 0.143139 0.132403 -0.166483 -0.0715202 0.257303 -0.0203341 0.219274 0.016331 0.220496 0.126908 0.0362358 -0.0460337 0.00788762 0.0450866 -0.0207731 0.119289 0.146078 -0.0813135 -0.0340319 -0.0752625 0.0463327 -0.0216293 0.0981194 0.074133 -0.036203 0.12987 0.0197003 0.0451561 0.0167589 0.122602 0.0313193 0.0471919 -0.0518988 0.0617049 -0.0923218 -0.125252 -0.0474757 -0.0538396 -0.0412657 -0.00677445 0.00664687 -0.0151709 0.0660873 0.0057746 -0.0669237 -0.0571354 0.0148141 -0.0553458 -0.0237498 0.0813175 -0.112942 -0.0722139 0.108488 -0.0436871 -0.00899112 0.0125104 -0.00420743 -0.0824601 -0.0149692 -0.0443743 0.0178737 -0.0108101 -0.00443378 -0.0115478 -0.0305833 -0.0638423 0.00839289 0.031425 0.0687215 0.0516734 -0.113032 0.0261829 0.0231924 0.0222469 0.010898 0.0573968 -0.0774943 0.0243819 -0.0717332 -0.0510219 -0.11233 0.0241285 -0.0395361 -0.116272 0.051247 0.00186886 0.140815 -0.0322275 0.0253629 -0.0643931 -0.118764 0.0637549 -0.0473133 0.00263862 0.106968 0.0412805 0.134282 -0.067881 0.0196571 -0.0146352 -0.0453542 0.0840814 0.0333041 0.038283 0.00965624 -0.0771132 -0.0669334 -0.0119719 0.0688867 -0.0768234 -0.0653682 -0.147494 -0.0461344 0.260666 0.0530371 0.0604321 0.0813161 0.0330039 -0.0596974 0.0807001 -0.120932 -0.0255009 0.0526412 -0.273463 0.0298817 -0.094887 0.113355 0.101123 0.0479593 0.112492 -0.165565 -0.0147938 0.155462 -0.11453 -0.0771729 0.0535977 0.093739 0.026167 -0.0727845 0.126543 0.052828 0.180248 -0.0309316 0.176733 0.101542 -0.0536345 0.0830723 0.12838 0.0579676 -0.0547704 0.0791261 0.104352 0.0762147 0.115914 -0.0166327 -0.0921488 -0.112504 0.0150712 -0.159892 -0.101996 0.0286739 0.0690563 0.101393 -0.107072 0.0816845 0.0243264 0.0517614 -0.0878367 0.00596662 0.0207759 -0.210193 -0.00571706 0.00703018 -0.108444 -0.0553119 0.0617895 -0.0967622 -0.0149193 0.0767027 -0.026416 -0.152223 -0.0573211 0.0624795 -0.0842631 -0.00962938 -0.0452435 0.100261 -0.0994503 0.113934 0.0454612 0.0256471 -0.116642 -0.0122179 0.0584408 0.13132 -0.0266012 -0.00439076 -0.0882843 0.00706615 0.0303411 -0.00237889 -0.0228107 0.0402323 0.120983 -0.0610805 0.0304656 -0.0211942 -0.137649 -0.0341322 -0.00300559 -0.0577401 0.0504402 -0.0224978 -0.108863 -0.120217 -0.111754 -0.10929 -0.00181541 0.00900673 0.0376632 -0.0513273 0.0721853 0.00620672 0.160626 -0.042768 0.03365 0.0252542 -0.0191588 -0.112571 0.0420388 -0.101721 -0.124765 -0.00931446 -0.0814377 0.0143328 0.124621 0.0609083 -0.0654533 -0.06485 -0.0402986 -0.0586811 -0.0933334 0.0929507 0.0279256 -0.0595865 -0.0287275 -0.0589449 -0.0772701 0.0196837 -0.0514534 -0.00279817 -0.0843971 -0.0378871 0.0351689 0.0423357 0.0259507 -0.0906054 0.0503451 0.0794232 0.116328 -0.0202132 0.130412 0.00345852 -0.0824822 0.0372667 -0.279099 -0.262586 -0.0195019 0.281984 -0.0794313 -0.0390719 0.179887 -0.260791 -0.0170302 0.0159802 -0.0483273 0.00689396 0.0795776 -0.058341 0.0428239 0.0147975 -0.0289376 0.014583 -0.00321427 0.187541 0.199909 0.155806 -0.054856 0.270811 -0.0877174 -0.0914755 -0.107115 -0.0367664 -0.0421752 -0.10228 0.105654 -0.0301954 0.0766125 0.0171391 -0.0376684 0.0901678 -0.0711664 -0.15209 -0.0513925 0.0306796 0.0801738 -0.00622782 0.160307 -0.0507721 -0.16011 -0.0587559 0.122965 -0.136258 -0.395479 0.0486671 -0.062891 -0.373491 0.244108 0.333686 0.149687 -0.15743 0.0672478 -0.445534 0.100147 0.278824 0.149092 -0.267806 -0.132318 -0.0696039 0.0416772 -0.0619127 -0.0661323 -0.124443 -0.244732 0.266811 -0.302555 0.368853 0.0249066 0.452628 0.218366 -0.0952989 0.107959 -0.0784074 0.168314 -0.012654 -0.00859513 0.210616 0.225977 -0.335122 -0.110681 -0.0113063 -0.275962 -0.15503 0.0747187 0.0685278 0.295621 0.0394735 0.206119 0.0971091 0.127949 0.0265083 0.067926 -0.0419337 -0.0670205 0.0286206 -0.176064 -0.0938827 0.0293676 0.128743 -0.110233 -0.161084 0.111599 -0.0670273 0.110634 0.0787887 -0.152722 0.00124008 -0.0251625 -0.179648 0.02798 0.0122425 -0.0368546 -0.0400183 -0.00596326 -0.0052632 -0.0118226 -0.048028 -0.00386447 0.0728785 -0.021555 -0.0827767 -0.0181424 0.168531 0.03089 0.0689467 0.0034752 -0.0983271 -0.00288939 -0.0794833 -0.122439 0.122202 0.0221366 -0.0438863 -0.130289 -0.059328 -0.00957422 0.0590521 0.00302806 0.0876558 -0.155738 -0.137515 -0.0428468 0.0025112 0.0513144 -0.114856 0.00984866 0.0770487 -0.0516899 0.00130607 -0.0594796 -0.200688 -0.0461537 0.00178487 0.0187368 -0.0607223 0.0227804 0.0722518 -0.0186254 -0.0993941 0.0446379 -0.209524 0.075506 -0.106424 0.0697603 -0.0105218 -0.118047 0.096357 0.0607021 -0.0984051 0.0541504 0.0531922 -0.0250464 0.129932 0.111753 -0.0453865 -0.0486882 0.134354 0.193761 0.102108 0.131676 0.153886 -0.0806421 -0.10216 0.162266 0.0753637 -0.147265 0.016921 -0.083779 0.0427887 -0.0541174 -0.0494104 0.00437658 -0.0563142 0.0356936 -0.0219131 -0.0608615 0.0195301 0.117398 0.08469 0.0998479 -0.0717583 -0.0860619 0.0308005 -0.0853515 0.0622796 0.00157009 0.0173876 -0.10811 -0.141722 0.0619668 0.0584986 0.0746851 0.012365 -0.213675 0.140345 -0.101484 0.00539599 0.0467686 0.00657335 0.155604 -0.122094 -0.0248689 -0.0203471 0.186182 0.0815926 0.158921 -0.114823 0.284661 -0.0684989 0.0619063 0.0957074 -0.128417 -0.0860986 0.0317424 0.0512534 0.00506691 -0.00281445 0.0627478 0.0532419 0.0579155 0.0216229 0.0314477 -0.0461603 -0.11247 -0.168022 -0.0967315 0.116519 0.145851 -0.130278 -0.0227623 -0.227901 0.156482 -0.278297 -0.274541 -0.180478 0.158878 0.0255689 0.130859 0.0437257 0.328471 0.0821736 -0.108651 0.177224 -0.0583749 0.097005 0.0792727 0.301682 -0.0335332 0.066262 0.218504 -0.299938 0.0430682 -0.214591 -0.128717 -0.182967 -0.0558904 0.116951 0.0481144 -0.137522 0.0685007 0.103637 -0.0465801 0.0838619 0.306108 -0.126563 0.128801 -0.180387 0.169513 -0.00276409 0.151864 -0.168592 0.055574 0.00810353 0.109745 -0.0863801 0.0284094 0.126906 0.0514177 0.0208531 0.10549 -0.0232633 -0.000111431 0.0637887 -0.163986 0.0675514 -0.047365 0.162892 0.00616905 -0.104681 -0.0234667 -0.0485302 -0.0719692 -0.029303 -0.0452699 0.0672023 -0.0738171 -0.0592046 0.00877504 -0.0960639 -0.0153916 -0.0620192 0.0321488 -0.0521208 -0.00815894 0.0134589 0.00308953 0.015498 0.0631957 0.012617 0.0992892 0.0102633 -0.127141 -0.0343411 0.0611012 0.0517544 -0.00768593 0.0139787 0.0383223 0.0285016 -0.0896721 -0.0312413 0.0591928 -0.0154728 -0.0904479 -0.190637 -0.0425781 -0.0522118 0.123824 0.00506423 0.0225552 0.0971006 0.0502881 0.0866277 0.227375 -0.0842618 -0.0886323 -0.00343725 -0.020397 -0.024129 -0.0918417 0.144889 0.0521524 -0.124264 0.143229 0.107163 0.142731 -0.0164289 -0.155848 -0.027035 0.00163632 -0.00295949 -0.0414405 -0.00446661 -0.0616246 0.00781846 0.0444876 0.0518891 0.0268738 0.0490019 0.0052068 -0.145498 -0.0161346 0.0113497 0.0500101 0.0752772 0.0528135 -0.105184 0.111497 0.0573313 -0.0132733 0.140839 0.0736711 0.0697517 -0.0692621 -0.163372 -0.00284996 -0.101707 -0.0647676 0.00234366 -0.0588077 -0.0405965 0.0603901 0.00478522 0.156996 -0.121063 -0.0612902 0.095476 0.0198467 0.0787077 0.14051 0.158739 0.0397739 -0.110028 0.0434777 -0.0397474 0.156987 -0.020232 -0.122616 -0.0537159 0.0163745 0.0910267 0.0189302 0.0585046 -0.200071 -0.167584 0.126878 0.0640361 0.0434492 0.135692 0.131151 0.115466 0.138371 0.150215 0.109601 0.0534305 -0.0846108 -0.0723201 0.071153 0.0218644 -0.0391426 -0.0401761 -0.0383078 0.0153915 0.275781 0.118296 0.013516 -0.0318111 0.118944 -0.0788634 0.185848 -0.211092 -0.0410423 -0.162981 -0.0718108 0.0562123 0.00495615 -0.161056 -0.219598 0.100195 -0.165994 -0.224093 -0.0797765 0.0961149 -0.373985 0.110355 -0.295233 0.134082 0.34588 0.162148 0.0601226 -0.0263055 0.101126 -0.114139 0.371621 0.21858 0.0256294 -0.0892305 -0.00427938 0.201951 0.0926605 0.0759727 0.211518 -0.160312 -0.0666 0.232491 0.0323483 0.430213 -0.0990442 -0.0858519 0.0885112 0.0892017 0.0747918 0.0102874 -0.0156371 -0.125773 -0.0195977 -0.195492 0.0420991 -0.028728 0.039219 0.167608 0.00899125 0.0149798 0.18548 -0.139358 -0.000755041 0.0580631 0.105441 0.051605 -0.0486001 -0.0378208 -0.120161 -0.101462 0.203369 -0.0610169 0.1424 0.0741876 -0.118242 -0.126281 0.166487 0.112931 0.00385381 0.0167204 -0.0872284 -0.0280746 0.119532 0.0233607 -0.00738418 0.0607864 -0.0408491 -0.084393 0.0838368 0.00979514 0.0742726 0.119478 0.0326908 -0.0858477 0.145494 -0.034123 -0.0550072 -0.013509 0.0622947 -0.0181884 0.0497557 -0.150536 0.189618 0.0437046 -0.0658824 0.0373698 -0.0324622 -0.142468 -0.0232374 0.0556315 -0.0563363 -0.232494 0.0595413 0.10526 0.0458921 0.0346522 -0.0324541 -0.137979 -0.117969 -0.0761513 -0.0987735 -0.0152991 -0.0949111 0.0734524 0.0069767 -0.187848 0.100121 0.046117 -0.0402105 0.0988317 0.131902 0.0576434 -0.0211162 0.134174 0.0789648 0.172763 -0.111851 0.0894288 0.0861796 0.172179 0.116564 0.245133 -0.0213267 0.0246208 -0.0776205 -0.178147 -0.0550329 0.0686357 0.0812525 -0.0737915 0.0126149 0.0531137 -0.245729 0.0325997 0.0913756 0.0857469 0.171143 -0.361252 -0.0535379 -0.0240519 -0.00947136 0.0880425 0.0341178 -0.159063 -0.0354812 0.191967 0.0384402 -0.143084 -0.0896873 0.00487393 -0.263687 0.131537 0.0345986 0.172242 -0.166313 0.257943 0.113924 -0.143228 -0.0534317 0.0578986 0.232513 0.138836 0.0888322 0.0487582 0.147695 0.104933 0.114046 0.0535523 0.0751774 0.0641379 0.0339131 -0.103559 0.125564 0.0984372 -0.265983 -0.0155781 -0.00181045 -0.01799 0.00434719 0.139516 0.0650253 0.0408237 0.209094 -0.327855 0.198045 -0.284044 0.115767 0.347635 -0.0787429 -0.295481 0.543785 0.103458 0.200056 -0.165342 0.142399 -0.0840974 -0.191135 0.614243 -0.153678 -0.11901 0.192443 0.170447 -0.512084 -0.180475 0.173858 0.0964875 0.252671 -0.0456495 0.0338928 -0.0363676 0.0894621 -0.0328376 0.0977813 -0.183061 -0.339528 -0.379203 -0.0546789 -0.451001 -0.132378 -0.0319487 0.0132161 0.153846 0.145479 0.0304704 0.24801 0.265903 0.193105 0.120028 0.00253845 0.0423582 -0.209992 -0.0124837 -0.00517895 0.232418 -0.0501618 0.217926 -0.154233 -0.379729 -0.0701316 0.10941 -0.136544 -0.195424 0.141471 -0.0881616 0.121145 0.250322 0.18215 -0.414803 0.114778 0.0207809 -0.212483 0.172716 -0.173541 0.37122 -0.329713 -0.00613568 -0.0890092 0.151885 0.0852415 0.0455268 -0.0571654 -0.0665315 0.0177476 0.308055 -0.2698 0.219065 0.173723 -0.0842391 0.0849212 0.114961 0.306042 0.0608654 -0.107096 0.107053 -0.159378 -0.0223825 -0.0976262 -0.107547 -0.00115634 0.0616492 0.0523871 0.117898 -0.0333532 -0.0419907 -0.0589592 0.0373136 -0.0910495 -0.0887972 0.0233576 -0.148932 -0.0364523 0.0609766 0.0309982 0.0210435 -0.115045 -0.0169646 0.0284228 -0.0326051 -0.0205705 -0.156207 -0.0279263 0.14903 -0.00611927 -0.0450058 -0.00148063 0.0170261 0.0248791 -0.120821 0.0597642 0.000911023 0.229736 0.0147088 -0.0317092 0.0297634 -0.0946419 -0.0534624 0.0670659 -0.0861664 0.0488408 0.105124 -0.0841511 -0.0990926 0.0729263 -0.0690575 0.00602481 -0.0238438 -0.110618 0.00814094 0.085875 0.0274634 -0.0510032 0.0353729 -0.0231166 -0.107601 -0.0303378 0.0442966 0.0426301 -0.0743007 0.136763 -0.148618 -0.0492663 -0.0206904 -0.0553688 0.141697 -0.0231704 -0.0298672 0.108636 0.19205 0.0575862 -0.108471 -0.0134308 0.0669115 0.0266727 -0.0203531 -0.0407184 0.142425 -0.0728708 -0.208163 -0.116109 -0.0999293 0.0288319 0.0319433 -0.0942295 -0.0382471 -0.0175728 0.0545713 -0.144612 0.0406902 -0.0597588 -0.00621942 -0.0605834 -0.101927 0.0632213 -0.127553 0.016669 -0.00913432 -0.134273 0.131404 -0.0208481 -0.193382 -0.121981 0.0661991 -0.109049 -0.0378357 0.0585929 0.0792029 -0.0263756 -0.245304 0.161872 -0.140941 -0.0603649 0.161681 -0.34125 0.0179176 -0.0361997 -0.323006 0.0461627 0.220533 -0.00980775 0.0523809 -0.142201 0.207178 0.235513 -0.0465623 0.032497 -0.068087 0.0055175 -0.149961 -0.0319354 0.143881 -0.145569 -0.0314563 0.0848285 0.119583 0.17891 0.0125725 0.0622705 0.0680556 -0.0177214 -0.106181 -0.208875 -0.149653 -0.165903 -0.0378626 0.0434891 0.0873838 0.10094 -0.0561427 0.0183295 -0.0156952 0.0576485 -0.00558096 -0.0068706 -0.145573 0.0130163 -0.202642 -0.0154053 0.0363295 0.00257545 -0.064872 0.164456 -0.00448367 0.106549 0.0372343 -0.221475 -0.0966503 0.0578069 0.107598 -0.0694679 -0.144104 0.0151995 0.091413 -0.257959 0.0279335 -0.10809 0.15704 0.106992 0.0376708 -0.0880873 0.117361 0.126284 -0.0811904 0.0204573 0.0581358 0.019257 -0.120181 -0.140173 -0.0601189 -0.093511 0.0180074 -0.0745539 0.0515532 0.111997 -0.16436 0.0244277 -0.000252055 -0.0832975 0.0150349 0.0232091 0.253932 -0.0501886 -0.0771338 0.00706967 0.0845696 -0.324707 -0.0715598 -0.350973 -0.0569704 -0.169432 -0.0238685 0.269978 -0.0359782 0.0818053 -0.0591928 -0.0744371 -0.0187622 0.119179 -0.115399 0.267324 -0.124444 0.239179 0.0364286 -0.515475 -0.28108 0.0480291 -0.102539 0.0140012 0.166728 0.15013 -0.13753 -0.0269624 -0.0429127 -0.312157 0.0547201 -0.161309 0.134023 -0.0110382 0.267152 0.316255 -0.0446013 -0.018126 0.017729 0.0121554 -0.121181 -0.197451 0.0632411 0.048276 -0.0779833 -0.00846231 -0.266271 -0.048697 0.119883 -0.25189 0.0735092 0.252682 0.206995 0.0404021 -0.082991 0.0641098 -0.603639 0.00235876 0.0470217 -0.159156 -0.0671075 -0.0296664 -0.257323 0.06866 0.145386 0.0621663 0.0166946 -0.0758052 0.272792 0.244366 0.157059 -0.0747901 0.114771 0.0468677 -0.270828 -0.132211 -0.154795 -0.10301 -0.0965573 0.0740206 0.0126953 -0.0352657 -0.132304 0.174455 0.0437746 -0.112285 -0.0612181 0.0912767 -0.287882 0.00110061 0.182242 0.0153346 0.0490634 -0.0745801 -0.279177 -0.0181728 0.0367365 0.107864 0.188837 0.412325 -0.233153 -0.0349652 -0.162252 0.1413 0.557691 -0.0856507 0.771742 -0.0234968 0.274701 0.0399431 0.0651164 -0.118721 0.0022977 -0.190743 0.289588 -0.156718 -0.0844113 0.112947 -0.176741 -0.473871 -0.359687 0.0145464 -0.273322 0.38959 0.079434 0.0809957 0.0405909 0.0198203 -0.085399 -0.0426398 -0.0512631 -0.133114 -0.270281 -0.540944 -0.260347 -0.0286519 -0.201027 -0.360808 0.479403 0.371766 0.0133953 0.324567 0.204725 0.162981 0.206236 -0.0283153 -0.20557 -0.027016 0.0857045 -0.208064 -0.216125 0.219884 -0.0072968 0.0760694 -0.266222 0.0105601 -0.18564 -0.28627 0.106256 -0.205734 0.215185 -0.299435 0.0288552 -0.0651548 0.252956 0.163942 -0.249497 0.000719055 0.250757 -0.0238725 0.0581321 0.110419 0.361104 0.0452978 -0.330583 -0.164465 -0.0353701 -0.06941 0.0292395 0.133494 -0.119793 0.427192 -0.130925 -0.196075 0.141463 -0.141619 -0.0920065 -0.0382031 -0.014695 -0.0350728 0.139408 0.123936 -0.0604933 -0.0372924 0.249302 0.0360275 -0.0730581 -0.0014631 -0.517574 0.226907 -0.0347045 -0.515181 0.0599535 -0.604099 0.0757385 0.151857 0.0948191 -0.38536 -0.474127 -0.535824 0.368248 0.284419 -0.0820914 0.179509 -0.00793595 0.676815 -0.219914 0.205298 0.00156668 0.0630627 -0.173289 -0.0440801 -0.266441 -0.246513 -0.0827833 -0.19328 0.0669683 -0.42346 -0.109498 -0.315693 -0.208888 0.0618727 0.401485 0.290784 0.428511 0.356606 0.511368 0.156976 -0.175746 -0.236872 0.481227 0.244135 -0.370369 -0.0588719 0.129043 -0.243649 -0.61571 0.277633 0.116895 -0.0656274 0.0292381 0.537326 0.303983 0.0667828 -0.38266 0.394192 -0.434646 -0.870265 0.0113421 -0.590139 -0.0564464 -0.0448822 0.00452621 -0.0013558 -0.312282 0.416999 0.0337872 -0.533032 0.10868 0.478837 0.539329 -0.672978 0.472522 -0.277439 -0.31178 -0.0627171 0.199281 0.0176377 0.259017 -0.410846 0.145243 0.266602 0.188511 0.0987224 0.158833 -0.010692 0.187868 0.148763 -0.491014 -0.672244 0.626513 0.0512532 -0.628652 -0.383248 -0.352213 -0.14875 0.127202 -0.111127 -0.0331688 0.636979 -0.110896 0.411162 -0.182743 0.582462 0.667025 -0.380111 0.0868744 -0.552562 0.386327 0.564691 -0.447868 -0.117619 -0.0466493 -0.224414 0.329071 -0.807517 -0.0301216 0.124854 -0.432271 -1.02058 -0.0847213 0.334423 -0.167145 0.567987 0.547013 0.086891 0.146712 0.246062 -0.149439 0.458346 -0.00833917 -0.197608 -0.374314 -0.680737 -0.80273 -0.371172 -0.472908 -0.615392 0.834749 0.629269 -0.339398 -0.0530538 0.5649 0.470884 -0.0105076 -0.151179 0.0684144 0.29041 -0.206448 0.561593 0.5671 -0.301252 0.0800996 0.226724 -0.185701 -0.198632 0.410714 -0.729089 -0.289485 -0.22315 0.0243673 0.39531 0.587798 0.086181 -0.373529 -0.2065 0.695042 -0.798663 0.0970971 -0.0185565 0.470698 -0.435211 -0.0597532 0.0318634 0.254509 0.217595 0.325146 0.114056 0.181061 -0.0384322 0.360087 0.0842089 0.264229 0.328357 0.425192 0.264116 0.380952 0.243893 -0.0403147 -0.0516265 0.271995 -0.182546 -0.333318 -0.274542 0.0260572 0.0729651 -0.127758 -0.0304936 -0.0666121 -0.167625 -0.13429 -0.0960357 0.0261247 -0.180226 -0.0381835 0.00727938 0.00228508 0.269001 0.127949 0.0658395 0.139627 0.0206838 0.0205178 -0.00910397 0.0767261 0.0554548 0.0409828 0.0563862 0.0654757 -0.00253827 -0.0396943 -0.140258 0.00340365 -0.0215488 0.0641142 -0.1185 0.0966902 -0.0616214 -0.0754234 0.0715277 0.0416091 0.0543326 0.00195841 -0.00137021 -0.020071 -0.00151477 -0.0755361 0.0128905 0.0750545 -0.0906916 -0.0361396 0.12708 0.0339287 0.0629176 -0.0459105 0.051392 -0.0883728 0.0294115 -0.134694 0.0522158 -0.067232 0.0211783 -0.051055 -0.0449494 -0.0509788 0.0315663 0.0323705 0.0964807 0.09418 0.0511834 0.0136998 0.0155723 0.0891021 -0.0222454 -0.0541347 0.00325233 0.0339637 -0.0562447 0.023867 -0.0481187 0.121177 -0.043365 0.14851 0.164237 0.0152995 -0.0305923 0.142773 -0.121204 0.0513969 -0.0277039 -0.0118904 0.0774934 0.0350593 -0.0327942 0.155108 -0.032616 0.106804 0.150575 0.0447129 0.0732615 -0.0548081 0.0570573 0.0657552 0.0411815 -0.0609155 -0.0274382 -0.184403 0.0894899 0.222613 -0.000598107 -0.0950622 -0.027867 0.0671643 0.251342 -0.0253139 -0.00465791 -0.151384 0.0573348 0.11687 0.0114902 0.0367856 -0.0743112 -0.133717 -0.179327 -0.130729 0.068703 0.0457956 -0.187678 0.00318627 -0.131055 -0.0311807 0.253453 0.00506676 0.104513 -0.0559343 0.0164203 0.117131 0.0937615 0.0830025 0.0509967 -0.0648195 0.114485 -0.00646818 -0.173459 -0.028777 -0.121384 -0.0923967 -0.158973 0.145977 -0.0690019 0.244427 -0.0553334 0.227979 0.0371914 -0.0642471 0.0503896 0.0104237 0.0601098 -0.174471 -0.150447 -0.136025 -0.18109 0.0624095 -0.204863 0.0499892 0.0068855 0.0499395 0.184038 0.129622 -0.0328746 0.112414 0.0758942 0.0432595 0.126189 0.118962 0.0363167 -0.0338937 0.0516219 -0.026814 0.0385465 0.0171413 -0.0658591 -0.0365425 0.0690431 -0.0884248 -0.0870367 -0.0800765 -0.160321 -0.0974364 0.0302193 -0.113006 -0.029596 0.106981 0.0562732 0.131098 0.0553539 -0.0142125 -0.0219836 0.0691879 -0.0156153 -0.0466291 0.0755294 0.0554611 0.0211093 -0.0539065 -0.0730231 0.119644 0.00024197 0.158401 -0.161714 -0.100069 0.141483 -0.0804851 0.0783088 -0.0603194 -0.137801 -0.0290126 0.00963043 0.0283291 0.00147452 0.0932043 -0.0820044 -0.144531 0.0106633 -0.0577699 -0.102478 -0.0711715 0.0896663 0.148304 -0.0508219 -0.110218 -0.0764508 0.0951547 0.0114364 -0.292771 0.0222123 -0.11171 0.152924 0.0710531 0.0802185 -0.172371 0.00292263 -0.0188054 -0.253026 0.101254 0.0547944 -0.0305518 -0.0170823 0.0219536 -0.038918 -0.0970854 -0.0814108 0.049858 -0.107362 -0.0171749 0.0706307 -0.183099 0.0175287 -0.0374491 -0.217445 -0.127113 0.0497958 0.11309 -0.0151149 0.0279583 0.092408 -0.0742246 -0.021154 0.0573534 0.0915905 -0.0713246 0.029291 -0.137061 -0.016568 0.135007 0.0502658 0.0251958 0.0687815 0.08298 0.255085 0.0691042 -0.164069 0.188324 0.0658562 -0.179249 -0.0545169 0.0166984 -0.039511 -0.0921373 0.0327868 -0.123748 -0.0807686 0.0203413 -0.170008 -0.0379554 -0.00282535 -0.0507883 0.0944856 -0.150936 -0.138731 -0.0230321 -0.00634533 0.03212 -0.0139862 0.0645869 -0.0648941 -0.122395 0.0482804 -0.0626769 0.55485 0.0416626 -0.0815131 -0.112904 0.152026 -0.0440378 0.0961862 0.0627347 -0.120422 -0.0412009 0.0795481 -0.102507 -0.0169318 0.0705564 -0.0410316 -0.485446 -0.149297 -0.0172996 -0.25759 -0.110254 -0.421199 0.190977 0.182787 -0.314869 0.0974036 0.176047 0.044126 0.165497 0.137627 0.0459661 0.0952281 0.302031 -0.331811 0.238583 0.0764899 -0.226069 -0.117443 0.337868 0.0965911 0.419926 -0.148379 0.269849 -0.0784054 -0.238689 0.0923343 0.135901 -0.0848268 -0.0908422 0.065617 0.0772915 0.000130333 -0.0362408 0.216675 -0.0952513 0.0946475 0.0661848 -0.0366271 -0.074597 0.0763248 0.0106413 -0.0317314 0.104996 -0.0431466 -0.138542 -0.00754052 0.266311 -0.14978 -0.0821173 0.192545 0.177773 -0.159098 0.000256834 -0.12045 0.0830382 0.219729 -0.281956 -0.0919906 -0.172651 0.146573 -0.0613336 0.0595537 -0.080972 0.0270849 -0.00354529 -0.366079 -0.0709429 0.0631113 0.0121906 -0.152888 0.0112183 0.126344 -0.0310441 0.188518 0.194582 -0.058614 0.0541133 0.0569898 0.0510475 0.0911803 0.0476278 0.104184 0.0458322 0.0386119 -0.121988 -0.099599 0.146236 -0.0463278 -0.0378929 0.148601 -0.0309548 -0.076369 0.00666738 0.11205 0.0543753 -0.161391 -0.00475848 -0.0387852 0.0577411 0.247937 -0.0704853 -0.0288065 0.0498372 -0.0556437 -0.00230436 -0.0183832 0.0240361 -0.107073 -0.016009 -0.111787 0.0922439 0.036879 -0.174 0.0541763 -0.161254 -0.0393716 -0.0815869 -0.0379049 0.0463167 -0.127537 0.0686927 0.00888112 -0.0905957 0.00909658 0.0777024 -0.00103774 -0.0818224 -0.0638718 0.105948 0.064653 -0.258888 0.0341175 -0.109436 0.0312709 0.0472716 -0.100427 0.0888017 0.0429908 0.00337546 0.067018 -0.00593358 -0.0715138 0.0791384 0.169452 -0.0189701 0.0178391 0.0708108 -0.0257953 0.0431379 0.212171 0.0120126 0.192613 -0.0307502 0.0306791 -0.051259 0.00367182 -0.082069 -0.0360204 -0.0271234 -0.184071 0.00162957 -0.00440962 -0.0485027 0.0424302 -0.0542261 0.0410995 -0.0268945 0.0744759 0.124895 -0.00659533 -0.0122389 0.106065 -0.00517194 0.0754256 -0.0102824 0.0434542 0.0314925 -0.0960779 -0.115813 -0.0531375 -0.181593 -0.0294978 -0.129274 -0.0155849 -0.220955 0.0271734 0.077606 0.0611792 0.143902 -0.0800223 -0.010617 -0.0962171 0.090394 -0.0309611 -0.176077 -0.136316 0.28574 0.0709219 0.0533569 0.139075 -0.19008 0.0199514 -0.00646877 0.0836452 0.0344433 -0.0131106 -0.126285 -0.0509713 -0.0158919 -0.24069 -0.153081 -0.0701199 -0.187155 0.193822 -0.234169 -0.16431 0.144188 -0.0905528 -0.00878951 -0.031693 0.00653839 0.150112 -0.15552 0.145522 -0.00299942 0.143276 -0.101548 0.086618 0.153546 -0.0620444 -0.145889 -0.089181 -0.0825684 0.0444279 -0.0663393 -0.180904 0.116361 -0.130034 0.12057 0.0516095 -0.140271 0.0189152 -0.0159256 0.105427 0.135654 0.112447 0.0332846 -0.00592114 0.0408678 0.141468 -0.0340469 0.0870967 0.030699 0.032125 -0.0222262 0.110704 -0.05909 -0.123325 -0.0658034 -0.195371 -0.0100206 0.0253442 0.0695545 0.0840033 -0.141156 -0.115307 0.00375094 0.0094032 0.0790252 -0.0324317 -0.0268667 0.100036 0.0507566 0.180478 0.0394361 0.109164 0.14248 0.104183 -0.0589042 -0.18091 -0.070941 0.00470207 0.029949 0.0172561 -0.0117568 0.0429155 -0.112595 0.0707159 0.0155774 0.0139606 -0.105889 0.0271292 -0.0239009 -0.107268 -0.0600894 -0.0187403 0.034291 -0.0523297 0.0131697 0.118502 0.126936 0.0433326 0.0398049 -0.0459931 -0.0281949 -0.110061 -0.0503213 -0.113773 -0.129087 0.00480633 -0.00960563 0.0407206 -0.079855 -0.0625346 -0.0427101 0.0640015 0.00570077 0.0473526 -0.0566421 -0.0624687 -0.0659263 0.0394966 -0.0500998 0.0706881 0.0798548 -0.00111206 -0.0102227 0.00587318 -0.090134 -0.0838902 -0.131793 0.0545046 -0.0190777 -0.189881 -0.059611 -0.0406859 -0.0491499 -0.0428906 0.0115725 -0.00944542 0.0518223 0.0360752 0.00464838 -0.0653478 0.0654726 0.0487151 0.15787 -0.0321699 -0.0721909 0.0340359 -0.0882922 0.0305511 -0.0373516 -0.0500817 -0.156775 -0.106752 0.0678135 -0.0711136 -0.0956449 0.0353445 -0.00139485 0.113489 -0.0893311 0.0870011 -0.0502837 -0.098801 0.0237992 -0.0715332 -0.0981253 -0.0375269 -0.0225687 -0.0656865 -0.0419919 -0.0117286 -0.0887932 0.0597801 0.0842643 -0.0028788 0.0505633 0.163815 -0.284348 0.0712354 0.0137491 -0.21016 0.0179859 -0.106877 0.232696 -0.116444 -0.101187 -0.0436242 -0.130194 0.105458 -0.0503805 0.156029 0.0356539 0.0997699 0.0556814 -0.207578 0.00312049 0.082424 0.118789 0.155672 -0.0739407 0.120517 -0.153967 0.164664 0.0609555 0.0165421 -0.128248 -0.0921161 -0.339014 0.00521269 -0.0598536 -0.376273 0.152429 0.219133 -0.256646 0.152685 0.147279 0.0761276 -0.180575 -0.0400983 -0.209941 0.0459301 0.0166386 0.0111198 0.0262283 -0.100331 0.0891219 -0.0873216 -0.0807579 0.0719847 -0.0866527 -0.158076 -0.103152 -0.0665983 -0.0767871 -0.023462 -0.0487501 -0.0318702 -0.0335148 0.0645397 0.105537 -0.0141673 -0.0953382 0.0760122 -0.0323926 0.100005 -0.0732822 0.113218 -0.00899565 -0.0184694 -0.10925 -0.019741 -0.0887836 -0.016798 -0.00198384 -0.0670181 -0.128177 -0.0685043 -0.137866 0.0896355 -0.0959262 -0.060203 -0.0469226 -0.0542753 0.0542035 -0.0818764 -0.182596 -0.0268116 -0.0199609 -0.0331591 0.0478181 0.173669 0.0126663 0.0625991 -0.0223764 -0.057111 -0.055999 0.0119644 0.0665332 -0.0535354 -0.035097 0.0311034 0.0177449 0.0670773 0.156392 -0.0398525 -0.0559925 -0.0186572 -0.0264617 -0.0559897 0.0647477 -0.0148408 -0.135273 0.0657288 0.167498 -0.14728 0.0453733 0.0631911 8.26149e-05 -0.0201963 0.0551231 -0.01263 0.0785214 0.144323 -0.157376 -0.0438573 -0.0878586 0.0335374 -0.0674568 0.0918257 0.0750625 0.122849 0.0516652 -0.103941 -0.0873784 -0.0495308 0.0611236 0.0487279 0.148402 0.0442216 -0.0013193 0.091423 0.00431542 -0.0904891 0.030776 0.0132887 -0.0427633 0.175839 0.134668 -0.00486272 0.0157378 0.137418 0.167227 -0.0523212 0.160568 0.0112978 -0.103835 0.100791 0.12457 -0.207713 -0.134566 0.0144343 -0.191776 -0.0926485 0.00383363 -0.131114 -0.101647 0.156337 0.0376633 0.132439 0.115295 0.0231507 0.055533 0.0418899 -0.120626 -0.0659861 0.0336112 -0.0440109 -0.0478732 -0.00938933 -0.118661 -0.126833 -0.0504266 -0.11694 -0.0547605 0.0521914 -0.0632325 -0.109323 -0.0247294 -0.121473 -0.0702963 -0.00358818 0.0622774 -0.183509 -0.00828263 -0.158527 0.03485 0.179092 -0.080111 0.0122208 0.12823 -0.147885 -0.0493934 -0.0376124 0.144831 -0.19094 0.171306 0.00333661 -0.150284 0.0419071 -0.115253 0.0195947 0.158405 -0.0784261 -0.245335 0.217936 0.109443 -0.0852311 -0.0707288 0.18952 0.0376668 -0.189012 -0.0124321 -0.0366742 0.230418 -0.127078 0.0922257 0.0260401 0.0463696 -0.126468 -0.0102262 -0.171889 0.036839 0.132088 0.163919 0.140016 0.19489 0.108563 0.0578559 -0.130987 0.227507 -0.187933 -0.176112 -0.0506967 0.0378561 0.105777 0.0662986 0.0992952 0.104076 -0.147019 -0.165892 0.114498 0.0841702 -0.0797851 0.128896 0.156387 0.0217051 0.187629 0.0373545 -0.15142 -0.13787 -0.0412597 -0.0215204 0.0301253 0.202367 -0.0108128 -0.0909873 0.0117714 -0.0685439 0.0499815 0.101431 0.0369632 0.202182 0.146336 -0.12116 -0.0782515 -0.0846522 0.0666001 0.0113655 -0.0716639 0.00402791 0.00627195 -0.10764 -0.165623 -9.5641e-05 -0.217787 0.0509665 0.0220376 -0.0357085 -0.0759704 -0.153628 0.0455821 0.0813483 -0.0768874 0.0227549 -0.0181426 -0.025045 -0.113107 -0.206337 0.0593259 -0.139067 -0.166282 -0.0850962 0.0473894 -0.046605 -0.0971228 -0.117213 0.042737 -0.112991 -0.0573659 0.0838575 0.0718031 -0.10614 -0.0351648 -0.0728097 -0.0563291 -0.0746857 0.0324464 -0.0352445 -0.00595984 -0.027024 -0.0836836 -0.0602997 0.127378 0.0745006 -0.0342232 0.0784397 -0.0373289 -0.0324618 -0.0572336 -0.126211 -0.0188811 0.0322521 0.159723 -0.0397018 0.0664092 0.0754695 0.0602695 0.0967839 0.147891 -0.12265 0.060511 0.0252399 0.0126004 0.127748 -0.000330938 0.00667894 0.0353996 -0.0925919 -0.067255 -0.0931198 0.160279 0.0678901 0.0252938 -0.178119 0.0144598 -0.043025 0.0574733 0.000186267 -0.123289 -0.00386903 0.0426295 0.0758428 0.102624 -0.139041 -0.0381949 0.0243351 -0.021731 0.0176204 0.123795 -0.0509073 -0.139328 -0.0249352 -0.077681 -0.104408 -0.0487684 0.0988045 -0.120563 -0.0155694 -0.0327504 0.0261973 -0.102908 0.187495 0.223559 0.0616036 0.0791603 0.0221417 0.182823 0.0196371 0.0528702 0.037053 -0.0129981 0.0327219 -0.136052 0.0777652 0.0805051 -0.0631927 -0.156958 -0.153434 -0.100085 0.197625 -0.0431586 0.17549 -0.0054333 -0.327877 0.13361 0.14703 -0.0666467 -0.180593 -0.00962111 0.156387 -0.0702089 -0.275614 0.117844 -0.0586362 0.034863 0.0562407 0.154007 0.0831657 0.269893 0.300077 -0.14648 0.0646504 0.301018 -0.145694 -0.0991234 -0.11602 -0.115083 -0.15061 0.0373782 -0.0233359 0.00427875 0.0927737 0.110792 0.082019 0.14801 -0.02022 0.26397 -0.235932 -0.118631 -0.173612 0.178213 0.0249816 -0.122218 -0.071003 0.139349 -0.00533753 -0.0218031 -0.205903 0.0337964 0.0560189 0.140434 -0.0276297 -0.0319141 -0.0103323 0.0135054 -0.0567239 0.371746 -0.198314 -0.0949214 0.160432 0.10086 -0.00300069 0.0287675 0.0984896 -0.00664335 0.0150926 0.0568818 -0.104586 -0.0562356 -0.00646174 0.0445531 -0.130784 0.149624 0.0300799 -0.173307 0.142463 -0.0839648 -0.260468 0.120441 -0.0972632 -0.130965 0.110105 0.277831 -0.148307 0.171983 0.0828265 0.0906912 0.0913021 -0.0440591 -0.234799 -0.0619487 0.0535734 -0.0939784 0.0551908 0.0320818 -0.0410745 -0.0698979 0.0496215 -0.00729328 0.0849305 0.0661737 0.0322428 -0.130814 0.057394 -0.0114716 0.103604 0.0872557 -0.0913145 0.0559422 0.00522052 0.0482179 0.00134834 -0.00950982 -0.0557623 -0.0747752 -0.0466781 0.112852 0.169884 0.00345385 0.0951205 -0.0356814 -0.00800131 -0.014323 -0.0815211 0.0703496 0.0189507 -0.0866715 0.130088 -0.0628694 -0.0767306 0.0697864 -0.0640442 -0.0238303 -0.0633137 -0.0331158 -0.0428687 -0.0245807 0.0272509 0.0739446 -0.171073 0.101162 0.176953 0.123801 -0.0381061 0.0335156 -0.0496188 -0.0392005 0.169313 -0.014512 0.00242616 0.167509 0.218932 -0.131779 0.167882 0.0411728 0.0281387 0.0748322 0.0589531 -0.137215 0.0316996 0.0369107 -0.170603 -0.0885698 -0.0573879 -0.0282702 -0.0873698 0.12123 -0.00508393 0.107954 -0.0839987 0.0932091 0.114211 0.0417569 -0.136911 -0.0198496 -0.0458466 -0.0852073 0.0946373 -0.102153 -0.0754491 0.00850011 -0.0246476 0.00387533 -0.150304 -0.00894447 0.0512854 0.000803436 0.0109857 -0.121708 0.0270844 -0.0080712 0.0586091 -0.000219072 0.117426 -0.0103735 -0.0216829 -0.0869975 -0.0297285 -0.415317 -0.316257 0.234482 0.0802669 -0.190306 -0.0504125 0.212234 -0.121167 -0.00759835 0.0540431 0.0401992 0.0390398 -0.0286428 -0.211521 0.15676 0.109961 0.00303335 -0.017668 0.0472225 0.27225 0.161723 -0.119456 0.130136 0.0884632 -0.0634966 -0.0734683 -0.011659 -0.10088 -0.219762 -0.235699 0.0198189 0.000329748 0.260126 -0.0710988 -0.208559 0.221267 -0.0689275 -0.245509 -0.0609967 0.0378821 0.238071 -0.0427391 0.238578 -0.0465881 0.204597 0.0876925 0.0897589 -0.0309803 -0.0188588 0.166404 -0.0594063 -0.0932331 0.202812 0.161609 -0.0623485 0.0943465 0.0669606 -0.0576965 0.109751 -0.0158391 -0.101601 -0.0762911 -0.0754423 -0.137787 0.0661221 -0.0328896 -0.121111 -0.179491 0.00112341 0.151153 -0.0549749 0.17236 0.0080807 0.160105 0.0286745 -0.167003 0.0508326 0.0451523 0.0154299 -0.0474958 0.126275 -0.017356 -0.0341259 -0.0480204 -0.104584 -0.0496857 0.00923185 -0.109446 0.0938787 -0.00643035 -0.0118361 -0.127123 0.067915 0.120329 -0.0608125 0.08913 -0.101545 -0.00817918 -0.0920343 -0.00109386 -0.0421743 -0.165029 0.0923862 0.0987069 0.094103 0.0590666 -0.11853 0.0336641 0.023 0.0616117 -0.0134789 -0.0512224 -0.0334314 0.0869345 -0.128736 0.167866 -0.0733749 -0.0557867 0.16403 0.134564 0.127336 0.0742612 0.0126513 -0.0585566 0.172422 -0.0664867 0.00229096 -0.070076 0.0221719 -0.0760447 0.0901856 -0.119435 -0.0938508 -0.00104039 -0.019119 0.0854495 -0.123329 0.0149242 -0.029531 -0.00440053 0.00396666 0.0680107 -0.0536722 -0.0254647 0.00544501 -0.0165311 0.071334 0.00791537 -0.0163788 -0.0138602 -0.121925 0.00959846 0.0533931 0.0519576 -0.0193048 0.0239257 0.0879859 0.028319 0.00230181 0.0209614 -0.0167713 0.0376022 -0.0725612 0.02658 -0.104531 0.0967973 0.0245572 0.0232312 -0.0179512 -0.0286572 0.0817869 -0.0413206 0.113204 -0.00344138 -0.100203 -0.279834 0.0837395 -0.121088 0.0853552 -0.0967642 -0.094632 -0.0939199 -0.0409039 -0.0552802 -0.0332297 0.0384666 -0.0630742 -0.000715625 -0.00163675 -0.0389109 0.0843633 0.166475 0.0980146 0.084045 0.0276562 0.104562 0.0467382 0.0682937 -0.0128994 -0.167041 -0.369282 0.0601264 0.0566078 0.0724199 -0.105255 -0.106512 -0.16586 0.222475 0.184555 -0.0134801 -0.105921 -0.0188201 0.098637 0.0347706 -0.0688311 0.0256209 -0.0988419 -0.134404 0.188749 -0.0774154 -0.143794 0.00243056 -0.283483 0.0173619 -0.251413 -0.15709 0.0537285 -0.0815009 0.143772 0.0477255 -0.177111 -0.278969 -0.0829726 -0.0549622 -0.129905 0.0685785 -0.00710021 -0.0152198 -0.177022 -0.114979 -0.0239969 -0.329635 0.157272 0.0588555 -0.120895 -0.0437808 0.0403449 -0.0123932 0.0752695 0.102663 -0.0145164 -0.0244921 0.0953155 -0.00491083 0.13517 -0.0522751 -0.0714745 -0.0968799 -0.0264105 0.0443911 -0.0340823 -0.136721 -0.0661116 -0.0211591 0.00924317 0.0810832 0.0826517 0.0485873 0.010632 -0.0549632 -0.0599152 -0.184627 -0.0347435 0.0529729 -0.0289354 -0.174074 0.134699 -0.0855159 0.193773 -0.0972331 0.0732255 -0.00512302 -0.0765008 -0.0962919 -0.0353175 0.105443 -0.105594 0.0668657 -0.0218021 -0.00974661 -0.0138604 0.0365459 0.0078876 0.124591 0.135733 0.224396 -0.144312 -0.0832486 -0.0612453 -0.135186 -0.428277 0.191399 -0.035593 0.188198 -0.163181 -0.295671 0.0961293 -0.0186302 -0.347025 -0.220154 -0.160502 -0.0895552 0.150945 0.0435263 0.209022 -0.0438256 0.217461 0.280909 -0.0134506 0.275733 0.687004 0.0921724 -0.151173 0.113589 -0.296465 -0.0674658 0.0438151 0.0658242 -0.181695 0.218896 -0.269454 0.236423 0.139338 0.11292 0.254909 0.303566 0.0147936 0.0659998 0.207395 -0.17402 -0.249001 0.351552 -0.0659695 -0.224417 -0.156246 0.0299456 -0.143753 -0.14276 0.413153 0.0948229 -0.237135 0.175873 0.0932324 0.220663 0.0662547 -0.0686228 0.104288 0.00269622 -0.0209591 -0.189962 -0.179125 0.00768901 0.0659986 0.121345 0.0237372 0.0414935 0.066295 0.334936 -0.315029 0.118581 0.623103 0.116751 0.0493073 0.09865 -0.121267 -0.0613087 0.225853 0.14847 -0.0841265 0.208341 -0.0574156 0.113398 0.0334469 0.0247227 0.119562 0.0588428 -0.0932762 0.0245878 0.18199 -0.0919412 -0.259678 0.175747 0.0450204 -0.144468 -0.0826472 0.122037 -0.425306 -0.265942 0.806822 -0.177679 -0.646395 0.328227 -0.34895 0.179884 -0.172537 -0.270136 0.133153 -0.0159889 0.0998809 -0.151382 -0.523915 0.136086 0.390745 0.178748 0.122719 -0.0642136 0.156039 0.511309 -0.611304 0.466235 1.55359 0.348706 -0.373472 0.566082 -0.19733 -0.137957 -0.0869482 0.0485866 -0.106467 0.141552 -0.0182833 0.0818303 0.245982 0.326126 0.501402 0.222324 0.106952 0.506134 0.37235 -0.119528 -0.328387 0.052047 -0.223087 -0.484317 -0.0329413 -0.0406518 0.0704292 0.0859909 -0.359458 0.11681 0.238896 0.0383146 0.0919998 -0.0166112 -0.0592834 0.2306 -0.0307317 0.031417 0.00679504 0.143059 0.0170435 -0.0598669 0.062508 0.200179 -0.0899821 -0.0164459 -0.0796313 -0.0109306 0.0734416 0.0192424 -0.177094 -0.0881184 0.407835 0.00274624 0.120131 0.216671 -0.165639 0.500208 -0.0181941 -0.0303135 0.133602 0.52236 0.00419628 -0.250363 -0.116657 -0.0834477 -0.0147752 -0.0644091 0.0043017 0.315023 0.192585 -0.196107 0.013461 0.165047 -0.0611616 0.00258179 -0.0916048 0.0904429 0.00655144 -0.0408041 -0.00558115 0.0487306 -0.0544977 0.109801 -0.0406107 0.0452482 0.0612143 0.0812863 -0.154777 -0.108588 -0.0646677 0.122319 -0.0844778 0.0121828 0.0843744 0.136366 0.118199 -0.0422816 0.0117529 -0.0283637 0.073946 -0.0521272 -0.126864 0.0169339 -0.0128603 -0.0567112 -0.0531415 -0.0339507 -0.0432384 -0.0426435 -0.0757574 0.0634145 0.0861028 -0.0592473 0.0372314 -0.0500919 -0.0629336 -0.116274 0.0479781 0.0419006 0.0255364 -0.0496214 -0.0287735 -0.01809 -0.0325578 -0.138666 -0.0355663 0.0863383 0.115243 0.0250321 0.127449 0.0157837 -0.0712159 -0.0128964 -6.29831e-05 0.0925008 -0.0383408 0.0694854 0.140149 0.0265308 0.089116 -0.130677 0.0226716 0.00633239 0.0634939 0.0848563 -0.108259 0.0932704 -0.163619 -0.0912252 -0.0497011 -0.0753667 0.0145409 0.0173656 -0.0101508 0.106658 -0.0442703 -0.0654551 0.114295 0.0871827 0.107349 -0.0622056 -0.105634 -0.10949 -0.0373859 -0.126895 -0.0775199 0.0895741 0.0616688 0.103098 0.102852 0.0208322 -0.0173235 -0.0509502 0.00802431 0.0506277 0.148404 0.0963649 -0.137601 0.00171412 0.0204068 -0.0295608 -0.0107363 -0.0570239 -0.0786009 0.193373 0.0427275 0.197831 0.187174 -0.0492763 0.0806331 -0.03478 0.000404971 -0.16872 -0.0951977 0.324568 -0.10691 -0.145891 0.291013 -0.0817826 0.290838 0.135123 -0.490947 0.0263723 -0.00607891 0.140314 -0.14347 0.102496 -0.0409508 -0.0509172 0.110892 -0.0701533 -0.0963727 -0.115988 -0.266464 -0.196553 -0.0596324 0.0572749 -0.0813118 -0.0445223 0.316911 -0.163776 0.114642 0.27485 0.0933044 0.0474544 -0.0380088 -0.0647832 0.0890944 0.0401383 0.00213829 0.1123 -0.0460914 0.0562092 0.0180487 0.145829 -0.014285 -0.0572274 -0.0656556 -0.0491222 0.115885 0.105861 0.0196146 0.0557831 0.0877911 0.0645837 -0.0192531 0.160577 0.0831608 0.0512138 0.028595 -0.0192218 -0.0725667 -0.0801632 -0.0153171 0.0316277 -0.0670894 -0.0468867 -0.0410763 0.0504355 0.0448659 0.10349 -0.078774 0.00849011 -0.125212 -0.0521107 -0.148869 -0.0686045 0.113948 -0.00646695 0.0991603 -0.119742 0.0951824 0.124248 0.0460645 0.0807699 0.122814 0.0434483 -0.0295529 0.0518233 0.00698732 0.258578 -0.074395 -0.106606 0.0856658 -0.24835 0.0331291 0.158602 -0.140592 0.0596991 0.0386222 -0.0440249 -0.0768994 -0.00513794 0.120407 -0.233311 0.17936 0.0119777 -0.0596343 0.0477189 -0.287546 -0.0817478 0.0818314 -0.0699391 -0.255731 0.0599976 -0.0241107 -0.0651183 -0.0676865 0.00951121 -0.25142 0.00537509 -0.00725901 0.171156 0.235878 0.346131 0.151532 -0.115495 -0.0107732 -0.138679 -0.113033 0.059888 -0.228589 -0.015662 -0.040268 0.132104 0.0900305 -0.189937 0.0666652 -0.0124248 -0.221125 0.0214709 0.0185378 0.133954 -0.0618049 -0.178656 0.101269 -0.181865 -0.147365 -0.00390798 -0.242187 -0.0353943 -0.164743 -0.214606 0.0232207 0.148708 0.0314574 -0.105394 -0.0726775 0.18799 0.0295973 -0.0676214 0.102011 0.0174259 -0.0189357 -0.10832 -0.0200582 -0.0478568 -0.0239375 -0.000336214 0.0318726 -0.0353997 -0.00201887 0.204993 0.136887 0.0698995 0.142013 -0.00443925 0.0111821 -0.222583 -0.0782357 0.199006 0.0445668 -0.033366 0.0781097 0.166636 0.0124987 -0.0544299 -0.0252264 0.0871256 -0.482893 0.332149 -0.237765 0.278919 -0.393636 -0.524193 0.285637 0.0787929 -0.401396 -0.105842 -0.286107 -0.0457287 0.0552488 -0.100013 0.144559 0.0339117 0.14373 0.126044 0.0454934 0.527577 0.534745 0.00878306 0.0840567 -0.0260505 -0.213764 -0.0478203 -0.000324541 -0.143572 -0.173282 0.000238654 -0.312924 -0.0218379 0.0325404 0.0563688 0.331349 0.271496 0.111092 0.00168633 0.0327075 -0.487918 -0.0207199 0.305598 -0.229189 0.114374 -0.0608406 0.0763959 -0.0389271 -0.0926733 -0.0789701 -0.0764587 -0.0246105 0.00915825 0.0540965 0.0747981 0.0318933 0.0102355 0.165355 -0.318151 0.110159 0.11611 -0.0993355 -0.00379803 2.15161e-05 -0.0694131 0.0404464 0.111494 0.0568305 -0.098875 -0.0297444 0.102361 -0.201992 0.0962703 0.029078 0.00932816 0.148643 -0.077413 -0.15801 0.0600764 -0.0659885 -0.0328672 0.170811 -0.0731981 0.112561 0.0829766 0.0118813 0.0693345 -0.146998 -0.10214 -0.0619491 -0.0195115 0.0516637 -0.0188541 0.134143 0.144882 0.111157 -0.159312 -0.130153 -0.143192 0.242709 0.345204 -0.0752804 0.399197 -0.119521 -0.0221427 0.582884 -0.580021 0.102926 -0.747535 -0.594902 0.242478 0.116403 0.19535 -0.577114 -0.190568 -0.0684914 0.0383096 -0.218435 0.0890778 -0.459972 0.536088 -0.544846 0.271779 0.353448 0.312972 0.229165 -0.0988539 -0.121197 -0.352736 0.243286 0.242472 0.279174 -0.0430411 0.700657 0.322701 -0.20081 0.842724 -0.390354 -0.164224 -0.148184 0.199632 -0.00552685 1.17223 0.0885598 0.043887 -0.0168104 -0.182444 -0.168442 -0.299299 0.117878 0.163712 -0.308824 -0.112791 0.153494 0.22088 0.118306 0.006111 0.277361 -1.65857 -0.10094 0.165007 -0.468164 -0.137047 0.0456827 0.00782772 0.201077 0.425472 -0.210086 0.244227 0.0233531 0.982372 0.248952 0.591456 -0.119226 0.564849 0.48348 -0.342415 0.120764 0.0812444 -0.0264322 -0.406525 0.276574 0.0161415 0.0364011 -0.11263 -0.132324 -0.196437 -0.321016 -0.282647 0.045018 -0.199728 -0.0712222 0.902763 -0.278272 -0.128252 -0.233022 0.350146 0.0642622 -0.751587 -0.121215 0.123376 -0.698813 0.237073 0.186025 0.525012 -0.320743 -0.655549 0.579618 -0.408811 -0.761642 0.06896 -0.507002 0.39951 -0.0938892 -0.330329 0.479769 0.396088 0.525842 0.0588857 -0.262914 0.00245793 0.17586 0.54332 -0.221008 0.327783 -0.774132 -0.396309 -0.0107386 -0.242206 -0.00101837 -0.353233 -0.370201 -0.183254 0.66803 0.310824 0.282421 0.612195 -0.122776 0.0241601 0.225354 -0.676572 -0.409827 0.0991413 0.172977 -0.245337 -0.088682 -0.194777 -0.0777902 -0.0194521 0.148548 -0.176299 0.220056 -0.0552805 -0.0287006 -0.119395 0.0170077 0.20219 0.178425 -0.413368 0.422442 0.0019308 -0.098025 0.0726176 0.295076 0.106982 0.119041 0.230569 -0.46471 0.179725 0.191733 0.555452 0.637805 -0.0372624 -0.496028 -0.00425939 0.661957 -0.0702814 -0.00744365 0.0233242 0.0370397 -0.399033 0.100343 -0.0953372 -0.299677 -0.0927 -0.112353 -0.536802 -0.106363 -0.184117 -0.114728 0.391069 -0.0242633 0.0991141 -0.0157649 -0.171543 -0.131802 -0.101075 -0.0432565 -0.0990532 -0.0641121 -0.208902 0.101996 0.0575599 0.0514927 0.0169289 -0.0452404 0.100942 0.107723 -0.190924 -0.0455197 -0.143977 -0.0266816 0.07414 -0.0662767 -0.0631994 0.163869 0.0616196 -0.0228587 -0.103025 -0.00634982 0.0496446 -0.00833104 -0.00391257 -0.0547138 -0.0532725 0.134694 0.0655862 0.0338149 -0.0438202 -0.331554 -0.0676151 -0.0159392 0.0408844 -0.00421335 0.115765 -0.0656247 0.157489 -0.00605611 0.158103 0.0745526 0.0837205 0.00210858 -0.0286283 0.0431352 -0.175188 0.0347267 -0.015324 0.0315668 0.0475105 0.0610017 -0.0149692 -0.263269 0.226012 -0.029114 0.185314 -0.0329042 -0.0539218 -0.0575115 -0.238606 -0.311209 -0.124075 -0.126172 0.132854 0.133449 0.0378545 0.124818 0.0520501 -0.12399 0.160317 -0.195124 0.0972717 0.282464 -0.0839292 -0.132595 -0.0266898 0.085094 -0.128281 0.068362 -0.0623855 -0.13361 -0.127179 -0.045938 0.110594 0.0578222 0.119261 0.207417 0.14681 -2.77113e-05 0.0104057 0.227297 -0.0171961 -0.0203153 0.0633157 -0.0496122 -0.0384735 -0.0986559 0.0223059 -0.083887 -0.191838 -0.226999 -0.0975454 -0.042734 0.127633 0.212749 0.210274 -0.0856962 -0.119141 0.0982093 -0.0707292 -0.190175 -0.205167 -0.232511 -0.027577 -0.0529134 0.0723042 0.418671 -0.0290775 -0.104368 0.0821678 0.143425 0.0366405 0.513745 0.375526 -0.390009 0.26085 0.333562 -0.11826 -0.0186144 0.199593 -0.0023966 -0.0940348 0.0219657 0.156441 0.0454781 0.0150175 0.160087 0.133278 0.0160712 0.0878969 0.0485335 -0.171146 0.0155892 -0.150953 0.0128486 -0.178595 -0.210297 -0.107232 -0.088043 0.0766925 0.144517 -0.218906 -0.00717943 0.266672 0.0546476 0.0149002 0.0773614 0.0233474 0.0356307 -0.134138 -0.127488 -0.123826 -0.00615785 -0.0592061 0.157499 -0.00440381 0.00901953 -0.0942652 -0.0862943 -0.00385214 0.0338389 -0.00357792 0.0914158 -0.105109 -0.103862 -0.0533277 0.16087 0.0577096 0.00414212 -0.043855 -0.210144 -0.123469 0.114002 0.0976103 0.0791865 0.142704 0.075574 0.0657486 -0.0512837 0.0573381 0.0871337 0.00758187 -0.0121509 0.0501256 -0.0196351 -0.0256652 0.133569 0.113746 -0.0472743 0.0212559 0.0422996 -0.130475 -0.0919828 0.281692 -0.0905204 -0.0398809 -0.0787509 -0.140678 -0.132702 -0.0988451 -0.358695 -0.257994 -0.343814 0.064575 -0.0370384 0.0527425 0.240374 -0.228068 0.21874 0.0457751 0.0321485 0.153407 0.304489 0.0958161 -0.127248 -0.038858 -0.209254 -0.238494 -0.0755181 -0.214004 -0.297421 0.10791 -0.218166 0.0613975 0.0432572 0.319436 0.148008 0.464888 0.468136 0.00606954 0.248886 -0.141318 -0.100656 0.257831 -0.0693424 -0.0984101 -0.0161642 -0.0762711 0.0256932 -0.0679538 -0.0383019 0.042013 -0.0407424 -0.0448644 0.0812813 0.0569629 0.160841 -0.153602 0.115143 -0.0886957 -0.155036 0.0659725 -0.124275 0.00755692 0.0681491 -0.0921661 0.125944 -0.213492 -0.0221049 0.0435361 -0.100335 0.104854 0.129971 0.0538727 0.0245649 -0.0905554 0.0437374 -0.0361647 0.0211203 0.0892313 -0.0451882 -0.0256295 0.0264686 0.0799799 0.00321952 0.103867 0.146798 0.0687762 0.103969 0.124094 0.0608512 -0.00250301 -0.000619322 0.047152 -0.0967294 0.120516 -0.1072 0.227849 -0.00478602 0.411248 -0.108401 -0.230268 0.52363 -0.0778883 -0.130152 -0.199601 -0.0119952 0.177294 0.0853135 -0.0013283 0.74259 -0.145813 -0.0591256 -0.00415996 0.0553091 0.11993 -0.0225923 0.0768579 0.104771 -0.363893 0.299534 0.225059 -1.00301 -0.488354 -1.03025 -0.352598 0.0331832 0.354589 0.0860717 -0.275036 -0.0310748 -0.107369 -0.00162845 -0.311761 -0.231894 -0.0356669 -0.182723 -0.144892 0.251963 0.0972634 -0.22591 0.29883 0.0915037 0.216823 0.244512 0.240198 0.200391 -0.0471338 -0.0459815 0.0557189 -0.255391 -0.103687 0.14607 -0.0181467 -0.176438 0.0329659 -0.0511686 -0.100171 0.0039901 0.0927949 0.120756 -0.122354 -0.00176809 0.0272772 0.0536356 -0.0158553 0.252433 -0.166318 -0.0300557 -0.0348488 0.227282 0.0478966 0.0359438 0.0428668 -0.473212 -0.0647572 0.199222 0.199055 -0.0627412 0.207331 -0.147853 -0.124024 -0.0481617 0.243129 -0.04291 -0.0727091 0.112228 -0.0384079 0.0353933 -0.126565 -0.0299332 0.121295 0.0146286 0.101565 -0.00544405 0.0803006 -0.0751255 -0.0557834 0.1682 -0.0457105 -0.0957495 -0.0173354 -0.029045 0.0958118 0.00368848 0.0128362 0.103531 -0.244261 0.00113693 -0.101996 -0.0646698 -0.0930235 -0.0576519 0.0416904 -0.0122818 0.0299141 0.0457028 -0.117165 0.0341142 -0.00177538 0.0251365 0.168763 0.19755 0.00301584 -0.147009 0.00908408 -0.0479205 0.0407758 -0.00879861 0.0630821 -0.0105583 0.0865418 -0.0197485 0.069348 0.0296526 0.104468 0.161676 0.264543 0.0468094 -0.115959 0.022417 0.00141033 -0.032231 0.189121 -0.173517 0.070044 -0.0508055 -0.0171609 0.0353144 -0.156701 -0.136487 0.104199 -0.234706 -0.16408 0.186112 0.163745 0.0338737 -0.229844 0.234283 -0.387176 -0.0207053 0.0623886 -0.0789909 -0.0405706 -0.178851 -0.0681747 0.0622794 0.188127 -0.119025 -0.0705422 -0.0461539 0.0828408 0.266639 0.069033 0.0493797 0.202492 0.0544917 -0.128521 -0.205715 0.227547 -0.0905082 -0.0552919 -0.0562061 0.121412 0.219886 0.0488695 -0.154682 0.169105 0.0474442 -0.159736 0.05577 -0.0437201 -0.0978751 0.0290318 -0.023313 -0.0812411 0.104108 -0.0709746 0.0768366 -0.265029 -0.250608 0.129857 -0.434957 -0.149993 -0.00930713 0.282115 0.0684907 -0.402369 0.222418 -0.0743815 -0.243661 -0.0199442 0.0536323 -0.228991 -0.280372 -0.215889 0.381396 0.105695 0.237688 0.144485 -0.0477104 0.153286 0.305818 0.344884 -0.276357 0.110503 -0.0334966 -0.18261 -0.0730394 0.0802935 -0.194633 0.241235 -0.144721 0.166567 0.402981 0.164463 -0.0294789 0.323037 -0.0240338 -0.194353 0.0778028 -0.122873 -0.0746425 0.0478128 -0.112875 0.00459276 -0.266938 -0.0614614 -0.0199057 -0.128646 -0.0937145 0.0303094 -0.0233831 -0.0301753 0.116523 0.0612913 -0.0764786 0.0342589 0.0819889 -0.24969 0.31254 0.123659 -0.0267631 0.127027 -0.205278 -0.297571 0.00884569 0.105475 -0.277861 -0.0639424 -0.20553 -0.00694912 0.0315713 -0.0633689 0.28141 -0.111121 0.0525707 -0.0611029 -0.109267 0.104519 -0.00122859 -0.066657 0.133 0.133923 0.0468259 -0.134785 -0.200795 -0.00360537 -0.0835172 -0.32148 -0.033972 0.144532 0.0583421 -0.0513527 0.173686 0.0936309 0.198129 -0.00705312 -0.0498694 -0.0786925 0.0647046 0.0173613 -0.117742 0.152953 -0.0289238 0.070261 -0.00252326 -0.00457267 0.056352 -0.0562164 -0.0438087 -0.0599172 0.0445399 -0.0152416 -0.129612 -0.0484369 0.0258135 0.0609887 0.109252 0.135585 0.00243257 0.0291115 0.128752 0.0240625 -0.0431134 0.140821 0.0396528 -0.0822868 0.0396407 -0.00530653 0.118777 -0.0193619 0.0191379 0.0190762 0.0249416 0.159879 -0.0133894 0.0500737 0.0242061 -0.00159638 -0.100623 -0.128276 0.0751022 0.0753951 0.00225646 0.00024085 -0.00181692 -0.119563 -0.0942157 0.0250345 0.1155 0.163165 -0.0741971 0.00436885 -0.00329877 0.13281 0.11245 0.0114012 0.0464564 -0.00955233 -0.163721 0.0436082 0.0132821 -0.100622 -0.0564159 -0.0690185 -0.0444445 -0.0347574 0.0692243 -0.0644568 0.0579884 0.0801648 0.0183416 -0.0623587 0.100673 -0.0509654 -0.101213 -0.121632 0.0379968 -0.146337 0.0794073 0.114045 0.0387604 -0.0637192 -0.0610688 0.0601459 -0.0637776 0.143861 0.0327855 0.1193 -0.0107124 0.0583667 0.0140536 0.0960681 0.015239 0.0935989 -0.15713 0.022976 -0.101791 -0.20088 0.0978862 0.0727993 0.14459 0.0730286 0.0682701 -0.175925 0.213056 -0.00417943 -0.159057 -0.244068 0.115252 0.075541 0.0437953 0.0539988 -0.155263 0.0199321 -0.0432158 0.0562888 -0.0507444 0.102856 -0.0798246 0.242692 -0.228956 0.177443 -0.0086073 0.174236 0.0328668 -0.22891 0.00902237 0.0411664 -0.113049 0.0874333 0.0160855 -0.087756 0.148944 -0.0864163 -0.152133 -0.0583384 -0.0364503 -0.259283 0.174149 0.166233 0.102158 0.227329 -0.0126502 0.0323745 -0.022577 0.0572231 0.0387903 0.025771 0.121109 -0.00925353 0.0524683 -0.0467125 -0.103691 -0.0405729 0.106103 -0.0795292 -0.051708 -0.0684522 -0.0805708 0.0779856 0.102599 -0.0491144 -0.100536 0.0133751 0.0641287 -0.0671323 -0.0234535 0.00869382 -0.0253607 0.0688331 0.0831109 0.0437582 -0.0514655 -0.00470702 0.0236384 -0.15353 0.182182 -0.130564 0.156629 0.0702415 -0.102376 -0.132561 0.080672 0.129662 -0.0614687 0.0417354 0.0193692 0.0797362 -0.126338 0.044369 -0.122031 0.0450116 -0.0355082 0.0267015 -0.0681621 -0.0478326 0.00153208 -0.10554 -0.00313236 0.145152 -0.191598 0.0366513 0.0668276 0.0432833 0.0246423 -0.144599 0.0336966 -0.112141 0.0302621 0.0848255 0.0247169 0.0552572 -0.155457 -0.05814 0.0868161 0.0867319 0.0229631 -0.111615 -0.236056 0.137112 0.0196668 -0.0626627 0.0581232 0.11629 -0.0665669 -0.17303 -0.0876016 -0.0318693 0.0162063 -0.00301651 -0.0683817 -0.0962163 0.413188 0.0346579 -0.0651759 0.171807 -0.158648 -0.130589 0.0121922 0.0841697 0.0366666 0.117529 0.0289648 0.0789208 0.141178 0.0931054 -0.0360492 -0.161167 0.123205 0.0275036 -0.19487 -0.111838 0.292847 0.134167 -0.0521319 0.0440497 0.224431 -0.407263 0.236671 0.0932283 -0.117348 0.147823 -0.0759699 -0.30478 0.0185838 0.540157 -0.0356686 -0.0574816 0.125119 0.0794125 -0.0736544 -0.0292762 0.198934 0.391403 0.0378328 -0.160906 -0.0458652 -0.158256 0.133827 -0.0441288 0.0898452 -0.201919 0.109474 -0.0169836 -0.259521 -0.149875 -0.237862 -0.117489 -0.0281337 0.0975442 0.0154956 -0.0143717 0.260797 0.139932 0.0448551 -0.213486 0.0128312 0.216867 0.12423 -0.294818 0.342717 -0.0182963 -0.453237 -0.207178 -0.124042 0.460257 -0.111547 0.254345 0.190181 -0.215676 0.0656878 0.0618831 0.137118 0.295823 -0.237185 0.0286801 -0.102302 0.156212 -0.0597932 -0.190727 0.0789076 -0.109033 0.213876 -0.50111 -0.258913 0.26291 0.0640854 0.271828 -0.129814 -0.15052 -0.0252624 0.0827389 -0.186846 0.113896 0.268468 -0.205767 0.113584 0.268351 -0.079011 0.315083 0.127425 0.149216 0.0934499 -0.182079 0.0427633 0.0260012 0.120533 -0.1186 -0.0825931 0.205482 -0.107612 -0.00862829 0.315581 0.0291539 -0.0573297 0.0307609 0.0975398 -0.256756 -0.0122659 0.110386 -0.0402573 -0.0211809 -0.0146099 -0.329868 0.00207895 0.398626 -0.0409176 0.0937287 0.0339443 0.0704538 -0.127989 -0.0805293 0.153485 0.0651222 0.0753531 -0.239779 0.0249604 -0.309946 0.127284 -0.0750141 0.0903949 -0.20919 -0.0145521 -0.138897 -0.0880605 0.036733 -0.225446 -0.210035 -0.252557 0.141073 0.0668155 -0.0134821 0.154301 0.233929 0.199908 -0.0428432 0.0910167 -0.0310736 -0.0609592 -0.0320574 -0.0284472 -0.0538933 -0.0271147 0.146737 -0.0307236 -0.0281841 -0.0280475 -0.00451646 -0.0660752 -0.07914 -0.0184014 -0.038779 -0.115821 -0.00190338 0.00132329 -0.0615793 0.146789 0.051077 0.0605795 0.106996 -0.00540499 -0.00408788 0.13881 -0.050866 -0.0820061 -0.0031115 0.061287 -0.078868 -0.126247 0.0581161 -0.056862 -0.0215878 -0.035816 -0.0925792 -0.108631 -0.0449505 0.0825456 -0.092239 0.0238606 0.0437063 0.0880514 -0.0187492 -0.0400702 0.0628112 0.0359709 0.00419085 0.0835801 -0.063659 -0.0213084 -0.0738589 -0.0532611 0.0340452 0.105486 -0.0278962 -0.0360192 -0.102155 0.133111 -0.0750224 0.0555668 0.0917801 0.106384 0.061057 -0.0624888 -0.0110091 -0.0752682 -0.0134603 0.0405719 0.0161309 -0.0187334 -0.0526708 0.0884086 -0.080495 -0.0470735 -0.073205 -0.0346043 0.0305336 0.0306465 0.121504 -0.051908 -0.028619 0.0705754 0.148158 0.0581305 -0.0600246 0.060913 0.0453244 0.0628571 0.0111776 0.0364076 -0.11282 -0.0976289 -0.0423139 0.0410885 0.0765067 -0.0365822 0.0346358 0.07156 -0.208423 0.202308 0.0467435 0.250125 0.0334153 0.0254021 0.0707383 0.0392837 -0.0616658 0.0188271 -0.0525345 -0.0373431 0.0709321 0.212009 -0.0400631 0.0038253 0.127697 -0.117504 0.00483841 -0.228015 0.202882 -0.274723 0.249848 -0.163327 0.0260811 0.13218 -0.0275962 0.0345189 0.111079 0.0130651 -0.533786 0.0989688 0.0636679 0.0758711 -0.0195579 -0.0315637 0.00568211 0.0284278 -0.113636 -0.0226904 0.0287266 0.0560183 0.0158445 0.0322117 -0.0380981 0.0359573 -0.0184742 0.174221 0.110638 0.0439906 -0.106374 -0.0101683 -0.0829108 -0.200443 -0.145075 -0.0309937 0.00215026 -0.131542 0.0355042 0.104527 -0.0691578 -0.0946658 -0.0417778 0.00337481 -0.0848732 -0.00545733 0.0166572 -0.00625214 0.0169612 0.16757 -0.098795 0.0775762 0.113715 -0.0478573 -0.0208191 0.0865522 0.0435845 -0.133279 -0.0512651 -0.0844801 0.0910199 0.0290888 0.0327786 -0.0469385 -0.0387225 0.0263087 -0.0770189 -0.0198411 0.0523682 0.0751992 0.0302618 -0.0424008 0.0777737 -0.0423515 0.061472 0.0862593 -0.0212203 0.0200887 0.129146 0.0579424 -0.0426299 -0.058408 -0.00709578 -0.0329751 -0.143087 0.128586 0.172256 0.0924571 0.0909468 0.0777975 -0.00395966 0.242256 0.00700179 0.0172907 0.0229322 -0.00310772 -0.164074 0.122476 0.330535 0.194545 -0.0766795 0.169655 0.128569 0.0135608 0.0245931 0.0619425 0.0552625 -0.0498182 -0.0132328 -0.127622 -0.0807721 0.0211308 -0.0588396 -0.0191875 -0.153502 -0.0242419 0.072 -0.0329483 -0.0921871 -0.0579809 -0.0104004 -0.0947475 0.000726399 -0.0678967 0.0431242 -0.0468306 0.0651328 -0.0660573 -0.0108557 0.0345998 -0.0811489 0.231646 -0.0723383 -0.225837 -0.0459744 -0.115083 0.143649 0.0401539 0.0566938 0.0182795 0.298185 0.251111 0.0547589 0.00988857 0.0853562 0.177253 -0.119128 -0.0835833 0.197159 0.013455 0.0260823 -0.108272 -0.0422564 0.00660907 -0.026572 0.220616 0.0186583 -0.165122 -0.23115 0.0432753 -0.254529 0.070935 0.0761268 -0.0810656 -0.359549 0.0453059 -0.000313294 -0.0784795 -0.0770298 -0.120175 -0.0673327 0.0301927 0.0731051 0.0383396 -0.0140489 0.150094 -0.0694679 0.0531946 -0.206679 0.0389833 0.260611 -0.506077 0.0408864 0.324096 -0.142801 -0.153184 -0.00359601 -0.231207 0.174577 -0.16449 0.0949133 0.234505 0.318008 0.0219781 -0.349084 0.249081 -0.0822928 -0.232455 -0.339891 -0.158145 -0.29901 0.0729508 -0.237266 -0.40467 -0.0399533 0.264387 -0.265783 0.192738 0.307753 -0.349006 0.403492 -0.0440297 0.144791 0.344831 0.637459 -0.0745313 -0.135703 -0.0726115 0.110836 0.416521 0.265264 -0.132591 0.0443751 -0.0423314 0.140859 -0.330668 -0.0605348 -0.031378 0.106911 0.0271082 0.0324284 0.0261477 -0.0752829 -0.135225 -0.132983 0.135008 0.116155 0.0966441 0.0324897 0.107881 0.227123 0.390186 0.129563 0.127126 0.0281313 0.187526 -0.205445 -0.178428 0.262233 0.0542813 0.00290443 -0.0520864 -0.0225244 0.0513703 0.033167 0.273884 0.128978 -0.12596 -0.17735 0.0629122 -0.191543 -0.0691501 -0.0183384 0.188325 -0.421152 -0.00895832 -0.156066 -0.242649 -0.205013 -0.280968 -0.21773 -0.109705 0.164446 0.100685 -0.120717 0.257344 -0.0167063 0.221176 -0.1042 0.0367782 0.159772 -0.159693 -0.202318 0.115298 -0.0851938 0.00063357 -0.0984818 -0.0529961 0.125389 -0.12875 0.127881 0.128348 0.130296 0.0539979 -0.0392974 0.111155 0.00325646 -0.0257205 0.124084 -0.0696572 -0.0154784 0.174976 0.0752765 0.0829443 -0.0844274 -0.197399 0.0824012 0.203619 0.029039 -0.0467726 0.0902751 0.0567429 -0.141332 3.03186e-05 0.0357478 -0.00524589 -0.141375 -0.104782 0.0574656 0.0941958 -0.0774288 -0.0865373 -0.0288673 0.143815 -0.00127144 0.0721509 0.140391 0.0942654 0.000950355 -0.0293143 0.124053 -0.131978 -0.204374 0.098158 0.128249 -0.050433 -0.0327168 0.0132854 0.0895259 -0.0903283 0.11299 -0.0341059 -0.197662 -0.089442 0.0838368 -0.0168832 0.187046 0.0746123 0.0975577 -0.0089459 0.0559802 0.194465 0.116636 0.143871 0.0223812 -0.00881951 0.0810002 0.00761877 0.0501886 -0.0362203 -0.0127432 0.0888853 -0.0412954 0.0319059 0.121481 0.0638254 0.194432 -0.0327926 0.204726 0.0897237 0.0131027 0.101747 -0.10381 0.086183 -0.0163753 -0.0403388 0.0663909 0.0128197 -0.149268 0.0433829 -0.0911555 0.257684 0.221278 0.148814 0.0616222 -0.162366 -0.150476 0.0228549 -0.0174782 0.12239 -0.0675205 0.0194176 0.072803 0.297915 -0.0181179 -0.118057 -0.0255193 0.0679946 -0.182162 -0.113616 -0.0462817 0.0127519 0.173207 -0.124524 0.127857 0.117966 0.015492 0.0554325 0.243753 0.0374351 0.0401129 -0.0813799 0.151119 0.0203537 -0.0675818 -0.281384 0.194744 -0.0451044 -0.0980708 -0.0759618 -0.119025 -0.0535081 0.232993 -0.243802 0.298052 -0.173019 0.0570319 -0.125155 0.0139488 -0.0337241 0.0833172 -0.165591 -0.220617 0.0509869 -0.0046455 0.0147568 -0.0589306 -0.20602 0.0664702 -0.132374 0.0270715 0.0975442 -0.10139 0.171153 0.0258994 -0.04634 0.0774872 0.149221 0.180693 -0.0180899 -0.0558372 0.313795 -0.0132642 -0.0586609 0.129038 -0.152662 -0.0338457 -0.00252817 -0.00367236 -0.0620119 -0.0682298 -0.039707 0.0118033 -0.0463613 -0.114408 -0.0749865 0.0614984 -0.0780417 0.0417187 0.191019 0.000942519 0.0030455 0.0516047 0.147605 0.0350228 0.111976 0.116282 0.0277203 -0.0963923 0.0225237 -0.0924984 -0.00441624 -0.100792 -0.0379019 -0.115181 0.0284118 -0.0489855 -0.0335256 0.14079 -0.0136554 -0.0958372 0.104763 0.0246411 -0.0889753 0.0198938 0.0628537 0.00263571 0.024123 0.0753516 0.0749279 -0.0925506 0.146604 0.0230036 0.0348463 0.0857825 0.0588736 0.136616 0.0843724 -0.0139203 -0.0486669 0.0594343 -0.0729949 0.0821798 0.101477 -0.0848127 0.0567486 -0.09726 0.00797444 0.00761125 0.0150304 -0.04633 -0.112528 -0.0145338 0.0227201 -0.110777 -0.0483662 0.133165 -0.00236134 -0.0705739 -0.0977119 0.0214892 0.0849941 0.0515414 -0.00419505 -0.0693218 -0.0451997 0.00154312 0.0666871 0.093002 -0.00576996 -0.0621371 0.0457544 0.143551 -0.0975468 -0.0380173 -0.0237782 -0.0228006 0.044457 -0.00403939 -0.0701643 0.105603 0.0348652 -0.0369664 0.0236004 0.0374366 -0.0637437 -0.00253125 -0.0577653 0.056314 0.00666177 -0.042813 -0.0212078 0.0491934 0.0655431 -0.0157318 -0.0373216 -0.0903824 0.0794726 -0.152926 -0.0117902 -0.0611411 0.0522572 -0.0625964 0.0355567 0.0599464 -0.0277532 0.0221101 0.14453 -0.0919083 -0.0196458 0.0226583 0.0166669 0.0385316 -0.0891391 -0.0418588 -0.130509 -0.0886362 0.195282 -0.198404 -0.186009 0.0562689 -0.0946951 0.106864 0.0330207 -0.0164295 -0.0679397 0.0343185 -0.153246 -0.162444 0.0855316 0.180471 -0.0559181 -0.10809 -0.0190104 -0.0706079 -0.0240418 0.24565 -0.0649355 0.152614 -0.1152 0.107859 0.182477 0.219851 -0.0490987 0.173804 -0.00797021 0.0321293 -0.0215665 0.166687 -0.0707155 0.0963786 -0.0368822 -0.0122181 -0.0670072 0.0684148 -0.104766 0.158889 -0.104358 -0.168462 -0.0251626 0.0340947 -0.0380026 0.0814838 -0.0789998 -0.0148221 -0.0852159 0.0249116 -0.00700716 0.0620856 0.0589079 -0.0784203 0.00608574 0.141458 0.104777 0.123892 0.0290674 -0.134882 0.110372 0.0570427 -0.110698 -0.0732784 0.114486 0.0274586 0.0312504 0.000999804 -0.0438695 0.117864 0.0911996 0.0221258 -0.0872592 0.0532981 0.0295568 -0.0380623 0.0551677 -0.0416542 -0.00132625 -0.138926 -0.0442431 0.00128615 0.000515368 -0.00983061 0.0783997 -0.0321562 -0.0223432 -0.0112712 -0.0766651 -0.00374253 0.132992 0.136188 0.0459825 0.0582053 0.102236 -0.106794 0.0148679 -0.00917732 -0.0797709 -0.00505234 -0.0405228 0.0920553 -0.00571329 -0.0301657 -0.0269687 0.0595971 -0.0112903 -0.0257759 -0.00817843 -0.0614078 0.0204687 -0.144732 -0.0397064 0.00923353 0.0032402 -0.0572766 0.00864202 -0.0357178 -0.0616395 -0.0707055 -0.111984 -0.110409 -0.0921426 0.0555853 -0.0843735 -0.00542834 0.072311 -0.078563 -0.031545 -0.0136004 -0.0261508 0.0426462 -0.0147451 0.0743281 0.0481058 0.0633787 -0.000731614 -0.00314045 0.157754 -0.0956116 0.029477 0.00110238 0.000373592 -0.11592 0.0204777 0.0297833 -0.0192318 0.110888 0.0603214 0.00910999 0.112647 -0.120862 0.0755035 -0.198431 -0.323574 0.0245099 -0.166637 0.0947345 -0.0795969 0.123679 0.0923128 0.0297118 0.0567073 0.0476758 -0.1639 0.154487 0.153457 -0.00346679 -0.0578547 0.015202 -0.103594 -0.0816388 0.0125758 -0.0373858 -0.0880797 0.151057 -0.262731 0.0147577 0.0965015 0.0336415 0.154791 0.089297 0.0202871 -0.0202921 0.0675732 -0.033687 -0.00663187 0.334151 -0.056744 -0.023929 0.0510239 -0.0730848 0.0609799 0.197561 0.00780662 0.0518123 0.415857 -0.269024 0.0409967 -0.208236 0.119962 0.112425 0.0218166 0.0900635 0.191259 0.00261164 0.259939 -0.0726796 -0.0405078 0.0398888 -0.0822186 -0.0409629 -0.333955 -0.0327218 -0.227782 -0.423344 -0.394055 -0.176575 0.193284 0.0217407 0.241859 0.259575 -0.00972489 0.235813 0.0560823 -0.00687288 -0.0120582 0.204889 0.0236053 -0.129971 -0.156282 -0.0770872 -0.137672 -0.0980262 -0.167673 0.195265 0.22859 0.0907742 -0.0159122 0.0304936 0.119614 0.0254547 -0.0497887 0.00270273 -0.0528475 -0.117549 -0.0460348 0.0773015 -0.0570093 0.00408615 0.106233 -0.0751144 -0.000652545 -0.125131 -0.184533 -0.0855848 -0.0140212 0.133014 -0.030741 0.0205189 0.0125788 -0.0409234 0.0550949 0.177914 -0.0990548 0.224113 0.154669 0.0136699 0.00331668 0.0133881 -0.0258154 -0.0274791 0.0297731 -0.0575078 0.00748463 0.0913557 -0.24854 -0.196882 0.055177 0.0203665 0.0446646 0.161116 0.080967 0.0793641 0.0775283 0.0218351 0.0253795 0.165806 -0.0190101 -0.150146 -0.0459391 0.0769631 0.0325921 -0.150466 0.10373 -0.198761 -0.0218114 0.0906944 0.0927717 0.0966891 0.0708339 -0.0142364 0.0241752 -0.0192512 -0.010377 -0.0276111 -0.0654687 0.123093 -0.0239264 -0.023341 0.0916603 0.215729 -0.0267273 0.064372 0.0217056 0.0816371 0.123145 -0.0111937 -0.215986 0.0499683 0.0373657 -0.0745139 -0.0976653 -0.101814 0.0818411 -0.104383 0.0586557 -0.125311 0.0359596 0.181748 0.0038638 -0.0930744 -0.0178277 0.0660947 0.12936 -0.00736462 -0.0628821 -0.0451441 0.0270166 -0.0348011 -0.0782856 0.0577839 0.0334828 -0.0948265 0.000474698 -0.0877204 -0.0117315 0.133164 -0.00689275 0.0424297 0.0661623 -0.00680889 -0.0582277 0.000590837 0.0967968 -0.0258475 -0.0184627 -0.0465977 -0.0391099 0.0418387 -0.0276958 0.0710511 0.0490049 -0.0152369 -0.102398 0.12107 -0.0626695 0.0331716 0.00709541 0.0650314 -0.0580555 -0.00161461 0.0348041 -0.115792 0.0863055 0.0104958 0.106405 0.000111824 -5.74613e-05 0.0739156 0.0185762 -0.0149926 0.0393448 0.0839025 0.108728 -0.111123 -0.135348 -0.104004 0.0434693 0.000152289 0.0276119 -0.0894108 -0.120667 0.0879409 0.100058 -0.0598043 0.214537 0.208973 -0.0987304 0.0399955 0.0979821 0.219447 -0.091703 -0.174559 -0.206987 -0.153414 0.0285751 -0.0418382 0.126161 0.290149 0.0854081 -0.253298 -0.112979 0.198238 -0.193871 -0.080946 0.0854056 0.153542 0.0100182 -0.308315 0.0792893 0.158741 0.156395 -0.0337339 0.0104773 0.122186 -0.070388 0.1001 -0.201232 0.134885 0.267443 0.0401605 0.0669986 0.105079 0.096869 -0.124038 0.0438138 0.0874223 -0.115518 -0.0113285 -0.174334 0.130958 0.0795234 0.00934604 0.0248559 -0.088026 -0.19796 0.0378303 0.161778 0.0847748 0.037626 -0.0579636 0.0799051 0.042006 -0.135897 0.0785834 -0.0177011 0.0130929 -0.123592 -0.0434174 0.135958 0.0867224 -0.0384672 -0.0285279 -0.041515 0.144956 0.050399 0.0996322 -0.00850629 0.083821 -0.0328495 -0.0896214 -0.0362922 -0.0981177 0.0292505 0.0112354 0.0550351 0.0936569 0.16005 0.16265 0.0693954 -0.0328024 -0.114995 -0.0331703 0.113393 -0.156059 -0.0689135 0.0747424 0.0627026 -0.151646 0.00149835 0.0223138 -0.0655884 -0.088929 -0.192774 -0.0845885 -0.0315238 0.164885 -0.0441637 0.0727539 -0.186663 -0.140091 -0.0587088 0.0460933 -0.0924494 -0.158187 0.196287 0.0400161 -0.111768 0.194732 -0.045019 -0.0270294 0.148438 0.0251933 0.128956 0.0408736 -0.0911392 -0.0361424 -0.107351 -0.0812141 -0.0430181 0.0338194 -0.0116146 0.110091 -0.0964386 -0.055894 -0.0082468 -0.0553301 0.0875183 -0.0969372 0.0681497 0.202198 -0.0472439 0.0906274 0.131644 -0.00689152 0.141005 0.102588 -0.101466 -0.0670807 0.104762 0.173178 0.111991 0.0247067 -0.0506503 -0.0690184 0.0311204 -0.0135046 -0.0189768 0.140434 -0.221409 -0.0238673 -0.113805 -0.0509556 -0.126152 -0.14143 0.121962 0.0665416 0.053009 0.110207 0.00962362 0.167549 -0.0081139 0.0715789 -0.0182441 0.115908 -0.0153122 0.10935 0.0233249 0.0771387 0.0670199 -0.0687543 -0.133923 0.0911059 -0.0800875 0.102596 -0.0158134 0.165275 0.056097 -0.152579 -0.110681 0.174214 -0.122767 -0.108277 0.0404507 -0.0817072 0.105231 0.212935 -0.0130271 0.15561 0.112213 -0.106597 -0.0817959 -0.105645 -0.0324514 -0.214766 -0.159472 0.0112706 0.139823 0.115194 -0.0202259 -0.275316 0.00456108 -0.0630542 -0.314139 0.220197 -0.341985 0.305103 -0.200594 0.233774 -0.0956078 0.036432 0.30414 0.0417269 0.037892 -0.00414309 0.0312668 -0.00392316 0.206027 0.0208703 -0.194766 -0.167743 0.067711 0.0817862 -0.197123 -0.0254429 -0.0333173 0.0526368 0.11665 -0.00401006 -0.070587 0.693973 0.0450763 -0.0390175 -0.0606976 -0.131987 0.109431 -0.0116412 -0.0124637 -0.114291 0.184924 -0.0569085 -0.102259 -0.0288037 -0.0168423 -0.0900165 -0.0409136 -0.0108623 0.0633577 -0.0344135 -0.073342 -0.0507879 -0.181904 -0.085964 -0.164118 -0.0819442 0.0238232 -0.0098715 -0.131346 0.119633 -0.125245 0.0246153 -0.076375 0.166207 0.0974198 -0.0451452 -0.160514 0.0978077 0.0318592 -0.00737722 -0.00281391 -0.0212704 -0.160527 -0.00233371 -0.0367531 0.146968 0.0240758 0.0341473 0.220578 -0.118191 -0.0406265 0.165928 -0.10404 0.0301745 0.122987 0.0598669 0.0405026 0.193615 0.0358582 -0.0170903 0.0152625 0.0264493 -0.089979 0.0367402 0.0427087 -0.297976 0.117189 -0.0401599 -0.158606 -0.0976651 -0.0642499 0.159162 -0.013811 0.0248213 0.0605209 -0.194648 -0.121439 0.0707267 -0.0229959 0.0339787 0.0108049 0.0164762 0.161519 -0.100301 0.174524 -0.0333924 0.0286987 0.101046 0.0732922 -0.0455636 -0.0520685 0.114334 -0.00794464 -0.0829841 -0.228406 -0.0850638 0.0131737 0.0087752 -0.00978463 -0.0574614 0.0571391 0.0274807 0.0205881 0.183267 0.099181 0.141069 0.117968 -0.00586439 -0.0197321 -0.191277 0.0997767 0.093889 0.035513 0.0201035 0.0245628 -0.0029223 0.023933 0.0351567 0.0459982 0.0559319 -0.0382744 -0.0190334 0.0794577 0.071396 -0.00519079 -0.0848962 -0.0998054 0.00601248 0.0715846 0.110165 0.164481 0.0439092 0.0671238 0.0479383 -0.146832 -0.00659778 -0.108923 0.110125 -0.00492026 0.0342352 -0.110871 -0.0616729 -0.0674211 0.0466226 -0.0999608 0.0887343 -0.0927721 0.0984056 -0.169367 0.0862305 0.213633 -0.0142478 0.10731 0.0401333 0.126767 0.049832 0.120162 -0.0327067 0.00646398 -0.0590005 0.0528285 -0.0107208 -0.0413363 0.183571 0.0732705 -0.0816043 0.0682899 0.216812 -0.159565 0.11664 -0.0275853 -0.203052 0.0848579 0.0966667 -0.195667 0.00727976 -0.144464 0.315779 -0.085318 0.103782 0.0558793 0.173544 0.0566981 0.017111 0.101553 -0.13387 0.265814 0.152196 -0.163152 -0.23343 0.0476901 -0.106613 -0.211155 0.0922986 -0.0408236 -0.00208268 -0.121977 0.0662 -0.00666845 0.0266141 0.0330512 0.218322 0.119082 0.129218 0.124495 0.0922872 -0.0725022 -0.250868 -0.139534 -0.138204 0.0725037 -0.0191244 0.0656915 0.177043 -0.00918546 -0.0164803 0.0651615 -0.0307661 -0.0130203 0.0394181 -0.0309668 -0.0543555 -0.0675255 0.0893441 -0.0943772 -0.127572 -0.0559133 0.0783165 0.0127635 0.107093 0.151641 -0.0645064 -0.0706544 0.0465148 -0.0693626 -0.0161612 0.045925 0.133232 -0.158574 -0.124455 0.0763939 0.158767 0.020023 -0.0617052 -0.0431838 -0.00857059 -0.010965 0.120342 -0.0404499 0.173153 0.0607043 -0.034012 0.00846877 0.11411 -0.00264524 0.0869843 0.00310781 -0.0628299 -0.0468131 -0.0458253 -0.0669297 0.149937 -0.0367729 0.0117302 -0.181987 -0.217585 0.0920481 0.0510609 -0.0861638 0.0550504 -0.108056 -0.130718 -0.142433 -0.0198656 -0.06239 -0.287876 -0.027767 0.0115721 -0.0204687 0.157238 0.19421 -0.0755211 -0.105021 -0.00976183 0.152878 -0.0132652 0.209423 0.0976951 -0.0285162 -0.0280966 0.000726208 0.0238138 -0.0599174 -0.109248 -0.137416 -0.0419182 -0.0966949 0.0300221 -0.0645585 0.19653 0.0726836 0.174665 0.0289548 0.13928 0.208486 0.118644 0.0893215 -0.163517 -0.0354361 -0.137125 -0.0281109 0.0728253 0.0336844 -0.0343238 -0.0767073 -0.176206 -0.0114671 0.295766 0.22219 0.324922 -0.0509034 -0.21839 0.0811283 -0.00989251 -0.0380808 -0.0219277 -0.017789 -0.063171 0.0924988 0.0552814 0.163668 -0.195803 0.012778 -0.0291165 -0.205884 0.0593461 0.191401 0.184963 -0.230317 0.00874273 0.0648595 -0.120954 -0.0264684 0.090412 -0.114053 -0.00366035 0.0244916 0.184471 0.0982578 0.141901 0.289879 0.217233 0.157205 0.103288 0.305048 -0.102008 -0.00368837 -0.0826616 -0.0098433 -0.0851023 -0.110168 -0.0113899 -0.0105044 -0.0935836 -0.0243404 -0.167401 -0.176478 0.142801 0.0144004 0.00743044 -0.0964249 -0.136986 0.187875 -0.0125305 -0.22733 -0.094788 -0.107107 0.112503 0.2752 -0.166045 0.230213 -0.0648451 -0.0575242 -0.0127553 -0.187718 0.0394454 0.252299 0.0253407 -0.0587707 -0.0870937 -0.144587 -0.121364 0.0769471 -0.144486 -0.0802716 -0.140988 -0.0924102 -0.0183067 -0.141229 0.225301 0.271148 0.0440165 0.163694 0.16317 0.0690652 -0.0937775 -0.122093 -0.151766 0.0746791 -0.144068 0.113965 0.0449945 0.00440147 0.0541966 -0.0955643 -0.0808528 0.129903 0.0643875 -0.0469113 -0.0317044 0.0241309 -0.29567 -0.0214241 -0.042698 0.0370416 -0.110311 0.21068 0.0661051 -0.0782583 -0.0733642 0.22091 -0.0831232 -0.00180045 -0.0850571 0.15582 -0.0554523 -0.108081 0.0705394 -0.177651 -0.109917 0.177786 0.0880044 0.0212113 -0.0276355 0.188676 -0.076449 -0.061453 0.179209 -0.0409984 0.30827 0.164406 0.0861832 0.179375 0.0080234 0.202072 0.117906 0.0111932 -0.188046 -0.0370009 -0.119881 -0.122261 0.0247424 -0.0852487 -0.113703 -0.234175 -0.456974 0.115345 -0.168577 -0.198975 0.12185 -0.177887 -0.0607485 0.101276 0.181229 0.185065 -0.227117 -0.287174 0.119588 0.0586674 -0.0340368 0.165461 -0.0561393 0.365809 -0.0685839 0.0642534 0.0583475 0.0259364 0.143532 -0.194401 -0.166948 -0.213995 0.116054 -0.141095 0.0112399 -0.264947 -0.121773 -0.178793 -0.0829784 -0.119668 0.161271 0.112249 -0.0676869 0.151304 0.152384 0.0583035 -0.0580566 0.0535676 0.0208994 0.158578 -0.148287 -0.0440813 -0.0592587 -0.0880338 -0.233051 -0.00832879 -0.107322 -0.214981 0.255887 0.259806 0.232005 -0.0099415 -0.17096 0.0114268 -0.121765 -0.301949 -0.0838964 -0.0745146 0.000337582 -0.0485133 0.0469369 0.048349 0.186797 0.258644 0.190146 -0.226209 0.238785 0.252473 0.31039 -0.286511 0.15648 0.0424885 -0.292411 0.00184356 0.0651092 -0.13406 0.0923528 -0.14357 0.0804802 0.242833 0.120276 0.143532 0.189345 -0.12968 -0.0158332 0.320385 -0.221312 -0.128074 0.339764 0.0842923 -0.133292 0.048926 0.159553 0.210597 -0.00122919 -0.250627 -0.301832 -0.179205 0.289671 -0.239744 -0.0378524 -0.096882 -0.574981 -0.144192 0.0238684 -0.564798 -0.231217 -0.00695598 0.206556 -0.0995321 0.29234 0.22861 -0.291242 0.229995 0.00795485 0.226804 0.0230749 0.288636 0.144405 -0.242295 -0.0553678 -0.0847569 0.0344761 -0.0953848 -0.00566138 0.11115 -0.10823 -0.189543 -0.0481734 0.0788337 0.384176 0.19621 0.117675 0.293347 0.19245 0.19053 -0.439131 0.138826 -0.0882118 -0.153959 0.0988569 -0.0195963 0.119116 -0.0906907 0.0391994 -0.142872 -0.210886 -0.00606538 0.0571539 -0.0529168 0.0590318 -0.0765498 0.100676 -0.160735 0.122347 -0.0752973 -0.160996 0.0390832 -0.0570664 0.0911945 0.187176 0.013466 -0.0329687 0.108016 0.107227 -0.065522 0.147914 -0.0785747 0.307199 -0.294449 0.067334 -0.01106 0.0966914 0.0149348 0.23585 -0.404648 -0.062802 -0.0741526 0.171884 0.191387 -0.156268 0.0389783 0.174993 -0.139842 0.0240656 0.13271 0.0502454 0.139048 0.16901 0.142282 -0.202579 0.0788849 0.105472 0.0772325 -0.0487205 -0.0599469 0.0301912 0.0919861 0.0184369 0.112132 0.117002 0.0642382 -0.120022 -0.0256194 -0.0320538 0.104647 0.0848173 -0.0231218 0.0358991 -0.0924125 0.00142071 0.0320519 -0.0235955 -0.0804866 -0.0662119 -0.0167535 0.0691856 -0.195373 -0.0566189 -0.00835798 -0.0223188 0.0257777 -0.129155 -0.0166489 -0.115085 0.0161051 -0.0910653 -0.0405348 0.0711379 0.0314165 -0.0617645 0.00656229 0.0349238 -0.07517 0.00795697 0.00908689 -0.0747734 0.121719 -0.0193621 0.159206 -0.0865339 -0.0844572 0.0889763 0.00699714 -0.0447441 0.0576925 0.0996097 -0.183824 0.192358 -0.00744144 0.110664 0.0395126 -0.104482 -0.0676229 0.101462 -0.23871 -0.0563791 0.0608308 0.00266888 0.0434593 0.0822929 0.0462445 0.0237408 0.112666 -0.0430364 -0.0591299 0.104889 0.131689 -0.000680445 -0.0705514 0.129012 -0.0859148 -0.116732 -0.00550401 0.0870221 0.00546593 0.0413448 -0.0790691 0.0773839 0.17414 0.145541 0.0109615 0.132906 0.0455152 -0.0047377 0.163651 -0.0984038 -0.0832369 0.0262188 0.0309657 -0.0290912 0.0310813 0.34232 0.102048 0.0331681 0.035709 0.0938138 0.161348 0.217774 -0.00139384 -0.0151972 -0.157345 -0.00410166 -0.0556735 0.454594 0.189684 -0.134048 0.180231 0.207222 -0.0656981 0.0626754 0.104123 -0.184181 0.135141 -0.116132 0.218649 -0.169546 -0.212996 -0.0735877 -0.351878 0.00571737 -0.104754 0.0203444 -0.12637 0.0206389 0.110967 0.0510687 -0.222433 0.0424639 -0.173526 0.0518695 0.0387815 0.0953037 -0.116309 0.148432 0.0811471 -0.18796 -0.232278 -0.27967 -0.227116 -0.141113 -0.254314 0.00810018 0.0114646 -0.108261 -0.0152267 -0.0070795 -0.0831617 0.0224555 0.0853178 0.222373 -0.00444696 -0.0960117 -0.0809334 -0.0552307 0.0110734 -0.00439525 0.0772344 0.0679678 -0.0588479 0.00082806 0.000529116 0.000968922 0.00565319 -0.00924397 -0.0238703 -0.0435177 0.113416 0.22346 -0.209495 0.0252558 0.171689 -0.00693431 0.0784726 0.0408935 -0.155523 0.0264315 0.0750071 0.10178 0.109549 -0.06843 0.138953 0.0873861 -0.0952189 -0.0650598 0.202198 -0.0657164 -0.0399682 -0.0330979 0.0220974 -0.0581963 0.0191493 -0.0477787 -0.0496662 0.094942 -0.0815551 -0.1784 -0.11955 0.139185 -0.0665828 0.00918236 0.0119199 -0.0276243 0.0999579 0.0986793 -0.027716 -0.0414888 -0.137094 0.00117304 -0.0534303 -0.109615 0.0814769 0.0801073 0.104653 0.110529 0.0381957 -0.036379 0.0951207 -0.0117416 0.0338141 0.0843954 0.0686674 -0.0159269 -0.069378 0.0279248 -0.0552449 -0.0613252 -0.0319008 -0.0316602 -0.151797 0.0102079 0.14955 -0.13483 -0.0954071 0.127305 -0.0763689 0.0327667 0.062947 -0.143508 0.151668 -0.0731556 -0.0184106 0.0230923 -0.0477451 -0.0515971 0.0290478 -0.097508 -0.0518504 -0.0219784 -0.0867354 0.00255253 0.0237334 0.00367934 0.0255104 -0.0446232 -0.0724037 -0.12283 0.0267004 0.00790881 0.110203 0.0653532 0.128506 0.0394361 0.17402 0.112721 0.05031 -0.0791964 0.148198 0.0605766 0.0472224 0.0144843 -0.12408 0.019987 -0.0425876 -0.145627 -0.0584298 -0.0595093 0.00856961 0.168291 -0.0281988 -0.0796723 0.0304552 0.160599 0.0578142 -0.00925709 -0.0161011 -0.0208475 0.065122 -0.07731 -0.0612316 -0.171806 -0.0759402 0.0249075 0.151507 0.0644551 -0.106199 -0.210774 -0.113302 -0.0469051 0.16861 -0.0148374 -0.00481363 0.0176388 -0.0272203 0.151422 0.0227766 -0.00231141 0.115283 0.00765608 0.0960547 0.106099 -0.0967926 0.229217 -0.170099 0.0571103 0.0749438 -0.236657 0.40835 0.0164495 -0.467499 -0.00299054 0.15892 0.112133 -0.18441 0.324827 0.0539382 -0.0794118 -0.0324305 0.0440197 -0.126757 0.139358 0.198663 -0.0803072 0.0285928 -0.0367501 -0.0111097 -0.0089683 -0.0513647 -0.274274 -0.0199597 -0.00361313 0.300497 0.0174824 0.0692032 0.0220861 -0.0263082 -0.135604 -0.0650937 4.0913e-05 -0.0116016 0.11237 -0.17814 -0.0146487 0.0403977 0.0553429 0.0597143 -0.0119705 -0.112824 0.074951 -0.0180109 0.042248 0.160463 -0.0749427 0.101345 -0.0406712 0.170412 0.12127 0.164957 0.103427 -0.0457544 0.111558 -0.0526668 0.0921632 0.0837136 0.0274201 -0.20456 -0.0537456 -0.00925395 0.0318427 -0.099033 0.0874317 0.148794 -0.0578747 -0.0645286 0.163861 0.0517462 -0.0309595 -0.0426594 0.0516001 0.0157314 0.0527159 0.0247323 -0.0265112 -0.0774902 0.0810374 0.0507763 -0.259728 0.0290892 0.0703159 -0.00554315 -0.103583 -0.0850755 0.018641 -0.0411717 0.139347 -0.0297309 -0.0882917 -0.00923638 0.19143 0.00813075 -0.0137663 0.138765 -0.0407844 -0.108413 0.0429761 0.162042 0.00947059 0.0259915 0.0449625 -0.126338 -0.161944 -0.00860066 -0.012941 -0.00729432 0.00712826 -0.234058 -0.0256471 -0.0214185 0.06713 -0.0296558 0.089047 0.191075 -0.000657104 0.0278784 0.122851 0.0303692 0.025779 -0.0965027 0.0236212 0.0899535 -0.210363 0.0260307 -0.0807432 0.0165159 0.098578 0.0426006 -0.215837 0.0113929 0.184865 -0.0454864 -0.0573467 -0.0628625 -0.141589 -0.103528 0.0259737 -0.055552 -0.0701423 0.0933322 0.053941 0.119475 0.00585132 0.0738618 -0.119037 -0.0013367 0.0979312 -0.0300699 0.0370564 0.0466465 0.141073 -0.0846979 -0.0716634 0.0366908 0.0217853 0.0420725 0.0557187 -0.127601 -0.0633499 0.00903533 0.052616 0.117233 0.14367 0.229665 0.133048 0.121683 0.163681 -0.0491467 -0.0720992 0.0736895 -0.0109053 -0.00793476 -0.142793 -0.105156 0.149605 0.104451 -0.0917578 0.081363 -0.115603 -0.0979221 0.0207818 0.1039 0.0633631 -0.28495 -0.0550032 0.169964 0.159809 -0.0139964 -0.119871 -0.16984 0.082508 0.155918 0.210671 0.0267688 0.0711621 -0.0233876 0.0971149 0.245336 0.0813422 0.315179 0.120628 -0.154247 -0.0335572 0.0176225 -0.128336 -0.118139 0.0711633 -0.151185 -0.0507637 -0.237158 0.0145264 0.109944 0.0883118 -0.0134203 0.0724862 0.0362578 0.181455 0.0840854 -0.242896 -0.0523724 -0.273453 -0.00414532 -0.0695838 0.0910057 -0.0729211 0.00135327 0.0760848 -0.0282379 -0.301745 0.175096 0.136349 -0.178108 -0.121177 -0.102259 0.0229973 -0.0959463 0.158804 0.081071 -0.15304 0.0413377 0.0724804 0.182794 0.0197375 0.162405 -0.0894462 -0.0245813 0.0149201 0.0786644 -0.137473 -0.127675 0.0170659 0.125363 -0.158565 0.140205 0.20246 0.0190101 0.0334338 -0.238146 -0.0767433 0.00120181 0.0676786 -0.0818391 -0.0463626 0.186671 -0.0638118 -0.0306459 0.0156605 0.0791835 0.228736 -0.0412352 -0.103645 0.043911 -0.0591928 -0.0471427 -0.00634436 0.020489 -0.136344 -0.100562 0.145398 0.158154 0.0997253 0.000554217 -0.0130124 -0.034162 -0.104566 0.0549258 -0.00739206 -0.0369332 0.0290971 0.176111 0.0741856 -0.0104006 0.00564902 0.126626 -0.110317 0.0492032 -0.0717439 -0.0036075 -0.0858183 -0.210364 -0.00919604 0.228259 -0.195652 0.0526133 -0.145369 0.0132102 0.00751124 0.105657 -0.0365376 0.182996 -0.125685 -0.101182 0.0165028 -0.0263801 0.0160642 0.00196827 -0.143491 -0.0718493 0.124762 -0.0127503 0.0790749 -0.0827091 0.0452554 0.0787628 0.0681629 -0.0256808 -0.096979 0.165226 0.0812313 0.0531949 0.0731494 0.214582 -0.0393139 0.112668 0.0273821 0.092732 -0.138341 0.0821224 0.113149 -0.0701251 -0.00292032 -0.0436945 -0.0896976 -0.151529 -0.134469 -0.121194 0.0401092 -0.139591 0.0396596 -0.0716609 0.0929945 -0.0545573 0.124986 -0.00498682 0.135742 0.120423 0.0688381 0.114603 -0.09437 0.220334 0.00873545 -0.231128 -0.0826937 -0.0837699 -0.124847 0.121663 -0.242452 -0.149692 0.136563 -0.177212 0.120054 0.0468214 0.0681971 -0.0272669 -0.229709 -0.0590153 0.375207 -0.244415 0.00572813 0.585794 -0.276426 -0.254826 -0.432255 0.1747 0.386787 -0.281835 0.545777 0.51341 0.106635 0.445013 -0.39608 -0.0946152 0.255846 -0.270033 -0.14132 -0.27635 0.0284759 0.138158 -0.659131 -0.350616 -0.178156 0.0348819 -0.382411 0.322389 0.595555 -0.00488353 0.366272 0.0131526 0.211791 0.300044 0.123491 -0.195515 -0.198966 -0.349922 -0.314511 -0.0536809 -0.0179607 -0.232888 0.676954 0.216302 -0.224969 -0.24791 0.128532 0.160354 0.10149 0.00847301 -0.0302267 0.17578 -0.0965226 -0.146172 -0.0234415 0.0261919 -0.0351295 0.0209765 0.0622873 0.100457 -0.147359 -0.100955 -0.125854 -0.0590234 0.112433 0.0145801 -0.00848957 0.14119 -0.197512 0.120654 0.201186 0.0181273 0.158429 -0.0103922 -0.15695 -0.0743204 -0.0270574 0.0320122 -0.0669559 -0.00721661 -0.0686452 0.0728646 0.0806181 0.231174 -0.137292 -0.0273126 0.0056963 0.0400531 0.153186 0.228851 -0.203128 -0.0256348 0.071153 -0.220257 0.253868 -0.0761929 -0.0932261 -0.0778631 0.115036 -0.0622257 -0.0262207 -0.0214879 0.0690512 0.0209489 0.0731055 -0.0425733 -0.0359306 -0.0448674 0.0659565 0.0865719 9.75103e-05 -0.0624747 -0.0842548 0.0373691 0.0408321 -0.117461 -0.0157923 0.0204159 0.110933 -0.0493983 0.0316566 -0.0711276 0.107916 -0.0764492 0.14404 -0.0313113 -0.049516 0.0585124 -0.0305467 0.054784 -0.0251959 0.133322 0.0292559 -0.00307063 0.0484701 0.0550362 0.0523232 -0.0544546 0.0604896 -0.0559875 -0.0601698 0.0651512 -0.0982244 0.020072 -0.0468181 -0.0500114 -0.0732602 -0.170313 -0.00969601 -0.0145812 -0.0617696 -0.0703933 0.192527 -0.0808401 -0.0571309 0.166415 -0.0217985 0.0397629 0.0282618 0.136248 0.114784 -0.150841 0.0514784 -0.0766725 -0.0195818 0.0925979 -0.135967 0.0693915 0.00635923 -0.14129 0.0301597 -0.0876649 -0.00917308 0.0269001 0.102411 -0.176056 0.0236241 0.0593654 -0.110521 -0.0604335 0.0187647 0.204747 0.0782073 0.0294341 0.108798 -0.127006 -0.00728226 -0.172738 -0.0706098 0.0454335 0.00390408 0.0852032 -0.0901907 -0.1377 -0.00144425 -0.0524609 -0.0712229 -0.180105 -0.151311 -0.106072 0.126468 0.0111195 -0.210371 0.0715966 0.00369409 -0.196137 -0.12239 0.125437 0.0786162 -0.125734 0.137779 -0.0981374 -0.0604214 0.108835 -0.234827 -0.0249287 0.126259 -0.0523678 0.0860808 0.100138 0.0854343 -0.0138859 0.158789 -0.255623 -0.0635942 0.212375 -0.0764734 -0.0949793 0.204199 0.132326 -0.0955925 0.121554 -0.106239 -0.0763844 -0.104777 0.0146084 0.0153864 -0.0949115 0.0306047 -0.0404789 -0.198477 0.0878524 0.0402079 0.121191 0.304294 0.101059 -0.0437496 -0.02473 -0.0706343 -0.0807523 0.16414 0.0587644 0.00349266 0.0303205 0.0903459 -0.0078058 -0.0220835 -0.0117466 0.100295 0.0593093 0.113105 0.0862721 -0.113102 -0.0294126 -0.0377413 0.0174957 -0.0576629 0.0451328 0.0429632 0.00198221 0.0708792 -0.0515316 -0.056539 -0.190867 0.0712991 -0.14024 -0.128517 0.00344286 0.0971942 -0.0371714 -0.132565 0.228011 -0.0621693 -0.0524206 -0.0165572 -0.170495 -0.0335119 -0.301051 -0.132863 -0.0395643 0.113664 -0.128653 0.0339402 -0.0152244 -0.0249651 -0.167569 -0.0511568 -0.215177 0.0884599 -0.0882129 -0.0396941 -0.103997 -0.28535 -0.103653 -0.0885068 -0.187292 -0.0185811 -0.137416 -0.176251 0.0362844 -0.0713207 -0.0448806 -0.109152 -0.148402 0.182255 -0.0670543 0.10474 0.168356 -0.0573503 0.257799 -0.103911 0.186124 0.090132 -0.16542 0.0360291 -0.104546 -0.0127572 -0.117749 -0.101405 -0.116461 0.0630571 -0.231787 -0.130539 -0.303729 -0.12393 0.00348104 0.130954 0.117229 0.214201 0.188806 -0.0117409 0.120749 0.0621172 -0.0739483 0.137778 0.0621903 -0.0669127 -0.107425 -0.0352103 0.082213 -0.108635 0.160344 0.0549772 -0.408107 -0.0396278 0.070843 0.209864 -0.1183 -0.237694 0.119988 -0.298741 -0.369259 -0.141714 -0.196801 0.042864 -0.155838 0.0188351 0.0464285 0.0689042 0.149622 0.117914 -0.128877 0.143748 0.32839 0.0619086 -0.146177 0.209581 -0.133313 -0.148041 -0.0782948 -0.0194403 -0.0914661 0.036588 -0.349916 -0.00684698 0.105866 0.0958592 0.22224 0.0955872 0.0325544 -0.0675338 0.0944266 -0.0492112 -0.127177 0.32963 -0.124419 -0.051529 -0.0290464 0.12424 0.0521014 -0.170561 0.0881884 0.2285 -0.558985 0.0847402 -0.0026672 0.0806298 -0.208435 -0.790242 0.0563626 -0.0642151 -0.598774 -0.109389 -0.200957 0.0404287 -0.00101255 -0.00339003 0.112636 -0.54626 0.47323 0.0304637 -0.0931217 -0.0170604 0.387209 -0.0990845 0.0315949 0.0884204 -0.678055 -0.223018 0.0598398 -0.35924 -0.208201 0.26122 -0.296941 -0.0155344 0.193532 0.44848 0.55135 0.49173 0.442365 0.116007 0.267906 -0.194792 -0.322427 0.0495854 -0.222994 -0.363656 -0.282515 0.00960341 0.0725749 -0.017604 -0.0815438 -0.0622444 -0.0463336 -0.0240905 -0.0213032 0.0398722 0.0532315 0.114766 -0.134132 0.225218 -0.1063 -0.122987 -0.0138105 0.16532 -0.0943367 0.0686262 0.0363152 0.155267 0.0277984 0.265164 -0.000387784 0.115783 -0.0241797 0.167648 -0.0821855 0.0421885 -0.0185175 0.0148791 0.0360266 0.0172068 -0.0962498 0.062563 -0.0828604 0.190361 0.132999 -0.115606 0.00431248 0.184169 -0.0549732 0.015562 0.135315 0.0880799 0.0923824 0.278137 0.134275 -0.092404 -0.0625512 0.0654395 0.0955775 -0.00123816 -0.0152703 -0.157371 -0.00700542 0.096599 -0.0375178 -0.0212846 0.0965174 -0.0530948 -0.0571727 0.0410979 0.0559062 0.0926682 0.1289 -0.0153186 -0.042358 -0.0530091 0.0101418 0.0948849 -0.034818 -0.0850054 0.0536646 0.121616 -0.0926039 -0.0921673 0.127275 0.0740461 -0.0571146 -0.14816 -0.0467813 -0.0490392 0.0142316 0.103847 0.0372433 -0.186792 -0.0354086 0.0369252 -0.0527195 0.073801 -0.0433866 0.080514 -0.0624833 -0.0927434 0.119095 0.0104386 -0.0151938 -0.0903289 0.0510787 -0.0294307 0.0786073 0.0718916 -0.0265134 -0.0707969 -0.0646285 0.0440872 -0.0184075 -0.0798704 0.0204629 0.0069304 -0.106299 -0.0572142 0.179001 0.0150129 0.0112751 -0.0535359 0.0190569 -0.0410476 -0.109749 0.0794939 0.012637 -0.0155607 -0.122732 -0.0123276 -0.0362691 0.0593566 0.08455 -0.0294108 0.106021 -0.0884292 -0.0696544 -0.00860933 0.0716587 -0.0371555 0.0966008 -0.0833498 0.0987104 0.0555932 0.00692551 -0.0483999 -0.0818977 -0.0856639 -0.0405623 0.0470718 0.104409 -0.028464 -0.0842186 0.087903 0.0361166 -0.0240089 0.0401548 0.0126185 0.0904796 0.0609915 -0.0552555 -0.199736 0.223208 0.210395 -0.148532 0.0457414 0.0518014 -0.0486101 -0.151672 0.0672996 -0.077227 0.0674962 0.0823707 -0.144883 -0.141056 0.134979 0.00277754 -0.00808819 -0.0484723 0.0442209 -0.194533 0.106848 -0.0426532 0.151794 0.0429038 -0.177739 0.106868 -0.187142 0.0765226 -0.173931 0.0225858 -0.18725 -0.0325454 -0.212109 0.0259061 -0.046614 -0.0380538 -0.196031 -0.0327915 -0.0749205 0.157864 -0.00648713 -0.0342289 0.223407 0.13303 0.0516224 0.0122361 0.0370577 -0.0809022 -0.1023 -0.0564394 0.00727282 0.146511 -0.0226461 0.0896419 0.0180549 -0.073685 -0.0142393 0.131032 -0.0125953 0.0617784 0.017727 0.0571594 -0.0118043 -0.00157755 0.0216156 0.106258 -0.0749274 -0.0952324 0.0963812 0.0326013 0.0566559 0.106655 -0.0284421 0.0715399 -0.0569831 -0.0969606 -0.162913 0.0746586 0.0413258 -0.127999 -0.0842517 0.068846 0.0113905 0.0342418 -0.100912 -0.109475 -0.0534501 -0.106011 -0.0513011 -0.0740825 -0.0430779 -0.0342349 -0.120753 0.105046 -0.0567702 0.000884777 0.0988322 0.0386571 -0.0882957 0.0414094 0.0325421 0.0922922 0.0464888 0.0777474 0.048194 -0.147469 0.0295533 -0.168375 -0.0420883 0.044844 0.0671859 0.0495589 0.11215 0.127329 0.0674048 0.00119896 0.0973584 0.0513524 0.128684 0.0510072 -0.0887039 0.0476611 0.00328122 0.0179858 0.0902677 0.077717 -0.143732 0.0221515 0.10612 -0.0574231 -0.0379161 -0.0585359 -0.0976733 -0.0104098 0.00722141 -0.054656 0.117417 -0.0113155 0.0446833 0.0400667 -0.0851082 -0.00568308 0.0195031 0.159972 -0.0748724 -0.0453592 0.0913236 0.0774962 -0.0762356 0.0147292 -0.0714437 -0.078115 0.0489179 -0.0307709 0.0021764 -0.003573 0.0573158 -0.154369 0.116541 0.000927433 0.0031033 -0.0221346 -0.000468142 0.0578646 0.0169472 -0.117615 0.0377082 0.113949 0.0885715 0.0572244 0.0662584 0.00204813 0.0059646 -0.040794 0.0585389 9.14068e-05 -0.0964496 -0.0656245 0.0174116 -0.0967428 -0.0670357 -0.0873784 0.0416333 -0.0575563 0.0144465 -0.0674554 0.00858376 0.0224516 0.0274695 -0.0434828 -0.00349304 -0.0613754 0.0760872 0.0262463 -0.182494 -0.0393716 -0.0844681 -0.0942289 0.204751 0.0433651 -0.0600735 -0.154943 -0.0237369 0.110394 -0.0308946 0.0929533 -0.17371 0.0874508 -0.0925381 0.040365 -0.226863 -0.0235671 -0.177054 -0.0183897 -0.000356353 -0.0972516 0.0852908 -0.0469744 0.0958242 -0.157652 -0.0673493 0.0959459 0.09902 0.102255 0.0598695 0.0398719 -0.00848658 0.0982438 -0.0311751 0.17028 -0.00435497 -0.0576475 -0.196119 -0.108648 -0.0240918 0.0028277 0.032683 -0.0847929 0.0489105 -0.00328814 0.0501617 -0.00611222 0.0922728 -0.0588841 -0.12222 -0.0604481 0.0507268 -0.00457824 0.070427 0.0733151 -0.12358 -0.067154 -0.0993606 -0.00614104 0.0479327 -0.0496611 0.0959011 -0.132703 -0.00600752 0.13758 -0.0367547 0.040454 0.112681 -0.0188522 0.0866458 -0.170191 0.0706927 0.162226 -0.00993967 -0.0229674 0.0199133 -0.00311464 -0.0626307 0.0126819 0.0201009 -0.0707357 -0.0928622 -0.0195716 -0.000385749 -0.0131961 -0.0355863 -0.0176691 -0.0812291 -0.106757 0.0945454 -0.0392731 0.0891344 -0.0117754 0.0391194 0.147976 -0.0142048 0.00755716 0.100515 -0.0124872 0.0965972 -0.0337821 -0.0194179 0.0859766 -0.0426259 -0.173338 -0.106136 -0.163928 0.0516217 -0.18507 -0.0449498 0.179385 -0.0656467 0.112681 -0.0461285 -0.146329 0.00873537 0.15786 -0.0811932 0.0848078 -0.00809212 0.13742 0.0218878 -0.0285929 0.00983361 0.114583 -0.0358765 0.0169672 -0.115961 -0.0353984 -0.075162 -0.0474984 -0.113633 -0.0438898 -0.083871 -0.00523095 -0.0129252 -0.0452215 -0.0270177 0.18404 -0.0789226 -0.00208064 -0.0660888 0.0654112 -0.02219 -0.0985931 0.0364897 0.110742 -0.142177 -0.0318105 0.097443 -0.0149425 -0.105515 -0.00857713 0.0567796 -0.0354314 0.0234631 -0.0856695 0.0872737 -0.00888697 0.0312585 0.0343133 0.0384203 0.00812554 0.0549812 -0.0593593 0.00130109 0.138374 -0.102408 0.0844617 0.0208227 -0.0167006 0.116688 0.000793773 -0.0336198 0.227743 0.0298622 -0.193986 0.00193704 -0.0551854 0.12891 0.0430214 0.145816 0.0335863 -0.142219 -0.00222504 0.200268 -0.0271456 0.0938258 0.126893 -0.00901622 -0.055079 -0.00579413 -0.0801331 -0.10587 -0.0498488 0.0504886 0.0281619 -0.0441138 -0.0930673 -0.0609704 -0.0999151 0.0342046 -0.0160101 -0.0635404 0.0326375 -0.29943 0.203883 0.0461149 0.0138742 0.250369 0.0788035 -0.0510726 0.00961942 0.090193 0.118737 0.00966737 0.0552316 0.200713 -0.0506987 0.155062 -0.15442 -0.00788679 0.0463548 -0.0213697 -0.0877051 -0.201097 0.132094 -0.0509906 -0.133616 0.129004 0.0949488 -0.117534 0.0304364 0.0310239 0.0713777 -0.187408 0.00825075 -0.332452 -0.145429 -0.10864 -0.052704 0.261454 -0.101896 0.0501914 0.087605 0.168518 0.158346 0.117976 0.0526273 -0.102622 0.101932 0.118009 -0.0612855 0.00243779 -0.0112297 0.0486951 -0.38972 -0.198357 -0.217178 0.116863 0.0564758 -0.0317786 0.219382 0.00427171 -0.0014368 -0.0816063 0.214925 -0.0914646 -0.0665221 -0.136507 -0.118754 -0.0296787 0.0610437 0.0763167 0.100168 -0.309799 0.018299 -0.0396707 -0.026655 0.209109 0.000790093 0.153618 -0.0398877 -0.164153 0.125154 0.0890386 -0.218298 -0.0230482 0.0202779 -0.179263 0.198398 -0.0114064 -0.220415 0.0616645 -0.0421711 0.0140657 0.0472695 0.15199 -0.111378 -weightContainer_hidden_0_0_to_output_deltas 50 -0.000270421 -0.000207879 -0.000354244 -0.000240481 0.000497344 -0.00162769 -0.00265719 0.000711668 0.000316384 -0.00231867 0.00134312 0.000797465 -0.00070355 0.00468708 0.00125893 -0.000548033 0.000682621 5.62173e-05 -0.00384231 0.000333699 0.00161013 -0.000216694 -0.00065047 0.00177588 -0.000279621 0.00160348 -0.00233056 0.000942209 -0.000318372 1.97684e-05 -0.0021463 0.000493356 -0.00178824 0.00158348 -0.00194487 0.000870129 -0.00400466 -0.00213001 -0.00135814 -0.000546375 -0.00319357 -0.00204631 -0.00102206 -0.000599156 -0.00010308 -0.00047158 -0.00040159 0.00362342 0.00108968 0.000648589 -weightContainer_hidden_0_0_to_output_plasticities 50 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -weightContainer_hidden_0_0_to_output_weights 50 0.018331 -0.0865791 -0.053692 0.0914351 -0.174866 -0.483997 -0.0297877 0.00339773 0.0753778 -0.0124048 -0.126507 0.0171024 -0.0637052 -0.671093 -0.0722282 -0.0626882 0.012409 -0.0596263 -0.0160657 0.0515984 -0.0568621 0.108657 1.11513 0.00590559 0.115777 0.159473 0.0495451 -0.267678 0.180788 -0.0870261 -0.159353 0.0313966 -0.317018 -0.088328 0.0734796 -0.106597 -0.0882449 0.0704977 0.138618 0.0794593 0.273421 0.0397432 0.0839295 0.0418557 -0.170016 -0.0959572 -0.187629 -0.0361972 -0.078782 -0.25085 -weightContainer_input_to_hidden_0_0_deltas 7200 -7.52859e-05 -1.9703e-05 -1.33206e-05 1.86766e-05 2.02159e-05 5.46696e-05 5.66951e-05 3.59237e-05 0.000144497 5.85831e-05 -2.47005e-05 -0.000111725 -6.0841e-06 -5.6877e-05 -7.36838e-05 0.000243191 0.000123374 -0.000174706 -8.85434e-06 3.0463e-05 -2.63755e-06 0.000100479 -2.51818e-05 -5.67563e-05 7.41244e-05 -0.000118988 9.12121e-05 3.45885e-05 1.81747e-05 -3.47924e-05 -6.54357e-05 2.45731e-05 -8.22835e-05 5.41013e-05 2.15176e-05 5.6382e-05 -0.000105662 1.30241e-06 2.55149e-05 7.80953e-05 2.22063e-05 3.22445e-05 0.000110688 -1.16187e-05 0.000112521 6.46409e-05 -0.000112477 -9.91688e-05 -3.62233e-05 -9.10354e-05 -0.000124315 0.000333669 0.000189185 -0.0002685 4.30233e-05 3.8741e-05 2.32374e-05 6.24772e-05 -6.37166e-05 -7.02688e-05 9.18487e-06 -3.97447e-05 -6.45683e-05 1.44983e-05 -3.33751e-05 4.53656e-05 -2.24336e-05 -2.24287e-05 6.58211e-05 -2.686e-06 -5.7042e-05 2.17986e-06 -8.76244e-05 -1.50416e-05 0.000116103 -0.000180861 -3.38102e-05 -0.000208475 0.000111507 0.000158377 0.000121568 -0.000125768 0.000428533 0.000155742 0.000231764 0.000225714 -0.000209219 -0.00055952 -0.000457656 0.000854178 -0.000199311 0.000170037 -0.000231347 3.35246e-05 0.000122903 -3.18001e-05 0.000214887 -0.000303139 -0.000142825 -2.22746e-05 0.000101418 -9.79885e-06 -5.10205e-05 -4.02745e-05 1.23153e-05 0.000206168 -0.000259242 9.77403e-05 -0.000120585 1.12393e-06 9.5555e-07 8.28065e-06 1.68376e-05 2.92893e-05 8.02568e-05 2.34389e-05 0.000193061 6.46729e-05 -4.40157e-05 -0.00010151 -2.32053e-05 -2.70374e-05 -0.000105795 0.000299472 0.000127862 -0.000190068 -2.20558e-05 7.17262e-05 -1.21086e-05 8.83916e-05 6.22856e-06 -5.47698e-05 2.58363e-05 -0.000130732 4.95549e-05 3.73806e-05 -1.98085e-05 -2.85175e-05 -5.20301e-05 4.22582e-05 -1.16379e-06 2.74154e-05 -4.28278e-06 3.87629e-05 -8.6824e-06 -2.78695e-05 -2.22106e-05 -2.20376e-05 1.49978e-05 5.10414e-05 -1.58218e-05 3.19193e-05 7.43827e-05 -1.08449e-05 -3.67516e-05 -7.36251e-05 -3.73852e-05 3.93268e-05 8.37972e-06 -3.19348e-06 2.22534e-05 7.46213e-06 -1.653e-05 -1.53079e-05 -4.1192e-06 2.5043e-05 -1.20445e-05 7.28181e-06 6.29848e-06 1.18684e-05 1.40099e-06 -1.63426e-05 -1.32186e-05 -8.72946e-06 1.16591e-05 2.89441e-05 -2.98038e-06 -1.47825e-05 8.45491e-06 1.48347e-05 -2.37831e-05 -4.99157e-05 -3.01172e-05 -1.73007e-06 1.23752e-05 1.5627e-05 -3.09408e-07 3.78604e-05 7.34925e-05 -4.24424e-05 -2.23606e-05 -3.55137e-05 -2.27731e-05 3.71102e-05 1.04837e-05 3.27915e-06 1.95218e-05 1.29518e-05 -1.42799e-05 1.00539e-05 3.97645e-06 3.54099e-05 -8.08294e-06 -1.2693e-05 4.53722e-05 -1.13469e-05 -1.90106e-05 -1.22507e-05 8.45765e-06 2.50302e-05 1.37155e-05 -1.92309e-05 -1.98142e-06 -2.02774e-05 -1.36595e-05 1.85956e-05 0.000297057 -7.01269e-05 7.13166e-05 7.73586e-05 -3.92434e-05 8.13019e-05 -0.000136612 -0.00019406 -0.000189924 0.000216913 8.03833e-05 -6.41457e-05 -5.36132e-05 1.71363e-05 -6.78542e-05 -3.86318e-05 6.48835e-05 -6.02323e-05 -4.08831e-06 1.25274e-05 -9.12531e-06 2.28187e-05 -3.91695e-05 -3.71081e-05 -1.73025e-05 -2.0121e-05 -1.68575e-05 -6.29519e-05 5.26938e-05 8.5439e-05 -4.80253e-05 -3.28205e-06 5.08048e-05 8.08619e-05 -9.48421e-06 -6.82486e-05 -1.93115e-05 -5.45206e-05 -5.59564e-05 -1.31152e-05 1.79181e-05 3.7598e-05 -5.64777e-06 4.58976e-05 8.36304e-05 -2.94779e-05 -2.25729e-05 -6.5758e-05 -5.86165e-05 1.91733e-05 2.28829e-05 2.23703e-05 4.08834e-05 -4.42818e-06 -4.51009e-06 -1.43841e-06 1.17682e-05 2.98386e-05 -2.04275e-05 -1.7546e-05 2.41122e-05 -1.40543e-06 -8.96936e-06 -1.53654e-05 3.93282e-06 7.33758e-06 1.72782e-05 7.30289e-06 6.52025e-06 -9.68328e-06 -7.54987e-06 9.39407e-06 8.59689e-05 -7.58824e-05 -6.57348e-05 -7.71478e-06 -3.87523e-05 -6.0111e-05 -0.000140946 0.000166678 0.000252804 0.000108489 -3.08022e-05 -3.16921e-05 -7.19598e-06 -0.000106509 3.34214e-05 -5.72389e-05 4.18545e-05 -5.19332e-05 -6.17551e-05 -6.96288e-05 0.000116552 6.5683e-05 -0.000210529 2.35381e-05 3.66536e-05 0.000234228 5.05601e-05 -0.000211858 0.000107397 5.40241e-05 4.50837e-05 3.13905e-05 -0.00014998 -0.000273981 0.000249431 9.19205e-05 1.30167e-05 -8.15598e-05 -6.67499e-05 -2.83944e-05 -0.000221171 -6.48727e-05 4.36589e-05 0.00027129 0.000100831 -5.56145e-05 2.89529e-05 6.67736e-05 0.0001114 -6.78153e-05 -0.000195035 -9.59478e-05 0.000186386 4.44116e-05 -5.35767e-05 2.48905e-05 -2.51646e-05 -5.03397e-05 0.000105303 6.89855e-05 7.7972e-05 -0.000100729 -0.000176774 -5.40654e-05 9.41094e-06 5.94059e-06 9.30623e-05 0.000165292 -3.02472e-05 6.38814e-05 -4.89917e-05 -0.000101666 0.000196308 -0.00011196 0.000116122 0.000308697 0.000134968 9.45779e-05 -3.65187e-05 6.005e-05 6.81176e-05 -2.29159e-05 -8.8213e-05 -0.000234097 -0.000156329 -0.000196659 -0.000331592 -0.000194812 3.54697e-05 6.74773e-06 -8.20539e-05 -0.000105923 3.6691e-05 -0.000211686 5.33021e-05 0.000129168 -0.000119646 -3.54039e-05 3.98112e-06 9.53799e-05 2.30525e-05 3.67606e-06 -3.15781e-05 7.73523e-05 -0.000216121 -4.67416e-05 0.000226098 2.66104e-05 0.000209217 -3.76197e-05 -0.000113584 -2.05122e-05 -0.000336058 -9.71093e-05 -0.000258799 0.000522932 0.00075671 -6.74467e-05 6.37868e-05 -0.000164128 -7.65062e-05 0.000274681 0.000141395 -0.000439489 -0.000153303 0.00019346 -0.000231317 9.36752e-06 -7.61224e-05 2.10544e-05 -4.45978e-05 8.89228e-06 0.000138944 0.000100186 1.75687e-05 -0.000212223 4.20011e-06 0.000192707 6.63149e-05 -6.34548e-05 -0.0001376 0.000130533 4.25867e-06 -0.000115304 -1.95776e-05 -4.04775e-05 -4.38847e-05 8.00598e-06 6.35869e-05 5.37247e-05 2.7475e-05 2.6185e-05 -2.70285e-05 2.22176e-05 1.44315e-05 1.07866e-06 -2.97419e-05 1.11902e-05 4.59875e-05 -1.23627e-06 -9.7036e-06 -2.52858e-05 -1.86015e-06 -3.45549e-05 3.78418e-06 -4.01596e-06 -4.07293e-05 -6.46861e-06 -1.72646e-05 2.83266e-05 3.84074e-05 5.86865e-05 2.54564e-05 -2.85054e-05 -5.48213e-05 -1.65936e-05 1.70747e-05 3.75542e-06 -1.33222e-05 1.34164e-05 -1.40192e-05 -4.17157e-05 -2.69127e-05 2.03297e-06 -1.53169e-06 3.47094e-05 2.86553e-05 5.08163e-05 3.37086e-05 8.66908e-06 1.33479e-05 1.02605e-05 -2.54477e-05 -3.95143e-05 2.46914e-05 2.08643e-05 2.44174e-06 -1.33437e-05 3.65184e-05 -2.66263e-05 1.11346e-05 -2.04951e-05 -6.7077e-05 9.29469e-06 -1.88527e-05 -3.86381e-06 1.8741e-05 -2.81065e-05 7.29729e-06 8.14043e-06 -3.65237e-05 -2.14951e-05 8.47516e-06 -9.09265e-06 4.65224e-06 5.22952e-05 -0.000123498 3.50522e-05 -8.93988e-05 -3.39006e-05 -4.17371e-05 -5.89341e-05 0.000187768 0.00023838 0.000273628 -9.40016e-05 6.60995e-06 0.000216158 0.000101894 -0.000147848 8.08873e-05 3.03774e-05 -0.000197469 -5.66734e-05 -5.75001e-05 -9.88275e-05 -5.4227e-05 4.82693e-05 -2.72953e-05 4.04319e-05 1.78892e-05 0.000132624 -4.31539e-05 4.89276e-05 8.08552e-05 1.31348e-05 4.27437e-05 -5.13963e-05 -4.24177e-05 -8.38169e-05 -9.87617e-06 -5.84001e-06 -3.37236e-05 -5.76283e-05 -6.19649e-05 2.96778e-05 5.3166e-05 5.76575e-05 3.7072e-05 2.50981e-05 1.17361e-05 7.16897e-07 3.73133e-05 -8.21559e-06 -5.91258e-05 -1.78605e-05 1.36325e-05 2.07844e-05 3.83484e-05 -6.19796e-06 3.60741e-06 1.21612e-07 1.91175e-06 -6.52528e-06 -5.77935e-05 -3.20512e-05 -1.05771e-05 1.27422e-05 2.55375e-05 1.34586e-05 2.07121e-05 -2.22385e-05 -7.59188e-05 -2.51562e-05 3.73868e-06 -1.30765e-05 -2.75628e-05 1.97103e-05 0.000145153 0.000131951 -3.31818e-05 0.000149889 4.27035e-05 6.32353e-05 3.46908e-05 -7.7727e-05 -0.000288686 -7.96924e-05 -6.01648e-05 -0.000101101 -8.72442e-05 -1.68942e-05 8.07395e-05 -0.000186295 -3.27099e-05 0.000102553 0.000139334 0.000120536 -2.37845e-05 4.64091e-05 -0.000103928 -0.000200513 -0.000110165 -2.44987e-05 0.000103406 1.79136e-05 -5.78388e-05 -3.47772e-05 -0.000108373 -0.000115493 0.000154295 0.000129643 -0.000164877 -0.000166119 0.000390454 0.000130987 -2.43105e-05 0.000136338 3.12853e-05 0.000118827 -0.000109825 -0.000123963 -0.00026746 -0.000126685 -0.000188368 -0.000267926 -0.000102807 -0.000108036 1.99539e-05 -0.000151887 -0.000139576 -7.6643e-05 4.9822e-05 2.22352e-05 8.79496e-05 1.27901e-05 -0.000104916 -8.78093e-05 -8.5751e-05 4.27798e-05 9.17007e-05 2.99897e-05 -6.12184e-05 1.75573e-05 -3.46035e-05 -2.17933e-05 6.28256e-05 0.000113136 -0.000101264 -7.36914e-05 0.00116782 0.000146849 -0.000290861 -0.000144049 -0.000405329 0.000123191 -0.00050905 -7.44054e-05 -0.000416813 -0.0002711 -0.000149727 0.000108681 0.000258518 0.000357483 7.78321e-05 -0.000839495 -0.000590455 0.000142894 0.000220628 -9.84917e-06 0.00013112 7.53828e-06 -0.000277224 -0.000121116 0.000175909 0.000122212 -2.60924e-05 -0.000290336 0.00017005 0.000451708 -2.68229e-06 -2.0772e-05 8.91956e-05 0.00015991 -0.000211089 4.77648e-05 0.000231278 3.80603e-05 3.19117e-05 0.000204367 1.09917e-05 4.25357e-06 -8.84151e-05 -3.95671e-05 -0.000175158 -0.00013971 -7.00427e-05 -0.000129098 -0.000164108 1.72395e-05 0.000130856 -6.51459e-05 -0.000104133 1.12478e-05 5.68265e-06 0.000113673 -2.24134e-05 3.22728e-05 1.98796e-05 -8.37967e-05 -8.81506e-05 -5.88179e-05 7.99428e-05 4.2639e-05 -4.78772e-05 6.61661e-05 -7.60628e-05 -9.73964e-05 7.71491e-05 9.73276e-05 -9.84175e-05 -5.41789e-05 1.91933e-05 0.000177143 -0.000382837 3.6233e-05 -8.99396e-05 0.000303309 -0.000198662 0.000159014 0.000553258 -0.0001606 -4.37685e-06 2.42906e-05 5.56719e-05 0.000632367 0.000420544 5.79445e-05 -0.000379878 -5.37982e-05 -0.000163999 -0.000430724 0.000162795 -3.04648e-05 9.04187e-05 0.000223687 2.54294e-05 9.40554e-05 0.000162913 0.00013783 -0.000116817 -4.08418e-05 0.00017775 -0.00016505 -0.000104676 -6.49083e-05 0.000137243 0.00015228 -1.02192e-05 6.5139e-05 -0.000293416 -0.000197057 -0.000102747 0.000199498 -8.09576e-05 0.000346266 0.000724212 4.34182e-05 0.000151168 6.43126e-05 0.000309799 0.000414206 0.000124302 -0.000102403 -0.000188745 -0.000100243 -0.000204778 -0.000305246 0.000197073 -8.73772e-05 -0.000143249 1.9657e-05 3.02543e-05 1.55768e-05 -4.09764e-05 0.000109343 0.000219947 5.65552e-05 0.000281259 -0.000448908 -5.65272e-05 -9.38618e-05 0.000101212 0.000138988 -0.000119492 -0.00017858 0.000188784 -1.74221e-05 0.000178033 3.06751e-05 0.000201699 0.000336554 -6.67518e-05 -0.000203436 -0.000793032 6.86623e-05 0.000626118 0.000271888 -3.74518e-05 -0.000352486 0.000225964 0.000447513 -0.000525871 0.000289717 -1.40628e-05 -0.000257038 0.000192191 -5.86926e-05 0.000183187 -0.000374689 -0.000393368 -9.27384e-05 0.00020023 -8.32341e-05 0.00016754 -0.000382552 -0.000189413 0.000133481 0.000280494 6.76594e-05 -0.000144403 5.94397e-05 -0.000542134 -5.58836e-05 -4.0358e-05 0.000288972 9.12589e-06 0.000472955 0.000736689 -0.000141744 0.000224533 0.000159767 0.000190024 0.000584039 0.000228437 -0.000467028 -0.000609482 0.000163511 -6.08284e-05 -0.000305031 0.000104565 -0.000207291 -0.000141203 -0.000153011 4.86709e-05 3.94757e-05 -3.43201e-05 0.000179865 0.00013367 2.30375e-05 0.000166593 -0.000230856 -0.000117371 5.75343e-05 9.05302e-05 5.00502e-05 -0.000154657 0.000124573 4.08506e-05 -5.66771e-05 -1.05161e-06 -8.72019e-05 5.5717e-05 3.75015e-05 0.000131777 6.26847e-05 0.000125394 8.36719e-05 0.000117009 -1.53012e-05 -0.000149381 -4.01352e-05 -0.000124688 -3.76817e-05 -2.10769e-05 2.53534e-05 3.01022e-05 6.34235e-05 1.56381e-05 -1.02298e-05 2.91463e-05 0.000159757 0.000107336 -1.33839e-05 6.25801e-06 -1.92014e-05 -7.68085e-05 -3.95227e-05 -3.86876e-05 -5.72159e-05 2.31675e-05 5.88649e-06 -0.000104818 0.000135971 0.000105181 -7.47898e-05 -4.57571e-05 -0.000104889 2.11694e-05 5.70288e-05 0.000183908 4.05242e-05 0.000120821 5.25972e-05 2.42552e-05 -2.1574e-05 -0.000131806 -5.95479e-05 -0.00010684 -2.11692e-05 1.34256e-05 -1.12602e-05 1.51925e-06 2.08038e-05 2.34518e-05 6.66326e-06 -7.91307e-05 -9.37615e-06 9.23259e-05 -4.58383e-05 2.78068e-05 -1.35651e-05 -5.08807e-05 3.978e-05 1.91066e-05 9.63725e-06 1.72417e-05 5.62517e-06 -0.00028399 0.000325885 0.000177116 -0.000147685 -0.000221159 -0.000443633 0.000188869 0.000252589 0.000376346 0.000118875 0.000317235 -4.18188e-05 -0.00019412 -8.82264e-05 0.000111829 0.000297194 -0.000261933 -9.71767e-06 -7.2504e-05 -0.000324739 -1.22279e-05 -0.000174022 -0.000244273 -0.000317033 -6.01375e-05 -4.75635e-05 3.07631e-05 -5.96447e-05 0.000124385 0.000420947 0.000266016 0.000108413 -4.54292e-05 5.42599e-05 7.39691e-07 -0.000245654 -0.000106057 0.000104964 8.16577e-05 -3.43889e-05 -4.19768e-05 -9.42375e-05 3.80219e-05 6.81077e-06 0.00014387 1.49359e-05 0.000128997 3.53867e-05 6.20714e-05 -8.40463e-06 -0.000199038 -4.96433e-05 -9.74495e-05 -6.18721e-06 6.21107e-06 4.4991e-05 -3.15454e-05 4.84574e-05 3.07152e-05 -9.81776e-06 -1.61796e-05 3.62016e-05 9.66659e-05 -3.58551e-05 4.46291e-06 1.32817e-05 -6.70944e-05 1.61101e-05 -3.74972e-05 -5.15152e-06 -2.78527e-05 -3.29817e-05 -9.36762e-05 9.25535e-05 -4.15658e-05 0.000111904 0.000102176 4.35994e-06 2.31408e-05 -8.62077e-05 -0.000195081 8.83475e-05 3.27786e-05 1.55724e-05 -5.71324e-05 -4.77775e-05 6.76169e-05 7.30993e-05 -3.26706e-05 2.56803e-05 0.000187485 -0.000193919 0.00011364 -1.45845e-05 -0.000124546 -1.42546e-06 -8.05674e-05 7.45289e-05 3.17806e-05 7.74192e-05 5.67551e-06 -3.25344e-06 0.000171434 8.62409e-05 -5.17539e-05 -8.46279e-05 4.19574e-05 -7.01743e-06 0.00023676 2.11102e-05 -2.78486e-05 0.000124428 -3.56684e-05 9.23316e-05 -0.000127014 0.000105255 7.13002e-05 -1.20185e-05 -1.66062e-05 5.02061e-05 -2.57757e-05 0.0001775 4.12031e-05 -0.000201123 -0.000138553 8.57411e-05 7.83434e-05 -4.39621e-05 1.75547e-05 2.31576e-07 -6.26069e-05 3.18499e-05 -5.65442e-05 5.77659e-05 0.000123566 -9.86611e-05 2.21931e-05 6.16107e-05 6.54958e-05 0.000128174 -3.13021e-05 -0.000105863 -9.6236e-05 -1.51887e-05 0.000304418 0.000189375 -0.000227459 -0.000214745 -0.000217658 0.000205417 -0.000640498 0.000134265 0.000754449 -0.000174605 9.24091e-05 -2.14605e-06 0.000323523 0.000599041 0.000418786 -0.000483241 -0.000385201 0.0002976 9.7456e-05 -0.000293346 -2.16985e-05 7.00088e-05 -0.00011316 -0.000147901 0.000114542 1.556e-05 -6.13565e-05 -5.0305e-05 0.000158665 0.000168921 0.000170073 -4.25059e-05 -8.44372e-05 0.000141009 0.000124207 4.91285e-05 4.97268e-05 2.78152e-05 -6.56422e-05 0.000181671 3.04418e-05 3.97415e-05 3.6362e-05 1.66041e-05 -0.000117893 -3.17617e-05 -7.71759e-06 9.62578e-05 2.86919e-05 6.82149e-05 1.62303e-05 -0.000107465 -0.000148121 4.35284e-05 4.59951e-05 5.758e-07 5.28627e-05 -2.20147e-05 -7.48559e-05 -7.2335e-06 -3.42648e-05 1.26611e-05 4.69104e-05 -1.85773e-05 2.45615e-05 5.04834e-05 4.73123e-05 8.16177e-05 -5.20292e-05 -5.86767e-05 -3.98476e-05 2.7769e-06 -0.000130047 0.000102108 0.00021782 7.34221e-05 -7.2001e-06 1.1836e-05 0.000276277 2.45222e-05 -2.22381e-05 3.26277e-05 7.1537e-05 0.000151455 2.35871e-05 -0.000250809 1.93849e-06 0.00015627 3.35308e-06 -0.000427901 1.0639e-05 -0.000103306 6.04414e-05 -0.000206991 1.67569e-05 0.000148603 -4.57456e-05 0.000102229 0.000156173 -8.00003e-05 7.2741e-05 -0.000127769 -4.34441e-05 0.00029574 -5.40879e-05 -8.76072e-06 -8.13445e-06 3.71546e-05 -6.4651e-05 -5.57453e-05 0.000197529 -1.24106e-05 -1.75908e-05 0.000119045 0.000158089 0.000237774 4.39836e-05 -1.78495e-05 0.000112106 0.000103671 -3.01869e-05 2.53849e-05 4.08358e-05 1.6264e-05 5.01414e-05 -0.000184309 -3.08922e-05 -7.00303e-05 6.60086e-06 -0.000100609 3.85884e-05 0.000126124 -9.50293e-05 3.53404e-05 3.82012e-05 -1.38249e-05 -3.52618e-05 -6.02228e-05 6.93445e-05 0.000215627 -1.19015e-05 4.66854e-05 -4.96871e-05 5.34834e-05 -6.56646e-05 5.36515e-05 -3.80483e-05 -0.000334472 -0.000265642 -7.55615e-05 1.19091e-05 0.000317824 0.000216129 -0.000185864 0.000156743 9.27834e-05 0.000124056 0.00031787 0.000196324 -0.000208656 0.000210195 0.000535805 5.00296e-05 -0.000311667 9.47457e-05 -0.00017748 -0.000163142 1.39137e-05 7.07156e-05 0.000157632 4.6295e-05 -9.48657e-05 9.18613e-05 0.00011359 0.000148583 3.84584e-05 -0.000151329 -1.00711e-05 0.00011832 -3.11402e-05 -0.000126021 -4.93424e-05 0.000277233 2.81047e-05 -3.47715e-05 7.70905e-05 0.000260423 0.000230071 4.78094e-06 -6.94932e-05 9.38159e-05 0.000200181 -4.17903e-05 -4.6359e-05 5.59126e-05 3.56062e-05 -7.4646e-05 -0.000341337 -2.44241e-05 -6.69401e-05 -1.20189e-05 -0.000124624 -9.80895e-06 0.000143026 -5.92243e-05 0.000122895 3.57415e-05 -0.000104932 3.52088e-05 -0.000109384 -9.51705e-07 0.000189173 1.93504e-05 2.066e-05 -1.54834e-05 0.000147313 5.81822e-06 9.61959e-05 -6.16594e-06 5.0309e-05 -5.90682e-05 -8.71273e-05 -1.26114e-05 -2.38499e-05 -0.000133664 -3.52772e-05 -1.75063e-05 0.000116842 0.000130011 4.84603e-05 -5.16719e-05 -0.000206909 -1.12579e-05 0.000397141 -2.23131e-05 4.58473e-06 5.02666e-05 -7.37181e-05 -4.18793e-06 3.56762e-05 4.89587e-06 0.000129671 -6.06586e-06 -6.26618e-05 -1.84255e-05 -0.000159175 4.21474e-05 2.74568e-05 -1.86697e-05 -4.20713e-05 3.57638e-05 -3.66673e-06 -1.77054e-05 0.000121966 -2.60311e-06 4.26947e-05 -7.14096e-05 -8.40894e-05 -4.90579e-06 2.02995e-05 -7.80249e-06 -6.13437e-06 1.52537e-05 3.28565e-05 0.000180535 2.49215e-05 -0.000102239 -0.000175716 -8.24416e-05 0.000145949 6.67226e-05 2.15898e-05 -5.12165e-08 -7.71955e-05 3.75145e-05 7.86399e-05 -4.49469e-05 1.90396e-05 7.92758e-05 -1.43464e-05 1.59192e-07 -2.46073e-05 -4.71827e-05 -0.000118277 -6.47807e-05 6.21338e-05 -4.36631e-05 -0.000239781 0.000319514 1.78737e-05 -0.000316547 7.66488e-06 -0.000170418 -5.00845e-05 -0.000111567 9.25686e-06 3.11667e-05 -0.000446011 -0.000424107 9.80651e-05 0.0003359 0.000272437 -5.30827e-05 -0.000206132 -0.000309877 -2.83554e-05 0.000345776 -0.000110069 -0.000173097 -0.000115222 0.000160616 0.000164543 -0.000225583 4.70694e-06 0.00025705 -0.000188467 -1.27785e-05 5.16075e-06 -0.000110941 0.000188247 -1.73202e-05 -3.33011e-05 0.000121001 0.00031985 3.68938e-05 8.35429e-05 1.30382e-05 4.68824e-06 -5.96287e-05 -9.51803e-05 -4.46688e-05 -9.41293e-06 -0.000155587 -8.15737e-05 -6.91982e-05 -2.64838e-06 0.000173779 6.22351e-05 3.18108e-07 -0.000300547 -1.74232e-05 0.000401059 5.2792e-05 -5.35e-06 5.52906e-05 -4.73351e-05 -2.80795e-05 5.55376e-05 -3.66885e-05 0.000148536 6.92888e-05 -4.37391e-05 7.48674e-06 -0.000163438 -5.80401e-05 -3.72194e-05 -4.08603e-05 4.92984e-05 8.70324e-05 -0.000140601 -0.000103133 -2.69023e-05 0.000246386 -0.000277832 -0.000113338 8.35151e-05 0.000203168 3.64675e-05 0.000167052 -8.46539e-05 0.000101281 6.64291e-05 5.25172e-05 4.498e-05 -0.000261783 0.000227593 0.000278839 5.35661e-05 -0.000127627 9.07952e-05 0.000172048 -0.000129074 5.63215e-06 1.22097e-05 2.79286e-05 -7.80362e-05 -0.000103368 -8.31301e-05 0.00014218 4.89396e-05 -0.000137437 -7.55416e-06 0.000214919 -5.12525e-05 -6.49822e-05 -3.17177e-05 -9.61997e-05 -1.63118e-05 4.61497e-05 -0.000191481 -9.49895e-05 7.12972e-05 0.000124082 2.10109e-05 0.000213193 2.53884e-05 7.77666e-05 2.17481e-05 -6.90435e-05 0.000106555 6.63372e-05 0.000115786 9.16179e-05 8.01413e-05 -6.77484e-05 0.000119057 -0.000134936 9.92664e-05 5.01124e-05 -3.92317e-05 -1.98146e-05 -2.72368e-06 3.03123e-05 5.19677e-06 -9.32314e-05 4.56713e-05 -5.49779e-06 5.55113e-05 0.000213393 -7.06639e-05 -0.000152756 9.75634e-05 0.000541555 -0.000234191 -3.46866e-05 0.000304047 -6.09969e-05 0.000402261 2.16342e-05 -3.91023e-06 -0.00065014 -0.000457409 -0.00056238 0.000233632 8.93838e-06 -0.000306042 0.000499374 2.85636e-05 0.000344673 -0.000332862 4.57542e-05 -0.000268719 0.000286123 -0.000224844 2.6496e-05 0.000106604 -6.17883e-05 3.55179e-05 8.21081e-05 -0.000188583 -7.70923e-05 2.33396e-05 0.000167678 -0.000197444 -0.000190118 -0.000196119 0.000221069 0.000409926 -0.000523799 0.000282599 0.000361188 -0.000187846 4.13134e-05 4.50552e-05 0.000221738 -1.01296e-05 4.35185e-05 -6.64412e-05 0.000223087 0.000149938 0.000132293 -1.97017e-05 5.18791e-05 4.21452e-05 -7.23511e-05 -0.000223716 -7.51256e-05 -8.26761e-05 -7.67782e-05 -1.62046e-05 0.000142403 -1.81483e-05 -0.000130227 -9.79476e-05 0.000105097 7.61723e-05 0.000111579 3.74023e-05 -3.49654e-05 2.8803e-05 0.000145015 -5.89562e-05 -3.69072e-05 0.000198019 -1.28607e-05 -3.40895e-05 5.38643e-05 -3.99171e-05 -0.000101793 0.000100601 6.486e-05 -8.76822e-05 -0.000159636 2.61949e-05 9.85078e-05 0.00014116 0.000174767 1.10787e-05 -2.14453e-05 0.000116168 8.5292e-05 -0.000187111 -8.56714e-05 -6.05729e-05 0.000152898 -9.71293e-05 -1.2471e-05 -0.00010051 0.000100402 0.000195838 1.19373e-05 9.43207e-05 -0.000174832 5.93853e-05 0.000130571 -0.000193208 4.20828e-06 -3.31956e-05 9.63227e-05 0.000153751 -0.000161444 -4.02212e-05 0.000132758 -3.74353e-05 1.06129e-05 -4.98904e-05 0.000272731 4.91902e-05 -0.000210204 0.000206579 7.00662e-05 0.000156861 0.000217904 -8.73172e-05 -0.000156279 -5.61247e-05 0.000130559 -4.59426e-05 -3.25175e-05 -3.02627e-05 -2.63261e-05 3.08162e-06 0.000104081 9.97341e-06 -1.19071e-05 -2.63378e-05 7.32353e-05 7.89152e-07 -0.000168846 -9.279e-05 -4.31765e-05 -3.83287e-05 9.60732e-05 -1.12347e-05 -6.52573e-05 0.000102924 -8.67994e-05 0.000161742 -0.000157174 -0.000243108 -0.000101177 2.17649e-05 -0.000323227 2.34957e-05 0.000343448 -3.54738e-05 0.000320518 -0.00027318 -0.0001561 0.000760158 0.000239015 -0.000578173 -0.000414621 0.000604211 1.05955e-06 0.00010273 6.3047e-05 -1.95891e-05 -1.26675e-05 -0.000183266 -0.000118552 -0.00021252 -0.000177392 0.000366037 -0.0001561 -0.000178677 -5.84976e-05 -1.18013e-05 0.00032321 6.04556e-05 5.0181e-05 -0.00025232 -0.000129261 7.34995e-05 0.000173355 -0.000245359 -0.000250276 -3.9221e-05 0.000229426 0.000136756 -4.35362e-05 0.000132998 0.00021228 0.00015599 0.00025718 -2.54268e-05 -1.60603e-05 -5.29398e-05 2.20399e-05 -1.94908e-06 -5.01857e-05 -3.24313e-05 2.37934e-05 -1.72166e-06 6.99893e-06 -0.000105976 5.12557e-05 9.51648e-05 5.97928e-05 0.000108301 -0.000138772 3.95766e-06 4.41802e-05 -0.000204125 2.96868e-06 -3.51449e-05 4.32496e-05 0.000184187 -0.000159287 -0.000107359 0.000225444 -5.25995e-06 -0.000216 -0.000346321 -4.09213e-07 7.19855e-05 5.94458e-05 6.04747e-05 0.000167604 -7.6036e-05 5.99962e-05 -0.000262742 -0.000142559 0.000298763 0.000515564 -8.55431e-05 0.000154854 6.57155e-05 -0.000115946 5.41483e-05 -0.000146448 -7.41438e-05 6.04084e-05 3.37799e-05 0.000105541 -1.25996e-05 -0.000111262 -8.92044e-06 4.89232e-05 -5.79734e-05 4.76001e-05 -4.51212e-06 1.17738e-05 -8.43558e-05 -7.03504e-05 -1.9667e-05 6.42014e-05 3.03398e-05 2.08679e-05 -5.6895e-05 4.42172e-05 1.30945e-05 -5.94825e-05 -1.96798e-05 5.49434e-06 4.96695e-05 0.000135238 -2.36384e-05 -7.70231e-05 3.29343e-05 3.46793e-05 2.27108e-05 2.32213e-05 9.69223e-07 -1.90389e-05 -1.23099e-05 -5.63651e-06 -1.83417e-05 1.17792e-05 2.24631e-06 9.23223e-06 2.4125e-05 -2.06947e-05 -5.40899e-05 2.28541e-05 1.10128e-05 -5.27451e-06 -4.88445e-05 -3.69072e-05 4.81701e-05 4.2669e-05 -2.2887e-05 6.52275e-05 -2.54602e-05 0.00013546 6.81642e-05 -2.66915e-05 0.000120476 0.000100787 2.1667e-05 -0.000291353 -0.000396503 -0.000117772 -0.000353717 -0.000144537 -1.93251e-05 0.000199181 -0.000165701 9.01838e-05 -1.32826e-06 0.000126911 -9.66658e-06 -7.85154e-05 -3.95716e-05 -0.000158599 6.39687e-05 7.71249e-05 2.34782e-05 -2.2266e-05 -0.000139824 5.88479e-06 3.33895e-05 -0.000192136 -2.84877e-05 0.000231817 8.6191e-05 5.63613e-05 -5.21872e-05 -3.43381e-05 0.000119573 1.24175e-05 -2.96933e-06 -9.55259e-05 6.89284e-05 8.6702e-05 -7.56177e-05 -2.85859e-06 -8.79328e-06 6.22767e-06 5.43466e-05 -1.71057e-05 -3.64424e-05 -6.06855e-05 1.3165e-05 -3.38281e-05 2.09733e-05 -2.64232e-05 1.84727e-06 1.30312e-05 -1.52425e-05 1.48218e-06 -5.37054e-05 1.21777e-06 6.81578e-05 7.6146e-06 3.36771e-05 4.16375e-05 -2.8539e-05 -4.4083e-06 3.07154e-05 -2.32227e-06 9.11429e-06 -2.80173e-05 0.000353037 -0.000175194 -0.000305447 -8.82926e-05 6.19679e-05 -9.27347e-05 0.000319227 0.000891985 0.000171445 -0.000309401 -0.000658181 -9.91884e-05 0.000554855 0.000134168 -3.91792e-06 -9.35391e-05 -0.000210661 -0.000596967 0.000611437 -0.000312503 5.47454e-05 0.00038362 -7.00553e-05 0.000295865 -0.000316146 -0.000178529 6.89542e-05 -0.000282668 6.22589e-05 0.000113456 -0.000219077 7.73632e-05 0.000210134 -6.35614e-05 9.63174e-05 -0.000485042 0.000493737 -0.000168434 -0.000975206 -0.000575511 -0.000366084 0.000101598 0.000396869 0.00123473 0.000377845 5.60991e-05 -0.000324214 0.000548224 0.000449552 0.000186048 9.30264e-05 -2.07717e-05 3.12159e-05 -0.000459669 0.000403658 -5.35814e-05 4.05254e-05 0.000291634 -9.17574e-05 0.000138354 -0.000431732 -0.000401597 -9.95059e-05 6.69555e-06 0.000113809 0.000203488 -0.00015196 7.94026e-05 8.73151e-05 8.48428e-05 -0.000110396 0.000629651 -0.000582567 -0.000145352 0.000248003 -0.000137753 0.000411963 -0.000123034 7.07219e-05 -0.000894105 -0.000820478 -0.00101635 -0.000176368 0.000396584 -2.06991e-05 0.00021621 -0.000366564 0.00065128 -1.5432e-05 0.000461779 -0.000378016 0.000173016 -0.00021373 -0.000299361 7.01855e-05 -0.000193964 0.000506899 0.000384171 0.000181443 0.000123386 -9.20758e-05 -0.000353217 0.000177108 6.80834e-05 -0.000210937 0.000399946 0.000150376 -0.000500068 -1.18516e-05 -0.000350081 -0.000146142 9.1367e-05 5.35848e-05 0.000198414 0.000538337 0.000902725 8.01736e-05 -4.33401e-05 -9.44627e-06 0.000321374 0.000364428 0.0002084 1.6806e-05 -9.02571e-05 -2.48078e-05 4.44602e-05 -0.000211292 -0.000111742 -0.000306258 -8.02586e-05 0.000111542 -8.36588e-05 -0.000156901 -7.76191e-05 0.000153879 4.22398e-05 -9.41884e-05 0.000196767 -4.04032e-05 2.67297e-07 0.000141246 0.000195631 -0.000128955 -2.22014e-05 -4.19082e-05 2.82617e-05 -7.61443e-05 -2.93676e-05 4.23168e-05 1.48754e-05 7.93814e-05 8.14959e-05 6.92739e-06 -7.02012e-05 -4.79671e-05 -5.17677e-05 -6.87964e-05 -1.63562e-05 2.5822e-05 9.59062e-05 2.45033e-05 -4.07824e-05 0.000117749 -1.73343e-05 3.55288e-05 -6.34012e-05 -3.08096e-05 2.63797e-05 -2.73532e-05 -2.62539e-05 -8.22348e-06 5.39674e-05 -3.74276e-05 -1.31615e-05 -6.72535e-06 -5.07343e-05 7.39838e-05 1.2843e-05 -3.26038e-05 -5.95364e-06 2.77769e-05 5.80435e-05 -1.96511e-05 -2.74232e-05 5.10583e-05 -2.68844e-05 3.32322e-05 5.51208e-05 7.89438e-06 -8.48264e-06 -9.79248e-05 -4.76089e-05 -2.6036e-05 -1.12896e-05 4.89317e-05 7.37905e-05 -6.24564e-05 -4.63208e-05 6.26139e-05 -1.64157e-05 4.49008e-05 4.50981e-06 -2.73047e-05 1.75414e-05 -4.90741e-05 -1.51202e-05 3.99713e-05 3.58244e-05 9.59794e-07 1.79864e-05 5.20828e-05 1.209e-05 4.03265e-05 -3.33285e-05 -7.29291e-05 0.000237589 -0.000160719 -0.000264486 -3.3508e-06 -0.000204483 4.29227e-05 -1.56099e-05 6.59562e-05 -3.19338e-05 -0.000150838 -0.000302537 1.60361e-05 0.000117394 0.000144916 0.000349802 -0.000230191 -5.95158e-05 4.61058e-05 7.74231e-06 -0.000153502 3.13102e-05 0.000118287 -0.000101331 -9.04359e-05 3.60155e-05 0.000372602 0.000145081 -0.000171317 -1.95228e-05 -5.35498e-05 1.14014e-05 3.15448e-05 0.000105378 8.50944e-05 0.000190341 0.000147154 -2.8411e-06 -4.08977e-05 1.98943e-05 -3.61858e-05 -2.874e-05 3.45305e-05 -3.45161e-05 9.79279e-05 0.000125575 -2.45255e-05 -8.19631e-05 -0.000123131 -7.31377e-05 -1.44598e-06 2.46527e-05 7.0179e-05 0.000112098 -6.35492e-05 -3.19485e-05 9.34219e-05 -1.29944e-05 5.97346e-05 -1.14437e-05 -2.05785e-05 8.56408e-06 -5.13452e-05 2.60754e-06 -2.19851e-05 2.97331e-05 -4.94551e-05 -1.49418e-05 1.71143e-05 -1.92951e-06 9.98554e-05 -1.87764e-05 -7.58655e-05 4.01423e-05 7.82321e-05 -0.000108252 -8.59029e-05 0.000222001 0.000205311 3.75155e-05 -0.000148354 -0.000274998 -4.36046e-05 4.73704e-05 8.09841e-06 0.000124591 0.000168299 -6.14551e-05 -0.000201227 -8.67136e-05 3.75214e-05 5.94815e-05 7.26843e-05 8.94635e-05 -0.00017518 0.000122233 0.000113494 4.99934e-05 -0.000242497 -0.00010932 0.000106912 0.000146224 3.80823e-05 -5.30098e-05 2.72191e-05 -3.55064e-05 -2.3562e-05 -0.000133407 0.000131532 8.43114e-06 3.93367e-05 -1.49502e-05 -0.000164963 0.000244149 0.00015064 8.88675e-05 -0.000140463 -0.000240471 -2.53109e-05 0.00013871 5.27228e-05 7.01389e-05 7.79907e-05 6.03797e-06 -0.000138834 -5.38517e-05 5.15489e-05 -2.67703e-05 7.15023e-05 0.000109036 -5.09535e-05 -5.71806e-05 -1.44253e-05 7.25265e-05 -3.22433e-05 -2.52956e-05 0.000103896 6.82645e-05 -1.22321e-05 -0.00010266 -0.000124132 0.000126021 2.75617e-05 -8.9874e-05 7.1362e-05 0.000242734 -5.36034e-05 -0.000158265 0.000381574 7.12131e-05 2.24271e-05 -0.000181208 -0.000354575 -0.00040846 2.10415e-05 -0.000327968 0.000338553 0.000268274 -9.68387e-05 -0.000137419 -0.000286869 0.000106252 0.000107172 0.000147979 -7.39545e-05 5.36982e-05 0.000119594 1.55525e-05 -7.81564e-05 -0.000163761 0.000271895 0.000132799 -0.000133714 4.24136e-05 4.96464e-05 -4.72162e-05 0.0002427 -3.47063e-05 -0.000345848 0.000162029 4.66844e-05 0.000116002 -4.06435e-05 -0.000122225 -0.000248498 0.000106354 0.000267799 6.67903e-05 0.000126578 -0.000151397 -0.000245328 0.000178893 -3.08143e-05 0.000211658 0.000297909 -0.00015116 -0.000388985 -7.16383e-05 0.000302441 -0.000229129 0.000182677 -1.88138e-05 -0.000182377 0.000191816 -7.07156e-05 4.93038e-05 -0.000280536 -0.000150757 0.000190294 8.41764e-05 9.77873e-05 -0.000131035 -8.97183e-05 0.000120691 0.000139047 -8.92485e-05 0.000133121 6.41663e-05 -0.00011291 7.84029e-07 -2.63477e-05 7.60657e-05 0.000162039 -0.000190047 1.54624e-05 0.000174012 1.64093e-05 -6.73875e-05 -0.000312016 -0.000193899 0.000141088 3.31472e-05 5.21599e-05 0.000205398 -2.31265e-06 -1.98245e-05 6.2171e-05 2.51204e-05 -5.4512e-05 -5.74916e-05 -2.60907e-05 5.11185e-05 -9.24584e-05 -2.52227e-05 -9.21374e-06 2.02471e-05 7.22635e-05 -3.93772e-05 -4.81707e-05 1.74039e-05 5.57179e-05 -4.0622e-05 2.85302e-06 3.62337e-05 -4.65796e-05 5.48735e-05 -4.71571e-05 2.37295e-05 0.000103893 -0.00010505 -4.23983e-05 0.00010508 -5.15562e-06 -0.000111049 -0.000244863 -0.000245933 -1.69859e-05 0.000133976 0.00016338 0.000137833 -6.75972e-05 -3.24619e-05 0.000111235 -1.19623e-05 -4.27686e-05 -3.22988e-05 -3.82615e-05 0.000138458 8.55151e-06 -8.99504e-05 -6.4754e-07 -4.79937e-06 0.000119178 0.00012234 -0.000125087 -7.38347e-05 -4.79613e-05 -3.23106e-05 -3.45355e-05 -0.000150252 0.000154015 4.2989e-05 -1.57397e-05 0.000124533 -6.27718e-05 0.000360548 0.000356574 0.000206503 -0.00018455 -0.000107208 -0.000207123 -1.94564e-05 1.96407e-05 -0.000270502 0.000206163 -1.37993e-05 0.000197069 -6.03088e-05 1.74075e-05 -4.21372e-05 -2.88044e-05 0.000181771 6.76008e-05 -6.02487e-05 -0.000376366 -0.000183999 0.000197735 -1.07199e-05 -0.000130032 6.79318e-05 6.16436e-05 -9.87592e-05 -7.82571e-05 -3.22838e-05 -0.000154988 0.000117281 -0.000143485 5.30718e-05 -5.09126e-05 0.000101486 0.000162874 -0.000262135 1.96263e-05 0.000279766 6.37832e-05 -0.000127206 -0.000461491 -0.000320715 0.000122874 0.000121989 5.05596e-05 0.000189488 -4.50292e-05 -7.79388e-05 0.000103786 9.15974e-06 -4.20956e-05 -7.41934e-05 -0.000112103 0.000100829 -7.33134e-05 -6.4954e-05 3.83071e-06 3.00797e-05 0.00012088 6.47974e-05 -0.00010471 1.8066e-05 7.75648e-06 -2.842e-05 -5.46107e-05 2.45133e-05 1.46736e-05 -3.92451e-05 7.21636e-05 -2.05416e-05 -6.84161e-05 -2.77447e-05 -2.10056e-05 -1.58218e-05 -8.56062e-05 -7.78395e-06 -3.58117e-05 -2.34796e-05 2.37444e-05 -1.15816e-05 3.89671e-05 3.44572e-05 -6.34242e-06 -5.08676e-05 -4.33123e-05 6.48424e-06 6.61816e-07 -6.83848e-06 3.22999e-05 7.41732e-05 -2.2404e-05 -5.01993e-05 -1.67452e-05 2.47971e-05 3.39933e-05 -1.95379e-06 -1.46715e-05 4.47678e-05 1.5816e-05 -1.6679e-05 -2.19197e-05 -1.85089e-05 -2.75323e-05 -6.85744e-05 6.27093e-05 8.02814e-06 -2.24574e-05 1.90844e-05 -3.97245e-05 -6.20226e-05 -4.22465e-05 3.43246e-05 4.30093e-05 -1.81799e-05 -1.06933e-05 -7.31793e-06 3.77469e-05 1.67968e-05 -4.42822e-06 1.79895e-05 -3.31317e-05 -1.10187e-05 -2.18159e-06 -3.14865e-05 2.13339e-05 1.22246e-05 1.56581e-05 -2.84501e-06 9.7899e-06 1.38724e-05 1.01819e-05 -1.54512e-05 2.01458e-05 6.33596e-05 -2.1764e-05 -2.23823e-05 -1.52211e-05 9.89104e-05 2.62431e-05 0.000205914 -4.02936e-06 -0.000123161 -0.000192688 -5.44045e-05 -0.000145477 6.67534e-05 0.00016554 9.4015e-05 -1.84196e-05 1.2655e-05 -0.00025338 -0.000328895 8.9703e-05 3.96551e-05 5.11512e-05 -0.000245927 0.000228825 8.55699e-05 -4.00903e-05 0.000232693 4.23995e-06 7.72396e-06 -0.000111739 -0.000177709 -2.07561e-05 -4.79505e-05 -8.5014e-05 -3.31068e-05 -0.000134003 -8.13173e-05 0.000165239 -4.17431e-05 -0.000135112 3.53032e-05 -1.55837e-05 -3.52384e-05 9.50727e-05 -3.10474e-05 -6.55082e-05 -5.89911e-06 -1.10357e-05 -3.71561e-05 -0.000102137 -2.49557e-05 -2.48687e-05 -2.04814e-05 1.77367e-05 -2.18897e-05 1.19018e-05 1.33005e-05 -1.21571e-05 -1.30394e-05 -2.82885e-05 1.34346e-05 -1.68659e-05 -4.59771e-05 3.72853e-05 5.02246e-05 2.50837e-07 -2.49004e-05 -3.96073e-06 6.02621e-06 5.04657e-05 -1.30222e-05 -3.19984e-05 5.3008e-05 6.29723e-07 -6.17528e-05 -2.22838e-05 0.000137124 3.60812e-05 -5.37468e-05 2.3791e-05 1.36581e-05 9.57187e-05 -0.000133507 0.000107781 0.000123835 7.10676e-06 -6.05856e-05 -8.4623e-05 7.64133e-06 0.000208354 0.000141715 -0.000166824 -0.000156096 4.76199e-05 -4.75819e-05 -1.92966e-05 -6.69957e-05 -6.95599e-05 2.60174e-05 5.72474e-05 -3.23248e-05 3.43788e-05 7.0868e-05 -0.000126859 8.81004e-05 1.0533e-05 -8.9984e-06 0.000124698 1.21104e-05 5.84639e-05 1.627e-06 3.18937e-05 8.46918e-05 0.00012688 -6.00491e-05 4.74155e-05 6.51393e-05 0.00010481 -0.000124748 5.7666e-05 5.93905e-05 -6.45679e-05 3.65223e-05 -2.06328e-05 -8.94866e-06 0.000127383 5.93026e-05 -0.00014622 -0.000118682 4.26986e-05 -0.000108386 2.85875e-05 3.51524e-06 -1.97034e-05 -5.04104e-05 -1.29472e-05 3.60869e-05 -8.78123e-05 -5.03111e-05 -8.77312e-05 0.000108798 5.23246e-05 -2.04921e-05 -6.26904e-07 -1.54449e-05 4.27055e-05 2.12243e-05 -4.8339e-05 -0.000123373 4.81346e-05 3.70789e-05 -1.04413e-05 -1.17116e-05 -0.000259365 0.000139044 3.0395e-05 0.0001546 -7.88751e-05 -2.59605e-05 7.73541e-05 2.68803e-05 -0.00021466 -0.000161116 0.000264064 0.000166038 9.57932e-05 -0.000149728 4.17176e-05 -8.90429e-05 -2.79755e-05 0.00010712 1.52752e-05 3.65722e-05 -6.8575e-05 -4.74078e-05 4.62388e-05 2.11992e-06 -7.52617e-05 2.02483e-05 1.67505e-05 -0.000172502 -8.99073e-05 5.27999e-05 6.03385e-05 0.000150385 7.79572e-05 -9.35873e-05 -1.3159e-05 -1.23601e-05 8.52937e-05 -0.000159705 0.000144065 0.000173532 -4.18942e-05 -5.61672e-06 -1.3034e-05 1.88947e-05 0.000181645 0.000129754 -0.000176125 -0.000140264 5.8167e-05 -0.000111315 1.65545e-05 -3.6807e-05 -3.7865e-05 -5.49446e-06 -1.01334e-06 5.35661e-05 -1.75489e-05 -2.98067e-06 -9.58206e-05 9.12022e-05 3.56906e-05 2.53603e-05 3.12519e-06 -6.83911e-05 5.6557e-05 5.00442e-05 -6.16216e-06 -2.73432e-05 6.82499e-05 1.6925e-06 -4.20911e-05 -2.73872e-05 -1.4603e-05 -7.56638e-05 -8.19672e-05 0.000172262 0.000147293 2.61197e-05 -4.56876e-05 -7.46068e-05 0.000105398 6.35816e-05 7.57543e-05 -0.000171004 -0.000181094 -5.21387e-05 0.00012232 -0.000103305 -8.90638e-05 1.65104e-05 -1.48287e-05 1.13038e-05 -0.000104378 -9.58782e-05 6.63517e-05 5.53269e-05 -1.04274e-05 -2.63287e-05 -3.97319e-05 8.82453e-05 5.25599e-05 -4.0851e-05 -6.74279e-05 -1.76114e-05 6.1225e-05 -6.69982e-05 -0.000124212 -5.22955e-05 -1.68603e-05 -6.0016e-05 -4.41297e-05 0.000143548 0.00017319 2.77372e-06 -1.95635e-05 4.66502e-05 6.58895e-05 0.000124166 6.07286e-05 -0.000203586 -0.000164193 -1.34051e-06 1.82888e-05 2.80231e-05 -5.10647e-05 2.93041e-05 5.68112e-05 1.0098e-05 1.4813e-05 -5.18495e-05 -2.18951e-05 2.82701e-05 2.02481e-05 4.47269e-05 -4.84951e-05 -1.20642e-05 -9.71251e-06 7.04157e-05 -4.29345e-05 -0.00015662 -5.42645e-05 5.50979e-05 -7.06127e-05 -0.000100513 -0.000100811 0.000159087 0.000190623 0.000148062 0.000100145 0.000157132 -0.000118037 -0.000190489 0.000208957 0.000158696 9.30154e-05 8.12109e-05 0.000173447 -0.000208715 4.7189e-05 -3.30994e-06 6.68414e-05 1.08448e-05 2.76958e-05 0.00015688 -0.000102501 2.62991e-05 6.01762e-05 -4.78783e-05 5.02939e-05 -2.67917e-05 -5.59488e-06 0.000151859 8.43312e-05 -0.000146246 8.39337e-05 -9.85549e-05 0.000288021 2.56548e-05 1.68674e-05 -8.12945e-05 -0.000134885 -7.93961e-05 -0.000158023 0.000181242 0.00018701 7.34995e-05 8.9682e-06 1.88687e-05 -9.08705e-05 0.000131229 0.000178496 -0.000282969 -0.000285695 -0.00010788 0.000162834 -5.69926e-05 -4.65737e-05 0.000119711 2.71536e-05 1.10799e-05 -0.000126868 -0.000158963 4.09665e-05 5.25241e-05 3.39076e-05 -1.49463e-05 -5.32206e-05 0.00011619 9.68908e-05 -1.90916e-05 -0.000135055 1.52453e-05 1.72669e-05 -1.09946e-05 5.6289e-05 -4.40777e-05 -5.31411e-05 -3.53813e-05 1.38224e-06 4.43502e-05 -3.12417e-05 3.72802e-05 4.40761e-05 1.59906e-05 -2.91072e-05 1.09958e-05 -3.64756e-07 -6.94672e-06 7.58569e-06 -3.21622e-05 4.96934e-05 -0.000104272 -2.84735e-05 1.91403e-05 -1.64506e-06 0.000126945 1.8067e-05 -8.23275e-05 2.96678e-06 2.61578e-06 2.26018e-05 2.21001e-05 -9.51767e-06 2.42998e-05 0.000137554 1.04165e-05 -9.97651e-06 -5.9849e-05 3.18303e-05 -3.83861e-05 0.000119057 4.8712e-05 -2.1923e-06 4.65404e-05 -1.27473e-06 2.34019e-05 3.94579e-06 9.85393e-06 6.16847e-06 -7.75926e-05 -8.18712e-05 -1.79165e-05 8.98096e-05 6.24219e-05 6.21139e-05 -4.64153e-05 7.94927e-05 -1.36457e-05 -4.52658e-05 3.71952e-05 2.13301e-05 3.27245e-05 -5.61782e-05 -2.16424e-05 4.69007e-05 4.53013e-06 1.73559e-05 -2.93586e-05 2.56415e-05 1.89913e-05 1.005e-05 -2.97413e-05 -7.2061e-05 0.000295645 -0.000266795 -5.38714e-06 -6.52258e-05 -8.74834e-05 0.0002434 -0.000161933 7.50284e-05 -0.000167311 -0.000335936 -0.000146548 -0.000134811 9.83513e-05 0.000316768 0.000192387 -0.000281859 0.000155275 0.000148126 0.000390849 0.000129664 -3.44654e-05 0.000189921 -0.00013341 -0.000126545 -0.000191464 -3.0292e-05 0.000264875 -7.96946e-05 -0.00010619 -9.55395e-05 -0.000131987 4.63355e-05 1.90502e-05 -5.20644e-05 -7.49607e-05 -2.57237e-05 0.000122459 1.95984e-06 -1.96926e-05 6.56262e-05 -0.000124122 -1.74855e-06 -0.000105215 3.91607e-05 0.00012965 -6.70959e-06 6.72063e-05 9.55822e-05 -2.95723e-05 -7.96161e-06 0.000108777 4.18587e-06 -7.13957e-05 1.91457e-05 -1.46215e-06 4.55167e-05 3.80478e-05 -7.07643e-05 -5.37135e-05 4.79274e-05 0.0001172 3.19238e-05 -3.3873e-05 1.19734e-05 4.50434e-05 -6.08432e-06 -3.82568e-05 -2.88523e-05 -3.5709e-05 2.48367e-06 -3.95314e-05 -2.40348e-05 7.43874e-05 -3.65256e-06 -0.000122885 0.000217263 4.44724e-05 8.25725e-05 4.75971e-05 0.000137609 -1.18513e-05 -9.47368e-05 4.48558e-05 -2.89136e-05 -0.000123906 5.149e-05 6.38667e-05 8.68689e-05 -0.000104209 3.03366e-05 5.7601e-05 2.65436e-05 -2.21114e-05 -0.000122473 0.000192466 6.91311e-05 9.18016e-05 3.18772e-05 -0.000275264 0.000124317 -0.000162089 5.10353e-05 0.000103019 -8.96474e-05 6.82277e-05 6.21064e-05 -3.2833e-05 -0.000116081 9.23266e-05 6.62925e-05 -6.73791e-05 7.43252e-05 0.000100216 4.76814e-05 0.000108958 6.12987e-05 -0.00021793 9.30342e-06 4.85413e-05 5.30741e-05 9.23171e-05 -5.02963e-05 -5.12364e-05 -1.3913e-06 -7.11316e-05 -1.22793e-05 -2.34443e-05 2.20505e-05 1.78323e-05 -7.56922e-05 8.19089e-05 -3.04126e-06 1.95856e-06 -8.29658e-05 -9.12863e-05 7.05224e-05 -7.43101e-05 2.36187e-05 0.00016285 -0.000106145 -6.01936e-05 2.71384e-05 5.59559e-05 -5.79704e-05 -0.000234795 0.000264234 -7.55854e-05 6.0187e-05 6.78339e-05 0.000180527 0.000366405 0.000285659 0.000212751 4.68177e-05 0.00048681 0.000136962 -0.00045751 -0.000136893 2.01625e-05 8.38294e-05 -6.44488e-05 0.000380844 -0.000161878 0.000229389 -0.000339349 0.000163605 0.000471894 9.79201e-06 2.79538e-05 -0.000298907 -0.000494789 0.000300272 -8.64467e-05 0.000214832 6.42253e-05 -0.000124993 0.000138393 0.000188552 -0.000314119 -0.000431825 8.61826e-05 2.4044e-05 -0.000102731 0.000232826 0.000111825 7.00375e-05 9.79875e-05 8.77952e-05 -0.000172676 -4.30125e-05 1.54962e-05 5.87746e-05 -4.01612e-05 -1.38169e-05 5.46315e-05 3.37808e-05 -0.000123673 -5.25373e-05 3.87129e-05 -2.90497e-05 3.23193e-06 -7.94957e-05 0.000139665 6.66581e-05 1.90183e-05 -4.57867e-05 -0.000181069 0.000100182 -3.64251e-05 6.6345e-05 0.000100529 -0.000113508 -4.18706e-05 2.21051e-05 5.73258e-05 -0.000165589 -8.22286e-05 9.65431e-05 -6.92117e-06 -6.44547e-05 -6.2688e-05 -2.03618e-05 -9.62141e-06 -6.38233e-05 0.000158834 0.000244489 0.000418114 -2.54403e-05 0.000118336 -1.47638e-05 -0.000256586 -0.000118912 -0.000257396 6.22184e-05 -0.000100604 -0.000132861 3.27409e-05 -5.63142e-05 0.000118995 -9.25683e-05 0.000135765 9.63646e-05 1.05067e-05 -0.000158633 -7.28229e-05 7.06945e-05 1.16339e-05 1.98547e-05 -2.02726e-05 -8.88044e-05 1.85727e-05 -6.01398e-05 -1.43933e-05 9.43247e-05 2.7667e-05 -2.63921e-05 -0.00015289 -0.000128977 3.02248e-05 -9.94431e-06 4.78451e-05 7.37607e-05 0.000334658 -2.3944e-05 0.000186266 -1.29423e-05 -0.000175428 -5.49695e-05 -0.000206814 2.95114e-05 -9.31933e-05 -3.93304e-05 1.71386e-05 6.08049e-06 4.84768e-05 -4.47943e-05 0.000118779 6.74455e-05 -6.18574e-05 -9.91005e-05 -3.0064e-05 5.09097e-05 6.4106e-05 -2.69493e-05 1.5794e-05 -7.43658e-05 1.72308e-05 -1.43092e-05 -0.000308316 -4.11789e-05 -0.000127985 0.000152266 0.000131377 -0.000191077 0.000151245 0.000354887 0.000328391 -2.02064e-06 0.000627131 0.000248395 -0.000268558 -0.000618196 -0.000219516 7.03631e-06 -0.000117418 0.000439399 -0.000154487 -0.000120896 -0.000187657 2.91537e-05 6.53009e-05 0.000180999 9.68049e-05 -1.59847e-05 -2.50243e-05 9.69754e-05 -8.92274e-05 7.00002e-05 9.27644e-05 -0.000171776 -0.000101388 6.93628e-05 -5.20466e-05 -0.000179202 -0.00135717 -4.84148e-05 -0.000407487 -0.000169249 0.000673507 0.000215846 0.000176625 0.000373035 0.000973968 9.11866e-05 0.000164919 0.000106278 0.000174123 0.000191081 -2.49231e-05 6.23419e-05 -5.62551e-05 -5.44894e-05 8.30375e-05 5.73131e-05 2.26706e-05 -0.000144536 -9.62216e-05 9.83096e-05 0.000118726 -8.78485e-05 -0.000163142 -2.5026e-05 -4.85029e-05 -0.000109166 0.000216603 -5.22162e-05 -4.4493e-05 1.6054e-05 2.63609e-05 -0.000217678 6.52158e-05 0.000123314 5.46377e-05 5.00619e-05 7.15102e-06 1.35245e-05 -1.50265e-05 -1.35902e-05 -2.99235e-05 -7.85298e-05 4.99201e-05 1.99132e-05 -5.32664e-05 0.000157315 0.000170142 -0.000166697 -0.000185195 9.35309e-05 4.23697e-05 -3.64293e-05 -6.75755e-05 4.9634e-05 -4.34089e-05 -4.69071e-05 -1.02449e-05 0.000109291 8.30011e-05 -6.40095e-05 9.63156e-06 -2.81889e-06 -9.50164e-05 8.94786e-06 6.54764e-05 -0.000108711 -8.77644e-05 0.000101491 -2.19781e-05 6.21088e-05 -3.23013e-06 8.98479e-05 -2.40943e-06 -3.05333e-05 1.8145e-05 2.85173e-05 0.000106173 -0.000109808 5.64665e-05 2.63691e-05 -0.000116583 0.00014861 0.000187499 -0.000210045 -0.000222778 0.000151348 -3.40485e-05 -0.00010798 -7.46705e-05 2.46395e-05 -1.41469e-05 9.90452e-06 2.68982e-05 0.000104829 0.000137795 -8.11991e-05 -7.17692e-05 -1.56876e-05 -1.67637e-05 -4.87482e-05 -5.61896e-05 -4.28609e-05 8.26923e-06 8.40213e-05 0.000338039 -0.000627314 1.17072e-06 0.000524524 0.000341679 0.000353934 -9.5154e-05 -1.56239e-05 -0.000357244 -8.65852e-05 -0.000296958 -0.000277098 -0.000445115 -9.98697e-05 -4.15251e-05 0.000118683 0.000429252 0.000183558 2.40953e-05 0.000371412 0.000196981 0.000191759 0.000116108 3.06493e-05 -3.20083e-05 5.7018e-05 0.000143967 2.31173e-05 3.44848e-05 -0.000233716 -0.000178879 -8.05872e-05 -0.000284742 1.47497e-05 -1.5444e-06 -0.000229391 7.14585e-05 8.76023e-05 -2.2593e-05 9.27497e-05 3.91013e-05 4.93485e-05 -7.8802e-05 3.21205e-05 8.99838e-05 -0.000210563 -2.50494e-05 -5.86829e-05 -0.000189254 0.000274458 0.000291726 -0.000204886 -0.000268954 0.000181157 -1.46333e-05 -0.000136588 -1.55763e-06 -4.14071e-05 -0.000119237 2.97064e-05 6.43565e-05 5.58208e-05 8.77643e-05 1.71377e-06 2.15435e-05 -5.67844e-05 -1.07646e-05 -4.1921e-05 -3.98033e-05 -5.56684e-05 3.87165e-05 0.000105546 0.000150762 -7.02309e-06 0.000198851 6.95971e-05 -4.93461e-05 2.18321e-05 6.36662e-05 -7.47995e-07 -7.91587e-05 8.98029e-05 0.000196054 7.07527e-05 0.000153475 -0.000128831 -0.000180862 -0.000163407 -0.000160474 6.07077e-05 -0.000180498 7.62865e-05 -5.74613e-05 3.00334e-05 0.000164239 -3.50401e-05 5.69066e-05 -4.96883e-05 -0.000138276 2.85135e-05 -0.00010477 -4.75289e-05 -5.86438e-05 -3.60603e-05 4.41723e-05 6.51126e-05 3.82781e-05 -4.41489e-05 -6.592e-05 -0.0001946 8.69494e-05 -8.5351e-05 -2.60785e-05 -4.83045e-05 6.55225e-05 4.92252e-06 -8.41233e-05 6.20502e-05 0.000194839 2.49825e-05 8.93659e-05 1.25085e-05 0.000101565 1.87575e-06 -0.000110642 -4.55996e-05 1.68363e-05 5.9342e-05 8.58933e-05 2.40111e-05 -5.9018e-05 -5.15245e-05 -3.0915e-05 -5.09449e-05 -0.000101206 4.57461e-05 3.13179e-05 1.86896e-05 -1.32449e-06 -1.56122e-05 4.5987e-05 -5.72143e-05 -2.98907e-05 9.15983e-06 0.00027 5.91028e-05 -0.000163665 6.50751e-05 -0.000192265 8.21175e-05 -0.000227116 1.78463e-05 0.000248062 7.57189e-05 0.000515255 0.000236643 -0.000362151 0.000259544 5.4011e-05 -0.00029258 -0.000454467 1.47914e-05 9.87342e-05 1.06842e-06 -2.15614e-06 1.65441e-05 -6.01589e-05 6.80333e-05 -8.92533e-05 7.16951e-06 0.00020701 -0.000160679 -7.90413e-05 -3.0885e-05 -3.76027e-07 0.000161599 0.000124814 9.41606e-05 -9.7479e-05 -1.6452e-05 -0.000240561 9.22695e-05 -3.27233e-05 -0.000250016 9.10409e-05 -3.68854e-05 0.00010692 0.000277501 0.000391479 7.86184e-05 0.000109781 -6.29918e-05 0.000317579 0.000155134 -7.13057e-05 -0.00021267 -8.51623e-05 -0.000108526 -7.20426e-05 -3.64857e-05 -8.38308e-05 0.000101381 4.86715e-05 4.3969e-05 6.12234e-05 -0.00011397 -3.56234e-05 1.03062e-05 0.000102581 2.72608e-05 -7.15541e-05 -8.70616e-05 8.79823e-05 0.000142317 -1.50895e-05 -0.0001288 0.000819531 0.00019903 -0.000161682 2.71682e-05 -0.00100536 -0.000516388 -0.000207498 0.000739684 0.000620625 -0.000646358 -0.000345408 0.000511396 -5.18499e-06 0.000648093 0.000121461 -0.000361103 -0.000548309 0.000104554 0.000324197 -0.000786759 -0.000470877 0.000321773 -0.000635691 1.98419e-05 -0.000125651 -0.000326085 0.000674878 0.000235591 0.000463755 0.000248659 0.000198081 -4.98014e-05 -0.000225609 0.000152501 0.000306959 0.000154754 5.88782e-05 0.000436137 0.000520599 -0.000577957 -0.00111789 -0.00139854 0.000405199 0.000685148 0.000979626 -0.000241591 0.000481589 0.00123808 0.00140348 -0.000159919 -0.000681105 -0.000503906 0.000177326 -0.000601098 -0.000539891 0.000497875 -0.000129505 0.000287532 0.000317166 -1.73664e-05 1.82586e-05 -0.000232049 0.00015846 5.15127e-05 2.48729e-05 -0.000333922 -0.00016194 -0.000279436 0.000133574 0.000388159 -0.000179749 9.25213e-06 0.000246197 -5.66688e-05 -4.81844e-05 -0.000218768 5.59302e-05 -0.000137343 -0.000467773 0.000625269 0.00011515 -0.000672759 0.000328801 0.000127807 0.00035465 0.000142269 0.000165 -0.000678093 -0.00116699 0.00061578 -0.000133776 -0.00014419 -3.73459e-05 0.000226026 0.000178377 -1.04347e-05 -0.000117849 -0.000273819 -1.49365e-05 3.66758e-06 -5.49509e-05 0.0004323 0.000117769 -0.000538791 -8.31812e-05 0.000327293 0.000264121 -0.000152869 -0.000611118 0.000136793 2.73554e-05 -0.000351673 -9.8152e-05 -0.0001675 -0.000116116 9.60009e-05 0.00067107 0.000138577 0.000555963 8.48894e-05 0.000532197 1.85718e-05 -0.000269871 -1.38011e-05 -0.000141232 0.000108447 -0.000278354 0.000313087 7.97837e-05 4.5059e-05 0.000389914 9.47114e-05 -3.39306e-05 -0.000389097 -0.000280248 2.04395e-05 -5.15244e-05 -3.02219e-05 -6.5824e-05 -0.000169132 7.45184e-05 0.000107831 2.44815e-05 -8.49694e-05 -0.000254169 0.000542686 5.08149e-05 0.00025415 -8.56299e-05 -0.000165746 0.000118262 -0.00036669 -0.000198228 8.3999e-05 0.000115515 0.000477386 -0.000232007 -0.000400014 0.000139191 0.000346759 -0.000151445 -0.000222667 0.000239904 -0.000308005 -5.03329e-05 -5.53559e-05 9.24311e-05 -1.23959e-05 -7.01445e-05 8.7147e-05 -0.00010113 0.000157314 -5.7784e-05 -3.85779e-06 0.00023105 -1.22012e-05 -7.09905e-05 1.72737e-05 0.000330078 -7.99873e-05 -7.49982e-05 1.43846e-05 1.56859e-05 0.000120528 -0.000162675 -0.000181712 0.000162729 -6.50577e-05 -0.000182545 0.000150681 0.00010944 0.000217442 -7.47182e-05 -0.000421024 7.02779e-05 0.000528949 3.00706e-05 -0.000163802 0.000129258 -0.000385025 8.896e-06 -0.000223407 -4.03467e-06 3.66738e-05 -0.000104988 0.000131209 0.000221508 0.000162629 2.31754e-05 -1.54846e-05 0.000278015 0.000154035 -0.000249898 -0.000124851 0.000172268 -0.000107262 -0.000194084 -9.00796e-05 0.000108579 -0.000381479 -0.000143088 -0.000258823 0.00020481 0.000534624 0.000593712 4.49836e-05 8.2407e-05 0.000375513 0.000171178 8.77753e-05 -6.63985e-05 -0.000216902 -0.000312424 0.000268639 -0.00030968 2.58352e-05 0.00014239 9.81395e-05 -6.42719e-05 0.000101498 9.82745e-05 1.02263e-05 0.000297928 -5.00339e-05 -0.000116732 -1.663e-05 -5.62002e-05 -4.61188e-05 3.94017e-05 -4.3154e-05 -0.000115743 0.000127187 -0.000236506 0.000192285 4.82353e-05 0.000153864 -3.34148e-05 -0.00028587 3.74367e-05 -0.000184331 3.24123e-06 0.00019384 3.63269e-05 0.000129322 -0.000279373 -0.000487241 0.000150046 0.000605673 7.37737e-05 -0.000195119 0.000217217 -0.000304285 2.7535e-05 -0.000193505 -1.47592e-05 -3.48814e-05 -1.54014e-05 0.00018941 1.88461e-05 9.19313e-05 -6.18711e-05 -2.47391e-05 0.000274146 0.000134015 -0.000158567 -0.000119949 0.000103682 -0.000115238 1.46249e-05 0.000140525 0.000202949 -0.000103624 -5.92917e-05 -6.29994e-05 -3.44135e-06 -2.92406e-05 0.000364937 -3.04501e-05 0.000344222 0.000262979 3.08447e-05 -0.000496671 -0.000494767 2.28657e-05 -0.000499774 0.00019186 -0.00010187 0.000241014 0.000165489 5.429e-05 -2.24066e-05 6.98181e-05 -0.000338388 -0.000386856 -0.000310498 0.00029591 0.000322944 0.000337847 0.00011207 -0.000728805 -0.000582929 -0.000525498 0.000172117 0.000541874 -0.000127038 0.000153615 -5.98494e-05 -1.0042e-05 -1.77373e-05 -3.63576e-05 -5.48075e-05 -7.3019e-05 0.000164216 6.75757e-05 0.000114818 -7.78407e-05 0.000146309 -2.04672e-05 -0.000139427 -8.91419e-06 -0.000164576 0.000122515 -2.66692e-05 -6.57793e-05 6.38023e-05 -0.000174049 2.46037e-06 -2.47958e-05 -2.36071e-05 -4.90503e-05 -4.49933e-05 8.74315e-05 -6.44524e-05 -1.15055e-05 6.51964e-05 -4.35995e-05 8.96743e-05 2.97233e-05 2.44301e-05 -5.44775e-05 -2.07656e-05 0.000279801 -0.000480566 0.000375023 -0.00024221 0.000109067 8.58646e-05 -0.00031572 -0.000376491 -0.00047602 7.58039e-05 0.00083278 0.000733653 -0.000247125 -0.000863336 3.57239e-05 -0.000766689 6.05643e-05 0.000206653 7.72056e-05 -4.88961e-06 -9.82053e-05 -0.000339992 -0.000290667 -0.000352839 2.73127e-05 -0.00023701 -0.000157309 -6.5283e-05 -0.000208226 4.01205e-05 0.000361387 0.000121462 -0.000374293 0.0001985 0.000336927 -0.000219006 2.95475e-05 -0.00025029 -0.000219055 -0.00011924 -0.000123636 -0.000117303 -0.000244315 0.000241915 6.76379e-05 -1.33787e-05 -6.58876e-05 0.000159107 0.000157011 -7.2757e-06 0.000205957 0.000282554 -5.05148e-05 9.99402e-05 -4.9879e-05 4.16645e-05 2.12398e-05 8.81716e-05 4.50709e-05 8.07002e-05 -0.000103282 -3.41334e-05 -1.07917e-05 -4.6799e-05 -6.36488e-05 -4.08625e-05 -0.000108092 -3.03967e-05 -7.51374e-06 -3.83619e-05 -7.33384e-05 -0.000101261 0.000203379 -0.000412961 0.000100228 5.53789e-05 -3.74373e-05 -0.000212892 -0.000247646 0.000281434 5.15759e-05 4.51033e-05 -4.01491e-05 -0.000243415 0.000376014 0.000482334 -3.41572e-05 -0.000368905 0.000154171 -0.000117414 0.000148597 -2.39129e-05 8.42604e-05 4.03101e-05 -3.01684e-05 -2.56222e-05 -0.000167842 -6.8721e-05 2.97915e-05 0.000107446 0.000169327 3.57082e-06 -7.36014e-05 -1.50403e-05 0.000239762 -1.72504e-05 -5.72974e-05 -0.000148403 4.63964e-05 -0.000256103 -0.000102573 5.03158e-05 7.52055e-05 -0.000255469 -7.31608e-05 0.000387006 0.000235136 0.000160724 -4.79419e-05 -0.000149815 0.000227003 0.000255624 -3.92131e-05 -0.00016915 0.000196061 -1.51951e-05 -0.000136651 0.0002106 -0.000174364 -8.11679e-05 5.34486e-05 -0.000128468 0.000110276 3.20695e-05 3.50287e-05 0.000107771 -1.16321e-05 9.21006e-05 -2.62515e-05 -0.000114226 -1.18549e-05 0.000107995 2.48717e-05 -1.07674e-05 8.24814e-06 4.58486e-06 -0.000222362 6.53479e-05 0.000191618 -0.000150573 2.22237e-05 0.000329762 0.000184247 0.000336765 0.000151992 -0.000100255 0.000151519 0.000451166 -0.000146929 -3.08778e-05 0.000169664 0.000106772 -0.000122257 -0.00012064 0.000123517 0.000126747 0.000177128 -6.02199e-05 9.56331e-05 0.000280246 6.32511e-05 5.86923e-05 -0.00014436 -0.000157863 1.35506e-05 3.69933e-05 4.26318e-05 -0.000108581 -4.33348e-05 -0.000398044 0.000342455 -0.000426616 -1.30979e-05 0.000166473 -7.62396e-05 2.2164e-06 -4.01959e-05 0.000270533 8.5032e-05 0.000138689 0.000127869 4.09537e-05 0.000149707 0.000248794 1.86921e-05 -0.000376561 3.44172e-05 6.58289e-06 -7.37007e-05 -6.82026e-05 5.41005e-05 3.22237e-05 6.04498e-05 -3.04744e-05 -6.5249e-05 -5.3941e-05 1.60774e-05 9.13583e-05 7.14572e-05 4.43515e-05 -5.43351e-05 -9.71313e-05 9.40275e-05 0.000102016 -3.71041e-05 7.00559e-05 4.28237e-06 -4.98999e-06 3.62195e-05 4.06495e-05 -5.66132e-05 -4.29859e-05 0.000105775 -9.05917e-05 -6.25499e-05 -0.000112703 -1.79398e-05 8.38114e-05 -2.5041e-06 5.49142e-05 -0.000149002 -8.74748e-05 0.000138875 -4.53887e-05 6.59399e-06 1.51736e-05 1.17848e-05 1.16877e-05 4.4325e-05 -0.00011455 9.22997e-05 4.60936e-06 8.44035e-05 6.93004e-05 -0.000117716 6.25432e-05 3.51911e-05 -8.01965e-05 -0.000143352 -8.53731e-06 -5.46251e-05 -3.37585e-05 4.56707e-05 -1.82986e-05 0.000136053 7.60036e-05 -4.66217e-05 -7.91193e-05 4.80605e-05 -9.01409e-05 -2.81094e-05 9.6342e-05 -0.000168122 7.08064e-05 -3.7299e-05 -2.26216e-05 -9.45106e-05 -8.5837e-05 -3.25291e-05 -8.2729e-05 5.78452e-06 -1.02527e-06 -5.40742e-05 2.77937e-05 0.000100573 -1.85811e-05 5.51145e-06 2.43156e-05 5.21159e-05 1.69015e-05 -5.15985e-05 7.53051e-06 8.96353e-05 -7.15938e-05 -2.57713e-05 4.00744e-05 -0.000106333 0.000156787 -3.90272e-05 0.000202739 0.000109885 -0.000220526 -3.57421e-06 -0.000168527 9.76114e-05 0.00042149 -9.9564e-05 -0.000239521 -0.000170722 0.000146714 0.000367999 -7.47092e-05 6.56006e-05 -2.37718e-05 -0.000199712 0.000180762 -1.67469e-05 0.000171671 8.23738e-06 -0.000264589 -0.000181838 0.00016048 0.000184159 0.00019543 -0.000274555 3.02145e-05 8.5698e-05 -0.000174636 -0.000241462 -8.82469e-05 0.000237814 8.70947e-05 6.23123e-05 7.05064e-06 1.31201e-05 -3.98053e-05 9.50553e-05 5.75213e-05 -4.64461e-05 -2.49029e-05 6.51216e-05 -0.000151728 -5.2981e-05 3.36761e-07 -5.91082e-05 0.000112515 1.46884e-05 2.59389e-05 -0.00016558 -6.24623e-05 0.000110838 -3.95711e-05 -7.13836e-06 -8.63093e-06 -1.97415e-05 -1.23797e-05 7.93101e-05 -4.47733e-05 3.1825e-05 1.03086e-05 5.12904e-05 1.74113e-05 -4.18178e-05 4.32656e-05 3.64423e-05 -5.78641e-05 -5.62965e-05 3.97789e-06 -6.97736e-05 0.000208691 9.7559e-06 -9.33615e-06 -3.40323e-05 -6.49281e-05 0.00013556 -0.00018887 7.18607e-06 0.000116195 8.50216e-05 -0.000158334 -1.20972e-05 -0.000112184 0.000120357 0.000318485 5.58045e-05 -9.75963e-05 -0.000246141 0.000161937 -9.26959e-05 -5.10356e-05 6.67781e-05 -0.000187507 -0.000172404 1.06816e-05 0.000137218 0.000311609 -2.07792e-05 5.29304e-05 -1.86636e-05 -0.000123758 0.000111124 0.000114005 4.99978e-05 -0.000125147 8.04853e-06 0.000208841 2.71582e-05 -0.000154346 4.65665e-05 -0.000165657 8.89374e-05 -0.000158662 0.000244755 0.000561311 1.61853e-05 -9.11766e-06 -8.35664e-06 -2.05851e-05 0.000165143 0.000303055 -1.0132e-05 -0.000242637 -0.000147529 -1.88137e-05 1.82441e-05 -3.80078e-06 3.35629e-05 -2.40079e-05 -5.03066e-05 6.71879e-05 3.844e-05 -7.05894e-05 -4.09407e-05 0.000223108 1.96786e-05 -2.11178e-05 2.04096e-05 -7.79666e-05 -5.73395e-07 -3.41424e-05 -3.39681e-05 -2.65782e-05 -9.71504e-05 0.000289743 0.000417568 0.000269081 0.000424511 -7.82565e-05 -0.000443768 -0.000554801 -4.11646e-05 -0.00032598 -0.000352881 -3.86361e-05 -0.000272726 -0.000101209 0.000334226 0.000421936 -0.000307352 0.000161149 -0.000135683 0.000121947 -0.000227789 -8.38259e-05 0.000133052 -0.00011861 0.000336661 0.000367415 -7.29042e-06 -0.000293127 -0.000312706 -5.09497e-05 0.000160028 0.000224314 -3.23033e-05 0.000132322 0.000216404 0.000214461 -8.10017e-05 -0.000352776 0.000186712 -5.40509e-05 0.000234669 -0.000275096 0.000146363 0.000529035 -6.99115e-05 -6.02152e-05 -8.70209e-05 -0.000202155 0.000365806 0.000570709 1.17402e-05 -0.000268158 -0.000137456 -5.05494e-05 7.75295e-05 -4.26897e-05 8.08486e-05 -0.000140951 -0.000171452 3.53027e-05 0.000128188 0.000146247 -0.000106945 0.000138157 0.000160333 -3.70764e-06 -4.62907e-05 7.54581e-05 8.40072e-05 -0.000180718 -7.29519e-05 -4.0017e-05 3.47985e-05 -9.51e-06 -1.27866e-05 1.36501e-05 2.85083e-05 1.89606e-05 1.09051e-05 -1.64399e-05 -2.18675e-05 -1.04827e-05 -4.78814e-05 2.24108e-05 2.56934e-06 -4.78189e-05 2.5796e-05 2.22584e-05 -2.66745e-06 -1.50889e-05 1.27344e-05 3.49782e-06 -1.5876e-07 3.01409e-06 1.31837e-05 -2.38651e-05 -2.02987e-05 -6.69632e-06 5.78365e-06 1.76204e-05 -4.80694e-05 -1.15417e-05 2.697e-05 -2.11718e-05 5.94259e-06 2.84285e-05 -1.99043e-05 -3.55265e-05 3.35594e-05 -5.73069e-07 -4.56233e-06 7.85231e-06 2.53978e-05 3.478e-06 -8.60905e-06 -1.9481e-05 -3.59782e-06 9.40422e-07 -5.12253e-05 1.1683e-05 1.34195e-05 -3.62218e-05 2.35372e-05 1.30905e-05 -1.17811e-05 1.93796e-05 -2.42116e-05 -1.69337e-06 1.89551e-06 -1.99559e-06 -1.82087e-06 -3.92942e-05 -7.67646e-06 9.97637e-06 1.17439e-05 -3.14001e-06 -1.18366e-05 -1.93114e-05 1.49956e-05 8.779e-06 -6.17035e-06 5.15868e-07 -2.42399e-05 3.94286e-05 6.4726e-05 -0.000181467 0.000329821 8.58334e-05 0.000111051 -2.86851e-05 -0.000132423 -0.0003028 -0.000130839 -5.78656e-05 0.000142173 6.48385e-05 -0.000106672 8.48012e-05 -8.56967e-05 -0.00012982 -0.000115893 0.000292384 -0.000149393 -2.51687e-06 -2.79606e-05 -0.000102623 1.48533e-05 -1.69843e-05 0.000181814 -5.77663e-05 -0.00012197 -5.37013e-06 -6.98993e-06 6.22003e-05 0.000105498 2.26592e-05 -1.70997e-05 3.20362e-05 -6.04469e-05 -3.03891e-05 3.98006e-05 -8.18099e-06 -6.24303e-06 1.36991e-05 2.87516e-05 7.11768e-06 7.68231e-06 -1.17494e-05 -1.72788e-05 5.7867e-06 -4.75247e-05 2.34068e-05 1.14912e-05 -5.30595e-05 2.56923e-05 9.52596e-06 -2.04061e-05 -1.32975e-06 -9.55133e-07 -5.24623e-07 7.58091e-06 4.58849e-06 1.15484e-05 -2.90693e-05 -1.79636e-05 -1.50222e-07 6.72075e-06 1.7279e-06 -4.17291e-05 -2.01023e-05 1.63521e-05 -4.99472e-06 1.22607e-05 9.09943e-06 -2.49491e-05 0.000158026 1.38778e-05 -0.00012543 0.000111401 -2.08277e-05 0.000193599 -9.94598e-05 4.58105e-05 4.97672e-05 -6.07761e-05 1.44199e-05 -7.1542e-05 -3.19676e-05 0.00017669 0.000121415 -0.00021305 -0.000158136 0.00014698 -9.36734e-06 -7.92613e-05 -2.80173e-05 1.16623e-05 9.87596e-06 2.33629e-05 3.50821e-05 0.00010564 7.09127e-05 1.66674e-05 4.06094e-05 3.3226e-05 -5.25418e-05 1.52811e-05 -2.03733e-05 -3.13351e-05 -6.54151e-06 -4.97917e-05 0.000305629 2.72719e-05 -0.000173038 5.96186e-05 -7.95279e-05 0.000232316 -0.000237608 0.000179858 0.000226525 -0.000140372 2.2707e-05 -6.96522e-05 -7.7495e-05 0.000344405 0.000219909 -0.000421457 -0.000293009 0.000263144 -8.83646e-06 -1.53618e-05 2.1805e-05 -1.73114e-05 -4.76789e-05 -4.53496e-05 3.72057e-05 9.04284e-05 1.87169e-05 -3.2506e-05 2.12701e-05 5.10363e-05 3.0582e-06 4.80868e-06 -3.14575e-05 -2.39775e-05 -6.91996e-06 -9.35802e-05 -0.000378917 -1.31356e-05 0.000302428 -0.000225474 7.60412e-05 -0.00020915 0.000288599 -0.000187051 -0.000325916 0.000232528 2.13132e-05 5.18696e-05 0.000219438 -0.000402789 -0.000428889 0.000356924 0.000393 -0.000170571 4.95821e-05 0.000171172 4.95038e-05 -2.24289e-05 -2.43434e-05 -2.42844e-05 -0.000194492 -7.39099e-05 9.5961e-06 -5.26578e-05 -4.31898e-05 -0.000114345 -5.0866e-06 -3.01332e-05 1.40539e-05 2.93778e-05 0.000103719 0.00011838 0.000139244 -1.05273e-05 -0.000163693 0.000131302 -1.61955e-06 0.000276064 -0.000120928 0.000172751 0.000124535 -0.000114528 5.59749e-05 -5.34591e-05 -6.11806e-05 0.000233979 0.0001965 -0.000314814 -0.0002196 0.000189088 3.45219e-05 -0.000112344 1.71847e-05 -7.25096e-05 -5.60157e-05 -4.45942e-05 4.43974e-05 0.000105665 7.10564e-05 1.93417e-05 3.37955e-05 6.01785e-05 -1.63638e-05 -4.46014e-05 -3.80033e-05 1.08146e-05 -7.00045e-06 -7.05421e-05 -0.000183689 0.000276047 -3.20356e-05 0.000182101 0.000141981 4.08066e-05 -2.51561e-05 -7.29032e-05 3.138e-05 -0.00018587 -4.36834e-05 0.000272562 -8.83401e-05 -0.000127013 0.000152422 0.000150858 -0.000168166 -0.000376278 0.00010622 -6.56284e-05 3.44434e-05 -7.73455e-05 7.62257e-05 -3.96124e-05 -0.000105941 4.27552e-05 0.000158122 8.07135e-05 -3.00384e-05 -1.40094e-05 -9.67658e-05 -4.32806e-05 1.68807e-05 7.72233e-05 2.1408e-05 -9.91955e-05 8.05123e-05 9.03586e-05 -0.000123443 0.000145812 0.000110312 2.28651e-05 9.51557e-05 5.97541e-05 -3.30454e-05 6.4838e-06 -2.27089e-05 7.62291e-05 -0.000246987 -7.82715e-06 -1.36002e-05 3.09635e-05 0.000117962 -0.000166388 -2.04336e-05 3.60354e-06 6.8614e-05 -0.000125023 -7.91322e-05 -8.36734e-05 2.27691e-05 5.96612e-05 3.42626e-05 5.3184e-05 -0.0001215 -4.70677e-05 5.34879e-05 -1.38793e-05 -5.00389e-06 1.43534e-05 3.1123e-05 -7.44807e-05 0.00023462 -6.78357e-05 -0.000456663 0.000140073 -0.000230615 0.000280081 0.000461917 -1.87896e-05 -0.00047046 -0.000189816 -0.000186401 0.000889372 0.000421706 0.000251074 0.000199289 -0.000321219 1.05382e-05 -0.000457437 0.000145552 -7.09417e-05 0.000171997 -2.12046e-05 -0.000195115 -3.49485e-05 4.30917e-05 0.000219978 0.000178543 -8.20616e-05 0.000149437 2.06244e-05 -0.000144393 7.87163e-06 -2.85348e-05 -1.66314e-06 7.42614e-05 4.81707e-05 3.35181e-05 -4.75839e-06 -9.60042e-05 0.00013281 0.00017802 9.2236e-05 -1.95093e-05 -9.94446e-05 -8.25033e-05 -3.49384e-05 3.01373e-05 3.03709e-05 -0.000233438 -3.7331e-05 6.42767e-05 0.000105043 4.77519e-05 -0.0001215 8.36633e-05 1.39028e-05 3.71796e-05 -8.71901e-05 -2.9205e-05 -4.04324e-05 2.24006e-05 4.56093e-05 2.5795e-05 8.48668e-05 -8.78214e-05 -0.00012425 -3.48173e-05 -9.19312e-06 -1.8307e-05 3.79088e-05 4.47556e-05 -1.89436e-05 4.33064e-05 -5.00875e-05 -6.33423e-05 -4.28919e-05 -6.04863e-06 4.68242e-05 -5.48943e-06 2.88545e-05 3.7699e-05 -5.71676e-06 -3.74418e-05 -4.00156e-05 -7.40838e-05 0.000113586 9.29717e-05 4.97315e-05 5.62951e-05 -8.81881e-05 -5.55939e-06 4.27688e-05 2.1084e-05 3.10973e-05 2.77416e-05 2.79974e-06 -1.40412e-05 1.77029e-05 -2.66942e-05 -4.47099e-05 -1.70558e-05 2.87218e-05 5.27025e-05 -8.96111e-05 -8.60729e-05 -1.65696e-05 -6.25746e-05 -1.33432e-05 7.23288e-07 -6.18756e-05 -9.09539e-05 -2.21353e-06 2.45707e-05 6.7467e-05 6.73565e-06 5.59054e-05 5.71763e-05 3.33798e-06 -3.78171e-05 -3.48882e-05 -3.84503e-05 4.53466e-05 1.62812e-05 4.64164e-05 5.33438e-05 -9.77037e-05 -2.10493e-05 1.3958e-05 -2.58476e-05 2.80486e-05 2.01352e-05 1.38857e-05 -3.81849e-06 1.28671e-05 -1.93371e-05 -2.73803e-05 -4.08774e-05 4.71247e-05 5.00805e-05 -8.02917e-05 -4.68571e-05 3.07426e-06 -5.95243e-05 3.63007e-05 -2.8839e-05 9.42099e-06 -0.000234621 3.87473e-05 9.31101e-05 0.000222748 8.73525e-05 -8.13944e-06 0.00012759 -8.12143e-05 -0.000202387 -3.93424e-05 -0.000218075 0.000189775 8.91468e-05 -9.08384e-05 -8.33836e-05 -8.30475e-05 -0.000115704 -0.000140045 -0.000134918 -6.30076e-05 4.41909e-05 0.000144209 6.73997e-05 6.33597e-05 0.000175585 5.75772e-05 -4.95529e-06 0.000123322 0.000123955 -6.07744e-05 -4.12742e-05 -5.16777e-05 -4.28431e-05 0.000152886 8.03512e-05 -7.26836e-05 -5.91339e-05 -4.58707e-05 -5.27946e-05 3.56188e-05 -3.1278e-05 5.37819e-05 5.24351e-05 -3.39513e-05 -5.08703e-05 -2.02544e-05 -7.00317e-05 8.61674e-05 6.33864e-05 4.12383e-05 4.09492e-05 -0.000120978 -6.18063e-06 4.49527e-05 2.26915e-05 1.54573e-05 -1.33149e-05 3.7727e-06 3.76385e-06 2.04987e-06 -3.24613e-05 -5.32374e-05 -3.96029e-05 1.72824e-05 5.89723e-05 -0.000108084 -6.88891e-05 -5.18054e-06 -6.69289e-05 1.64831e-05 -0.000106442 1.20358e-05 -8.42655e-05 3.04903e-05 1.61341e-06 -8.78367e-05 0.000140429 7.34798e-05 5.55542e-05 1.94179e-05 -2.74079e-05 0.000118161 -3.72297e-05 -0.000106731 5.99181e-05 0.000186079 0.000101857 2.36726e-05 -0.000113023 3.40035e-05 -0.000129632 3.98519e-05 8.29065e-05 -0.00011591 -0.000114758 6.00109e-05 0.000107047 -6.67914e-05 -5.34763e-05 1.65817e-05 2.03244e-05 6.17119e-05 5.13636e-05 9.93614e-05 1.30239e-05 -9.62899e-05 -0.00014255 -3.34438e-05 -0.000128996 4.71569e-05 -3.60635e-05 -0.000114932 0.00010674 9.29576e-05 9.57796e-05 1.36163e-05 4.36987e-05 0.000105283 -6.25294e-05 -1.20629e-05 1.42957e-05 0.000147517 9.28573e-05 4.29419e-06 -3.11756e-05 3.82772e-05 -7.16457e-05 -3.3637e-06 4.96508e-05 8.31333e-06 -6.21433e-05 -3.61875e-05 2.14416e-05 2.94408e-05 -2.71867e-06 -6.13052e-05 -9.75596e-07 6.04557e-05 -6.31712e-05 -3.39344e-05 5.31373e-05 6.77003e-06 0.000222214 -7.38842e-05 0.000226371 7.309e-05 6.48015e-05 0.000201569 8.19433e-05 -0.000282046 -0.000824876 -0.000284652 -1.93253e-05 0.000295361 0.000239151 0.000149338 3.84254e-05 -0.000363464 -0.000131354 0.000255413 0.000286329 -0.000160131 8.14076e-05 -0.000241219 -0.000144356 8.56677e-05 -1.30702e-05 -4.26837e-06 -0.00019034 0.000189917 0.000209666 0.000107881 4.75159e-05 0.000151436 6.25423e-05 -0.000340064 0.000100375 8.53378e-05 -5.81985e-05 1.97272e-05 -0.000109526 1.11288e-05 -3.82468e-05 -0.000116403 0.000117977 -6.79473e-06 -5.47421e-05 2.37693e-05 -2.30614e-05 0.000220763 8.86052e-05 -5.17632e-05 -1.83529e-05 1.93755e-05 2.24977e-05 4.83816e-05 7.45817e-06 2.37823e-05 -2.58716e-05 -4.76518e-06 -7.78958e-06 -2.57415e-05 -5.42792e-05 -9.3459e-06 4.07355e-05 -2.77695e-05 -2.09847e-05 -6.94172e-05 -4.38376e-05 -3.69879e-06 2.2843e-05 3.3652e-05 -1.04388e-05 4.56307e-05 1.69553e-05 7.79512e-05 -5.11372e-06 -4.55331e-05 -5.42798e-05 -4.9396e-06 -5.16302e-05 -1.22599e-05 6.91535e-05 -4.96022e-05 2.97121e-05 -1.09956e-05 1.12517e-05 8.4237e-05 7.91038e-05 -3.68693e-05 -6.86315e-05 -3.41263e-05 1.97138e-05 -2.12992e-05 3.51821e-06 5.10791e-06 -1.8525e-05 1.40602e-05 6.21119e-06 4.17569e-05 6.25441e-06 -2.12483e-05 1.18255e-05 -4.78185e-06 2.25407e-05 2.53294e-05 3.02656e-05 -1.21012e-07 -2.03111e-05 -2.98739e-05 3.23388e-05 6.43717e-05 -5.8618e-05 -1.56588e-05 -5.3982e-05 3.77364e-06 -5.95183e-05 -1.56476e-05 3.30958e-05 -3.27776e-05 1.59901e-05 -2.83419e-05 3.67857e-05 9.56654e-05 8.00342e-05 1.1703e-05 -2.09126e-05 -4.12837e-05 3.45618e-06 -3.49743e-06 -6.95876e-06 -4.08436e-06 8.84675e-06 3.23584e-06 3.24042e-05 3.4712e-05 -1.85464e-05 9.89852e-06 1.40551e-05 1.1063e-05 -1.29502e-07 1.7227e-05 -9.95715e-06 -3.02767e-05 -1.98965e-05 -6.24762e-06 -8.48515e-05 0.000207508 0.000235767 -0.000234171 -0.000160593 -0.000220009 0.000194374 2.33904e-05 -4.05865e-05 4.04375e-05 -5.51769e-06 -1.85135e-06 0.00023238 -6.99461e-05 -0.00021883 0.000148489 4.56164e-05 -5.66426e-05 -8.43289e-05 -1.67965e-05 -4.25127e-05 -9.71028e-05 2.94984e-05 -0.000149044 -3.01995e-05 -5.87065e-05 -3.31988e-05 4.89915e-05 5.39133e-05 0.00013944 0.000134373 -0.00011473 -3.64418e-05 -6.39302e-05 5.04694e-05 4.85839e-05 8.77207e-05 8.95187e-05 -6.70389e-05 -1.17829e-05 -7.05982e-05 -9.91702e-06 -7.26015e-05 4.36063e-05 8.30095e-05 -8.1501e-05 2.39666e-05 2.84602e-05 2.0179e-05 0.000130816 0.000103845 -8.52338e-05 -0.000144689 -2.44917e-05 8.16149e-07 -2.06883e-06 -8.23953e-06 -8.50007e-06 -8.35846e-06 -7.04451e-07 3.83987e-05 3.22662e-05 -8.74961e-06 -6.02727e-06 2.49105e-06 -1.32353e-05 8.78265e-06 5.54771e-05 1.07905e-05 6.68097e-06 -3.88792e-05 -1.90409e-05 8.27953e-05 9.42946e-05 -0.000214553 -0.00010473 0.000108236 9.39017e-05 1.11802e-05 -2.79123e-05 -2.86052e-05 -0.000184446 -2.33672e-05 -0.000122784 -0.000165922 7.32994e-05 -0.000149563 0.000139171 -1.42366e-05 -0.000201817 1.43849e-05 -0.000115457 -2.34242e-06 1.37946e-05 -9.10183e-05 -5.04554e-05 0.000119538 6.71321e-05 -8.79213e-06 -6.07078e-05 -2.71052e-05 0.000187496 0.000122738 -0.00019629 -0.000114766 1.78362e-05 4.80471e-05 2.81369e-05 3.03437e-05 -2.42523e-05 -0.000155708 -7.32859e-05 1.66743e-05 -5.73879e-05 -4.43923e-05 9.74797e-05 0.000153105 -0.000100401 -2.31062e-06 3.99351e-05 -9.16778e-05 1.26632e-05 -0.000143744 3.04181e-05 9.00581e-05 5.4337e-05 -2.04831e-05 -5.07356e-05 5.72707e-05 0.000137143 -0.000133054 -6.94328e-05 2.74081e-05 8.59449e-05 0.000105545 1.55994e-05 4.63799e-05 0.00012501 6.95334e-05 -0.000135336 7.37973e-05 1.92851e-05 -2.15385e-05 7.39677e-05 -0.000143739 0.000455861 -0.000449786 0.000261145 -8.8419e-05 -0.000118272 0.000233498 0.000343322 0.000213223 -0.000482525 0.000406381 2.12711e-05 -0.000535114 0.000201453 0.000498148 9.04735e-05 -0.000658137 0.00026986 3.11999e-05 -6.86188e-05 -3.09918e-05 -0.000335634 5.03487e-05 -0.000130874 -4.82768e-05 0.000112824 -4.39293e-05 9.47669e-05 -0.000181977 -1.27065e-05 -6.93819e-05 -4.20862e-05 -0.000142842 -3.25649e-05 0.000354684 -4.519e-05 0.000129079 -0.000102726 -0.00021671 -2.29589e-05 0.000127854 8.71975e-05 -2.56516e-05 7.09413e-05 0.000105759 -0.000186685 -0.000105853 -0.000149765 -0.000153361 6.30349e-05 -0.00015857 6.90174e-05 0.000102297 1.64054e-05 -6.8651e-05 -4.33355e-05 -6.96115e-07 3.52737e-05 -5.30987e-05 -0.00010192 6.9517e-05 1.26469e-05 9.60047e-05 4.58439e-05 -4.50059e-05 0.00012459 1.13615e-05 -0.000226482 1.98508e-05 6.12143e-05 2.06271e-05 8.63447e-05 -0.000127754 -5.8486e-05 0.000129299 -0.000131452 -2.29872e-05 9.16762e-05 9.489e-05 -5.13034e-05 -0.000188464 4.13486e-05 -0.000104036 8.03041e-05 0.000133475 -0.000160178 -0.000166862 -4.95825e-07 0.000216158 8.38477e-05 -7.99841e-05 7.55323e-05 3.80292e-05 0.000102852 -2.22837e-05 -8.52877e-05 3.87633e-05 -0.000166936 1.61705e-05 8.89828e-05 8.50797e-06 7.78125e-05 4.4221e-05 9.31923e-05 0.000134344 -0.000102733 -0.000194772 5.43499e-05 -0.000152946 2.94027e-05 0.000107222 -9.06688e-05 3.56088e-05 2.28576e-05 0.000188536 -0.000141187 -8.78364e-05 8.46889e-05 -0.000102223 0.000118418 7.63826e-05 -0.000118151 -8.08425e-05 -3.31197e-05 4.30689e-05 0.000103921 -5.04736e-05 5.1785e-05 -1.05361e-05 7.58097e-05 4.29588e-05 -1.90964e-05 -9.16293e-06 -0.000106475 4.04056e-05 3.24382e-05 -1.01468e-05 -2.71e-06 -2.19927e-05 8.21488e-05 0.000131903 -8.27691e-05 -0.000147525 3.59953e-05 -0.000513844 0.000113635 0.000105288 -0.000202892 8.99606e-05 -0.000124992 0.000292694 8.06769e-05 0.000271284 2.42502e-05 5.0777e-05 0.000198914 9.29388e-05 -0.000256841 -0.000334795 0.000262482 7.07335e-05 7.01225e-06 -0.000196599 2.17539e-05 -0.00021665 0.000137826 8.7984e-05 -9.73702e-05 -0.000186072 -0.000108284 -1.09445e-05 3.5031e-05 -1.01252e-05 2.59006e-05 3.56881e-05 0.000225725 0.000204249 4.68529e-05 -0.000129146 -0.000217579 -0.000175572 -9.82668e-05 9.66277e-05 -9.79608e-05 6.18266e-05 5.6587e-05 0.000150149 -0.000156142 -0.000230262 7.21355e-06 -0.000123084 0.000190613 0.000121049 -0.000178494 -0.0001546 -5.33533e-05 0.000141116 0.000234177 -6.16209e-05 0.000106603 -6.44127e-05 0.00013881 2.63859e-05 -0.000130962 2.97053e-05 -0.000161475 3.69917e-05 6.61087e-05 2.96657e-05 7.31185e-05 -9.46116e-06 5.70492e-05 0.000142278 -5.79628e-05 -0.000164846 6.53747e-05 2.51882e-05 0.000255921 0.000219309 0.000111006 -2.19945e-05 -0.000223562 -0.000105792 -0.000232616 7.398e-05 0.000196843 4.64689e-05 9.53216e-05 -1.95046e-05 0.000132369 -9.08574e-05 -0.000146771 -0.000133092 0.00014948 -6.96434e-06 0.000115067 0.00010519 9.57729e-05 0.000244494 0.000102597 -0.000110959 -0.00049543 -0.000243797 -5.1802e-05 1.36554e-05 0.000201312 0.000151051 5.09199e-05 0.000143861 -0.000101002 -0.000259512 -0.00014999 -1.77986e-05 0.000121294 0.000172144 0.000160529 0.000123354 -0.00016873 1.13338e-05 -0.000312052 -0.000185628 0.00014757 8.51726e-05 0.000214939 0.000144477 5.81133e-05 -0.000116961 -0.000131832 -0.00015868 9.37061e-05 1.64503e-05 -6.60746e-06 -7.86107e-05 -6.2748e-05 5.06867e-05 9.04778e-05 1.47304e-05 8.09661e-05 -6.5268e-05 -6.00446e-05 1.27813e-05 9.41345e-05 5.55275e-05 -8.55981e-05 0.000147017 3.3831e-05 -1.45839e-05 -4.40674e-05 -0.000632672 0.000238935 0.000185393 -0.000109327 -1.22586e-05 -0.00044059 2.43984e-06 -0.000136346 0.000646161 0.000684673 0.00019695 -0.00014511 -0.000117637 -6.96412e-05 -0.000104474 0.00028667 -0.00011744 -7.30589e-07 -0.000124049 0.000117396 -7.09024e-05 8.05995e-05 7.73964e-05 -0.000139963 -0.000231036 -0.000304184 6.08458e-05 0.000360759 0.00016219 -8.93793e-05 -0.000101309 5.45273e-05 0.000123333 7.26867e-05 -0.000155737 -0.000251016 -3.97415e-06 9.79617e-05 6.85109e-05 9.68714e-05 1.16126e-05 -0.00011903 1.10632e-05 -0.000163379 -1.45686e-05 5.50985e-05 -2.46421e-05 0.00011533 -3.87955e-05 8.64431e-05 9.87923e-05 -0.00012118 -0.000155797 0.000116706 1.37064e-05 2.07292e-06 -1.0894e-07 4.03968e-05 7.34765e-05 6.03035e-05 3.57066e-05 -9.36925e-06 -2.43724e-05 2.66826e-05 -1.35494e-05 6.03671e-06 2.29344e-06 -1.04753e-05 5.97731e-05 -2.36757e-05 -4.05586e-05 3.11575e-05 -0.000399002 0.000422801 0.000222019 -0.000446082 0.000561229 0.000182118 7.21143e-05 0.000144753 5.85594e-05 -1.0272e-05 -0.000397036 -0.00052354 0.000243066 0.000186921 -0.000316813 -0.000140262 0.000156303 -0.00022795 -0.000135898 0.000239741 -0.000592039 0.000175973 0.000605666 -8.33522e-05 -5.47594e-05 -0.000327458 0.000145187 -1.05581e-05 5.69203e-05 -0.000158703 3.94679e-05 -8.96184e-05 -0.000253215 0.000226277 8.82027e-05 -0.000142848 -0.000413519 0.000521016 1.73956e-05 -0.000295903 0.000287991 0.000119748 0.000215809 8.44711e-05 0.000432513 0.000167564 -0.000131742 -0.000338447 9.42168e-05 0.000161796 -0.000179764 7.35001e-05 -5.57931e-05 -0.000251264 4.86437e-05 0.000124993 -0.000347642 0.000199198 0.000195295 -0.000159316 -0.000109843 -0.000257839 1.33663e-05 1.92856e-05 8.9779e-05 7.95344e-05 3.51538e-05 1.69884e-05 0.000109612 0.000269251 -5.00144e-05 -0.000223732 -0.00041479 0.000273149 -0.000330131 -6.56931e-06 0.000114561 -0.000217446 0.000180852 -1.89703e-05 0.000416579 0.000532935 0.000743853 7.21687e-05 -0.00029369 3.49518e-05 8.15907e-05 0.000254124 -0.000225014 -0.000163038 -0.000170467 -0.000157789 -4.06991e-05 -0.000475895 0.000626486 0.000512754 -0.000102627 -0.000378831 0.000104854 0.000109993 -0.000352558 4.7087e-05 3.16282e-05 -0.000292653 -0.000355635 0.000284429 9.81108e-05 -0.000306074 -0.000470102 0.000461641 0.000218543 -0.000101663 0.000405438 0.000143358 0.000176181 -7.67416e-05 -4.48392e-05 2.24437e-05 -2.37162e-05 -0.000125048 2.94052e-05 0.000224828 -0.00016237 -4.19679e-05 -6.52636e-05 -1.46798e-05 1.97772e-05 2.56611e-05 -0.000257937 6.5963e-05 0.000201089 6.26268e-05 -0.000116714 -0.000258539 0.000106557 0.000200321 5.74939e-06 4.75824e-05 3.73452e-05 -4.71378e-06 8.23489e-05 0.000144317 1.20827e-06 -9.63851e-06 0.000113458 2.65944e-05 -2.45159e-05 0.000100797 0.000116805 0.000125153 -9.53943e-05 -8.40578e-05 -7.92155e-06 1.96202e-06 7.54273e-05 -6.91146e-05 -0.000125318 0.000113196 9.06237e-05 -3.3491e-05 -2.72805e-05 -2.35799e-05 4.0581e-05 -3.43113e-05 -6.37715e-05 0.000167357 -8.11521e-06 7.53357e-06 -1.34706e-05 1.37905e-07 0.000147424 4.34482e-05 2.97585e-05 -6.31429e-05 1.77253e-05 8.37562e-05 -7.9145e-05 -6.34436e-05 8.71986e-06 -8.11078e-05 7.14504e-05 2.54145e-05 -4.96314e-05 0.000117779 2.41428e-05 9.3524e-06 -8.32334e-05 -6.67337e-05 9.16559e-05 4.3161e-06 4.04842e-05 8.1689e-05 3.33508e-05 6.09074e-05 2.63767e-05 -8.85434e-05 -8.90131e-05 1.51749e-05 1.62741e-05 -8.41204e-05 -1.36673e-05 4.33017e-05 -9.33754e-05 -4.69722e-05 4.32593e-05 0.000112727 6.39955e-05 -8.20341e-05 -5.50435e-05 -1.11308e-05 3.44348e-05 4.51546e-05 4.08222e-05 -2.45151e-05 -4.97862e-05 -1.81085e-05 0.000153842 -7.38006e-05 5.74441e-06 0.00032883 0.000299578 -0.000326443 0.00012426 0.000220392 0.000242646 0.000374954 0.000436982 0.000106425 -0.000128992 -0.000204456 -0.000490124 -1.26441e-05 -0.000108778 -0.000113198 -0.000347693 0.000341189 -9.78462e-05 0.000107437 0.00027231 0.000169527 -6.23016e-05 -0.00013125 0.000124876 8.75366e-05 -0.000192339 -0.000213307 -0.000184409 0.000115587 1.97717e-05 -3.31466e-06 -6.25312e-05 -0.000173819 -5.66481e-05 7.62677e-05 -6.37037e-05 1.11227e-05 1.99222e-05 1.50359e-05 -9.63256e-05 -3.45717e-05 0.00017277 8.56624e-05 9.10939e-05 -6.76404e-05 -2.32833e-05 0.000158177 4.68918e-06 -1.27936e-05 -0.000121843 -8.66166e-05 2.37318e-05 3.74113e-05 4.9067e-06 3.22161e-05 -3.9729e-05 -7.96104e-06 2.36996e-05 -7.58532e-05 -1.11672e-05 -2.01311e-06 3.07016e-05 7.32071e-05 1.60195e-05 -1.21929e-05 3.55639e-05 -8.76715e-06 -5.16995e-05 -7.90775e-05 3.33873e-07 -5.45612e-05 7.9505e-05 5.42046e-05 -8.43958e-05 -0.000113227 0.000102866 7.89133e-05 -5.46009e-05 -4.62803e-05 -0.000149552 7.48651e-05 -2.35163e-06 -0.00018478 -4.02377e-05 0.000101159 0.000201962 0.000169522 -4.4267e-05 -6.04735e-05 -1.30175e-05 0.00012255 -4.5913e-05 -0.000101368 0.000113311 0.000145449 -5.29261e-05 -4.6149e-05 -5.84372e-05 9.06295e-05 0.000108376 -0.000118094 3.9043e-05 0.000103312 -2.37418e-05 -3.23303e-05 9.18544e-05 -2.69919e-05 -1.80404e-05 8.82938e-05 -0.000121537 -6.63788e-05 5.33723e-05 6.58773e-05 -6.65699e-05 2.99923e-05 -5.67567e-05 0.000133127 1.84141e-05 -0.000149501 2.52742e-05 0.000167241 0.000125169 7.71338e-05 -6.05819e-06 9.79814e-06 -6.21813e-05 1.88324e-05 3.82318e-06 6.99551e-06 -3.64471e-05 2.67986e-05 4.44848e-05 1.77636e-05 3.51001e-05 2.80902e-05 1.7059e-05 8.78875e-05 6.9922e-05 1.09915e-05 -7.45625e-05 -8.91208e-05 -0.000321593 3.87601e-05 0.000360883 0.000131948 -0.000225768 -0.000726407 5.12382e-06 2.9071e-05 0.000512759 0.000337247 0.000215851 3.18532e-05 -0.000618685 -0.000380415 -3.21017e-05 0.000551711 7.93382e-05 0.000298294 -0.000242477 0.000317308 -9.39734e-05 0.00029738 0.000155769 -9.78397e-05 0.000141016 6.63517e-05 3.32538e-06 0.000127112 -0.000316679 -0.000164689 1.08315e-05 -0.000148864 4.56213e-05 9.68986e-05 -0.000267604 0.000110061 0.000181315 -2.73274e-05 3.36679e-05 9.773e-05 -0.000235772 -0.000119226 9.17647e-06 0.000101752 -2.12044e-05 -6.8345e-05 -0.000150218 6.38762e-05 1.64955e-05 -0.000121612 3.83841e-05 0.000115843 0.000109813 9.36493e-05 4.96365e-06 -5.90021e-05 -3.83288e-05 3.00598e-05 -2.20259e-05 -1.01613e-05 -4.42285e-06 7.02707e-05 1.82895e-05 -8.22008e-05 7.06997e-05 6.15538e-05 7.25196e-05 4.66947e-05 3.44652e-05 7.22337e-05 -8.72988e-05 -4.59624e-05 -0.000125878 0.000100931 1.42857e-05 8.43843e-05 -1.63644e-05 1.3368e-05 2.01212e-05 3.63234e-05 0.000135044 -2.82645e-05 -9.87975e-05 -7.98337e-05 0.000101424 1.4686e-05 -0.000127195 2.01971e-05 6.73094e-05 -2.03186e-05 2.66171e-05 -0.000147722 0.000156879 -1.68654e-05 -0.000208043 4.70535e-05 6.773e-05 0.000129381 0.000175985 -0.000227478 4.50733e-05 3.42314e-06 -8.8554e-05 7.09136e-05 -0.000109936 9.04183e-05 0.000115391 -6.54366e-05 -0.000195229 0.000130922 3.0696e-05 -3.24617e-05 -7.1993e-05 4.23182e-05 1.7536e-05 7.04444e-05 8.11514e-05 -8.56366e-05 2.5281e-06 -9.17554e-06 1.72376e-05 5.92815e-05 -5.43856e-05 6.32462e-05 -1.79705e-05 -9.10398e-05 -1.72584e-05 -9.53224e-05 -1.9377e-05 -2.09e-06 -7.09568e-05 -3.69667e-05 3.66547e-07 3.62197e-05 0.000114362 -0.00012248 -3.81007e-05 3.17251e-05 -7.40521e-05 5.92776e-05 0.00010419 0.000100511 -2.61512e-05 -3.48326e-05 -0.000598721 0.000255009 0.000210824 5.66154e-05 -0.000200944 -0.000497635 3.36778e-05 0.000130074 0.000735559 0.000276348 0.000239917 -0.00027906 -0.0004793 -1.60579e-05 0.000351616 0.000397936 -0.000163498 -4.42889e-05 -9.21153e-05 0.000126038 -3.37541e-05 3.95308e-05 2.60869e-05 5.5194e-05 -0.000103997 -0.000178534 0.000131235 -0.000174356 -2.74433e-05 -7.75529e-05 -4.38433e-05 9.31755e-05 9.05053e-06 -5.99266e-06 -8.36072e-05 -0.000253695 -0.000137291 1.91408e-05 4.79785e-05 6.43084e-05 7.21278e-05 -1.7777e-06 -3.67721e-06 8.70681e-05 0.00017285 -0.000149875 -0.000106805 -8.48437e-05 -4.43282e-05 9.61978e-05 -9.53805e-05 -1.10184e-05 5.21335e-05 4.84225e-05 2.51144e-05 -0.00012628 3.53816e-05 -7.73243e-05 -0.000126704 2.46987e-05 8.75191e-05 0.000108019 8.46889e-05 -0.0001038 3.39963e-05 -6.51623e-06 -0.000112342 7.85456e-05 -3.80135e-05 2.27938e-05 5.48942e-05 -2.98444e-05 -0.000159196 0.000355726 -7.66521e-05 -2.8264e-05 0.000183387 4.25933e-05 7.73358e-05 -0.000117981 0.000215367 0.000139503 0.000214544 2.33089e-05 -4.97771e-05 0.000219711 0.000125294 -0.000103205 -0.000216723 -6.81569e-05 3.20576e-07 0.000169022 -0.000181824 0.000141158 0.000260488 0.000283844 -5.1926e-05 -0.000607474 -7.15267e-05 0.000163356 7.29574e-06 8.14809e-05 -9.94375e-05 -0.000102145 0.000322628 0.000454793 -0.000223141 -0.000183266 -0.000116899 0.000253968 -0.000105356 -6.23302e-05 9.77184e-05 3.38681e-05 6.6556e-05 -4.36553e-05 0.000350906 0.000198302 0.000142333 0.000174119 5.29485e-05 0.000181274 0.00021425 -7.62675e-06 -0.000252428 -9.56078e-05 -5.68966e-05 -3.22481e-05 -7.86952e-05 6.85906e-05 4.47486e-05 -2.6963e-05 -6.51048e-05 -7.10889e-05 2.50279e-05 1.57889e-05 5.91183e-05 9.29291e-05 4.14245e-05 -6.65369e-05 0.000163348 0.000184921 -3.46695e-05 -0.000130354 0.000293958 -0.000381075 -9.36063e-05 0.000363637 0.000124508 0.000190029 7.43917e-06 -0.00015293 -0.000490928 -0.000149126 -0.000419458 5.4329e-05 -3.34607e-05 -0.00015143 -7.92885e-05 -9.67739e-05 0.000432976 0.000287981 0.000139079 -0.000124603 0.000184333 0.000107584 -0.000238845 -0.000146684 1.8308e-05 0.000560324 0.000261294 -0.000193643 -0.000219639 -7.07901e-05 0.00024338 1.09578e-05 -0.000117283 -9.6763e-05 0.000173162 6.95494e-05 -4.62905e-05 0.000241044 -9.65591e-05 -6.56309e-05 8.28205e-05 5.58656e-05 -1.70572e-05 -7.71075e-05 0.000227413 5.19566e-05 -5.18841e-05 4.31715e-05 0.000103923 0.000129104 0.000177469 -6.56931e-05 -0.000169314 -0.00011469 2.79277e-05 7.34223e-05 -4.75543e-05 1.12853e-05 -2.93234e-05 -6.16852e-06 -8.67089e-05 -0.000134166 -5.50944e-05 -0.000103231 -5.74132e-06 0.000140096 2.13594e-05 -5.2473e-05 0.000103932 0.000100971 -4.33116e-05 -2.17487e-05 -3.29363e-06 2.37052e-05 0.000176296 -6.93992e-06 -0.000201005 -0.000101949 4.28781e-05 -2.70638e-05 -9.39755e-07 4.23208e-05 0.000112663 0.000218603 -2.58681e-05 -9.40934e-05 4.98023e-06 6.64335e-05 -4.04834e-05 -6.17758e-05 -3.24675e-05 -6.47112e-05 0.000153825 2.77046e-05 -0.000134147 -1.15614e-05 8.3335e-05 -4.8577e-05 -7.18451e-05 -0.000115484 5.74764e-05 0.00019094 0.000119856 -1.55309e-05 -5.68116e-05 -0.000125167 -0.000101616 0.000164332 -3.041e-05 4.51183e-05 0.000238941 -3.85524e-05 -0.000233313 -0.000127007 0.000109658 3.07119e-05 -7.87781e-06 -7.75303e-05 0.000138104 0.000324422 7.11076e-05 -0.000103248 -4.05551e-05 -0.000103505 -7.46644e-05 0.000121755 -7.11736e-05 1.59061e-05 -1.3619e-05 9.91798e-06 0.000103833 2.31742e-05 7.32087e-05 9.90379e-06 -7.97828e-05 -2.73978e-05 -6.34852e-05 6.64897e-06 2.88528e-05 -3.13698e-05 4.26738e-06 -6.98074e-05 -0.000105785 0.000120454 0.000239877 -0.000159806 0.000101613 2.97535e-05 0.000120239 0.000356412 -0.000305795 -0.000147678 -0.000204772 7.40185e-06 -0.000412183 -0.000119581 5.65362e-05 0.000165342 4.96078e-05 -0.000283885 8.44812e-05 -3.46532e-05 0.000187361 -7.28431e-05 2.3418e-05 -6.52135e-05 0.000148887 0.000242534 -9.63095e-05 9.29109e-05 2.05935e-06 4.11431e-05 -2.47534e-05 -0.000195399 -0.000104782 0.000114453 -0.000112695 -0.000123056 0.000162143 0.000153294 -5.16251e-05 7.8319e-05 0.00032942 -1.52237e-05 -0.000326402 -0.000122544 0.000162137 -2.6529e-05 -0.000110224 2.89001e-06 0.000184372 0.000450966 6.61085e-05 -0.000171345 3.2662e-05 2.06974e-05 -7.26222e-05 -7.92114e-05 -3.53766e-05 -1.91938e-05 6.14039e-05 -2.09328e-05 -1.79521e-06 3.07714e-05 0.000107821 3.00117e-06 -0.000117703 -7.28713e-05 -1.62941e-05 7.28842e-05 7.45202e-05 3.40877e-06 3.91525e-05 -0.000122929 -9.04465e-05 0.000190672 2.36637e-05 -4.50159e-05 6.39864e-07 -1.77311e-05 -4.20859e-05 -5.17723e-06 5.00778e-05 2.41444e-05 -2.26317e-05 -4.57662e-05 2.12058e-05 5.31042e-05 -3.32915e-05 -8.47528e-05 -1.37217e-05 1.8454e-05 2.98637e-05 1.86562e-05 1.44808e-05 -1.39395e-05 -4.16982e-05 9.71777e-06 2.9653e-07 -4.75687e-05 5.31119e-06 2.55936e-05 -8.53873e-07 -1.53866e-05 -5.10001e-06 -1.97346e-05 3.43247e-05 1.98767e-05 3.58508e-05 4.34316e-05 -3.14412e-05 -1.51947e-05 3.79626e-05 -1.15147e-05 -4.16073e-05 -3.44198e-05 -2.62217e-05 -2.85341e-05 4.32768e-05 4.14954e-05 -3.74964e-05 -0.000101668 -3.00017e-05 1.09047e-05 3.78315e-05 3.11517e-05 -3.24977e-05 3.67384e-05 2.41916e-05 -7.75935e-05 1.77865e-06 -7.90551e-06 -4.05229e-05 1.31679e-05 1.65948e-05 -2.18616e-06 3.55207e-06 1.94737e-05 3.29965e-05 2.23583e-05 -1.94308e-05 -3.09623e-05 9.92237e-06 6.24017e-05 2.12172e-06 3.47953e-05 7.97025e-06 1.81188e-05 0.00018274 -7.8887e-05 -0.000242578 -9.87785e-05 -4.95043e-05 0.000296165 9.55516e-05 0.000140719 -0.000307812 -0.00037905 8.11612e-05 -6.67713e-05 6.1966e-05 0.000363009 -5.07841e-05 0.000133982 0.000107889 -0.000102486 -3.55753e-05 -1.27175e-05 -4.45572e-05 0.000120015 0.000128453 7.44886e-05 -6.14885e-05 -6.85174e-05 -7.66369e-05 -7.84222e-05 6.82445e-06 5.57951e-06 1.49977e-05 0.000179864 0.000100707 -4.54273e-05 2.26306e-05 0.000155115 4.00763e-05 -3.83327e-06 9.1624e-06 2.8462e-05 -1.30129e-05 -7.56409e-05 -5.77437e-07 3.60291e-05 -4.54674e-05 -9.78059e-05 -4.97122e-05 2.3273e-06 -4.97274e-05 -9.30827e-05 2.82562e-05 5.84271e-05 -1.87832e-05 -1.59217e-05 -3.80031e-05 9.32686e-06 -1.19155e-05 3.80805e-05 -1.34025e-05 -2.63415e-05 1.93234e-05 -1.6547e-05 3.27015e-05 3.37767e-05 3.326e-05 -6.62365e-06 -2.75618e-06 2.73026e-05 2.18218e-05 3.90334e-05 -3.56502e-05 7.84471e-06 9.40322e-05 -8.65425e-06 -3.24512e-05 3.12479e-05 -2.96861e-05 2.60176e-05 -9.30316e-05 5.42578e-05 8.17682e-05 -6.1582e-06 6.18628e-05 3.47611e-05 -7.09982e-06 3.40289e-05 -6.53925e-06 -7.60455e-05 -5.94539e-05 8.14774e-06 -2.00674e-05 -9.44847e-06 -2.08671e-05 1.40332e-05 -1.54811e-05 -1.10821e-05 -2.47569e-06 -2.19659e-05 5.25729e-06 6.98146e-06 1.09541e-05 -1.8196e-05 1.0975e-05 1.50545e-05 9.22109e-06 3.20021e-05 2.48254e-05 1.08221e-05 4.74122e-05 -1.91583e-05 -4.22503e-05 3.1707e-05 -8.0591e-06 3.3832e-05 -4.062e-05 -6.97081e-06 3.82001e-05 -3.44568e-06 5.13207e-05 1.99733e-05 -2.7311e-05 9.56996e-06 3.25231e-05 2.57544e-05 -1.04821e-05 1.04882e-05 -1.46371e-05 -3.9441e-06 2.66295e-06 -3.06433e-06 -5.11208e-07 -1.49058e-05 1.63191e-05 -6.05232e-05 -2.77543e-05 2.4115e-05 5.75459e-06 -3.37141e-05 1.79754e-05 4.61394e-05 1.28364e-06 -3.04579e-05 1.61101e-05 1.84004e-05 0.000305757 3.59654e-05 0.000112654 0.000111823 7.62933e-05 0.000268223 -0.000333673 7.08099e-05 -9.7889e-05 -0.000210518 -0.000244066 -0.00031579 3.87998e-06 0.000204496 1.13064e-05 -0.00035526 -0.000219796 0.000120354 0.000141511 8.76412e-05 8.08944e-05 -2.91667e-05 -6.17456e-05 -7.05456e-05 -4.71316e-05 -1.80831e-05 -3.5122e-05 -7.03147e-05 -3.75161e-05 -0.00011692 -3.579e-05 6.87721e-05 -1.79007e-05 -4.11068e-05 -0.00011377 -1.67573e-05 2.02129e-05 -3.67616e-05 -3.93392e-05 1.70143e-05 6.18179e-06 -2.93895e-05 -5.6243e-05 3.10251e-05 6.53026e-05 4.07499e-05 0.000100119 5.74369e-05 -4.71638e-05 -3.86822e-05 -3.26396e-05 -2.13992e-05 -1.55696e-05 -5.62029e-05 -1.93876e-05 -6.54759e-07 8.12647e-06 -1.65984e-05 -5.0711e-07 -1.09975e-05 3.06164e-06 -3.7772e-05 -5.85529e-06 2.36018e-05 -2.22471e-05 -4.91881e-05 2.8216e-06 4.35977e-05 2.51899e-05 -2.23123e-05 -1.4845e-05 2.77444e-05 0.00013295 -0.000153662 -9.49401e-05 0.000134705 0.000103349 3.71238e-05 -0.000126715 0.000138102 9.13067e-05 7.28059e-05 -0.000197402 -1.9093e-05 -0.000133502 -7.52066e-05 -3.72665e-05 5.8139e-05 1.9847e-05 -0.000111425 8.78536e-05 -0.000135776 6.31138e-05 -2.9513e-05 -6.54721e-05 -6.5711e-05 -9.25675e-05 0.00025987 0.00026815 -4.69828e-05 -0.000104416 -0.000174353 0.000177985 4.77971e-05 -0.000184627 9.1373e-05 0.000157963 -0.000120923 0.000222631 -0.000309449 -0.000121001 6.25241e-05 1.90685e-05 -3.27796e-06 -0.000120535 0.000235809 0.000329917 7.27324e-05 -0.000167298 -0.00022565 -0.000129352 7.21457e-05 -0.000144449 5.00734e-05 0.00021036 -7.68433e-05 -2.49181e-05 -3.10188e-07 4.96299e-05 -7.51719e-05 -6.9754e-05 -1.76654e-05 0.000125281 -5.14878e-05 9.88623e-05 -0.000115589 3.13452e-05 -8.84881e-05 3.39094e-05 7.43214e-05 -0.000113067 -4.15016e-06 8.55874e-05 4.44485e-05 0.000376362 -0.000287275 -0.000100021 0.000391882 0.00022171 0.000483046 -8.02203e-05 -0.000400845 -0.000775187 -0.000138413 -0.000169552 0.000197529 -9.65486e-05 0.000147773 0.000419445 -0.000131774 -8.15249e-05 -3.83332e-05 0.00017027 -0.000192764 0.000277414 2.83693e-05 -0.000151213 0.000139794 0.000260264 0.000162219 -9.41979e-05 -0.000337712 8.38401e-05 0.00014989 -0.000127949 -4.2168e-05 5.45357e-05 -5.7857e-05 -0.000232888 0.000104564 0.000195615 -0.000281939 -0.00014464 -3.47774e-06 6.95881e-05 5.49439e-05 -0.000131414 0.000328198 0.000261106 3.80429e-05 -0.00027469 -0.000174947 -0.00019616 8.79752e-05 -6.26257e-05 8.20719e-05 0.00025308 -0.000128989 3.66126e-05 -0.000113984 7.8341e-07 -5.87335e-05 -4.54183e-05 -1.52354e-05 -5.17482e-05 0.000151193 0.00019732 -0.000128755 -9.6251e-05 -0.000126408 0.000142172 0.000119799 -0.000197024 4.24109e-05 0.000238296 -2.8831e-05 -0.000108154 0.00014005 -5.88161e-05 -2.10069e-05 1.41483e-05 -8.32922e-05 -7.57881e-06 -0.000106109 -1.75964e-05 -5.87047e-05 0.000111757 6.17622e-05 -3.39805e-05 2.82218e-05 9.34093e-05 5.26757e-05 -0.000131176 -4.98984e-05 -8.60076e-05 0.000143524 -6.4829e-07 -0.000102599 7.04636e-06 -4.29773e-05 6.0807e-05 -3.9528e-05 -0.000170031 -2.07171e-05 2.88261e-05 7.04133e-05 5.11554e-05 1.93486e-05 3.22711e-05 1.37006e-07 -2.01783e-05 -3.54564e-05 -0.000117232 6.11056e-05 4.24637e-05 -0.000123954 -6.07133e-05 -7.28703e-05 2.12519e-05 5.4682e-07 -4.25336e-05 1.36741e-05 0.000123843 0.000118788 5.87181e-05 1.58793e-05 7.1501e-06 2.2204e-05 -9.43109e-05 -2.23923e-05 -4.64158e-05 3.95591e-05 -8.9765e-06 -7.82104e-05 1.94046e-05 3.08982e-05 6.94188e-05 5.63049e-06 -8.54725e-05 4.72088e-05 -4.48986e-05 6.00349e-06 7.20219e-05 -1.58138e-05 2.10569e-05 1.85799e-05 3.62359e-05 3.20023e-05 0.00025772 -6.03879e-06 -3.63278e-05 4.60923e-05 -9.08817e-05 -8.37474e-05 -0.000166808 -0.000443623 -0.000287616 9.66268e-05 -0.000129642 4.4758e-08 -0.000117523 -2.63084e-05 -0.000284991 -5.1872e-05 5.97032e-05 0.000196543 0.000153807 6.98443e-05 3.38415e-05 2.25829e-05 -0.000111338 9.70318e-06 -3.60602e-05 3.10453e-05 1.87794e-05 -1.21318e-05 8.32814e-05 -0.000118966 -0.000102875 0.000155916 -0.000185398 -0.00020117 0.000154116 0.00016638 -0.000168535 0.000177591 0.000106997 -0.000185937 -0.000106899 -0.000113991 5.59421e-05 -0.000104775 1.4962e-05 0.00011885 0.000277719 6.97312e-05 -5.33913e-05 9.00851e-05 7.54964e-05 5.26346e-05 -0.000253269 -4.12694e-05 -7.7641e-05 0.000202718 0.00010863 -0.000161807 5.25457e-05 5.27397e-05 8.48029e-05 -8.27206e-05 -0.000195058 3.35578e-05 3.63453e-05 1.63016e-05 6.78494e-05 -6.25527e-05 1.28651e-05 1.29541e-05 4.68622e-06 3.55982e-05 -weightContainer_input_to_hidden_0_0_plasticities 7200 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -weightContainer_input_to_hidden_0_0_weights 7200 -0.024238 0.0831481 0.156692 0.088098 -0.117357 0.0654326 -0.127868 0.0123384 0.0963387 0.147643 0.0461988 0.0300506 -0.0926132 -0.123047 0.0515269 0.109034 0.282002 0.00276459 0.0769242 -0.178259 0.134785 0.0584939 -0.0207822 0.0884894 -0.281889 0.339503 -0.236911 0.0268272 0.0195066 -0.0398158 0.0633983 -0.0948887 0.101622 0.0427896 0.0654147 -0.0201197 0.0162434 -0.0388198 -0.0325715 -0.00638709 -0.0485469 0.13943 -0.134437 0.0600339 -0.0751849 0.158209 0.054945 -0.0535397 -0.0478103 -0.114309 -0.106045 0.00380376 0.290631 -0.0667401 -0.062905 -0.040305 0.0953553 -0.16666 0.0623389 0.0608631 -0.266438 0.172362 -0.101537 0.0246391 -0.0155682 -0.116084 0.0554795 -0.0790821 -0.00242237 0.170256 -0.00500894 0.0196135 -0.00856626 0.148979 -0.0147421 -0.0478496 -0.04072 0.0792305 0.0266857 0.165001 -0.228722 -0.0740218 -0.132372 -0.0275719 0.102505 -0.052908 0.129423 -0.467646 -0.346637 -0.0930085 -0.00830274 -0.0312964 0.208424 -0.196012 -0.168658 0.255865 -0.372061 0.443386 -0.371216 0.0985864 0.0746252 0.0133168 0.269279 -0.222878 0.154501 -0.111337 -0.211272 -0.0947324 0.0980318 -0.0649341 -0.0415206 0.081539 0.060061 0.141366 -0.249821 0.13896 0.00158639 0.164464 0.00717421 -0.0817531 -0.0331921 -0.201946 0.059302 0.232805 0.348103 -0.0643145 -0.067715 0.0593452 0.19236 -0.0608023 0.00999742 0.0898059 -0.43672 0.264335 -0.276477 0.0716894 0.0305134 -0.0237455 0.095437 -0.249389 0.137905 0.0388086 0.000506887 0.0115 0.0441528 -0.0631134 -0.10637 -0.219446 0.000275399 0.104984 -0.0154293 0.0456343 0.11074 -0.00589192 0.0748011 0.0478567 0.0471559 -0.0651854 -0.0215303 -0.0389655 0.0265106 -0.0775011 0.00229157 -0.11824 -0.0392629 0.0973311 0.0765289 0.0398239 -0.118903 0.00754683 0.131903 -0.108567 0.0386298 0.0982188 0.0422125 -0.155919 -0.0219562 0.187459 -0.00319048 -0.160286 0.186862 -0.106099 0.0421935 0.0145788 0.0354287 -0.0193222 0.0894451 0.144621 -0.0341902 -0.129587 -0.0370165 0.146898 0.0703497 -0.141085 -0.0749964 -0.0486298 -0.0335555 -0.189769 -0.166559 0.117215 0.0925124 0.123961 -0.0109449 -0.0873365 0.164419 0.0354077 0.0158984 -0.0354769 -0.0751876 -0.150888 -0.0389705 -0.0201987 0.0751914 0.00302783 0.0442398 0.0526447 0.23316 -0.123961 -0.0921809 -0.0272516 -0.174961 0.130758 -0.157733 -0.0928758 -0.00507385 -0.00199975 -0.0167253 -0.165767 -0.0822499 0.139355 0.0164261 0.0180308 -0.039593 0.114932 -0.121375 -0.10195 0.0206709 0.172376 0.00712142 0.0545062 -0.0778576 -0.0354972 -0.00620943 0.00205971 0.011526 0.0460488 0.0512683 0.171687 -0.0549667 -0.00291178 -0.0333187 0.180175 0.133409 0.124977 0.0480537 0.0752474 0.171897 -0.121168 0.107319 -0.061878 -0.0161923 -0.0353867 -0.0916533 -0.0188307 0.0236704 -0.0121815 0.0535039 -0.00879707 -0.0629193 -0.0468586 0.0851812 0.0223738 0.019961 0.059851 0.0604635 -0.100048 0.0237208 -0.0635694 -0.0254584 -0.0305908 -0.0153272 -0.0565349 0.0799136 -0.045804 -0.00545311 0.0055979 0.0954241 -0.067463 0.366713 0.280324 -0.0938689 -0.320981 -0.0638368 -0.0652613 0.0608536 0.0231677 -0.00820484 -0.0843875 0.130346 0.0551896 0.0165765 0.041611 -0.301735 0.00120671 0.0568084 -0.0609585 -0.0713654 0.0746309 -0.165904 -0.144355 0.216227 0.246629 0.268845 0.112863 0.169203 -0.0489627 -0.0577621 -0.0690545 -0.172051 0.0438924 -0.127301 -0.0218893 0.189088 -0.0599913 -0.0119863 0.108425 -0.242845 0.202654 0.318978 0.302832 -0.00129704 -0.105631 -0.246548 -0.215676 -0.244276 -0.039137 0.0237464 -0.133758 0.0281677 -0.0294849 0.176013 0.0494105 -0.0702797 -0.0321255 0.235073 0.202946 0.13015 -0.0251707 -0.10069 -0.322977 -0.0335861 0.0728559 -0.175303 -0.111213 0.157505 0.115741 0.0469247 -0.140108 -0.0297352 -0.124117 0.588742 0.110156 0.0821631 0.242432 -0.331429 -0.400222 -0.0078338 0.615668 0.344971 0.31025 -0.0978686 -0.242453 0.0698129 0.101094 0.0648747 -0.210506 0.0638267 -0.0112411 -0.120247 -0.181467 0.346315 0.127672 -0.726777 -0.366026 0.371432 0.490899 0.12721 -0.404653 -0.0890296 -0.0231745 0.0495622 -0.194307 -0.0585312 0.0711346 0.151125 -0.168525 0.233643 0.0504848 -0.0190115 -0.0692618 0.162402 -0.245185 -0.130757 -0.236218 0.087821 0.0177981 -0.040424 -0.0930957 0.0512351 0.0428793 -0.102606 0.107012 0.0111653 0.16178 -0.254363 0.115105 0.343697 -0.225066 -0.039833 -0.0874128 -0.321706 -0.417751 -0.00452597 0.411669 -0.0193136 -0.0904361 -0.0251434 0.160089 -0.00248408 -0.228877 -0.0553096 -0.0550377 -0.24633 0.017232 -0.0819724 -0.0343877 -0.184408 -0.106878 0.0319913 0.164859 0.137871 0.0121447 -0.110544 -0.17591 -0.162042 -0.00255422 -0.0494011 0.0209591 0.128395 -0.0548997 -0.238544 0.178973 0.180071 -0.0832519 -0.244698 -0.179079 -0.0248562 0.329708 0.205298 0.0593644 0.0935221 -0.00895935 -0.0378961 -0.0734575 -0.14069 -0.0587738 0.0804551 0.0485188 -0.14864 0.210962 -0.0763817 0.106472 0.111881 0.0548297 -0.0302409 0.104917 -0.0158781 -0.116635 0.0291957 0.036353 0.0881758 0.157817 0.216611 0.00651386 -0.0534016 -0.0577201 -0.193107 0.226657 0.121272 0.195167 0.226612 0.13517 -0.00862345 -0.091808 0.0199437 -0.0533296 -0.0330363 0.00999867 0.0888316 0.110222 0.00296701 -0.0158799 0.0581277 0.114276 0.0298602 0.386922 0.115208 0.0861395 -0.0307885 -0.157265 -0.112682 0.099203 0.00601897 -0.234063 -0.0647323 0.0137964 0.0305806 0.0801108 0.0709332 0.0258639 -0.0152458 -0.038069 -0.0481275 0.247041 -0.074413 0.126133 0.238719 0.2324 0.14052 -0.1523 -0.0473711 -0.190158 -0.196133 0.010963 0.0859141 0.0788597 0.0575578 -0.0520606 -0.00612423 0.0187522 -0.0276099 0.248538 -0.110616 0.104808 -0.114198 0.0996467 -0.232891 -0.032359 -0.0302989 0.00485466 0.0734009 0.0805478 0.0410229 0.104905 0.00106349 0.0830592 -0.0980939 0.0446764 -0.399278 0.181327 -0.346852 0.156575 0.367244 0.403913 0.0662146 -0.298671 -0.036637 -0.097938 -0.107505 0.0937143 0.013648 0.0495948 0.129375 0.103696 -0.0810295 -0.0070509 -0.077499 -0.00713937 0.359918 0.0320135 -0.0946247 -0.169921 0.145781 0.0961233 -0.162513 -0.123713 0.149906 0.105494 0.040244 -0.113942 -0.0824022 -0.117534 0.0478359 -0.0254023 0.284464 0.276999 -0.0284357 0.107224 -0.0548911 -0.0844645 0.254052 -0.113599 0.0331692 0.107645 0.0455201 -0.161176 0.0697245 0.0294018 -0.15256 0.0207951 -0.0626805 0.0117525 -0.122365 -0.0475792 -0.0949739 -0.0724207 0.052915 -0.0343631 0.138529 0.142146 -0.073044 -0.147292 0.000162088 -0.0129956 -0.00867623 -0.172071 0.179372 -0.0186394 0.137067 -0.00581786 -0.0354694 0.400251 -0.0600193 -0.249869 -0.269211 -0.107568 0.118211 -0.00186958 0.108692 0.0984119 -0.173087 0.0866795 0.031925 0.12353 -0.0611282 -0.0329764 -0.153244 0.0716542 0.0775352 -0.623792 -0.0912691 -0.00976556 0.329462 -0.336463 -0.0504377 0.149846 -0.0802974 -0.0670837 0.181895 0.120943 -0.122448 -0.0693468 0.173589 -0.149918 -0.019868 0.110232 -0.15523 0.039106 -0.384181 0.298043 0.21084 0.218739 0.00104856 -0.0682396 -0.0843486 0.162903 0.14623 0.111895 -0.0750203 -0.00414001 0.180735 -0.00829317 0.000838893 0.00894623 0.0229288 0.0725331 -0.0709031 -0.165814 0.0681159 0.108959 -0.0936259 -0.0469289 0.20539 0.0470994 -0.222804 -0.0927579 -0.0191309 0.129474 -0.0656783 0.147791 -0.10353 -0.129194 0.45096 0.12614 -0.154312 -0.294219 -0.304594 -0.0905819 -0.0313037 0.0466014 0.188525 -0.0616584 -0.0681954 0.0199963 -0.025839 -0.0957905 0.0765171 -0.0691832 -0.0316108 -0.0918585 0.125721 -0.252993 0.218178 -0.323196 0.175085 -0.395231 0.220759 0.0188161 0.0823609 -0.0771299 0.00686 -0.0429338 0.249766 -0.0614495 -0.0764658 0.0412098 -0.023395 -0.00365725 -0.89781 0.462511 0.0341432 -0.340697 0.125868 -0.201811 0.164183 -0.181523 -0.0937034 -0.145218 0.217185 -0.148456 0.165168 0.0480315 -0.0347093 0.0563788 0.0484874 0.0235814 -0.0878702 0.114313 -0.0458599 0.127747 0.0849883 -0.0494404 -0.0524839 -0.0866802 -0.0233556 -0.23232 0.0284776 -0.157009 -0.172731 -0.198698 0.188346 -0.116186 0.107772 -0.0390953 0.31784 -0.103165 0.0134395 0.0137509 -0.0216969 0.0963469 0.130231 0.109646 0.0108912 -0.0740266 -0.185806 0.00812022 -0.0993809 -0.0883866 0.0207792 0.0638841 -0.0255738 -0.0627268 0.170748 -0.13514 -0.357452 0.0525704 -0.151338 0.140761 -0.0775363 -0.0233547 -0.0837511 0.0193042 0.0207092 0.0476196 0.005573 0.0365868 -0.0442171 -0.0471757 -0.0133315 0.118219 -0.0617684 -0.257304 -0.253901 0.0378481 -0.192902 -0.0259089 -0.193322 -0.000617127 -0.110365 0.116059 -0.0623604 0.102738 -0.0124913 0.0126592 0.0392589 0.0743933 -0.0442269 0.057998 -0.574807 0.0623915 0.0714593 0.144265 0.298248 -0.0132642 0.0471096 0.00498736 0.0526886 0.0718506 0.0985395 -0.0231198 -0.0486939 0.0480024 0.0758911 -0.0573129 0.0746279 0.0306062 -0.201627 0.12919 0.0750555 0.251152 0.238256 0.0910866 0.0367766 -0.140406 -0.00187014 -0.0319176 0.121345 0.0398942 0.0205151 -0.00331213 0.0247593 -0.0134848 0.0527451 -0.00123081 0.0761651 0.0840602 0.0322083 0.159379 0.0800246 0.0245784 -0.099803 -0.200291 0.0857814 -0.0988517 0.188808 -0.133632 0.110131 -0.150878 0.0389279 -0.118825 0.0185862 -0.0938511 0.1046 0.0659034 0.175143 0.335107 0.271449 0.239296 0.196038 0.0104804 -0.0479451 0.0199175 -0.238528 -0.306193 -0.286303 -0.177233 -0.261668 -0.0919173 -0.000214449 0.0294447 -0.110077 -0.0559021 -0.163364 0.0823053 0.127263 0.0341123 0.0892356 -0.183569 -0.133113 -0.0170664 -0.137975 -0.0697119 -0.0231682 0.00952845 0.101845 0.0453667 -0.162597 -0.0699552 -0.187741 0.0776718 0.0183297 -0.012416 0.163488 0.21095 -0.0589849 0.0290422 0.0242462 0.0821638 -0.0583499 -0.0902166 -0.162956 0.00417101 -0.0909735 0.0683343 -0.00579114 0.1167 0.250434 0.173498 0.0897062 0.125591 -0.0562924 -0.0821127 -0.0288288 -0.108169 -0.0207397 -0.157973 -0.112642 -0.246757 -0.090299 -0.164901 0.0599672 0.0464611 0.0540327 -0.000793813 -0.1431 -0.332582 -0.33542 -0.355349 -0.252583 -0.375177 -0.241497 -0.317584 -0.0988317 0.0365095 0.162527 0.222032 0.266937 0.221831 0.144771 0.161035 0.0332971 0.0228562 0.227366 0.0135941 -0.200058 0.0928482 0.042835 0.150483 0.0571342 -0.21018 -0.0742853 0.0134514 -0.00714563 -0.113551 0.12425 -0.0466925 0.0863328 0.040779 -0.052799 0.0548529 -0.245863 0.335175 0.00316636 0.296424 0.329087 0.207206 0.108315 -0.145772 0.0833857 0.103894 0.0347765 -0.0156121 -0.168755 -0.0127698 -0.0553354 -0.0529411 -0.0862301 -0.0560175 -0.194563 -0.149686 0.0958659 -0.0180887 0.287869 -0.0233292 0.0756905 -0.120728 -0.0987482 -0.165926 -0.0146358 -0.129221 0.0591822 -0.0399636 -0.0196319 -0.0183073 0.00370414 0.0543926 -0.214447 0.284206 0.221558 0.0839868 0.161147 0.0491741 0.0688882 0.0492508 0.0209688 -0.0318319 -0.0119905 0.0435696 -0.00326126 -0.0777898 -0.0548172 0.115109 0.0977897 -0.0379416 -0.37609 0.0534254 -0.0210033 0.254764 0.151704 -0.0417505 -0.101555 0.0340679 0.0844496 0.0329509 -0.0286671 0.122794 0.0321034 -0.185482 0.167449 -0.079748 0.0766215 0.217559 0.117022 0.115866 0.0286581 0.204209 -0.034073 0.198037 -0.0437011 -0.0721075 -0.0859998 -0.0397244 0.00785915 -0.0110282 -0.0298051 0.0947298 -0.0328737 -0.0416322 -0.0689493 -0.0358416 0.15502 -0.106494 -0.209695 -0.483332 -0.282287 -0.16444 -0.0155049 0.142573 0.121438 -0.000717262 0.0789736 -0.0302178 0.0773526 0.0314766 -0.0927042 0.0312027 0.0865817 -0.149389 -0.877062 0.345902 -0.186323 -0.0294075 0.0486802 -0.0176892 -0.00202708 0.139805 0.104203 -0.00876829 -0.0298823 0.00701443 0.05965 -0.0336346 -0.0596571 0.0496323 0.0619121 0.00509505 -0.239968 0.279355 0.153091 0.375139 0.331141 -0.0661301 0.02094 -0.229585 -0.0838515 -0.033561 -0.0724115 -0.0883053 0.0721396 -0.0248273 -0.0274175 -0.0879868 -0.108795 -0.00932981 0.510212 -0.0389731 -0.00750731 -0.0774664 -0.179297 0.119783 0.0234812 -0.155223 0.026804 0.00824763 0.100114 0.0479733 0.0531191 0.0486741 0.154162 -0.0778476 0.0339301 -0.0954922 0.226656 0.217862 -0.0727609 0.185286 0.295848 -0.184288 -0.111082 -0.0630491 0.0877769 -0.00945723 -0.244429 -0.203672 -0.0464313 -0.258739 -0.100501 -0.127699 -0.231139 -0.216911 -0.0713769 0.234302 -0.346149 0.108975 0.214487 -0.137214 -0.00444387 -0.136979 -0.0790572 -0.0227218 -0.253024 0.0229847 0.192614 0.105316 0.102208 0.020922 -0.0104385 -0.0733168 -0.100559 0.0490276 0.0669721 0.14613 -0.142093 0.162865 0.252204 -0.196452 0.0271191 0.044067 -0.177132 -0.0541028 -0.245336 -0.0276417 0.00791751 0.00613267 -0.107844 -0.110019 0.256312 -0.121317 -0.171683 0.297778 0.163574 -0.155942 -0.203402 0.0197452 0.114733 -0.0547466 -0.0296394 -0.250832 0.282213 -0.134422 -0.0282324 0.17835 0.0633753 0.0960454 -0.381536 -0.262867 -0.513456 -0.108566 -0.107859 -0.182482 -0.33709 -0.159566 -0.0886036 0.23771 -0.0122844 0.164319 0.0352479 0.349512 0.0770061 0.0627991 0.0877133 0.356693 -0.649177 -0.138868 -0.22282 0.378489 0.378319 0.017756 0.229676 0.0957227 0.330766 0.534568 -0.10468 0.518083 -0.0176573 0.080148 0.124607 -0.11407 0.0680819 0.0269233 -0.317646 0.157259 -0.256984 -0.0583682 -0.117967 -0.0232311 -0.133577 0.115898 0.186762 -0.0102522 -0.00701095 0.114022 -0.37428 0.0141632 -0.231701 -0.144186 -0.0902303 -0.351809 -0.110171 0.341815 0.110514 0.273217 -0.145741 0.0421338 0.142556 -0.0240655 0.0520397 0.133976 -0.0574689 0.0121876 -0.22809 -0.0534381 0.0610279 -0.133389 -0.0324974 -0.0181874 0.119899 0.0307696 0.0267087 -0.053299 -0.0659223 0.0693893 0.00388578 0.00931885 -0.0129846 -0.0374135 -0.159361 -0.251404 -0.0177682 0.125616 -0.0408687 -0.102978 -0.18903 0.158083 -0.128775 0.0836136 -0.0257395 0.252861 0.198604 -0.171946 -0.177668 -0.00615935 0.106431 -0.0579232 0.0599856 -0.130727 -0.169122 -0.14258 0.0877172 0.225133 0.0934763 0.0517297 0.27826 0.0413213 -0.125204 0.064578 0.0278934 -0.0830492 -0.0565897 0.0268532 -0.0880178 -0.10686 -0.103821 0.0112467 0.0732129 0.0502277 -0.0891591 -0.248898 -0.170865 0.0886083 0.24703 0.0619775 -0.110599 -0.129802 0.0431855 -0.139315 -0.0541727 -0.125848 0.0540588 0.130214 -0.0445483 -0.167049 0.00226904 0.00832049 -0.0135072 -0.0295835 0.132839 0.0194889 -0.128418 0.516136 -0.023735 -0.0381176 -0.135319 0.0496575 0.00945731 0.106298 -0.112815 0.11097 -0.191482 0.0703283 0.0317941 0.10134 -0.0643303 -0.306428 -0.265885 0.140365 -0.530438 -0.506514 0.164201 -0.185502 -0.259344 0.0600271 -0.129889 0.198367 -0.057035 0.0743254 -0.0433704 -0.0748593 0.0349683 -0.0377938 -0.0209367 -0.0538798 -0.0512008 0.0429807 0.204056 -0.0376964 -0.299724 -0.068228 -0.0324318 -0.255758 0.0190302 0.102969 0.149169 -0.181934 0.035391 0.0247575 0.012695 0.152943 -0.234347 -0.21881 -0.222988 -0.0656424 0.129118 0.324198 -0.151182 0.0226718 0.050798 -0.0754103 0.0209436 -0.109186 0.029247 -0.109908 -0.140098 -0.187902 -0.0933169 0.186924 -0.0755407 -0.0415981 -0.159711 -0.0797964 0.694232 0.253598 -0.533514 -0.114819 -0.132495 -0.0123605 0.0359674 -0.0513083 0.0585394 -0.047001 -0.0960617 0.147711 -0.085924 0.00580715 0.0363797 0.000277488 0.0139967 -0.0222674 -0.0231078 -0.166618 0.00097242 -0.195454 0.235459 0.0374126 -0.012227 -0.126375 0.0471344 -0.314059 -0.184513 -0.0396354 0.153759 0.00116119 0.42545 0.146418 0.234497 0.0144031 0.177144 0.18549 -0.319468 0.00156475 -0.133733 0.0588021 0.133136 0.248991 -0.0612309 -0.0476031 -0.17811 0.0123184 0.00590625 0.176027 -0.0800362 0.0090133 -0.137798 0.141868 -0.674222 -0.191053 0.359529 0.315224 -0.03509 -0.0281697 0.132598 -0.23386 -0.0582587 0.07529 0.0551525 0.0416298 0.148227 -0.0642761 -0.11282 -0.114481 -0.194221 0.00487634 -0.496286 -0.0687881 0.741367 -0.0489026 -0.0133862 -0.0235388 0.00873436 -0.0596186 -0.00960799 -0.0757325 0.155022 0.104713 0.116108 0.0266001 -0.0305222 0.0558614 0.115283 -0.0442663 0.0741008 0.229441 0.486218 -0.451044 -0.266201 -0.169992 -0.0312682 -0.1062 -0.0100644 0.00903123 0.0798082 0.120344 -0.248306 -0.0248754 -0.0483819 -0.00731089 0.0380034 -0.0727823 0.545938 -0.0813682 -0.262278 0.228364 0.166432 0.0792646 -0.0657012 0.126805 -0.00407468 -0.103278 0.0954531 -0.0174983 0.0512513 -0.14106 0.0842332 -0.150103 0.115981 -0.0235967 -0.340845 -0.421529 0.068928 0.578989 0.243422 0.213307 0.00204067 0.0590502 0.310425 -0.222182 0.158104 -0.0953741 0.171308 -0.0893278 -0.200587 -0.0214176 0.0167229 -0.00618162 0.0543929 -0.257325 -0.313341 0.396814 0.287168 0.216504 0.0816621 -0.239837 -0.111641 0.167534 0.0290944 0.202438 -0.0513814 -0.0840328 0.03473 0.0625967 0.159915 0.120815 0.0141571 0.181864 0.177789 0.14759 -0.0511322 0.123987 0.0714574 -0.193833 -0.0074548 -0.348783 0.0913701 0.0993557 -0.191389 -0.0613623 0.0938027 0.0027341 0.10006 0.187833 0.0360087 -0.184373 0.0774311 0.421256 0.294871 0.205671 -0.143987 -0.233667 -0.0139916 -0.112008 0.0479594 0.0175781 0.228717 -0.100401 -0.120062 0.230771 0.228716 -0.106146 -0.0199438 -0.0288759 -0.0635058 -0.131495 0.0210488 0.138608 0.0157507 -0.22682 -0.0378673 -0.15705 0.0154595 0.0193348 0.103308 0.0287765 -0.0915438 0.00360683 -0.0589638 0.0469937 -0.423173 -0.0410451 -0.292472 0.349101 0.541122 0.0856671 0.0705769 0.102131 0.185039 -0.129154 -0.51279 0.0680818 -0.21611 0.179252 0.17031 -0.1355 -0.0530428 0.0637283 0.262424 0.064763 0.0336953 0.295578 0.131504 0.261225 -0.0450029 -0.522505 -0.160948 -0.292565 0.308783 -0.253913 -0.105378 0.14183 0.0101347 0.250136 -0.0743936 -0.00758074 0.427943 -0.123071 -0.00729987 0.19672 -0.202863 -0.0492088 0.0205579 -0.170229 -0.000121788 -0.027076 -0.0967094 0.073449 0.172839 -0.128196 -0.0194812 -0.0732399 -0.13424 -0.286658 -0.184497 0.065826 -0.306795 -0.0574908 0.0243192 0.0387761 -0.119609 -0.175867 -0.00289854 -0.371698 0.149077 -0.258427 0.0185824 0.0382651 -0.246851 0.110859 -0.0963393 0.0111769 0.113471 0.464166 0.465241 0.151715 -0.0182246 0.0373046 0.0273846 -0.0115642 0.0369683 -0.147568 -0.0315068 -0.100215 -0.336833 -0.211655 -0.180573 0.105157 0.0612095 0.0257308 -1.01085 -0.320639 -0.0847427 -0.330503 -0.193563 0.0391683 0.0664143 -0.0401303 0.444313 -0.0832009 -0.2306 0.2738 -0.0738526 -0.167662 0.203426 0.123616 -0.15294 -0.261679 -0.244881 -0.140675 0.153326 0.0603034 0.328974 0.0497627 0.187702 -0.0146561 -0.113677 -0.258171 0.0530143 -0.0635792 0.0985763 -0.000635326 -0.0552713 -0.0033738 0.0749584 0.191354 -0.00694705 -0.106831 -0.0256127 -0.0257453 -0.112335 -0.140874 0.0233805 0.172839 0.0556517 0.0231894 0.0522727 -0.0287152 -0.0650501 -0.0833001 -0.0657665 -0.0105148 0.0169963 -0.023152 -0.0699006 0.0568768 -0.555576 -0.577227 -0.628741 -0.507039 -0.192581 0.385591 0.249013 0.194629 0.213457 0.0349348 0.135501 0.036268 0.045629 -1.31985e-05 0.584106 -0.382301 1.08731 0.130907 -0.326389 -0.0914419 -0.422595 -0.479729 -0.253673 -0.114897 -0.0181818 0.223204 -0.175979 0.0853184 0.023208 -0.0423706 -0.028891 0.0670488 0.157491 -0.370643 0.0371154 0.710815 0.440047 0.840975 0.400389 0.0499925 0.101243 -0.357722 -0.30849 -0.180609 -0.284732 0.0388575 -0.00633045 0.0161891 0.117943 -0.181083 -0.377323 -0.269212 0.123541 -0.232331 -0.273004 -0.137823 -0.0283919 0.0440493 0.0711015 0.167137 0.0739107 -0.00494333 0.0243752 -0.186491 -0.126799 -0.0101467 -0.0685583 -0.22025 0.178701 0.153932 0.0510439 -0.141203 -0.0262942 -0.195179 -0.192786 -0.0695845 0.0414523 -0.0252566 -0.1522 -0.0180156 -0.164491 -0.0595736 -0.10024 -0.0871258 -0.098258 -0.0562009 0.0468179 -0.0552517 0.647738 -0.499684 -0.166974 -0.171914 -0.251733 0.0161008 -0.235867 0.00847337 0.00706891 -0.00331271 -0.00299924 -0.0338166 0.0409945 -0.151564 -0.0170833 -0.0283917 0.010349 -0.0707336 0.357097 -0.133442 0.210183 -0.0450635 0.000393728 -0.0744447 -0.00332304 -0.0317979 -0.0202789 -0.0574927 0.0198746 -0.0172648 0.0498621 -0.0863941 0.0307207 -0.0554309 0.0302759 -0.0203416 -0.441922 -0.034034 -0.0112972 -0.0380946 0.157469 -0.0470087 0.102682 -0.0575572 0.0407647 0.0332675 -0.0501978 0.00784559 0.0108887 -0.018894 -0.00516572 -0.0316335 0.00220007 -0.000349774 -0.218788 0.00439093 -0.12677 0.0951307 0.121337 0.0317339 -0.0654089 0.0539912 0.159557 0.0398743 0.153714 -0.0123725 -0.0183154 0.0608491 0.076366 0.0195074 -0.00408015 0.0805816 -0.605841 0.251621 0.109162 0.278335 0.24868 0.0369328 0.123438 -0.0269623 -0.0127454 0.0633571 0.0509826 0.0815508 -0.0112323 0.123853 -0.00757301 0.0196002 0.0252491 0.0645522 0.506327 -0.238212 0.0676912 -0.143826 -0.0740062 -0.0505544 -0.0654515 0.00847796 0.0273298 -0.00518086 0.013874 0.0122774 0.0127647 -0.0579879 -0.0157013 -0.0579825 -0.0261315 -0.0201964 0.798131 -0.0164766 -0.0231309 -0.198849 -0.122721 -0.0323859 -0.00496166 -0.00348791 0.0108625 -0.0473496 -0.0661195 -0.0511084 -0.0300391 0.0245797 0.00211133 0.00659337 0.0064156 -0.00632644 0.00513316 0.0847764 0.111202 0.126756 0.180457 -0.0387135 0.187516 -0.158308 0.0598278 0.0133507 0.133 -0.0312383 -0.164382 -0.106181 -0.117826 0.132647 0.00762435 0.147434 0.306396 0.261434 -0.12767 -0.276352 0.0103665 -0.211007 -0.106041 0.104837 0.0473103 0.126944 -0.0508836 -0.0895867 -0.0146479 0.0263911 -0.023885 0.0384882 0.0854025 0.0565903 0.249777 -0.111862 -0.158735 0.0468168 0.0842608 -0.104796 0.0964849 0.0986799 0.108269 0.0595543 -0.0424054 -0.0196979 0.0137548 -0.152129 -0.13127 -0.0856146 0.117157 -0.0106996 -0.22016 -0.0157277 -0.231685 0.0498426 0.082483 0.134296 0.0709351 0.267529 0.17784 -0.103307 -0.0228711 0.0318831 -0.0147726 -0.0737202 0.0267483 -0.136565 -0.0107117 0.0718384 -0.335219 0.040411 0.0347034 -0.0119342 -0.200974 0.304135 -0.0879287 0.131443 -0.0267247 0.0630792 -0.0459766 0.0426209 -0.163947 -0.14548 0.0618483 0.0213735 0.159698 0.112743 -0.974183 0.376075 -0.0425644 0.10422 -0.0894774 0.0855218 -0.0351145 -0.0209485 0.0660785 -0.0587439 0.0883196 0.0244079 -0.0619741 -0.0169052 0.0158919 0.0374794 0.145309 -0.0176948 0.0101959 0.13186 -0.129841 0.0976769 0.229837 -0.266894 0.0659126 0.00823888 0.232701 0.0104413 0.12039 -0.0997295 -0.229297 0.0497844 -0.034332 0.152438 0.0645699 0.0429688 0.15483 -0.166319 -0.164956 -0.218385 0.100682 -0.143678 -0.149193 0.0886365 0.193895 0.162091 -0.120635 -0.00486288 -0.0595731 -0.0615885 -0.0133664 0.0944259 0.0178611 0.0201577 -0.0713798 0.105261 -0.159743 0.116959 -0.113392 -0.00892442 0.0302805 -0.154701 -0.0743032 0.0670623 0.187788 0.152562 0.350758 -0.117338 -0.0232441 -0.0651483 -0.0690427 0.117778 0.158609 -0.121891 -0.175633 -0.0957448 -0.191135 -0.0428844 0.0244134 0.176302 -0.0201488 -0.228701 0.0658814 0.202516 0.300077 -0.16208 -0.308083 -0.0876494 0.127286 0.0360735 -0.166244 -0.00805838 -0.100302 0.329323 0.110102 0.105192 0.141772 -0.263418 0.147672 0.0367144 -0.0470765 -0.0305402 -0.113399 0.11033 0.0754458 0.0179201 0.0123168 0.0631464 0.178019 -0.0910919 0.0809741 -0.0403543 -0.0843598 0.133267 -0.0858885 -0.242485 -0.177163 0.0794046 0.0223306 -0.0323055 -0.172836 0.02821 -0.0705095 -0.0626693 -0.080249 0.0246209 0.498298 -0.0246713 -0.284876 -0.599181 -0.132138 0.419314 0.246546 -0.16407 -0.278896 -0.00198975 0.0244008 0.169219 -0.0426332 0.159518 -0.0435945 -0.0800095 -0.0265564 0.0699315 0.165779 0.0959997 -0.312989 -0.498674 0.26074 0.436475 0.27944 -0.383614 -0.153394 -0.00690337 0.239867 0.0312492 -0.0602188 -0.000606651 0.0684262 -0.141259 -0.0193251 0.135205 0.137471 0.150631 0.0300052 0.0441684 -0.282115 -0.536243 -0.245586 0.270881 0.286902 0.0658838 -0.147801 0.119941 -0.110393 0.0313528 -0.0787207 -0.061321 0.113353 -0.100945 0.502152 -0.158998 0.250777 0.239538 -0.2442 -0.485284 -0.478688 0.146174 0.0222339 0.026712 -0.06932 0.0613119 -0.0744498 -0.0729277 -0.0274306 -0.0187585 -0.0212793 -0.106062 0.246411 0.0815619 0.200273 0.133511 0.0697571 -0.210098 -0.348154 -0.206343 0.156102 0.217614 0.286583 0.0574319 -0.230062 0.165342 0.00744225 -0.179026 -0.0402819 -0.263144 -0.0327359 0.14941 -0.00911902 0.0979971 -0.116699 -0.273026 -0.15703 0.210287 0.0594695 -0.0550099 -0.0381631 0.00262171 -0.0238062 -0.107483 -0.0959004 0.107548 -0.076804 0.0587557 0.151414 0.0630485 -0.0800093 0.0447372 0.00186359 -0.0460519 -0.0589348 -0.0387255 0.134329 -0.0076888 -0.115644 -0.137218 -0.135412 0.0279537 -0.078109 -0.0592436 -0.0923389 -0.0448507 -0.265566 0.135547 -0.212457 0.0591987 0.0866288 -0.0878697 0.268413 0.268308 0.0163764 -0.0139885 0.0508451 -0.0341506 0.00792905 -0.0754503 0.0325324 0.16503 -0.0579411 0.122897 -0.216025 0.469053 0.158902 0.145884 -0.0999809 -0.360334 0.0256889 0.0621599 -0.381748 -0.14358 0.183169 0.298987 0.306703 -0.304609 -0.200195 0.00767054 -0.0651717 0.112072 0.692655 0.171517 -0.318177 -0.196619 -0.0807002 -0.166259 0.0185335 0.22669 0.141748 -0.0661658 -0.119561 -0.116589 0.0228387 -0.00746383 -0.0185802 0.0389472 0.28983 -0.0203499 0.131841 0.126047 0.146099 0.110875 -0.105803 -0.199472 -0.0461762 0.176694 -0.129689 0.062189 0.141218 -0.183148 -0.0646356 -0.0451281 0.113766 0.211371 0.00377784 -0.295344 -0.197576 0.261405 -0.188084 0.195176 0.0927691 -0.12629 0.165892 0.131168 0.196916 0.01202 0.0563768 -0.0429448 0.0062314 -0.0269453 0.0476194 0.0221539 -0.0707513 -0.00738128 -0.0149123 0.140291 -0.214325 0.294425 0.121547 0.295776 -0.00830103 0.179082 0.127415 0.149887 0.129057 0.11483 -0.178316 -0.00620377 -0.00626184 0.099295 -0.072034 0.042662 -0.137387 0.0290435 -0.0299751 0.123412 0.133036 0.156146 0.0640463 -0.030992 0.035989 -0.0315892 -0.0128495 0.138452 -0.0567846 0.0375338 -0.0842569 -0.0163649 -0.0837317 -0.0549161 0.148279 -0.0603713 0.00547592 0.147041 0.0948078 0.016326 0.0735484 0.0485767 0.0136147 0.154013 0.198828 0.118866 0.049541 -0.00133288 -0.0193642 0.0411211 0.0103611 -0.0539195 0.257841 0.0286607 0.18986 -0.0378361 -0.0763011 -0.0112912 0.0369525 0.0201886 -0.148201 -0.303223 0.100593 0.10084 0.0414247 0.0325322 -0.0942887 -0.0900252 -0.00103879 0.027242 -0.145273 -0.356506 -0.139289 -0.126973 -0.0687448 -0.0790193 -0.341077 -0.0258775 -0.00607998 0.0205505 0.0335373 0.0736514 -0.0546791 0.161878 0.0311126 0.0485519 -0.0376505 -0.0688151 -0.213707 0.203819 -0.117622 0.000473458 -0.003242 -0.0131685 -0.0809289 0.000485036 -0.00530658 -0.0616835 -0.21157 -0.164727 -0.174839 -0.0726749 -0.0656506 0.103005 0.0232492 -0.0892438 0.0736397 0.0723687 -0.0225891 0.305336 0.359042 0.247418 -0.129927 0.0894906 0.273383 0.20979 0.0233173 0.0926554 -0.114977 0.0658344 -0.0629331 0.0389857 0.0655794 0.0230177 -0.0336141 -0.188146 -0.0396072 -0.00484002 0.122321 0.191362 0.0725619 -0.039697 0.12929 0.0422301 0.0517358 -0.148405 -0.0971274 -0.155008 0.036063 0.00578603 -0.0973758 -0.164117 0.032674 -0.00155808 0.0915968 0.0466229 -0.086682 0.111808 -0.00800216 -0.145524 -0.218544 -0.0367262 0.0236805 -0.0201494 0.12856 0.166935 0.288578 0.0270399 -0.0594374 0.0233597 -0.0505762 -0.0750828 0.0303089 0.0817711 -0.0244834 0.154314 -0.103405 -0.0407434 0.026578 0.118821 0.100112 -0.182669 -0.104737 0.0186634 -0.0544434 -0.105355 0.129631 0.0582785 -0.209714 -0.205457 0.161842 0.0680213 0.0667555 -0.352357 -0.188487 -0.0671663 0.00805673 -0.225255 -0.0954198 0.0512034 -0.0302194 -0.0669237 0.0295943 0.0607582 0.0286105 0.150186 -0.206974 -0.3972 0.0141827 -0.114805 -0.134124 -0.0864526 0.117013 0.0859012 0.0181937 -0.0139992 0.146171 0.0337084 -0.211909 -0.029774 -0.0308754 -0.0201204 0.117195 0.103344 0.803816 0.561896 0.307871 0.286546 -0.164686 -0.278665 0.0525608 -0.121407 0.147928 0.0548279 -0.0365577 -0.0360091 0.021428 -0.0395969 0.0068324 -0.222437 -0.0305511 0.0358957 -0.344721 0.287988 0.0426794 0.383041 0.112086 -0.116901 -0.27269 -0.193061 0.147322 0.160352 0.456688 0.189882 -0.128238 -0.176205 -0.128273 -0.196301 -0.0631153 0.111 -0.216097 -0.0860495 0.0593879 -0.00782516 -0.0280071 -0.278475 -0.297004 -0.127333 0.0593735 -0.0715713 0.150556 0.0579815 0.0878492 -0.0137254 -0.0985724 -0.0835977 -0.0813621 0.00327585 -0.288627 -0.170233 0.162098 0.193195 0.044979 -0.0384532 -0.160121 -0.0438449 -0.129587 -0.0927847 -0.0023727 0.0245451 -0.0607467 -0.0572926 0.0282049 0.0254312 -0.0698632 0.0646109 0.0618674 -0.269396 0.0625829 -0.32987 -0.207722 -0.0356152 -0.230337 -0.0503929 -0.0335833 -0.117872 0.111952 0.152578 0.180183 0.302225 0.320623 0.0111159 -0.128088 -0.408731 0.187047 -0.306939 0.0360648 -0.262394 -0.406167 0.0765263 -0.0526761 -0.00783317 -0.131362 -0.0194942 -0.0143381 -0.153619 -0.105404 -0.00454133 0.118694 0.216066 0.101125 -0.0238309 0.161649 -0.336815 -0.241292 -0.170464 -0.289319 -0.116548 -0.0266807 -0.117236 0.105665 0.0140275 -0.164628 -0.159091 0.129728 0.182418 0.0101841 0.12865 0.0219859 -0.147646 -0.081037 -0.0763679 -0.0131999 -0.205483 0.105865 -0.0502311 0.195319 -0.105357 -0.0322315 -0.0036876 0.250249 0.185138 0.109095 0.134229 0.0688935 -0.146047 -0.203754 -0.114671 0.184001 -0.456702 -0.13482 -0.316432 -0.0312928 0.00698603 0.137665 0.0358432 -0.0651593 0.0558311 0.106579 0.00749095 -0.224842 -0.238135 -0.242381 -0.0721735 0.251204 0.485238 0.368938 -0.713186 -0.193174 -0.287712 -0.351227 -0.0159932 -0.140785 0.0174985 0.152954 -0.103304 -0.0559908 0.196454 0.0505816 -0.0324825 -0.358786 -0.0624277 -0.091983 0.221232 -0.183217 0.0482828 -0.182517 -0.172162 0.164212 -0.0232669 0.203097 0.117376 0.310116 -0.185916 -0.163921 -0.0976453 0.0691213 -0.13794 -0.229476 -0.0127778 -0.263915 -0.0415743 0.0301771 -0.280225 -0.276498 -0.143195 -0.196684 0.0297871 0.0374617 -0.0442477 0.250452 -0.0835495 0.04406 0.090295 0.109452 0.020481 -0.0297148 0.0473985 -0.00563129 -0.016259 -0.239415 -0.044407 -0.153863 -0.0910467 0.188196 0.25793 0.0217088 0.0372324 -0.22181 0.148135 0.15572 0.0593023 -0.0912922 0.0949748 0.00490421 0.0263703 -0.0911997 -0.0559765 -0.0561375 0.328638 -0.139444 0.102206 0.0538803 0.0804712 -0.07992 -0.0143253 0.0219362 0.0940451 -0.176061 -0.0892635 0.0180609 0.054922 -0.0602355 0.0269891 0.0239371 0.0667877 -0.0858524 0.058399 -0.122228 0.120392 0.387046 0.127217 -0.0629314 -0.365437 -0.126528 0.133673 -0.167943 0.072309 -0.00597585 0.120712 0.179951 -0.0370867 -0.0406462 -0.0802689 -0.0280939 0.0314294 -0.014054 -0.225735 -0.0482502 -0.11886 0.106768 0.0504694 0.0751365 -0.030301 0.0503517 0.0385138 -0.0690362 -0.187492 0.0301329 0.130332 -0.0617992 0.0750933 -0.376218 0.571037 0.294777 -0.0813501 -0.181476 -0.24999 -0.022106 0.00397737 0.0590586 -0.0534154 0.0271072 0.0355562 -0.0780782 0.0396398 0.117336 -0.117674 0.158735 0.103988 0.389192 -0.279643 -0.276823 -0.481229 0.0638163 0.0998049 0.311959 0.318558 -0.0185298 -0.310204 0.0113575 0.0334291 -0.0300096 -0.0559768 0.194648 0.0899677 -0.0761535 0.136001 0.0250883 -0.0757457 -0.167817 0.0454937 0.204415 0.0990877 0.0786257 0.0258433 0.0682242 0.0928803 0.0122114 -0.161669 -0.0371185 0.0143105 0.0309096 0.168915 0.147219 -0.0814893 -0.61337 0.342097 0.174318 -0.015576 0.0499082 -0.0411192 0.101671 -0.0972296 -0.0644964 0.167379 -0.136577 0.0173226 -0.0824653 -0.053072 -0.0501974 -0.0787873 0.0517932 0.100107 0.0482925 0.0391849 0.143271 -0.162705 -0.178867 -0.000766868 -0.0817972 0.112899 0.00298917 -0.0183514 0.0596742 0.00676655 -0.025325 -0.0403513 0.178444 -0.0357615 -0.0188541 -0.0617353 0.126001 -0.0196404 0.0694711 0.20675 -0.393778 0.216215 -0.00268804 -0.0384649 0.335175 -0.491807 0.266423 -0.232426 0.162973 -0.0936664 0.0909089 0.0431594 0.171289 -0.097565 -0.341506 -0.0660495 -0.133134 0.0150274 -0.436267 0.175179 -0.124054 -0.0618332 0.148159 -0.0848194 0.115363 -0.0831405 0.17336 0.00967097 -0.135311 -0.103788 0.0121435 0.0709118 0.206447 -0.0104296 0.221109 0.147015 -0.0540772 -0.0248004 -0.103533 -0.179418 0.0706914 -0.033148 0.0345904 -0.000966819 0.126249 -0.0564014 0.061789 -0.0836859 0.00649576 0.0054537 -0.0751254 0.230368 0.168781 -0.150791 -0.0513894 0.148243 -0.0747798 0.04198 0.11581 -0.019515 0.155447 -0.169027 0.215086 -0.130319 0.0543228 -0.138301 0.0976121 0.0196869 -0.0921582 0.352331 0.187571 0.335896 -0.643042 -0.0343998 -0.296974 -0.170323 0.531932 -0.22589 0.591167 -0.435497 0.203167 -0.223886 -0.0761574 -0.174392 -0.0104626 0.173526 -0.178606 0.0334193 -0.0905539 0.0914296 -0.194953 0.270186 -0.105547 -0.0221951 0.0521352 -0.00860182 0.0455863 -0.198023 0.107546 0.0492892 -0.0131295 -0.0587969 -0.121512 -0.00414923 0.388942 0.0499602 0.328018 0.0605106 -0.235918 -0.0185974 -0.222663 -0.149602 0.32873 -0.0187216 0.267927 -0.281322 0.041857 0.0331867 0.048955 -0.0825005 -0.131616 -0.0312951 0.0999468 -0.00450746 0.162791 0.0344254 -0.0547923 -0.0374789 -0.117899 -0.0692937 -0.102684 0.0664844 -0.0127431 -0.022053 -0.00304965 -0.0130777 -0.0376987 -0.0488238 0.0368022 -0.0166646 0.39264 0.0964916 0.0877005 0.0300813 -0.0903715 -0.0213464 -0.0108616 -0.062805 0.0469093 -0.0179769 -0.00075409 -0.0366806 -0.0236476 0.0439536 0.0150912 0.0611322 0.0426701 0.0466895 0.0239238 -0.116985 -0.0249856 -0.0189068 -0.00189994 -0.0211352 0.0898603 0.0314812 0.0891495 -0.0205849 0.096541 0.0487188 0.0691097 0.00970126 0.0400176 0.0151607 -0.0494678 0.0138437 0.00247811 -0.0399653 0.0444036 -0.0683233 0.0132025 -0.0349287 0.0640359 0.0925876 -0.00346191 -0.0290051 -0.00520027 0.0107336 0.0364858 -0.0294481 -0.0524256 -0.0972591 -0.0282102 -0.0762165 0.175258 -0.133173 -0.0170167 -0.0373337 -0.132648 -0.123664 -0.0400552 -0.0175484 -0.0313768 -0.091539 -0.0325589 -0.0276535 -0.0291243 -0.048734 -0.00204659 -0.0837145 -0.0143172 -0.0254641 -0.0157401 -0.0510966 0.0218516 -0.0367572 -0.126105 -0.0990673 -0.0601547 -0.0464409 -0.0218409 0.0172716 -0.0372226 -0.0349322 0.00611188 -0.00650958 0.0107772 -0.00742059 -0.00895961 -0.0269014 0.113815 0.0944881 -0.0229815 0.0668634 0.039089 -0.0210079 0.0759928 -0.0334926 -0.0246132 -0.0537328 -0.0440075 -0.0295821 0.00739142 -0.0487333 0.0250794 -0.00561746 0.0014074 0.00461801 -0.179729 -0.0588758 -0.00158605 -0.00876918 0.0168003 -0.0273115 -0.0212363 -0.00162431 0.0223185 0.0290998 0.0141904 0.0139179 0.0411099 -0.0074382 0.0383637 -0.00466698 -0.0122213 -0.0147104 0.312567 0.0178622 0.126022 0.110228 -0.156891 -0.237366 0.0297628 0.0390416 -0.0952678 -0.0215535 -0.186778 0.00260428 0.0241997 0.0173268 0.0256534 -0.0578269 0.0712924 -0.0127166 0.203557 -0.052284 -0.102835 0.224419 0.045233 -0.0759402 -0.228385 -0.0917024 0.0166029 -0.11588 0.0369916 0.0926309 0.149679 0.00996919 0.0856976 0.0903764 0.106641 -0.139955 0.00499009 -0.0878177 -0.0468987 -0.0584263 -0.155313 0.115119 0.188652 -0.0748055 0.0492947 0.105332 0.075273 -0.00809269 0.0594039 0.0514428 -0.0667542 0.000263121 0.108999 0.0125297 0.106604 -0.00808864 -0.0182403 0.0185737 0.086653 -0.0381906 -0.0785727 0.0227547 0.00656579 0.0117066 0.0196557 0.0161769 -0.183914 -0.145464 -0.141849 -0.0698373 -0.0731759 -0.00955521 0.294896 -0.129036 -0.0987547 -0.0187095 0.0843862 0.0039861 -0.267534 0.0270568 0.118507 -0.0669385 0.165667 0.166016 -0.310829 0.0304865 0.126015 -0.123854 -0.235573 0.220973 0.837017 0.0863444 -0.163148 -0.408987 -0.236586 -0.274841 -0.272336 0.00434433 0.0699029 -0.105955 -0.0433364 0.142435 -0.187149 -0.129488 0.188203 -0.0715323 -0.145138 0.0318052 0.254562 0.139239 -0.250522 -0.132662 -0.0300058 0.14818 0.233213 -0.074085 0.0585349 0.2804 0.048981 -0.228023 0.138604 0.0574621 -0.165885 0.0880044 0.0434044 -0.125056 0.381677 -0.0713957 0.1092 -0.176342 -0.240929 -0.00370018 0.241969 -0.165889 -0.0804317 0.15973 -0.0292384 -0.141206 0.0211153 -0.114788 -0.204466 -0.0170963 -0.00911315 -0.0267745 0.569355 0.115334 0.342378 0.00447226 -0.0748735 -0.139848 0.148674 -0.110073 -0.244053 -0.142796 -0.11235 -0.0441801 -0.116321 -0.239269 0.0545984 -0.134028 -0.0451491 0.0809848 -0.544522 -0.0362521 0.0239713 0.161623 0.153898 0.135923 0.0540306 0.0119716 -0.18436 0.0255573 -0.0394318 -0.00444535 -0.0690799 0.0623169 0.0906459 -0.0556715 -0.115547 -0.0243085 0.161999 0.0676146 0.0621123 0.131117 0.211149 -0.00700326 0.0917189 -0.153143 -0.139689 -0.116551 -0.0496194 0.0486905 -0.0194863 -0.0353216 0.120309 -0.0077151 0.00102057 -0.111272 -0.134252 -0.0917866 -0.166886 0.0953524 0.170224 0.125437 0.0468254 0.0685908 0.00446458 0.0155124 0.0774717 0.0527132 0.00365326 -0.051306 -0.00940316 -0.0540456 0.0094608 -0.0252058 0.283566 0.0244438 0.131936 0.146744 -0.0720758 0.0713354 0.142237 0.0271652 -0.201666 0.0446226 0.0161002 0.0423159 -0.151282 -0.00200867 0.0916789 0.034383 -0.0708367 -0.0899668 -0.153994 -0.00438925 0.0370434 0.0349368 -0.0175262 0.0618484 -0.043718 -0.0164531 -0.069791 -0.104572 0.0596929 0.102478 -0.0773961 -0.0305246 0.00660834 -0.0123642 -0.0420706 -0.0295025 -0.0224763 0.00734526 0.0260345 0.0934902 -0.097924 0.0295236 -0.0437551 -0.0330113 0.0182991 -0.0037314 0.0342614 0.133083 0.0172641 0.0324415 -0.0413209 0.123247 -0.00240345 -0.0315566 -0.13889 0.028054 0.0969322 -0.0527096 -0.0577664 -0.149321 -0.129456 0.0586488 0.0494739 0.0993518 -0.0552739 0.00675513 0.0267491 0.0183901 -0.0532495 -0.0279832 0.0202917 0.0463063 -0.168432 0.0543619 -0.189591 -0.100393 0.0789489 -0.00408454 -0.0259166 0.0116912 0.112501 0.0549982 0.087612 -0.0989549 -0.0141358 0.101813 0.196748 0.0495617 0.107726 -0.0780873 0.190949 0.330772 0.158446 -0.321104 0.123276 -0.122447 0.0150361 0.114445 -0.297381 -0.127064 0.0869791 -0.0686221 -0.0438053 0.15266 0.00104262 -0.147304 0.0436372 0.0376962 0.214894 0.0755083 0.163423 -0.0559403 0.0135125 -0.269308 0.16747 -0.0635882 0.167059 -0.253434 0.204592 -0.148289 0.182338 -0.256631 0.00674426 -0.104163 -0.0414875 -0.134197 -0.120559 -0.0206157 -0.0581666 0.053164 -0.0346616 -0.134809 -0.0011038 -0.0432978 0.0202431 -0.0531003 0.0501928 -0.0749746 0.120018 -0.161085 -0.0174228 0.0707048 -0.0273773 0.05217 -0.0362473 0.0449666 0.0711924 0.0312465 0.119751 0.0230409 0.0626034 0.0543431 0.0545849 -0.007767 -0.00396528 0.0877578 0.0311001 -0.0844305 0.129219 -0.0698585 0.0542236 -0.0286556 -0.504615 -0.0407948 -0.0404361 0.0446157 0.208578 -0.164763 -0.0388199 -0.0860717 0.0241557 0.0888214 -0.0485491 0.0923382 -0.114415 -0.223021 -0.0685509 0.0198727 0.0104284 -0.0436651 -0.451473 0.060738 -0.130895 0.0756926 0.0375304 0.110592 0.0674053 0.0603931 0.0596321 0.0415275 0.0788618 0.188907 -0.0395103 0.0489059 -0.0921771 -0.0107375 -0.047137 0.00466637 0.0122086 0.107983 -0.142248 -0.162261 -0.00781544 -0.124009 0.00804381 0.115133 -0.0200123 -0.0541566 -0.00981601 0.0456828 -0.00748708 -0.0276934 -0.0152454 0.00376821 -0.0157506 -0.018966 0.0707072 -0.0356542 0.147876 -0.267135 -0.0794781 -0.0575371 0.101789 -0.0224188 -0.10755 -0.0403375 0.163606 0.0209735 0.239321 0.0427998 -0.114137 -0.0568678 0.0841091 -0.134065 0.59145 -0.132526 0.171351 0.187468 0.21299 0.398067 0.303934 0.165592 0.0778583 -0.106324 0.0782205 -0.142444 -0.272373 0.00256554 -0.419944 -0.143177 -0.0708987 -0.296145 -0.207039 0.0479508 -0.123951 -0.368385 -0.119659 -0.263093 -0.0856879 0.0242959 0.0196109 -0.00856245 0.243874 0.0299072 0.0966033 -0.0259764 0.166621 0.104281 0.107547 0.0834185 0.445716 0.258107 0.249727 0.482885 -0.0294553 0.0739953 -0.00379493 0.15699 0.0245101 -0.0902078 -0.322793 -0.0366849 -0.0338425 -0.0523436 -0.0335717 0.143275 0.095793 -0.0220207 0.825289 -0.318602 0.286817 -0.353292 0.240738 -0.10741 -0.0396391 -0.164031 -0.23532 -0.248577 0.0172911 -0.330731 0.118503 -0.147636 -0.39545 -0.261319 -0.0792707 0.0711148 -0.557208 0.502959 -0.139846 -0.165131 -0.226046 0.181162 -0.152325 -0.0799276 -0.135124 -0.280172 0.19739 -0.151046 -0.126089 0.105019 0.248187 0.338117 0.0625087 0.364646 -0.490017 0.0730616 -0.278814 -0.103576 0.16258 -0.0638771 -0.0757354 0.0443474 0.118744 -0.120741 0.294617 -0.172937 -0.123015 0.00831951 0.123504 0.142973 -0.0430393 -0.0346843 -0.0645523 -0.093476 -0.231601 -0.152871 -0.12909 -0.0140783 0.111827 -0.0762277 -0.122217 0.217753 0.224589 0.0498481 0.197054 0.200592 0.352276 0.318803 -0.156136 0.0376243 -0.524929 -0.342185 -0.0647748 0.12406 0.129985 -0.314325 0.103765 -0.00859581 -0.127811 0.0771023 0.0180316 -0.121444 -0.0742671 0.0107682 0.111646 0.0510689 0.00978137 -0.0329803 -0.220256 -0.122328 0.227085 -0.116568 -0.226191 0.0193129 -0.313416 0.186784 -0.318257 -0.0121528 -0.207466 -0.0955595 0.00884221 0.202488 0.0531668 -0.0400112 0.0366807 0.0826333 -0.416492 -0.0288337 -0.362233 0.275096 0.125542 0.421131 0.000574831 0.0592216 -0.0731219 -0.292521 -0.0549936 0.152151 -0.221417 0.150992 -0.0863691 -0.0957123 0.0480574 0.110457 0.191792 0.052726 0.0702266 0.058743 0.16713 -0.241277 -0.112952 -0.0502574 0.164467 -0.164856 -0.0462388 -0.166831 -0.00321226 0.0991217 -0.00751651 0.0242796 0.149166 0.0428854 -0.805713 0.544252 -0.596595 0.303311 -0.0413322 0.123146 0.0659661 -0.0814185 0.133232 -0.172062 -0.0282099 0.122829 -0.0615019 0.120799 -0.0799832 -0.0634344 0.233743 0.0968285 -0.561942 0.283782 -0.0401467 -0.00299908 0.191179 -0.196094 0.225201 -0.150606 0.232043 -0.122561 -0.00331921 -0.0921037 0.0943569 0.267752 0.136366 0.172996 -0.0569499 -0.0515545 -0.00594715 0.176424 0.0381194 0.255666 -0.0916532 0.269209 -0.0767338 0.149898 -0.121861 0.0125024 -0.0173862 0.153752 -0.0541249 0.110712 0.00980171 0.0182749 0.00939194 0.0860998 -0.297702 0.276901 -0.28238 0.232447 -0.196197 0.183184 -0.00200459 0.0895679 -0.00614255 0.11818 -0.0100065 0.124408 -0.0341187 -0.000932673 -0.0100305 -0.00555827 0.0160597 0.0492126 0.0503603 -0.518485 0.162463 -0.0430098 -0.241385 0.262697 0.02297 0.0558154 -0.0194154 0.0905861 0.108192 -0.00960369 -0.090676 0.135216 0.00939703 -0.00182408 -0.190157 0.0271535 -0.562319 0.00374465 0.324932 0.164486 0.0130191 0.299129 0.0501195 -0.0465597 -0.154144 -0.0834853 -0.000348987 0.0772778 -0.0964293 0.0342438 0.0232629 -0.000310488 0.0169615 0.0310004 -0.0583186 -0.242866 0.261936 0.177315 0.201215 -0.0351545 -0.0438803 0.00560521 0.155601 0.144336 -0.15311 -0.0502384 -0.233354 -0.00868896 0.0870168 0.0457729 0.00963087 -0.0241303 0.208625 0.325793 0.0744343 0.111275 0.12058 0.106705 0.072526 -0.1003 0.0172442 -0.136374 -0.294736 -0.115813 -0.128693 0.12102 0.0761149 0.00869704 -0.0419123 -0.0712093 0.541092 -0.628957 0.931951 -0.258289 0.153377 -0.0136785 0.141568 -0.0637993 0.0658593 -0.0844052 0.0929996 0.153964 -0.00823791 0.0918472 -0.00302266 -0.0962602 0.230585 -0.153886 0.0483773 -0.536375 0.797212 -0.00148872 0.000771769 0.0177346 0.075474 -0.021811 -0.0376043 -0.0282791 -0.000794901 0.102299 -0.00367195 0.153457 0.0778651 0.0169971 0.0391536 0.13005 -0.36106 -0.177097 0.150376 -0.0653458 -0.202681 -0.0726052 0.0493469 -0.0347877 0.191937 -0.0611839 0.0276016 0.311417 0.0940558 0.00189498 -0.104033 0.0950375 0.0927085 -0.00920851 -0.230884 -0.519349 0.298746 -0.146745 -0.0970489 -0.0834371 0.0944531 0.085114 0.0509687 0.0875537 -0.0327689 0.0259859 0.0627039 -0.0111399 0.00719268 -0.0866638 -0.0188094 0.0937511 0.0356559 0.0918933 -0.0825765 0.296126 -0.13807 -0.0130523 0.0136769 -0.336564 0.158495 -0.220176 0.338972 -0.258141 0.217578 0.0018225 -0.181271 0.0447486 -0.155401 0.143873 0.0542325 -0.158148 -0.329486 0.0522569 0.100439 -0.154111 0.326404 -0.0149051 0.307784 -0.146219 0.0413436 0.109012 -0.103157 -0.0412715 -0.0456008 0.214235 -0.0521757 -0.155157 0.0851777 0.0428077 -0.20484 -0.0512946 -0.236217 0.10126 0.287455 0.138663 0.284989 -0.0407187 0.0308831 -0.120223 -0.0725222 0.0341242 -0.0346155 0.184557 -0.169207 0.0571814 0.227951 0.071492 0.198208 -0.114273 0.136063 -0.150258 -0.136864 0.141355 -0.304636 0.0600085 -0.298 0.0663748 -0.131526 -0.108774 0.0173536 -0.059313 0.0748895 0.116427 0.185801 0.0139949 0.0557756 -0.331806 0.197639 -0.300105 -0.222516 0.325102 -0.467979 0.308576 -0.470986 0.130797 -0.186564 -0.0470568 0.00753617 -0.200152 0.113976 -0.00693871 -0.110057 -0.154441 -0.280224 -0.258285 -0.179729 0.238251 -0.373983 0.373178 -0.0866635 0.193979 -0.0874048 -0.132024 0.0180042 -0.109304 0.00784317 -0.203449 0.0251231 -0.123062 0.0935465 0.143563 -0.266013 0.146286 -0.224211 0.198431 0.234609 -0.000290014 0.31794 -0.34844 0.0562523 -0.156822 -0.14084 0.109322 -0.0556877 0.0104185 -0.180729 0.223837 0.150158 0.181874 0.37034 0.0507387 0.125452 -0.111138 -0.00564298 -0.198089 -0.158956 -0.111146 -0.117935 -0.0475872 -0.053349 0.110513 -0.00588794 0.0430358 -0.155502 0.0821507 -0.218504 0.116958 0.294799 0.0770573 0.0224202 -0.168873 -0.0467219 -0.100717 -0.261949 -0.137456 0.042182 -0.136605 0.0122804 -0.0614511 0.027883 0.0913899 -0.0525449 -0.164916 -0.299473 -0.31574 -0.0118593 -0.0457259 0.0675336 0.03555 -0.270044 0.290746 0.183267 0.163714 0.188319 -0.0260251 0.10856 0.047408 -0.0151552 -0.166567 -0.0576337 0.025377 0.0856706 0.299349 0.205008 0.0454866 0.206102 0.100474 0.0844876 0.0509666 0.000752418 -0.0675357 0.0156663 -0.0432232 0.0420222 -0.014371 0.09922 -0.151072 0.0381514 -0.0646461 0.157684 -0.298647 -0.0708436 -0.000173108 -0.147823 -0.0258458 0.227264 -0.0340875 -0.0514811 0.390189 0.013694 -0.114941 -0.088326 0.0280318 -0.0465034 -0.0308882 -0.0355335 0.0741518 0.575374 -0.0288563 0.0532454 -0.00108795 0.0862796 0.286044 -0.173987 -0.0134526 0.0801591 0.0749838 -0.204796 0.0408839 -0.184418 -0.0475712 0.0434631 0.0536234 -0.106511 -0.0515272 1.15508 0.741339 0.353123 0.272812 -0.081578 -0.634086 0.0413221 -0.24029 0.314644 -0.185174 0.0324115 -0.154334 -0.151204 -0.0684484 0.0545255 0.0335756 -0.0271374 -0.0476512 -0.539413 -0.151526 -0.201007 -0.0374052 -0.0563368 0.231335 -0.174705 0.0878734 -0.0628054 0.0973614 0.0370528 0.0731248 -0.217688 0.0334329 -0.0363217 0.176878 0.132215 0.1056 -0.216521 0.00100411 0.149794 -0.186651 -0.0610915 0.477957 0.0710678 0.119094 -0.112335 -0.191719 -0.206181 0.0439583 -0.136822 -0.170091 0.213481 0.229575 -0.0107079 -0.0300039 -0.0735076 0.19939 -0.0196926 0.209383 0.0670265 -0.0144627 -0.139061 0.00110933 -0.0670106 -0.0295996 0.0391765 0.0611205 -0.0422732 0.00373045 0.00776601 -0.0722637 -0.0414421 0.0321749 0.00408789 -0.012116 -0.0920461 0.112503 0.00333588 0.0230601 -0.00928017 0.0391064 0.00839114 -0.116377 -0.00686855 -0.10857 -0.0314397 0.0502427 -0.0363783 0.0172646 0.0751795 -0.0435952 0.0565889 -0.0670986 -0.146668 0.11446 -0.00683086 0.237752 -0.126146 0.0872486 0.00170062 -0.0242106 -0.0825325 -0.0754243 -0.0880368 0.0137197 -0.0201357 0.0679326 0.134731 0.0582976 -0.0811129 0.0271671 -0.034956 -0.182738 0.0501442 0.1214 0.254534 0.0092504 0.066143 0.130549 -0.0845733 -0.00447458 0.018546 -0.0485039 0.0180187 -0.0124464 -0.0240386 0.0207111 -0.316123 0.0589742 -0.13793 -0.0716833 -0.142851 0.0347254 -0.00523805 -0.0281389 -0.0897305 -0.0926704 -0.0578454 -0.0758919 -0.0904668 -0.0284361 -0.115334 -0.033062 0.0275913 -0.0465096 -0.0176048 0.0388559 -0.0208405 -0.00190538 -0.0592707 0.0510554 0.00656715 0.0760651 0.0830014 0.00197137 0.0743302 -0.0176104 -0.00929492 0.0602265 -0.00936344 -0.00552712 0.0536554 -0.0266826 -0.0191343 0.211458 -0.167108 0.441023 0.0403327 0.16872 -0.0807284 -0.00253435 -0.0523338 -0.0706856 -0.143071 0.0674584 -0.15348 -3.90066e-05 0.0817589 0.0567258 0.0844296 -0.0405935 0.124106 -0.096544 -0.0372987 0.0212435 0.0930455 0.0115567 -0.160748 0.0328032 0.0817004 0.0448361 0.00910748 0.00946978 -0.000570596 -0.0164439 -0.00372486 -0.0415296 0.00846501 -0.061918 -0.332343 -0.19554 -0.180896 -0.146199 0.191245 0.0571907 0.0269391 0.0217833 0.146009 0.215954 0.0787621 0.0187443 0.0135049 -0.108423 -0.0667623 -0.0350658 0.0615908 0.00165448 -0.560697 0.0523437 -0.486411 -0.102616 -0.0289398 0.151621 -0.0323319 -0.0650587 0.0304769 0.1586 0.171155 0.0913186 -0.075223 -0.0335123 -0.0602471 0.0299264 -0.0358479 -0.0148394 -0.0762482 0.420645 -0.210745 -0.221062 -0.0289429 -0.17875 0.175949 0.0760275 -0.0320505 -0.329723 -0.0402851 -0.139092 0.0591384 -0.0738161 -0.0661102 -0.0975614 0.00188609 -0.0637518 0.395852 -0.0466833 0.0211632 0.00101845 -0.184471 -0.19254 -0.167087 0.0590608 -0.0157031 0.0257138 0.0145273 -0.13556 0.0657993 0.0542869 -0.0543365 -0.0248384 -0.000486939 -0.0272606 0.36242 0.110792 0.09414 0.143442 0.028205 0.196883 0.0227753 -0.116107 -0.0620009 -0.0164984 -0.0140813 0.00950729 0.0754193 0.0027037 0.103661 0.00213206 -0.0303398 -0.00742899 0.698834 -0.306998 0.0885804 -0.0430881 0.102577 0.180787 -1.77445e-05 -0.11477 0.04719 -0.0189978 0.00760255 -0.0382022 0.00478847 -0.0865111 0.0914736 0.0240899 0.00270574 -0.0113627 -0.449157 0.266914 0.0263643 -0.0620438 0.0526707 -0.146843 0.0867263 0.0355629 -0.0454152 -0.0925637 -0.0641849 0.0346697 0.0294993 0.0256108 0.0433476 -0.0249995 -0.00833175 -0.0122965 -0.657407 -0.0536899 0.109214 0.0656339 0.143954 -0.064156 0.0648258 0.123597 0.125951 -0.0315583 -0.0472979 0.031754 0.0500555 0.0491696 0.038106 -0.027903 0.0087914 0.00684266 0.0603479 0.164251 0.165423 0.110399 -0.0349456 0.0507896 0.0139389 0.143179 -0.157763 -0.0241374 -0.103421 0.202621 -0.118918 0.0141984 -0.106676 0.168724 0.141406 0.224834 0.235021 -0.279375 0.251264 0.361615 -0.259709 -0.318857 -0.0145688 -0.0242677 0.291758 -0.131371 -0.175347 -0.251201 0.0563524 0.0477667 -0.0545288 0.0252192 0.0268256 -0.095301 0.586479 0.147018 0.102304 -0.0578635 -0.380135 -0.166839 -0.0577772 -0.147512 -0.154322 -0.0471552 0.365575 0.101513 -0.259279 -0.0172949 0.118924 0.0790666 -0.064732 -0.0353593 0.154311 -0.200738 -0.148053 -0.18183 -0.0400629 -0.130989 -0.0593038 0.0215229 0.133686 0.0122566 0.115152 -0.0919082 -0.0792216 -0.0808386 0.17713 0.0763935 0.0315306 -0.0151888 0.532517 0.0274238 -0.390451 0.189653 0.269541 0.369249 -0.100669 -0.279149 0.165087 -0.134127 0.392419 0.322168 -0.245113 -0.237317 0.108739 0.219678 -0.037155 0.108496 -0.301864 -0.626799 -0.0523864 0.100146 0.539623 0.303725 -0.0739295 0.0446588 -0.0879373 0.424925 0.0701205 0.0311797 -0.217313 0.0594558 0.0142305 0.0505473 0.136606 -0.0903106 0.633861 0.120006 0.0684832 -0.0605775 -0.236825 -0.0597716 -0.147742 0.0185596 0.02269 -0.0530305 0.0508676 -0.0134972 -0.126969 -0.172903 -0.0501483 0.0315373 0.00103502 0.0546934 -0.0745796 0.053314 0.104318 0.132321 -0.311562 -0.359525 0.211541 0.000594782 -0.108956 -0.113369 0.0461666 0.0751137 -0.0777433 -0.0947384 -0.0682904 0.175775 0.142953 -0.0653753 -0.173566 -0.136968 0.0880674 -0.0484785 -0.00211854 0.0980478 0.00402503 -0.014135 -0.035046 0.0440022 0.0775809 0.0855016 -0.0728874 0.111748 0.0128008 -0.0534822 -0.0510731 0.109626 0.0384742 0.0499806 -0.190085 0.0332993 0.235182 0.0591925 -0.137664 -0.121854 0.11671 -0.0169987 -0.0401064 0.0329428 0.0923855 -0.0597885 -0.177348 -0.109103 -0.0590156 -0.0151763 -0.254673 -0.0709109 0.0312014 -0.0652366 -0.100529 0.128606 0.109088 0.0703447 -0.0600539 -0.00470008 -0.0142321 -0.00346926 -0.136081 -0.049586 -0.0805649 0.0925227 -0.0825643 0.169619 0.0985659 0.0210756 -0.0745315 -0.0238228 -0.224237 -0.251339 -0.0516473 0.108886 -0.0822554 0.00367609 0.0333304 0.00252371 0.109358 -0.0391713 0.0763835 0.0625809 -0.00253433 0.056174 0.306562 -0.493196 0.542681 -0.332412 -0.0760011 0.081516 -0.00546318 -0.113964 -0.0669717 0.0380036 0.155996 0.0606986 -0.26947 0.0271799 0.0815785 0.0182487 -0.0371381 0.0860665 -0.233016 0.260443 -0.100989 0.052316 0.0917698 -0.00211579 0.0312586 -0.0497563 -0.0153006 -0.14733 0.0492269 -0.0205591 0.0874082 0.0882376 -0.058289 0.128763 0.0503012 -0.00330489 0.0518264 -0.168168 0.176424 0.001762 -0.0707937 0.279906 -0.0565057 -0.0592796 0.0199654 0.0713605 0.0978072 -0.00175121 -0.217667 0.13711 -0.0317029 0.0623666 -0.0940363 0.0297523 -0.350827 -0.0437924 -0.14586 -0.0570311 0.119909 0.0538243 0.0108133 0.0839905 -0.0398921 0.0694291 -0.0412033 -0.00217059 -0.0288657 -0.00115903 0.0457418 0.13946 0.0193626 -9.6696e-05 -0.26679 0.0772714 0.143559 -0.0661076 0.0809759 0.0745007 -0.116495 0.0588356 -0.11838 -0.0300845 -0.115008 -0.0261651 -0.0783664 0.0768275 0.0461367 0.0805463 -0.0167991 0.0739141 0.181418 -0.0881166 0.00942596 -0.435385 -0.390551 0.0566313 -0.0321577 -0.0803596 -0.0152357 0.289209 -0.0237065 -0.0919739 -0.0172134 0.0772633 0.0770426 -0.0115599 0.0983214 0.0476574 0.136548 -0.134892 0.0314457 -0.285082 -0.431259 -0.09473 0.00532582 -0.312505 -0.1863 0.0704465 0.0562834 0.0471199 0.131979 0.0616617 0.0661749 -0.0590009 0.0562261 0.104546 -0.126099 -0.27306 -0.113815 0.10315 0.305976 0.135271 0.0181513 -0.130255 -0.18484 -0.0820827 -0.0193871 0.0664598 0.0924492 -0.103258 -0.0782594 -0.066301 -0.124854 -0.0321171 -0.050453 -0.236693 -0.384309 0.260907 0.0764604 -0.00181417 0.157589 0.0336074 0.135512 0.0161823 0.0296644 0.161961 0.162521 -0.142671 -0.0613516 0.0200053 -0.0828338 0.0609099 -0.517488 -0.159504 -0.249924 0.387669 0.469226 -0.0517176 -0.133168 0.0739067 0.165043 -0.0998542 0.0940286 0.107513 0.019671 0.0317338 0.0317524 0.0839626 0.0124566 0.00464982 -0.069814 0.0308934 0.230117 -0.175197 -0.205232 0.144451 0.0134557 -0.200649 -0.299892 0.149482 0.204561 0.090222 0.00844513 0.00569229 0.000935842 -0.116332 -0.117112 0.0362152 0.377091 -0.0425487 0.0749396 -0.130015 -0.277345 -0.0150269 -0.0389178 -0.07466 -0.068594 0.0364878 -0.0172824 0.0260333 0.00401925 -0.0653209 -0.0383554 -0.0443934 -0.0925567 -0.046927 -0.165969 -0.0517096 0.0965856 0.250943 0.0807204 0.1328 0.0526446 0.085909 0.13211 0.00587204 0.119366 0.116869 -0.0182341 0.0970162 -0.0714112 0.0274952 -0.0682101 0.0239336 -0.294961 -0.163806 -0.185485 0.0234831 0.106974 -0.133567 -0.141111 0.257757 0.0669364 0.0509162 -0.00788026 0.0397974 -0.0763799 0.00680433 0.114283 -0.000537495 0.000608899 0.0516275 0.0129448 0.079688 0.0900807 0.0242152 0.184354 0.0204661 -0.0943088 -0.0675444 -0.00447166 0.0776767 0.0531631 -0.0675515 0.0738351 -0.0853867 0.0578983 0.0334688 -0.0453221 0.0224648 -0.359665 0.0951472 0.00212435 -0.0968217 0.0184601 -0.121866 -0.0121074 -0.0895667 -0.163232 0.212924 -0.063323 0.0785786 0.0375447 -0.0557171 -0.158879 -0.0656196 0.0149439 0.150689 0.24224 -0.244496 0.0216921 -0.278839 -0.341068 -0.120132 -0.116931 0.213351 0.0139575 -0.134982 -0.0825014 0.176649 -0.0921517 -0.0079085 -0.0322712 0.0221022 -0.0875418 0.105493 0.295434 0.107212 -0.155597 0.106911 0.0302013 0.190314 -0.123188 -0.0131628 -0.10362 -0.0652164 -0.103635 -0.0535725 0.0188447 0.0894119 0.0458241 0.0508295 -0.0959796 0.0300429 -0.0986824 0.112097 0.0146006 0.116369 -0.00763559 0.0406879 0.115994 0.195981 0.0234928 -0.264702 -0.21414 0.143492 -0.0207255 0.0319306 0.0354118 0.061008 -0.0982885 0.0865729 -0.340411 0.112134 -0.130539 -0.237254 -0.0103252 -0.00520174 0.135087 -0.033832 0.0467878 0.0912849 -0.0111041 0.00216883 0.0284299 -0.109983 0.00797592 -0.0385682 -0.0769956 -0.0241059 0.219131 -0.0753424 0.064628 -0.182144 0.0161726 0.198717 -0.0213781 -0.228639 -0.166882 0.158374 -0.110943 -0.11314 0.150686 0.0510213 0.00155086 0.206332 -0.0164745 -0.161934 -0.00659287 0.207057 -0.0698618 0.176755 -0.112096 0.00790802 -0.335148 -0.469859 -0.125295 0.0338378 0.0621415 0.0645371 0.179136 0.121326 0.224668 -0.0230443 -0.149033 0.165626 0.219483 -0.125755 0.3625 0.00332407 0.0168273 0.143542 -0.34768 -0.281958 -0.0879594 -0.108763 -0.117159 -0.132537 0.250816 -0.0451199 0.124573 0.230219 -0.0869138 0.056355 -0.105065 0.504099 0.134496 0.441324 0.141212 0.405645 0.112008 0.127985 -0.0804288 -0.297371 -0.13413 0.0207554 -0.157077 -0.0895015 0.050491 0.250466 0.0965462 -0.142761 -0.194963 0.682663 0.82716 0.109369 -0.409966 -0.151488 -0.290969 0.230705 0.11802 0.447496 0.13243 0.0441441 -0.0903714 -0.162346 0.0215512 -0.359056 0.026601 0.0461757 0.0877522 0.16143 0.172178 0.270429 0.30614 0.218296 -0.0150418 0.0484542 -0.0605185 0.0434151 0.107557 0.0396379 -0.0219181 0.274215 0.000821984 -0.082004 -0.0249974 0.0520248 0.210962 -0.15727 0.345257 -0.00823571 -0.103742 -0.0137604 -0.174622 -0.033122 0.0783007 0.0462813 0.0466708 -0.249781 0.102466 -0.130464 -0.183264 -0.246864 -0.0116746 0.029649 -0.199759 0.0755447 -0.12531 0.287268 0.20124 0.32103 0.0616534 -0.133926 -0.176273 -0.294436 -0.264107 -0.127467 0.0968805 0.132958 0.236436 0.0788141 0.00372209 0.0624262 -0.0300718 0.23735 0.0575881 0.002061 -0.259858 -0.0865459 -0.141816 0.0568474 0.184865 0.0826282 0.257022 -0.0925439 -0.0894438 -0.070957 0.0166964 -0.0624995 -0.0513126 -0.019251 0.117116 -0.367351 -0.0680362 -0.221255 0.0681109 0.088888 -0.0275856 -0.0452598 0.0486331 0.0541275 0.111342 0.0474706 0.000693079 0.112382 0.0467807 0.0946939 -0.0149819 0.149606 -0.00101244 -0.208567 0.0470385 -0.17312 0.0611894 0.214082 0.23802 0.0420711 0.174587 0.0766657 0.104275 -0.0605427 -0.0603649 -0.0728886 0.300587 -0.00135731 -0.0791746 0.0455143 -0.254204 -0.282581 -0.0351129 -0.209012 0.234971 0.114087 0.165263 0.21346 -0.0521414 0.0227601 -0.089567 0.0830319 0.040053 -0.125362 -0.0407889 0.172341 0.0456444 -0.0807319 0.538724 0.696561 -0.456343 0.267343 0.0745503 0.0887893 0.179168 0.162938 0.509182 0.0403401 0.104878 -0.105167 -0.029366 0.0950945 0.0507264 -0.126042 -0.111362 -0.0933655 0.0196509 -0.0905567 0.12562 -0.468207 -0.0148617 0.0459553 0.191657 0.0995822 0.1342 0.0462253 -0.140099 -0.109752 -0.143901 -0.00353464 -0.0567208 0.0809091 -0.105367 -0.164643 0.123138 0.0732768 -0.503124 0.157651 0.0783188 0.0894153 0.0578102 0.0116896 0.198876 0.106149 0.0986878 0.0410295 0.0780925 0.0952681 0.063896 -0.0184734 0.0651155 0.126474 -0.20959 -0.00538747 -0.238826 -0.288733 0.0375707 0.0961968 0.23774 -0.134819 0.0918536 0.158458 0.050837 0.017788 0.0590008 0.0564985 0.094541 0.0774909 -0.0304891 -0.00900815 0.122511 -0.217551 -0.0228244 -0.271366 -0.37482 -0.18336 -0.136293 -0.215907 -0.107478 0.109005 0.267962 0.168686 0.220513 0.145122 -0.00848397 0.0423112 0.0379542 -0.0835479 -0.305381 -0.205857 -0.00615925 -0.264518 -0.017432 0.178784 0.27803 0.0855791 -0.266606 -0.315983 -0.157443 0.0346354 0.0918554 0.257643 0.110054 0.0726684 0.0481967 -0.101219 0.122055 -0.235134 -0.0559019 0.0427345 -0.00844811 0.104121 0.147791 -0.04536 -0.125748 -0.0775912 -0.0279053 -0.0155415 -0.0672843 0.0119913 -0.0933009 -0.170196 -0.03207 0.0962406 -0.325198 0.0858826 -0.164266 0.0842977 0.23112 0.150369 0.25028 -0.0195274 -0.12085 -0.153951 -0.0975147 -0.0579206 -0.0261243 0.0251013 -0.0546052 -0.0117369 -0.00575005 0.0586769 -0.184273 -0.395171 -0.36086 -0.530864 -0.109572 0.186511 0.221562 0.311655 -0.0271461 -0.122634 -0.187569 -0.0317561 -0.0682304 -0.175166 0.0136675 -0.0524679 -0.0653404 -0.115417 -0.174608 -0.25911 -0.399264 -0.37491 -0.208214 -0.0254744 0.224699 0.399727 0.235792 -0.168349 -0.149466 -0.0662725 -0.267182 -0.226475 -0.0397162 -0.0261684 0.12738 0.0137057 0.307298 -0.114962 -0.162173 -0.105196 0.160087 0.38407 0.485126 0.324118 0.102573 -0.314309 -0.420302 -0.21341 -0.25665 -0.148808 0.0946552 0.153536 0.0792132 0.225851 0.167105 -0.0787178 -0.0959315 -0.117844 0.0394018 0.0273515 0.246837 0.316368 0.244684 0.0469862 -0.116033 -0.136013 -0.26248 -0.199568 -0.0300762 0.0557625 0.117516 0.102549 0.0409209 0.136875 -0.0434196 0.0839042 0.0273692 -0.27622 -0.0126305 0.129621 0.0656939 -0.17914 -0.145186 -0.0455046 0.0184035 -0.131342 -0.04779 -0.0583469 0.158717 0.032404 -0.0183481 -0.0360525 0.306789 0.000695852 -0.530471 -0.391737 -0.0295994 -0.0495065 -0.117727 0.0519633 0.0856655 0.0519793 0.0429306 0.0291838 -0.0277827 0.121749 0.0417665 0.0558113 0.247166 0.396028 0.442412 -0.210877 -0.237199 -0.197525 -0.0167929 -0.0806786 0.0851234 0.0029181 -0.110409 -0.11248 -0.0328546 -0.0764938 0.0796986 0.198657 0.149328 -0.028101 -0.438014 -0.0381066 -0.0871418 0.00555011 -0.0239523 -0.00198173 0.0814083 -0.0869309 0.000389981 0.131215 0.0652716 -0.0253891 0.0830576 0.132846 0.021494 0.073135 -0.030216 -0.0852265 0.958217 0.234181 0.0731243 0.0401579 -0.518939 -0.126294 -0.0576384 0.0993001 -0.0807148 -0.0260706 -0.104678 -0.0878226 -0.0940228 -0.110045 -0.0631681 0.0879148 -0.0182079 -0.0272567 0.495217 0.19924 0.719363 -0.0483477 -0.381826 -0.175924 -0.112066 0.0174284 -0.228415 -0.0568683 -0.0605056 -0.0125383 -0.103132 -0.0936424 -0.0444165 0.0495236 0.0174295 -0.056627 0.910677 -0.011777 0.443815 0.0386955 -0.306143 -0.153968 -0.00737721 -0.0869214 -0.270109 0.0383636 -0.0945486 -0.0679358 0.0660802 0.111717 -0.00410491 0.00690337 -0.128343 -0.0600406 -0.142231 0.24965 0.308208 0.23266 0.0520253 -0.0828694 -0.0334565 0.128223 -0.215427 0.0142981 -0.117156 -0.0564992 -0.156703 -0.0136527 -0.0383912 -0.0179024 -0.0342711 0.0579347 0.333561 -0.109913 -0.292047 -0.020367 -0.0491262 -0.18798 -0.0247658 0.0755908 -0.00766519 -0.0727738 -0.0405941 -0.00658847 -0.0115425 -0.166544 0.0559409 -0.0310851 -0.058849 0.00380344 -0.24117 -0.0719822 -0.0820552 -0.114157 0.0588534 0.245615 0.049023 -0.0785571 0.142826 -0.0248087 0.285052 0.0699102 0.100022 0.0847188 0.090524 0.0197199 -0.00520906 0.0517568 0.376354 -0.00723147 0.095688 0.131127 0.0147843 -0.179688 -0.0772801 -0.160305 -0.0144132 -0.0574858 0.136889 0.113507 0.0560935 -0.0845217 -0.0785592 -0.101778 -0.0842293 -0.0836161 -0.0859494 -0.0592827 -0.0975957 -0.028005 0.108137 0.116407 0.160795 0.0307125 0.0281218 -0.108549 0.0601557 0.00403307 0.00656835 0.0444443 0.222376 -0.00205973 -0.0362298 -0.121302 0.812561 0.00221774 0.237814 0.316045 0.172356 -0.000726804 0.0407577 0.00819434 -0.0840609 -0.26455 -0.281341 -0.0190242 0.0240845 -0.0266649 0.116759 0.0889722 0.0590214 0.0585379 -0.201653 0.0872233 -0.289718 -0.457144 -0.317052 -0.0738113 -0.0603764 0.146265 0.100289 -0.194254 -0.244155 0.00766624 0.0842816 0.0731751 0.0230254 0.114509 -0.0632 0.0189756 0.206379 0.0678411 0.0256787 -0.182593 -0.00608559 -0.190303 -0.0427254 0.133847 -0.0750359 -0.20806 -0.00944696 0.0478108 0.0124722 -0.232867 -0.175049 -0.019309 0.0293643 -0.0814017 -0.293671 0.22981 -0.0104054 -0.136699 -0.0055413 -0.0656998 0.318127 -0.0300018 -0.181007 -0.0437111 -0.0649685 0.147509 0.204009 -0.130125 0.19829 0.100886 0.00626445 -0.0863327 -0.154592 -0.312055 -0.0383216 -0.0865081 0.217963 0.176309 -0.0192059 0.0869867 0.0485337 0.0269649 -0.0297697 0.0831298 0.0946569 -0.0291246 -0.0987588 0.00582951 0.175148 0.105519 0.0944496 -0.185184 0.0181165 -0.236548 -0.0232191 0.0698924 0.0891822 0.121864 -0.0443506 0.00829986 0.163004 0.0108472 0.0283505 -0.181511 -0.0650762 0.0845149 0.0962171 -0.190564 0.10749 0.0939773 -0.0234348 -0.223743 0.10236 0.112693 0.100129 -0.0644053 0.0180405 -0.142215 0.305966 0.0851624 -0.0169614 0.04291 0.0627372 -0.0131749 0.0261668 -0.0633883 0.279467 0.230274 -0.150363 -0.0693517 0.100927 0.119295 0.0356948 -0.0856852 -0.0555285 0.0619101 -0.00146945 -0.0702843 -0.203981 -0.0856431 0.0947453 -0.0793924 -0.109503 -0.017296 0.242396 -0.0641928 -0.305567 -0.293712 -0.123715 0.18374 -0.116372 -0.252151 0.0179801 0.162959 -0.00288657 -0.0208934 -0.0350224 0.15635 0.0258522 -0.0522835 -0.135265 0.076039 0.489693 0.377187 -0.169667 -0.0829182 0.223771 0.130441 -0.13213 -0.151948 0.186407 -0.0800281 0.0691533 -0.127172 -0.00550914 0.0364167 -0.0910068 -0.0767431 0.056986 0.00941525 0.268233 -0.0830731 -0.237192 -0.135812 0.236819 0.281531 0.0287555 -0.0762722 0.11051 -0.0249007 0.197386 0.0505611 -0.0148811 0.102492 0.137345 -0.01075 -0.0219163 -0.155191 0.017922 -0.19235 -0.138305 -0.353044 0.0648529 0.177144 -0.139283 -0.227006 0.13526 0.0743115 0.135356 -0.129395 -0.107466 0.00304908 0.0135733 -0.0191982 0.0610791 -0.0298849 0.330069 0.040014 0.00389974 -0.0763725 -0.0818869 0.0118807 0.150931 -0.00963188 -0.0240398 0.174136 -0.0114336 0.0642045 -0.141171 -0.135121 -0.19397 -0.125707 -0.00523646 -0.122284 0.092907 0.329919 -0.0528091 -0.0457051 0.210247 0.234763 0.274601 0.144384 -0.0581128 0.122856 -0.192228 0.11114 -0.0609331 -0.193515 0.00259363 -0.110397 -0.229842 -0.0590318 0.244321 0.0527196 -0.144256 -0.367605 -0.281714 -0.0960706 -0.140442 -0.00707071 -0.127257 0.172667 -0.0561947 0.0292984 0.0489565 -0.0452082 -0.178461 -0.0120474 0.010209 0.0340465 -0.199646 0.205306 0.097943 0.262355 0.043019 -0.0695479 -0.0226927 0.114929 0.0805469 -0.0883551 -0.0136051 -0.0016808 0.0143139 -0.215833 -0.0286458 0.0710461 0.0465273 0.0864994 0.406736 0.348563 -0.0941463 -0.393989 -0.284865 -0.129725 0.0442062 -0.0535966 -0.234892 0.0972417 -0.285781 -0.0514919 -0.212302 -0.00087499 0.184246 0.0931008 0.013839 -0.172422 -0.305535 0.564938 -0.483718 -0.280091 0.141919 -0.101998 -0.185934 -0.192785 -0.0986174 0.279985 -0.363658 -0.0052367 -0.0163078 -0.0844433 0.133885 -0.0453188 0.00681035 0.0378583 0.0397831 -0.139054 -0.0160363 -0.295454 0.0292263 0.0320583 0.00775532 -0.0472026 -0.0376298 0.313992 -0.167365 0.236145 0.0295398 -0.0993126 -0.271789 -0.266154 -0.045571 0.0991098 0.069383 -0.0429165 -0.293631 -0.223343 -0.0402408 0.0668075 -0.147962 -0.0599618 -0.0215618 0.19598 -0.0872555 0.16412 0.130912 -0.0516799 -0.0351091 -0.0858394 0.079511 0.126206 0.147499 -0.105008 0.0437526 0.00334311 -0.155593 -0.128052 -0.25617 -0.220503 -0.155964 0.16822 0.139196 0.0510098 0.083358 0.031194 0.0796548 -0.00824945 0.0188701 0.00194814 -0.592292 -0.119832 0.172057 0.0854024 0.0200436 0.103208 0.14633 0.230934 -0.118833 -0.00581487 -0.0652085 0.123197 0.0124339 0.0319724 0.0813049 0.134597 0.148948 0.0272596 0.0347649 -0.233163 -0.0303612 0.0556118 0.16519 0.0622524 0.246736 0.216037 0.0441449 -0.21074 -0.0406344 -0.0261562 -0.0198293 -0.0157723 0.0956641 -0.111215 0.110414 0.106349 -0.056217 0.0221296 -0.0964693 -0.0699945 -0.0696948 -0.190964 0.0763363 0.016398 -0.0235602 -0.0132751 0.0898094 0.150693 0.16738 0.085356 -0.13858 -0.182686 -0.0305354 0.0225444 0.0535916 0.255359 -0.102334 -0.0618353 0.139136 0.0826349 0.0308509 -0.172683 0.0758153 -0.0513096 0.0470565 0.0309468 0.0657697 -0.0126726 0.0498616 -0.0793396 0.0522932 0.0456826 0.632042 0.294071 0.0649154 0.159579 0.139544 0.38189 0.0965171 -0.37988 -0.0539192 -0.0809122 -0.093278 0.0402246 0.0147224 0.0635799 0.242198 0.325805 0.0847972 0.11527 0.0285272 -0.000430261 0.189992 0.126215 0.00741998 -0.0914052 -0.0595758 0.191186 0.162207 -0.0834596 -0.152032 -0.0768655 0.0632626 -0.0225199 -0.0879601 -0.007016 0.0747599 0.0405774 0.474316 0.211239 0.128164 0.0289047 -0.124025 -0.295682 -0.1478 0.0291071 0.0196847 -0.16969 -0.0809769 -0.0862648 0.0112549 0.0195121 -0.103755 -0.116085 -0.0102248 -0.034915 0.210896 -0.0104463 -0.0326057 0.0257041 -0.00386209 -0.0690295 -0.0663693 0.03231 0.0108088 -0.183522 0.140274 -0.0802235 0.0737071 -0.13641 0.0970416 0.013265 -0.0485375 -0.110257 0.033317 0.133928 -0.392694 -0.0934875 0.489666 0.031283 0.0654826 -0.0423284 -0.130295 0.143551 0.0526587 -0.0446382 -0.13458 0.019795 -0.0408275 0.0636842 0.0476816 0.134551 0.0951618 -0.121522 -0.270953 -0.168724 0.334443 -0.0593911 -0.220457 -0.0962335 0.0253848 0.0427121 -0.0907547 -0.131499 0.0159227 -0.00249678 0.0301277 -0.0741113 -0.0948609 -0.0914437 -0.133278 -0.0355998 0.0976815 0.140688 0.132693 0.2199 0.160216 -0.147906 -0.0818684 0.2128 -0.175882 -0.0748416 -0.017371 0.134433 0.0237579 -0.102023 -0.179224 -0.042943 0.041963 -0.0967519 0.45462 -0.118356 -0.702984 0.0528589 0.187009 -0.0787802 -0.0975742 0.0337318 0.0988493 0.271396 -0.0697229 -0.00117778 -0.0821759 0.0622327 -0.0723649 -0.0749225 -0.135177 -0.21193 0.542375 0.0986715 -0.782175 0.0960739 0.186603 -0.10651 -0.209715 -0.102128 0.0769135 0.119829 0.180862 0.0273667 -0.106463 -0.129499 -0.218767 -0.0229906 0.192874 -0.110624 -0.155576 -0.0492239 0.394693 -0.13618 -0.464193 -0.118028 0.0790558 0.0443933 0.0286333 -0.150573 0.106851 -0.0677337 -0.0161629 -0.0576436 0.108346 0.00546154 0.281962 -0.118069 -0.206207 -0.110655 0.266896 -0.0393143 -0.0876163 0.0125116 0.119085 0.0509402 -0.0911 -0.128684 -0.103647 0.0449241 -0.0131619 -0.0737869 -0.0636343 0.0158374 0.360293 0.0816556 0.262505 0.0295852 -0.127196 -0.324842 -0.0729737 -0.0259931 0.108417 -0.0981648 -0.0727229 0.0112416 0.153169 -0.093807 -0.15055 0.035216 0.155644 -0.0972454 0.431165 0.0445774 0.35729 -0.238629 -0.761138 -0.203992 0.0620572 0.140433 0.0484328 -0.0760749 0.0663699 -0.0323713 -0.0825792 -0.081931 -0.100433 0.0087554 -0.0294358 -0.122986 0.367566 0.0832562 0.386404 0.0113549 -0.113161 -0.11585 -0.0454134 0.00119299 0.0658329 -0.0551982 0.199972 -0.0726621 0.0404892 -0.143587 0.161663 0.00989744 -0.0583548 -0.0641471 -0.126149 -0.105765 -0.180871 -0.0140971 0.0993396 0.0626786 0.0164829 -0.120393 -0.0120236 0.0267269 0.0369891 -0.0278692 0.0697173 0.00157279 0.0346318 0.0365465 0.0364351 -0.0463293 0.0719872 0.234179 0.0700754 0.0454905 0.0179139 0.00595942 0.00178118 -0.0757482 0.122689 0.0301975 -0.0582152 -0.0393595 0.0426631 -0.0308872 -0.155719 0.0245356 0.0514281 -0.0331139 0.16308 0.147502 0.224563 0.00149026 -0.19422 -0.00245891 0.00201232 0.0104737 0.00952506 -0.087858 6.47322e-05 0.0314169 -0.0510392 -0.0137016 0.0144097 -0.0295847 -0.0166223 -0.0935091 0.132211 -0.0996081 0.297871 -0.0929839 -0.404187 0.00734247 0.0342272 0.0465792 0.10261 0.101541 -0.0710669 -0.0647102 -0.0167732 -0.0792188 0.114399 0.0084752 -0.0984425 0.0487576 0.104527 0.0104202 0.25442 -0.132452 -0.147611 -0.260759 -0.171302 -0.00105613 -0.0352155 0.0471581 0.0503479 -0.0304953 0.0811992 0.0571881 0.0241816 -0.0302046 -0.042417 -0.0158246 0.0789319 0.278062 0.134237 0.0776471 -0.0215679 0.163599 0.00440529 -0.251491 -0.0694608 0.244747 0.0525392 -0.174708 0.0384829 0.186693 -0.0194743 -0.100282 -0.0706602 0.0455089 0.036666 0.0560859 -0.0455239 0.123939 0.0318264 0.0234766 -0.0573187 0.107605 -0.0486884 -0.0651118 0.0378355 -0.0347981 0.00422118 0.0338115 0.0272182 0.00532772 -0.0101238 0.100865 0.137984 0.192333 -0.0230741 0.0145724 0.183426 0.155987 -0.057101 -0.192028 -0.243608 0.302293 0.0796913 -0.293148 0.00127396 -0.019316 0.093773 0.117825 0.0864045 0.0216239 -0.0627421 -0.152207 0.184666 -0.0225224 -0.0524557 -0.0367394 -0.048723 0.100491 0.202537 0.000745996 -0.0288756 0.00148543 0.0784119 -0.0592042 0.0685676 0.134821 -0.0762534 0.0510426 -0.425051 -0.243875 0.0961206 0.206394 0.118967 -0.00696505 -0.0815457 0.342184 0.291138 -0.215723 -0.121786 0.228353 -0.193869 -0.120802 0.0608357 -0.0235667 -0.145194 0.00759666 -0.034862 -0.0469551 0.123362 -0.0226347 -0.00974243 0.117364 -0.0843802 -0.055497 0.0215514 -0.0301978 0.0112418 0.0368944 -0.0893707 0.129628 0.0243118 -0.0220287 -0.0459718 0.0799326 -0.143523 0.471748 -0.012469 -0.0580974 -0.0525712 0.128289 0.149932 -0.00302388 -0.125934 0.0786458 -0.048059 -0.00901601 -0.0404284 0.117521 -0.121534 0.108784 0.126158 -0.114182 0.257331 -0.0310021 0.0695447 0.153758 -0.0636068 -0.0998118 -0.0717972 -0.102052 -0.114542 0.0407005 -0.117379 -0.0749038 -0.0115072 0.0580869 0.0671776 -0.000304893 -0.0538705 -0.117465 -0.00287373 -0.0256009 -0.0636826 -0.0312657 -0.13077 -0.0061836 0.0432434 -0.0595603 -0.163516 0.0870283 0.274406 0.00354131 -0.302371 0.157017 0.236665 -0.147954 -0.196912 -0.111815 -0.0337404 0.0821758 0.0989727 0.175779 0.000249754 -0.25664 0.0464443 -0.0548022 0.0210559 -0.0606205 -0.00415924 0.116475 -0.10726 -0.0444887 0.168687 -0.18906 -0.109001 0.115015 0.155224 -0.0138517 -0.0679595 -0.0751129 -0.0129427 0.0919048 0.172384 -0.00683679 -0.0836871 0.0586344 0.122329 -0.0920789 -0.103059 0.0642979 0.15209 -0.0522484 -0.038811 0.0493885 0.0917311 -0.103801 -0.0485947 0.0726457 -0.0256357 -0.0392485 0.128359 0.133325 -0.0966681 -0.151468 0.150596 0.0487153 0.0293802 0.0944193 -0.0302072 -0.0383394 -0.0784558 -0.0446012 0.181688 -0.503953 -0.234605 0.23727 0.125257 -0.0732608 -0.307531 0.199292 0.100369 -0.0449628 -0.128511 -0.0610341 0.0708762 -0.0824378 -0.15822 0.116048 -0.146321 -0.0616026 -0.149122 -0.690181 0.0923413 0.239125 0.235905 -0.183657 -0.500252 0.223169 0.581313 -0.0424044 -0.33193 -0.118295 0.463475 0.0325293 -0.376496 0.0201681 0.168377 0.0165691 0.211439 -0.37421 -0.0812108 -0.0972299 0.0226568 0.225501 0.204552 -0.121544 0.0419528 -0.101529 0.00181799 0.086009 0.031965 -0.0309837 0.0202111 0.0361025 -0.0279149 0.0476917 -0.117005 -0.116634 0.0720398 -0.373911 -0.254457 0.237642 0.270035 -0.119457 -0.414178 0.15323 0.337276 0.0735205 -0.234025 0.00362945 0.0573864 0.00701362 -0.0361344 0.0402088 -0.417454 0.185565 -0.257488 0.178168 0.256465 -0.0665193 0.0522047 0.0736985 0.00840293 -0.0452689 -0.243279 0.0624759 0.043181 -0.082835 -0.0272137 -0.0719697 -0.032596 0.0147108 0.213514 -0.19047 -0.472857 0.277827 -0.0427543 0.000576973 -0.10838 0.0926987 0.090293 -0.0995884 -0.192612 0.0651771 -0.113166 0.161899 -0.0260323 0.0167942 -0.0327622 0.0281352 0.0844825 -0.417291 -0.353655 -0.119017 -0.169474 -0.0697634 -0.152224 0.214902 0.197915 -0.151216 -0.169451 0.237557 0.120469 0.153692 -0.148378 0.0173856 0.105836 0.0457673 -0.162221 0.3293 -0.11986 0.104763 0.20654 0.032141 0.0980827 0.187595 0.0906171 -0.179668 -0.031349 -0.0915287 -0.0624823 0.0247889 0.0411239 -0.0252026 -0.071556 -0.100806 -0.467319 0.462235 -0.163684 -0.0339773 -0.0815014 0.105674 0.134531 -0.0560339 -0.0560827 0.0136451 0.217139 -0.108433 -0.11713 0.132442 0.0381024 0.0264875 -0.0728866 -0.0141755 -0.996327 0.463087 0.0162716 -0.279275 -0.0785188 -0.0626995 0.117591 0.00260401 -0.0809912 0.0832688 0.168961 -0.117573 0.0153485 0.0387164 0.0114593 -0.0777107 0.0527547 0.00628565 -0.26301 -0.417872 0.0559441 0.16125 -0.0321918 0.105246 -0.304421 0.0210794 0.00638279 0.103374 -0.0240736 0.176431 0.00167034 0.00176263 0.019307 0.0437794 -0.0407008 0.15164 0.256638 -0.243051 -0.0234826 0.0427931 0.0314591 0.150012 -0.102223 -0.0941515 -0.0728122 -0.0252282 -0.0547703 0.0272074 -0.0126805 0.00370477 0.0193586 0.0134075 -0.0187448 -0.0449414 diff --git a/conf/vad/rplp18d_norm.dat b/conf/vad/rplp18d_norm.dat deleted file mode 100644 index b93271f79d6a72fe67734673efea3ac8bbb9da02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 576 zcmV-G0>Aw&DuNwa!05k!U-i6q==Q&cc86mrxZuACVF3~8&h@_~DQu$5-sHc+^83qg zB=Em*xvIaaYvjMq;}}xC!sfrod9g~`8Z6EwAqL&Lw1@=bjs+_ArRTcw0_nWDeO=k1wmhMqrcR;K$3(XBtR#3A+! zv8}%E*TD4WADupOVYcsVKBhivsCI(#pu0XP3yz$w*2O;1CBxuh2E0BD09k91FNZ!R zy9*QhS&qI`pFdR$Z=60v`xY!7l%77Tk?Utu5{5o^j{#h$ zTYNr#9^S06G_pR7>_|XDC#$~of(OIKv3b6=vt(;pa4RdaHtJyzDT5bnQ|JFYy zUMkbLu-HEh6mdd_fY?6(PZG8_k=j2nQU;Ol`Pe__$L+7e64*cFLpTtfHrPLI>C+|v z+15XAdJPxx;nY80$r;q1tJFVu#^h9{z|ue8+kJY>8PPxVRCGSS$P7$hJRU=Hme>XSYAShExrR z*tkC?Hn-$SiMu}>Xr_0?ow`5GYUdy(Yq~!{!y%XDNV`AMU(kUz+_^tN4Uil!Hn=}! zzO4#bythBE)Q=^f%e6lg$wk1EGPFN!bk`fdBeFjX+Y|g openSMILE LSTM-RNN voice activity detector< ////////////////// -///////// ////////////////// -///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// -///////// All rights reserverd. ////////////////// -/////////////////////////////////////////////////////////////////////////////////////// - - - - -;; turn detector configuration module - -[componentInstances:cComponentManager] -instance[turn].type=cTurnDetector - -[turn:cTurnDetector] -reader.dmLevel=vad_VAD_voice -writer.dmLevel=isTurn -readVad=1 -threshold = -0.1 -threshold2 = -0.1 -writer.levelconf.noHang=1 -msgInterval = 0 -messageRecp = waveSinkCut -eventRecp = waveSinkCut -statusRecp = waveSinkCut -debug=\cm[turndebug{4}:set this to 1 to see turn/speaking debug messages] -;; examples for constraining the turn length -;; minTurnLengthTurnFrameTimeMessage=0.9 -;; maxTurnLength=10.0 -; default (0) is infinite maximum length -maxTurnLength=0 -maxTurnLengthGrace=1 -nPre = 8 -nPost = 35 - - diff --git a/conf/vad/vad_opensource.conf.inc b/conf/vad/vad_opensource.conf.inc deleted file mode 100644 index bda8551..0000000 --- a/conf/vad/vad_opensource.conf.inc +++ /dev/null @@ -1,189 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -///////// > openSMILE LSTM-RNN voice activity detector< ////////////////// -///////// ////////////////// -///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// -///////// All rights reserverd. ////////////////// -/////////////////////////////////////////////////////////////////////////////////////// - - -[componentInstances:cComponentManager] -instance[framer].type = cFramer -instance[vectorPreemphasis].type = cVectorPreemphasis -instance[windower].type = cWindower - ; magnitude FFT spectrum -instance[fft].type=cTransformFFT -instance[fftmag].type=cFFTmagphase - ; compute critical-bands from power spectrum -instance[melspec_VAD].type=cMelspec - ; compute PLP 1-12 from critical-band spectrum -instance[plp_VAD].type=cPlp - ; compute log-energy from raw signal frames - ; (not windowed, not pre-emphasised: that's the way HTK does it) -;instance[energy_VAD].type=cEnergy - ; compute delta coefficients from PLP and energy -instance[delta_VAD].type=cDeltaRegression - ; compute acceleration coefficients from delta coefficients of PLP and energy -;instance[accel_VAD].type=cDeltaRegression - ; MVN (2x) -instance[mvn_VAD].type = cVectorMVN -;; experimental MVN adaption, uncomment to enable -;; and also change reader.dmLevel of lstm_vad component -;instance[mn2_VAD].type = cVectorMVN - ; LSTM for VAD -instance[lstm_vad].type=cRnnProcessor -instance[dataSelector].type = cDataSelector - -[framer:cFramer] -reader.dmLevel = wave -writer.dmLevel = frames -// nameAppend = -copyInputName = 1 -frameMode = fixed -// frameListFile = -// frameList = -frameSize = 0.025000 -frameStep = 0.01 -frameCenterSpecial = left -buffersize = 100000 -noPostEOIprocessing = 1 - -[vectorPreemphasis:cVectorPreemphasis] -reader.dmLevel = frames -writer.dmLevel = prframes -// nameAppend = -copyInputName = 1 -processArrayFields = 1 -k = 0.970000 -de = 0 - -[windower:cWindower] -reader.dmLevel = prframes -writer.dmLevel = winframes -// nameAppend = -copyInputName = 1 -processArrayFields = 1 -gain = 1 -offset = 0 -winFunc = ham -;sigma = 0.400000 -;alpha = 0.160000 - -[fft:cTransformFFT] -reader.dmLevel=winframes -writer.dmLevel=fft - -[fftmag:cFFTmagphase] -reader.dmLevel=fft -writer.dmLevel=fftmag - -[melspec_VAD:cMelspec] -reader.dmLevel=fftmag -writer.dmLevel=melspec_power -; no htk compatible sample value scaling -htkcompatible = 0 -nBands = 26 -; use power spectrum instead of magnitude spectrum -usePower = 1 -lofreq = 0 -hifreq = 8000 -specScale = mel - -[plp_VAD:cPlp] -reader.dmLevel=melspec_power -writer.dmLevel=plp_VAD -buffersize=100 -firstCC = 1 -lpOrder = 18 -cepLifter = 22 -compression = 0.33 -htkcompatible = 0 -newRASTA = 1 -RASTA = 0 -rastaUpperCutoff = 29.0 -rastaLowerCutoff = 0.9 -doIDFT = 1 -doLpToCeps = 1 -doLP = 1 -doInvLog = 1 -doAud = 1 -doLog = 1 - -[energy_VAD:cEnergy] -reader.dmLevel=winframes -writer.dmLevel=energy_VAD -htkcompatible=1 -rms = 0 -log = 1 - -[delta_VAD:cDeltaRegression] -reader.dmLevel=plp_VAD -writer.dmLevel=plpde_VAD -deltawin=2 -blocksize=1 - -[accel_VAD:cDeltaRegression] -reader.dmLevel=plpde_VAD -writer.dmLevel=plpdede_VAD -deltawin=2 -blocksize=1 - -[mvn_VAD:cVectorMVN] -reader.dmLevel = plp_VAD;plpde_VAD -writer.dmLevel = plpmvn_VAD -// nameAppend = -copyInputName = 1 -processArrayFields = 0 -mode = transform -initFile = rplp18d_norm.dat -htkcompatible = 0 -meanEnable = 1 -stdEnable = 1 -normEnable = 0 - -; experimental incremental MVN adaptation -; disabled by default -[mn2_VAD:cVectorMVN] -reader.dmLevel = plpmvn_VAD -writer.dmLevel = plpmvn2_VAD -processArrayFields = 0 -mode = incremental -updateMethod = fix -fixedBuffer = 30.0 -meanEnable = 1 -stdEnable = 0 -normEnable = 0 - -[lstm_vad:cRnnProcessor] -reader.dmLevel = plpmvn_VAD -;; enable this, if you enable the -;; experimental incremental adaptaion -; reader.dmLevel = plpmvn2_VAD -writer.dmLevel = vad_VAD -netfile = lstmvad_rplp18d_12.net - -[dataSelector:cDataSelector] -reader.dmLevel = vad_VAD -writer.dmLevel = vad_VAD_voice -nameAppend = vadBin -copyInputName = 1 -selectedRange = 0 -elementMode = 1 - -[turn:cTurnDetector] -reader.dmLevel=vad_VAD_voice -writer.dmLevel=isTurn -readVad=1 -threshold = -0.1 -threshold2 = -0.1 -writer.levelconf.noHang=1 -msgInterval = 0 -messageRecp = waveSinkCut -eventRecp = waveSinkCut -statusRecp = waveSinkCut -debug=\cm[turndebug{4}:set this to 1 to see turn/speaking debug messages] -maxTurnLength=0 -maxTurnLengthGrace=1 -nPre = 8 -nPost = 35 - - diff --git a/conf/vad/vad_segmenter.conf b/conf/vad/vad_segmenter.conf deleted file mode 100644 index 2c81751..0000000 --- a/conf/vad/vad_segmenter.conf +++ /dev/null @@ -1,62 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -///////// > openSMILE LSTM-RNN voice activity detector< ////////////////// -///////// ////////////////// -///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// -///////// All rights reserverd. ////////////////// -/////////////////////////////////////////////////////////////////////////////////////// - - -[componentInstances:cComponentManager] -instance[dataMemory].type = cDataMemory -instance[waveSource].type = cWaveSource - -[waveSource:cWaveSource] -writer.dmLevel = wave -filename = \cm[inputfile(I){input.wav}:name of input file] -monoMixdown = 1 -start = 0 -end = -1 -endrel = 0 -noHeader = 0 -buffersize_sec = 10 - - - ; inculdes a VAD module -\{vad_opensource.conf.inc} - ; and a turn detector module -\{turnDetector.conf.inc} -;\{\cm[turnDetector(T){turnDetector.conf}:filename of turn detector config file]} - - -[componentInstances:cComponentManager] - ; the wave file segmenter -instance[waveSinkCut].type = cWaveSinkCut - ; optional: CSV output -instance[csvSink].type = cCsvSink -printLevelStats = 0 - -[waveSinkCut:cWaveSinkCut] -reader.dmLevel = frames -fileBase = \cm[waveoutput(W){output_segment_}:prefix of WAV output files] -fileExtension = .wav -fileNameFormatString = %s%04d%s -startIndex = 1 -preSil = 0.1 -postSil = 0.1 -multiOut = 1 -sampleFormat = 16bit -; sample rate should be read from the input level -; automatically. In some cases this does not work due to -; round-off errors, so you can force it manually here: -;forceSampleRate = 44100 -;forceSampleRate = 16000 -saveSegmentTimes = \cm[saveSegmentTimes{times.dat}:file to save segment times to] -showSegmentTimes = 1 - -[csvSink:cCsvSink] -reader.dmLevel=vad_VAD_voice -filename= \cm[csvoutput{?}:name of VAD output file] -printHeader = 0 -timestamp = 1 -number = 0 - diff --git a/launcher/.DS_Store b/launcher/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0" + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of Yunitator +cd $CLASSIFY + +# Iterate over files +echo "Starting" +for f in `ls ${audio_dir}/*.wav`; do + ./run537classify.sh $f + base=$(basename $f .wav) + mv $audio_dir/${base}.rttm ${audio_dir}/537cls_${base}.rttm + mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/537cls_${base}.frame_prob.mat +done + +echo "$0 finished running" diff --git a/launcher/diartk.sh b/launcher/diartk.sh new file mode 100644 index 0000000..1b01eb5 --- /dev/null +++ b/launcher/diartk.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + + +### Read in variables from user +audio_dir=$BASEDIR/1 +trs_format=$2 + + +### Other variables speicfic to this script +# create temp dir +workdir=$audio_dir/temp/diartk +mkdir -p $workdir + +### SCRIPT STARTS +cd $BASEDIR/repos/ib_diarization_toolkit + + +# Check audio_dir to see if empty or if contains empty wav +bash $UTILS/check_folder.sh $audio_dir + + +for fin in `ls $audio_dir/*.wav`; do + filename=$(basename "$fin") + basename="${filename%.*}" + echo "treating $basename" + + featfile=$workdir/$basename.fea + scpfile=$workdir/$basename.scp + + # first-first convert RTTM to DiarTK's version of a .scp file + # SCP format: + # __=[start,end] + # RTTM format: + # Type file chan tbeg tdur ortho stype name conf Slat + # math: convert RTTM seconds to HTK (10ms default) frames = multiply by 100 + case $trs_format in + "ldcSad") + sys="ldcSad" + $conda_dir/python $UTILS/rttm2scp.py $audio_dir/ldcSad_${basename}.rttm $scpfile + ;; + "noisemesSad") + sys="noisemesSad" + $conda_dir/python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile + ;; + "tocomboSad") + sys="tocomboSad" + $conda_dir/python $UTILS/rttm2scp.py $audio_dir/tocombo_sad_${basename}.rttm $scpfile + ;; + "opensmileSad") + sys="opensmileSad" + $conda_dir/python $UTILS/rttm2scp.py $audio_dir/opensmile_sad_${basename}.rttm $scpfile + ;; + "textgrid") + sys="goldSad" + $conda_dir/python /home$UTILS/textgrid2rttm.py $audio_dir/${basename}.TextGrid $workdir/${basename}.rttm + $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + rm $workdir/$basename.rttm + ;; + "eaf") + sys="goldSad" + $conda_dir/python /home$UTILS/elan2rttm.py $audio_dir/${basename}.eaf $workdir/${basename}.rttm + $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + rm $workdir/$basename.rttm + ;; + "rttm") + sys="goldSad" + # Since some reference rttm files are spaced rather than tabbed, we need to + # tab them before using them. + cp $audio_dir/${basename}.rttm $workdir/${basename}.rttm + sed -i 's/ \+/\t/g' $workdir//${basename}.rttm + $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + ;; + *) + echo "ERROR: please choose SAD system between:" + echo " ldcSad" + echo " noisemesSad" + echo " tocomboSad" + echo " opensmileSad" + echo " textgrid" + echo " eaf" + echo " rttm" + echo "Now exiting..." + exit 1 + ;; + esac + + # don't process files with empty transcription + if [ -s $scpfile ]; then + # first generate HTK features + HCopy -T 2 -C htkconfig $fin $featfile + + # next run DiarTK + scripts/run.diarizeme.sh $featfile $scpfile $workdir $basename + + # print results + #cat $workdir/$basename.out + cp $workdir/$basename.rttm $audio_dir/diartk_${sys}_${basename}.rttm + fi + if [ ! -s $audio_dir/diartk_${sys}_${basename}.rttm ]; then + # if diarization failed, still write an empty file... + touch $audio_dir/diartk_${sys}_${basename}.rttm + fi + + + +done + +# Delete temporary folder +rm -rf $workdir \ No newline at end of file diff --git a/launcher/eval.sh b/launcher/eval.sh new file mode 100644 index 0000000..ac5e864 --- /dev/null +++ b/launcher/eval.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + +### Read in variables from user +audio_dir=$BASEDIR/$1 +system=$2 + +### Other variables speicfic to this script +#none + +display_usage() { + echo "Usage: eval.sh <>" + echo "where data is the folder containing the data" + echo "and system is the system you want" + echo "to evaluate. Choices are:" + echo " ldcSad" + echo " noisemesSad" + echo " tocomboSad" + echo " opensmileSad" + echo " lenaSad" + echo " diartk" + echo " yunitate" + echo " lenaDiar" + echo "If evaluating diartk, please give which flavour" + echo "of SAD you used to produce the transcription" + echo "you want to evaluate" + exit 1 +} + +if [ $# -lt 2 ] ; then + display_usage +fi + + + +### SCRIPT STARTS +case $system in +"tocomboSad"|"opensmileSad"|"ldcSad"|"noisemesSad|lenaSad") + sh $UTILS/evalSAD.sh $audio_dir $system + ;; +"yunitate"|"lenaDiar") + sh $UTILS/evalDiar.sh $audio_dir $system + ;; +"diartk") + sad=$3 + sh $UTILS/evalDiar.sh $audio_dir $system $sad + ;; +*) + display_usage + ;; + +esac diff --git a/launcher/ldcSad.sh b/launcher/ldcSad.sh new file mode 100644 index 0000000..83a42ce --- /dev/null +++ b/launcher/ldcSad.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + +### Read in variables from user +audio_dir=$BASEDIR/$1 + +### Other variables speicfic to this script +LDC_SAD_DIR=$REPOS/ldc_sad_hmm +workdir=$audio_dir/temp/diartk +mkdir -p $workdir + +### SCRIPT STARTS +if [ $# -ne 1 ]; then + echo "Usage: ldcSad.sh " + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +# Check audio_dir to see if empty or if contains empty wav +bash $UTILS/check_folder.sh $audio_dir + +# Set CWD as LDC_SAD_HMM +cd $LDC_SAD_DIR + +# launch ldc +$conda_dir/python perform_sad.py -L $workdir $audio_dir/*.wav +echo "finished using ldcSad_hmm. Please look inside $1 to see the output in *.rttm format" + +# move all files to name them correctly +for wav in `ls $audio_dir/*.wav`; do + # retrieve filename and remove .wav + base=$(basename $wav .wav) + rttm_out=$workdir/ldcSad_${base}.rttm + if [ -s $workdir/${base}.lab ]; then + grep ' speech' $workdir/${base}.lab | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $rttm_out + else + touch $rttm_out + fi +done diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh new file mode 100644 index 0000000..2fd5bc2 --- /dev/null +++ b/launcher/noisemesSad.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# noisemes_sad.sh +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run OpenSAT with hard coded models & configs found here and in /vagrant + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to OpenSAT (go on folder up and to opensat) +OPENSATDIR=$(dirname $BASEDIR)/OpenSAT + +if [ $# -ne 1 ]; then + echo "Usage: noisemes_sad.sh " + echo "where dirname is a folder on the host" + echo "containing the wav files (/vagrant/dirname/ in the VM)" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + +# let's get our bearings: set CWD to path of OpenSAT +cd $OPENSATDIR + +# make output folder for features, below input folder +mkdir -p $audio_dir/feature + +# first features +echo "extracting features for speech activity detection" +for file in `ls $audio_dir/*.wav`; do + SSSF/code/feature/extract-htk-vm2.sh $file +done + +# then confidences +#python SSSF/code/predict/1-confidence-vm3.py $1 +echo "detecting speech and non speech segments" +$conda_dir/python SSSF/code/predict/1-confidence-vm5.py $audio_dir +echo "finished detecting speech and non speech segments" + +# take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. +for sad in `ls $audio_dir/hyp_sum/*.lab`; do + base=$(basename $sad .lab) + rttm_out=noisemes_sad_${base}.rttm + if [ -s $sad ]; then + grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out + else + touch $audio_dir/$rttm_out + fi +done + +# simple remove hyp and feature +rm -rf $audio_dir/hyp_sum $audio_dir/feature +# mv hyp and features folders to a temp that the user can delete. +#if [ ! -d "$audio_dir/noiseme_sad_temp" ]; then +# mkdir -p $audio_dir/noiseme_sad_temp +#fi +# +#if [! -d "$audio_dir/noiseme_sad_temp" ]; then +# mv $audio_dir/hyp_sum $audio_dir/noiseme_sad_temp +#else +# echo "can't move hyp_sum/ folder to noiseme_sad_temp/ because temp is already full" +#fi +# +#if [! -d "$audio_dir/noiseme_sad_temp" ]; then +# mv $audio_dir/feature $audio_dir/noiseme_sad_temp +#else +# echo "can't move features/ folder to noiseme_sad_temp/ because temp is already full" +#fi +# diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh new file mode 100644 index 0000000..5e60b5a --- /dev/null +++ b/launcher/opensmileSad.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + +### Read in variables from user +audio_dir=$BASEDIR/$1 + +### Other variables speicfic to this script +OSHOME=$REPOS/openSMILE-2.1.0/ +CONFIG_FILE=$UTILS/vad_segmenter_aclew.conf +OPENSMILE=$OSHOME/bin/linux_x64_standalone_static/SMILExtract +workdir=$audio_dir/temp/opensmileSad +mkdir -p $workdir + +### SCRIPT STARTS + +if [ $# -lt 1 ]; then + echo "USAGE: $0 " + exit 1 +fi + +filename=$(basename "$1") +dirname=$(dirname "$1") +extension="${filename##*.}" +basename="${filename%.*}" + + +cd $OSHOME/scripts/vad + +# Use OpenSMILE 2.1.0 +for sad in `ls $audio_dir/*.wav`; do + + file=$sad + id=`basename $file` + id=${id%.wav} + > $audio_dir/${id}.txt #Make it empty if already present + echo "Processing $id ..." + LD_LIBRARY_PATH=$BASEDIR/usr/local/lib \ + $OPENSMILE \ + -C $CONFIG_FILE \ + -I $file \ + -turndebug 1 \ + -noconsoleoutput 1 \ + -saveSegmentTimes $workdir/${id}.txt \ + -logfile $workdir/opensmile-vad.log > /dev/null +done + +for output in $(ls $workdir/*.txt); do + id=$(basename $output .txt) + awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > $audio_dir/opensmileSad_$id.rttm +done + +# Delete temporary folder +rm -rf $workdir \ No newline at end of file diff --git a/launcher/test.sh b/launcher/test.sh new file mode 100644 index 0000000..b293cce --- /dev/null +++ b/launcher/test.sh @@ -0,0 +1,249 @@ +#!/bin/bash +# +# This script tests numerous tools +# from a downloaded 5 minute section of the HomeBank VanDam daylong audio sample +# ("ACLEW Starter" data) + +# this doesn't work because .bashrc exits immediately if not running interactively +#source /home/vagrant/.bashrc -i +# instead: +export PATH=/home/vagrant/anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin +LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH" + +conda_dir=/home/vagrant/anaconda/bin + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/vagrant/tools +BASEDIR=`dirname $SCRIPT` + +# Paths to Tools +LDC_SAD_DIR=$(dirname $BASEDIR)/ldcSad_hmm +OPENSATDIR=$(dirname $BASEDIR)/OpenSAT # noisemes +OPENSMILEDIR=$(dirname $BASEDIR)/openSMILE-2.1.0/ +TOCOMBOSAD=$(dirname $BASEDIR)/To-Combo-SAD +DIARTKDIR=$(dirname $BASEDIR)/ib_diarization_toolkit +#TALNETDIR=$(dirname $BASEDIR)/TALNet +DSCOREDIR=$(dirname $BASEDIR)/dscore +YUNITATORDIR=$(dirname $BASEDIR)/Yunitator + +FAILURES=false + +echo "Starting tests" +echo "Downloading test audio..." + +cd /vagrant/data +# get transcript +wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip +unzip -q -o VanDam-Daylong.zip + +# This is the working directory for the tests; right beside the input +cd VanDam-Daylong/BN32/ +# Get daylong recording from the web +wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 + +WORKDIR=`pwd` +DATADIR=data/VanDam-Daylong/BN32 # relative to /vagrant, used by launcher scripts +BASE=BN32_010007 # base filename for test input file, minus .wav or .rttm suffix +BASETEST=${BASE}_test +START=2513 # 41:53 in seconds +STOP=2813 # 46:53 in seconds + +# get 5 minute subset of audio +sox $BASE.mp3 $BASETEST.wav trim $START 5:00 >& /dev/null 2>1 + +# convert CHA to reliable STM +/home/vagrant/tools/chat2stm.sh $BASE.cha > $BASE.stm 2>/dev/null +# convert STM to RTTM as e.g. BN32_010007.rttm +# shift audio offsets to be 0-relative +cat $BASE.stm | awk -v start=$START -v stop=$STOP -v file=$BASE -e '{if (($4 > start) && ($4 < stop)) print "SPEAKER",file,"1",($4 - start),($5 - $4),"","","","","" }' > $BASETEST.rttm +TEST_RTTM=$WORKDIR/$BASETEST.rttm +TEST_WAV=$WORKDIR/$BASETEST.wav + + +# Check for HTK +echo "Checking for HTK..." +if [ -s /usr/local/bin/HCopy ]; then + echo "HTK is installed." +else + echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" + echo " and rename it to HTK.tar.gz ?" +fi + +# First test in ldcSad_hmm +echo "Testing LDC SAD..." +if [ -s $LDC_SAD_DIR/perform_sad.py ]; then + cd $LDC_SAD_DIR + TESTDIR=$WORKDIR/ldcSad-test + rm -rf $TESTDIR; mkdir -p $TESTDIR + $conda_dir/python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldcSad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} + # convert output to rttm, for diartk. + grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm + if [ -s $TESTDIR/$BASETEST.rttm ]; then + echo "LDC SAD passed the test." + else + FAILURES=true + echo " LDC SAD failed - no output RTTM" + fi +else + echo " LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" +fi + + +# now test Noisemes +echo "Testing noisemes..." +cd $OPENSATDIR +TESTDIR=$WORKDIR/noisemes-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +<<<<<<< HEAD +./runDiarNoisemes.sh $TESTDIR > $TESTDIR/nosiemes-test.log 2>&1 || (echo "Noisemes failed - dependencies" && FAILURES=true) +cp $TESTDIR/hyp_sum/$BASETEST.rttm $TESTDIR +======= +./runDiarNoisemes.sh $TESTDIR > $TESTDIR/nosiemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} +>>>>>>> 053a3d0b196066a04d60bf41fbc2b62843374814 + +if [ -s $TESTDIR/hyp_sum/$BASETEST.rttm ]; then + echo "Noisemes passed the test." +else + FAILURES=true + echo " Noisemes failed - no RTTM output" +fi +# clean up +rm -rf $OPENSATDIR/SSSF/data/feature $OPENSATDIR/SSSF/data/hyp + + +# now test OPENSMILEDIR +echo "Testing OpenSmile SAD..." +cd $OPENSMILEDIR +TESTDIR=$WORKDIR/opensmile-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +<<<<<<< HEAD +/home/vagrant/tools/opensmile_sad.sh $DATADIR/opensmile-test >$TESTDIR/opensmile-test.log || (echo "OpenSmile SAD failed - dependencies" && FAILURES=true) +======= +/home/vagrant/tools/opensmile_sad.sh data/VanDam-Daylong/BN32/opensmile-test >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} +>>>>>>> 053a3d0b196066a04d60bf41fbc2b62843374814 + +if [ -s $TESTDIR/opensmile_sad_$BASETEST.rttm ]; then + echo "OpenSmile SAD passed the test." +else + FAILURES=true + echo " OpenSmile SAD failed - no RTTM output" +fi + +# now test TOCOMBOSAD +echo "Testing ToCombo SAD..." +cd $TOCOMBOSAD +TESTDIR=$WORKDIR/tocombo_sad-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +<<<<<<< HEAD +/home/vagrant/tools/tocombo_sad.sh $DATADIR/tocombo_sad-test > $TESTDIR/tocombo_sad_test.log 2>&1 || (echo "TOCOMBO SAD failed - dependencies" && FAILURES=true) +======= +/home/vagrant/tools/tocombo_sad.sh data/VanDam-Daylong/BN32/tocombo_sad-test > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} +>>>>>>> 053a3d0b196066a04d60bf41fbc2b62843374814 + +if [ -s $TESTDIR/tocombo_sad_$BASETEST.rttm ]; then + echo "TOCOMBO SAD passed the test." +else + FAILURES=true + echo " TOCOMBO SAD failed - no output RTTM" +fi + + +# finally test DIARTK +echo "Testing DIARTK..." +cd $DIARTKDIR +TESTDIR=$WORKDIR/diartk-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +# run like the wind +./run-rttm.sh $TEST_WAV $TEST_RTTM $TESTDIR > $TESTDIR/diartk-test.log 2>&1 +if grep -q "command not found" $TESTDIR/diartk-test.log; then + echo " Diartk failed - dependencies (probably HTK)" + FAILURES=true +else + if [ -s $TESTDIR/$BASETEST.rttm ]; then + echo "DiarTK passed the test." + else + FAILURES=true + echo " Diartk failed - no output RTTM" + fi +fi + +# finally test Yunitator +echo "Testing Yunitator..." +cd $YUNITATORDIR +TESTDIR=$WORKDIR/yunitator-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +# let 'er rip +./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/Yunitemp/$BASETEST.rttm ]; then + echo "Yunitator passed the test." +else + FAILURES=true + echo " Yunitator failed - no output RTTM" +fi + + +# Test DSCORE +echo "Testing Dscore..." +cd $DSCOREDIR +TESTDIR=$WORKDIR/dscore-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +cp -r test_ref test_sys $TESTDIR +rm -f test.df +python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/test.df ]; then + echo "DScore passed the test." +else + echo " DScore failed the test - output does not match expected" + FAILURES=true +fi + + +# testing LDC evalSAD (on opensmile) +echo "Testing LDC evalSAD" +<<<<<<< HEAD +cd $LDC_SAD_DIR +TESTDIR=$WORKDIR/opensmile-test +cp $WORKDIR/$BASETEST.rttm $TESTDIR +~/tools/eval.sh $TESTDIR opensmile > $WORKDIR/ldcSad-test/ldc_evalSAD.log 2>&1 || (echo "LDC evalSAD failed - dependencies" && FAILURES=true) +# clean up +rm $TESTDIR/$BASETEST.rttm +if [ -s $TESTDIR/opensmile_sad_eval.df ]; then + echo "LDC evalSAD passed the test" +======= +if [ -d $LDC_SAD_DIR ]; then + cd $LDC_SAD_DIR + TESTDIR=$WORKDIR/opensmile-test + cp $WORKDIR/$BASETEST.rttm $TESTDIR + ~/tools/eval.sh $DATADIR/opensmile-test opensmile > $WORKDIR/ldcSad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} + if [ -s $TESTDIR/opensmile_sad_eval.df ]; then + echo "LDC evalSAD passed the test" + else + echo " LDC evalSAD failed - no output .df" + FAILURES=true + fi +>>>>>>> 053a3d0b196066a04d60bf41fbc2b62843374814 +else + echo " LDC evalSAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" + FAILURES=true +fi + + +# test finished +if $FAILURES; then + echo "Some tools did not pass the test, but you can still use others" +else + echo "Congratulations, everything is OK!" +fi + +# results +echo "RESULTS:" +for f in /vagrant/$DATADIR/*-test/*.rttm; do $BASEDIR/sum-rttm.sh $f; done +echo "DSCORE:" +cat /vagrant/data/VanDam-Daylong/BN32/dscore-test/test.df +echo "EVAL_SAD:" +cat $TESTDIR/opensmile_sad_eval.df diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh new file mode 100644 index 0000000..8eba2d0 --- /dev/null +++ b/launcher/tocomboSad.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + + +### Read in variables from user +audio_dir=$BASEDIR/1 +trs_format=$2 + + +### Other variables speicfic to this script +# create temp dir +workdir=$audio_dir/temp/tocomboSad +mkdir -p $workdir +TOCOMBOSADDIR=$REPOS/To-Combo-SAD +MCR=/usr/local/MATLAB/MATLAB_Runtime/v93 + +### SCRIPT STARTS + +if [ $# -ne 1 ]; then + echo "Usage: tocombo_sad.sh " + echo "where dirname is a folder on the host" + echo "containing the wav files (/vagrant/dirname/ in the VM)" + exit 1 +fi + +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + +# let's get our bearings: set CWD to path of ToComboSAD +cd $TOCOMBOSADDIR + +mkdir -p $workdir/feat +rm -f $workdir/filelist.txt +touch $workdir/filelist.txt + +# create temp dir to store audio files with 1 channels, if needed (i.e. if audio to treat has 2 or more channels.) +# Indeed, To Combo Sad Fails when there are more than 1 channels. +for f in $audio_dir/*.wav; do + # Check if audio has 1 channel or more. If it has more, use sox to create a temp audio file w/ 1 channel. + n_chan=$(soxi $f | grep Channels | cut -d ':' -f 2) + if [[ $n_chan -gt 1 ]]; then + base=$(basename $f) + sox -c $n_chan $f -c 1 $workdir/$base + f=$workdir/$base + fi + + echo $f >> $workdir/filelist.txt + +done +echo "finished" + +export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64: + +./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt + +# Retrieve the outputs from the temp folder +mv $workdir/*ToCombo.txt $audio_dir + +#convert to rttms +for f in $audio_dir/*.ToCombo.txt; do + bn=`basename $f .wav.ToCombo.txt` + python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > $audio_dir/tocombo_sad_$bn.rttm +done + +# Delete temporary folder +rm -rf $workdir \ No newline at end of file diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh new file mode 100644 index 0000000..01d58f2 --- /dev/null +++ b/launcher/yunitate.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run OpenSAT with hard coded models & configs found here and in /vagrant +# assumes Python environment in /home/${user}/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to Yunitator (go one folder up and to Yunitator) +YUNITATDIR=$(dirname $BASEDIR)/Yunitator + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of Yunitator +cd $YUNITATDIR + +# Iterate over files +echo "Starting" +for f in `ls $audio_dir/*.wav`; do + ./runYunitator.sh $f +done + +echo "$0 finished running" + +# take all the .rttm in $audio_dir/Yunitemp/ and move them to /vagrant/data +for sad in `ls $audio_dir/Yunitemp/*.rttm`; do + _rttm=$(basename $sad) + rttm=$audio_dir/yunitator_${_rttm} + # Remove not needed SIL lines + # sed -i '/ SIL /d' $sad + mv $sad $rttm +done + +# simply remove hyp and feature +rm -rf $audio_dir/Yunitemp diff --git a/toolbox/README.md b/toolbox/README.md deleted file mode 100644 index 235eca6..0000000 --- a/toolbox/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## Toolbox ## -A place to store utility programs. (Not run scripts for proper Tools like DiarTK, Yunitator, OpenSmile, etc. which have their own repository) - -### rttm2labels.py ### -This tool accepts on standard input an RTTM file and produces on standard output a text file that can be imported and displayed along -audio waveforms in Audacity. Audacity prefers the label files to have a `.txt` extension, but any filename can work. - 1. Example usage: `cat test2.rttm | python toolbox/rttm2labels.py > test2.txt` - 2. Run Audacity, opening the corresponding WAV file, e.g. `audacity test2.wav` - 3. Using the menu File->Import->Labels... bring up the file selection dialog and navigate to the labels file e.g. test2.txt - 4. You should now see a labels track beneath the audio waveform track in Audacity's edit window - - ### other utilities here ### - diff --git a/utils/.DS_Store b/utils/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..17c15323e9fc7e01f36bd4b08d901ca2dd7b15cb GIT binary patch literal 6148 zcmeHKyH3ME5S)b+kAHDXxOnQv9s3#Y`S!)o}jI@xMMu{fRYZ&42GiHcG{ z3d|L_%t0>C4=4(Fhg;QeCnGZTqKLf6dObYz90$;G87Bm0= literal 0 HcmV?d00001 diff --git a/utils/README.md b/utils/README.md new file mode 100755 index 0000000..5d3acd0 --- /dev/null +++ b/utils/README.md @@ -0,0 +1,105 @@ +# WUT +This repository contains wrappers to use all the tools available inside the ACLEW Diarization VM. +These wrappers were created in order to create a more simple user experience + +## Overall summary + +### SAD tools +``` +ldc_sad.sh +noisemes_sad.sh +noisemes_full.sh +opensmile_sad.sh +tocombo_sad.sh +``` +### Talker Diarization tools +``` +diartk.sh +yunitate.sh +yuniSeg.sh +``` +### Scoring tools +``` +eval.sh +evalDiar.sh +evalSAD.sh +``` +### VM Self-test +``` +test.sh +``` +### Utilities +``` +chat2stm.sh +check_folder.sh +chunk.sh +high_volubility.py +parse_cha_xml.py +``` + + +## Further information about some of these + + + +### elan2rttm.py + +Convert annotations made using the ELAN tool, in .eaf format, into rttm transcriptions. Please note that, using this script, some information is lost, notably +the vocal maturity annotation (coded in tier vcm@CHI), does not appear in the RTTM format. These information could be retrieved and put in the rttm. If you need this information in the RTTM, please raise an issue on github. + +### textgrid2rttm.py + +Convert annotations made using Praat, in .TextGrid format, into rttm transcriptions. Requires: + +* [pympi](https://github.com/dopefishh/pympi) +* [tgt](https://github.com/hbuschme/TextGridTools/) + +### adjust_timestamps.py + +This script is specific to the data in ACLEW, with the ACLEW annotations conventions. It takes as input a daylong recording in wav format (available on databrary), and a transcription in .eaf format that contains annotated segment coded in an "on_off" tier (or "code" tier for some corpora that were annotated before the new convention). +It then takes each annotated segment of 2 minutes, extract it from the daylong recording to output a small wav file of 2 minutes, with the name: +corpus_id_onset_offset.wav +where corpus is the name of the original corpus, id is the name of the daylong recording (which is itself the id given to the recorded child), onset is where the segment starts in the daylong recording (in seconds, with 6 digits padded with 0's if necessary), offset is where the segment ends in the daylong recording (with the same convention). +For each of these segments extracted, it also writes the annotations in rttm format, with the timestamps adapted to correspond to the small wav, and with the same name as the small wav previously written. + +### remove_overlap_rttm.py + +Take a transcription in RTTM format, and convert it to a SAD annotation in RTTM format. The SAD annotation contains less information, as it only indicated "speech" segment (i.e. the talker is written as "speech", no matter who the original talker is), and there are no overlap between speech segments. + +### make_big_corpus.sh + +This script is called to treat all the daylong recording with their annotations, using the previous adjust_timestamps.py script. It also creates gold SAD rttm using the remove_overlap_rttm.py script previously described. + +## Further info on the formats + +### RTTM + +RTTM is an annotaion format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) +This format is used by the [DiViMe](https://github.com/srvk/DiViMe). + +We provide code to translate annotations from other formats into RTTM: + +**ELAN .eaf fromat** + +WARNING: the current version does not handle subtypes when parsing annotations e.g. TIER\_ID 'CHI' would be written in the RTTM output file but 'vmc@CHI' would not. This is due to the time references being based on other TIER\_ID's annotations for subtypes. + +You should run the script as follows: + +``` +python elan2rttm.py -i my_file.eaf -o my_output_folder +``` + +**Praat TextGrid format** + +You should run the script as follows: + +``` +python textgrid2rttm.py my_input_folder +``` +### TextGrid + +TextGrid is a standard format for speech annotation, used by the Praat software. + +### Eaf + +Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. diff --git a/utils/adjust_timestamps.py b/utils/adjust_timestamps.py new file mode 100755 index 0000000..c598301 --- /dev/null +++ b/utils/adjust_timestamps.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python +# +# +import pympi as pmp +import shutil +import os +import argparse +import subprocess +from collections import defaultdict +from operator import itemgetter + + +def eaf2rttm(path_to_eaf): + """ + function to write a new .rttm file which is a transcription of the .eaf + given as input + + """ + + # in EAF, timestamps are in milliseconds, convert them to seconds + # TODO read scale from header of EAF + sampling_freq = 1000.0 + + print('\n') + # read eaf file + EAF = pmp.Elan.Eaf(path_to_eaf) + + participants = [] + + # gather all the talker's names + for k in EAF.tiers.keys(): + + if 'PARTICIPANT' in EAF.tiers[k][2].keys(): + + if EAF.tiers[k][2]['PARTICIPANT'] not in participants: + + participants.append(EAF.tiers[k][2]['PARTICIPANT']) + + print('participants: {}'.format(participants)) + + base = os.path.basename(path_to_eaf) + name = os.path.splitext(base)[0] + + print('parsing file: {}'.format(name)) + + # get the begining, ending and transcription for each annotation of + # each tier + rttm = [] + for participant in participants: + if participant not in EAF.tiers: + continue + for _, val in EAF.tiers[participant][0].items(): + # Get timestamps + start = val[0] + end = val[1] + + t0 = EAF.timeslots[start] / sampling_freq + length = EAF.timeslots[end] / sampling_freq - t0 + + # get transcription + transcript = val[2] + + rttm.append((name, t0, length, transcript, participant)) + + return rttm + +def eaf2rttm_CAS(path_to_eaf): + """ + function to write a new .rttm file which is a transcription of the .eaf + given as input + + """ + + sampling_freq = 1000.0 + + print('\n') + EAF = pmp.Elan.Eaf(path_to_eaf) + + participants = [] + + for k in EAF.tiers.keys(): + + if 'PARTICIPANT' in EAF.tiers[k][2].keys(): + + if EAF.tiers[k][2]['PARTICIPANT'] not in participants: + + participants.append(EAF.tiers[k][2]['PARTICIPANT']) + + print('participants: {}'.format(participants)) + + base = os.path.basename(path_to_eaf) + name = os.path.splitext(base)[0] + + print('parsing file: {}'.format(name)) + + # get the begining, ending and transcription for each annotation of + # each tier + rttm = [] + for participant in participants: + + for _, val in EAF.tiers[participant][0].items(): + # Get timestamps + start = val[0] + end = val[1] + + t0 = EAF.timeslots[start] / sampling_freq + length = EAF.timeslots[end] / sampling_freq - t0 + + # get transcription + transcript = val[2] + + rttm.append((name, t0, length, transcript, participant)) + return rttm + +def write_rttm(output, rttm_path, annotations): + """ write annotations to rttm_path""" + + with open(os.path.join(output, rttm_path), 'w') as fout: + rttm_name = rttm_path.split('.')[0] + print len(annotations) + for name, t0, length, transcript, participant in annotations: + fout.write(u"SPEAKER\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n".format + (rttm_name, 1, "%.3f" %t0, "%.3f" %length, transcript, + "", participant, 1 )) + +def get_all_on_offs(eaf): + """ + Return all the annotated intervals from the current file + """ + EAF = pmp.Elan.Eaf(eaf) + + all_intervals = EAF.tiers['on_off'][0] + + # get the segments delimited for "on_off" tier, + # as those give the timestamps between which are the annotations + on_offs = [] + for key in all_intervals: + interv = all_intervals[key] + beg_end = interv[2] + beg, end = [float(time) for time in beg_end.split('_')] + # store in seconds, not milliseconds + on_offs.append((beg/1000.0, end/1000.0)) + + return on_offs + +def get_all_on_offs_CAS(eaf): + """ + Return all the annotated intervals from the current file + """ + EAF = pmp.Elan.Eaf(eaf) + + all_intervals = EAF.tiers['code'][0] + + on_offs = [] + for key in all_intervals: + interv = all_intervals[key] + beg_end = interv[2] + _beg = interv[0] + _end = interv[1] + beg = EAF.timeslots[_beg] + end = EAF.timeslots[_end] + + # store in seconds, not milliseconds + on_offs.append((beg/1000.0, end/1000.0)) + + return on_offs + +def cut_audio(on_offs, input_audio, dest): + """ + Extract from the daylong recordings the small parts that have + been annotated + """ + + # for each annotated segment, call sox to extract the part from the + # wav file + # Also, write each onset/offset with 6 digits + for on, off in on_offs: + audio_base = os.path.splitext(input_audio)[0] + wav_name = os.path.basename(audio_base) + dir_name = os.path.split(os.path.dirname(audio_base))[-1] + + # add the necessary number of 0's to the onsets/offsets + # to have 6 digits + str_on = str(int(on)) + str_off = str(int(off)) + + str_on = (6 - len(str_on)) * '0' + str_on + str_off = (6 - len(str_off)) * '0' + str_off + output_audio = '_'.join([dir_name, wav_name, + str_on, str_off]) + '.wav' + cmd = ['sox', input_audio, os.path.join(dest, output_audio), + 'trim', str(on), str(off - on)] + print " ".join(cmd) + subprocess.call(cmd) + +def extract_from_rttm(on_offs, rttm): + """ + For each minute of annotation, extract the annotation of that minute + from the transcription and write a distinct .rttm file with all the + timestamps with reference to the begining of that segment. + """ + sorted_rttm = sorted(rttm, key=itemgetter(1)) + + # create dict { (annotated segments) -> [annotation] } + extract_rttm = defaultdict(list) + for on, off in on_offs: + for name, t0, length, transcript, participant in sorted_rttm: + end = t0 + length + if (on <= t0 < off) or (on <= end < off): + # if the current annotation is (at least partially) + # contained in the current segment, append it. + # Adjust the segment to strictly fit in on-off + t0 = max(t0, on) + end = min(end, off) + length = end - t0 + extract_rttm[(on, off)].append((name, t0 - on, + length, + transcript, participant)) + elif (on > t0) and (end >= off): + # if the current annotation completely contains the annotated + # segment, add it also. This shouldn't happen, so print a + # warning also. + print('Warning: speaker speaks longer than annotated segment.\n' + 'Please check annotation from speaker {},' + 'between {} {}, segment {} {}.\n'.format(name, t0, + end, on, off)) + extract_rttm[(on, off)].append((name, 0, off - on, + transcript, participant)) + elif (end < on): + # wait until reach segment + continue + elif (t0 >= off): + # no point in continuing further since the rttm is sorted. + break + + return extract_rttm + +def main(): + """ + Take as input one eaf and wav file, and extract the segments from the + wav that have been annotated. + """ + parser = argparse.ArgumentParser(description="extract annotated segments") + parser.add_argument('eaf', type=str, + help='''Path to the transcription of the wave file, ''' + ''' in eaf format.''') + parser.add_argument('wav', type=str, + help='''Path to the wave file to treat''') + parser.add_argument('output', type=str) + parser.add_argument('-c', '--CAS', action='store_true', + help='''By default the script detects the segments''' + ''' using the "on_off" tier. For the CAS corpus,''' + ''' we should use the "code" tier.\n''' + ''' Enable this option when treating the CAS corpus''') + args = parser.parse_args() + + output = args.output + print output + #if not os.path.isdir( os.path.join(output, 'treated')): + # os.makedirs(os.path.join(output, 'treated')) + #if not os.path.isdir( os.path.join(output, 'treated', 'talker_role')): + # os.makedirs(os.path.join(output, 'treated', 'talker_role')) + + if args.CAS: + # read transcriptions + complete_rttm = eaf2rttm_CAS(args.eaf) + + # extract annotated segments + on_offs = get_all_on_offs_CAS(args.eaf) + else: + # read transcriptions + complete_rttm = eaf2rttm(args.eaf) + + # extract annotated segments + on_offs = get_all_on_offs(args.eaf) + + # cut audio files according to on_off/code tier in eaf annotations + cut_audio(on_offs, args.wav, output) + + # store in dict the annotations to write in rttm format + extract_rttm = extract_from_rttm(on_offs, complete_rttm) + + # write one rttm file per on_off/tier segment + for key in extract_rttm: + base = os.path.basename(args.eaf) + + # get the name of the corpus by taking the name of the folder and removing "raw" + dir_name = os.path.split( os.path.dirname(args.eaf) )[-1].split('_')[-1] + + name = os.path.splitext(base)[0] + # check is initials of annotator are in eaf name + if '-' in name: + name = name.split('-')[0] + + # add 0's to have exactly 6 digits (i.e. 1 second is 000001 s) + str_on = str(int(key[0])) + str_off = str(int(key[1])) + + str_on = (6 - len(str_on)) * '0' + str_on + str_off = (6 - len(str_off)) * '0' + str_off + + rttm_path = '_'.join([dir_name, name, + str_on, str_off]) + '.rttm' + write_rttm(output, rttm_path, extract_rttm[key]) + + +if __name__ == '__main__': + main() diff --git a/utils/catspa-syllabify-corpus.pl b/utils/catspa-syllabify-corpus.pl new file mode 100755 index 0000000..36a8c4a --- /dev/null +++ b/utils/catspa-syllabify-corpus.pl @@ -0,0 +1,93 @@ +#!/usr/bin/perl + +# Alex Cristia alecristia@gmail.com 2015-07-13 adapted VERY MINIMALLY this code from scripts +# distributed by Lawrence Phillips & Lisa Pearl, 12/23/13 (UCI-Brent-Syllabic Corpus) - credit is owed mainly to those authors + +# Uses the maximum onset principle to fully syllabify a corpus +use File::Basename; + +$language=$ARGV[0]; +$filecorpus=$ARGV[1]; +$output=$ARGV[2]; +$dirname=dirname($filecorpus); + +#print "\n the language is $language\n"; +# /input/ OR /scripts/ ? +# Save valid onsets from ValidOnsets.txt +%onsets = {}; +open(ONSETS, "<$dirname/$language-ValidOnsets.txt") or die("Couldn't open $dirname/$language-ValidOnsets.txt\n"); +while(defined($fileline = )){ + chomp($fileline); + #print "$fileline\n"; + $onsets{$fileline} = 1; #This is an odd way of stating things + #print "added"; +} +#print "out of the while"; +close(ONSETS); + +# Save valid vowels from Vowels.txt +%vowels = {}; +open(VOWELS, "<$dirname/$language-Vowels.txt") or die("Couldn't open $dirname/$language-Vowels.txt\n"); +my $vowels = ; +close(VOWELS); +#print "$vowels\n"; + +# Go through CORPUS.txt, +# for nonsyllabified words: for each syllable, find its vowel, and its maximum onset, given acceptable onsets and beginning of word. +# print syllabified version to syllabified-CORPUS.txt. +open(SYLLABIFIED, ">$output") or die("Couldn't open $output for writing\n"); +open(CORPUS, "<$filecorpus") or die("Couldn't open $filecorpus for reading"); + + + +while(defined($fileline = )){ + #print "entered first while\n"; + chomp($fileline); + $currline = $fileline; + @wordarray = split(" ", $currline); # divide the line into a set of words + $syllline="";#we start with a clean slate for each line + while(@wordarray > 0){ + $currword = pop(@wordarray); # cut out the last word in the word array & put it in currword + #print "now looking at $currword\n"; + @chararray = split(//, $currword); + + $syllword="";#we start with a clean slate for each word + $currsyllable=""; #and for the syllable + + while(@chararray > 0){ + $currchar = pop(@chararray); # cut out the last char in the char array for this word & put it in currchar + $currsyllable = $currchar.$currsyllable; # append currchar to current syllable - that will be necessary regardless of whether it's a vowel or a coda + # if hit a vowel.. + #if($currchar =~ /[ae3EiOo0u]/){ + if($currchar =~ /[$vowels]/){ + # print "$currchar\n"; + #if(@chararray[@chararray-1] !=~ /[ae3EiOo0u]/){ + if(@chararray[@chararray-1] !=~ /[$vowels]/){ + # print "@chararray[@chararray-1]\n"; + #if this char is a vowel and the previous one is not, then we need to make the onset + $onset = ""; #we start with nothing as the onset + #then we want to take one letter at a time and check whether their concatenation makes a good onset + while(@chararray > 0 && exists($onsets{@chararray[@chararray-1] . $onset})){ + #print "$onsets{@chararray[@chararray-1] . $onset}\n"; + $currchar = pop(@chararray); + $onset = $currchar . $onset; + } + #we get here either because we've concatenated the onset+rest or because there was no onset and the preceding element is a vowel, so this is the end of the syllable + $currsyllable = $onset . $currsyllable; + # add syllable to word entry + } + $syllword = "\/" . $currsyllable . $syllword; + $currsyllable = ""; + }#we end the if we are looking at a vowel + }#when we end this while there are no more characters in this word, so we can add it + $syllline=$syllword. " " . $syllline; + #print "$syllword\n"; + + } #while we work our way through the words in the line -- so when we exit this, we are ready to print out a syllabified line + if($syllline){ + print SYLLABIFIED "$syllline\n"; + } +}#while there are lines in this file + +close(SYLLABIFIED); +close(CORPUS); \ No newline at end of file diff --git a/utils/change_tsi_lena_names.py b/utils/change_tsi_lena_names.py new file mode 100755 index 0000000..88134ce --- /dev/null +++ b/utils/change_tsi_lena_names.py @@ -0,0 +1,43 @@ +import glob +import os +import re +import argparse + +parser = argparse.ArgumentParser(description="Convert the old naming convention of tsi/lena files into the new one.") +parser.add_argument('-f', '--folder', type=str, required=True, + help="path to the input folder tsi/lena (containing C25_NA_M14_20170719_56040.{wav|rttm} files).") +args = parser.parse_args() + +path_tsi_lena=os.path.join("/vagrant", args.folder) +rttm_files = glob.iglob(os.path.join(path_tsi_lena, '*.rttm')) + +for rttm in rttm_files: + dirname = os.path.dirname(rttm) + basename = os.path.splitext(os.path.basename(rttm))[0] + basename_splitted = basename.split('_') + + old_name = os.path.splitext(basename)[0] + if basename[0] == 'C' and len(basename_splitted) == 5: + new_name = '_'.join([basename_splitted[0], + basename_splitted[3], + basename_splitted[4]]) + + # Modify rttm name + new_path_rttm = os.path.join(dirname, new_name+'.rttm') + os.rename(rttm ,new_path_rttm) + + # Modify wav name + old_path_wav = os.path.join(dirname, old_name+'.wav') + new_path_wav = os.path.join(dirname, new_name+'.wav') + os.rename(old_path_wav, new_path_wav) + + # Do the change within the rttm (column 2 containing the filename) + new_name = os.path.splitext(new_name)[0] + f = open(new_path_rttm, 'r+b') + f_content = f.read() + f_content = re.sub(old_name, new_name, f_content) + f.seek(0) + f.truncate() + f.write(f_content) + f.close() + diff --git a/utils/chat2stm.sh b/utils/chat2stm.sh new file mode 100755 index 0000000..90285d6 --- /dev/null +++ b/utils/chat2stm.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# +# Shell script to convert .CHA format to .STM format +# +# ./cha2stm.sh .cha produces .stm +# +# To have this use replacement words instead of marking OOV words as "" +# swap (uncomment) the last line to change the arguments to parse_cha_xml.sh + +BASEDIR=$(dirname $0) + +if [ $# -ne 1 ]; then + echo "Usage: cha2stm.sh .cha" + echo + exit 1; +fi + +filename=$(basename "$1") +dirname=$(dirname "$1") +extension="${filename##*.}" +basename="${filename%.*}" + +# Install Java 8 and CHATTER +# First get chatter +mkdir -p ~/bin/lib +( +cd ~/bin/lib +if [ ! -f chatter.jar ]; then + wget http://talkbank.org/software/chatter.jar || exit 1 +fi + +# now get java 8 +if [ -d zulu8.17.0.3-jdk8.0.102-linux_x64 ]; then + : + #echo "Not installing Java 8 since it is already there." 1>&2 +else + echo "Downloading and installing Java 8" 1>&2 + wget http://cdn.azul.com/zulu/bin/zulu8.17.0.3-jdk8.0.102-linux_x64.tar.gz 1>&2 || exit 1 + tar -zxvf zulu8.17.0.3-jdk8.0.102-linux_x64.tar.gz 1>&2 + rm zulu8.17.0.3-jdk8.0.102-linux_x64.tar.gz 1>&2 + echo "Done installing Java 8" 1>&2 +fi +) + +if [ -f $dirname/$basename.cha ]; then + # + # First convert CHA to CHATTER xml + ~/bin/lib/zulu8.17.0.3-jdk8.0.102-linux_x64/bin/java -cp ~/bin/lib/chatter.jar org.talkbank.chatter.App -inputFormat cha -outputFormat xml -output $dirname/$basename.xml $dirname/$basename.cha + + # Convert CHATTER xml to STM + #python scripts/parse_cha_xml.py $dirname/$basename.xml --stm --replacement + python $BASEDIR/../tools/parse_cha_xml.py $dirname/$basename.xml --stm --oov +fi diff --git a/utils/check_folder.sh b/utils/check_folder.sh new file mode 100755 index 0000000..d7be677 --- /dev/null +++ b/utils/check_folder.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +check_folder=$(readlink -f $1) + +# First check that the folder is not empty +if [[ -z "$(ls -A $check_folder)" ]]; then + echo "data folder is empty!" + exit +else + echo "wavs and transcriptions found !" +fi + +# Then, check the consistency of all the files -> check if +# the wav have no amplitude +# (credit to http://decided.ly/2013/02/06/find-silent-audio-files/) +## A quick hack like script to list all the files that have +## a low amplitude. + +Max=0.0 # Any amplitude greater than this will NOT be listed +#OutList=~/output.list # The name of the file that contains a +# list of file names only of all the +# low-amplitude files. + +# rm $OutList +for each in `ls $check_folder/*.wav` +do + amplitude=$(sox "$each" -n stat 2>&1 | grep "Maximum amplitude" | cut -d ":" -f 2 | sed 's/ //g') + if [[ $(echo "if (${amplitude} > ${Max}) 1 else 0" | bc) -eq 0 ]] + then + echo "$each --> $amplitude" >&2 + echo "$each seems empty !" + fi +done + +echo "Tests finished" diff --git a/utils/chunk.sh b/utils/chunk.sh new file mode 100755 index 0000000..572e163 --- /dev/null +++ b/utils/chunk.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# chunk.sh - break files into 5 minute segments in a special folder +# then run a processing script on the folder of chunks +# then merge the resulting RTTMs back together into the +# folder where the input file resides +# +# assumes $1 is full path to a large WAV file +# assumes $2 is path to script to run (such as are found in tools/ +# that takes a folder name in /vagrant, and processes all WAVs in it) +# +# produces a single .rttm in the same folder $1 was found in +# +# uses /vagrant/chunk/ for temporary results + +if [[ $# < 2 ]]; then + echo "Usage: " $0 " " + echo " e.g. tools/chunk.sh /vagrant/ami.wav tools/yunitate.sh" + exit +fi + +WORKFOLDER="/vagrant/chunk" + +# remember basename for later ;) +filename=$(basename "$1") +basename="${filename%.*}" # name without extension +dirname=`dirname $1` # input folder + +if [[ -f $WORKFOLDER ]]; then + # clean out the folder first + rm -rf $WORKFOLDER/* +else + # create the folder + mkdir -p $WORKFOLDER +fi + +# Create 5 minute (except for last piece) named chunk-001.wav chunk-002.wav etc. +sox $1 $WORKFOLDER/chunk-.wav trim 0 300 : newfile : restart + +# run whichever tool you were going to run over the $WORKFOLDER folder +# assume tools are like in ~/tools and assume path is /vagrant/ +# but are only given +$2 chunk + +# assume output is in $WORKFOLDER/chunk-00x.rttm - rename/ rejoin + +OUTFILE=$dirname/$basename.rttm +rm -f $OUTFILE # don't want to append to existing one! +touch $OUTFILE + +COUNT=0 +for f in `ls $WORKFOLDER/*chunk-*.rttm`; do + + # add $COUNT seconds to start time (column 4) of RTTM, and concatenate to $OUTFILE + cat $f | awk -v ADDME=$COUNT '{print $1,$2,$3,($4+ADDME),$5,$6,$7,$8,$9}' >> $OUTFILE + + # increment COUNT in 5 minutes' worth of secons (300) + COUNT=$(($COUNT + 300)) + +done + diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh new file mode 100755 index 0000000..47e5a9e --- /dev/null +++ b/utils/create_ref_sys.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +audio_dir=$1 +model_prefix=$2 +create_lab=$3 + +base_directory=$(echo "$audio_dir" | awk -F "/" '{print $2}') + +if [ "$base_directory" != "vagrant" ]; then + audio_dir=/vagrant/$1 +fi + +display_usage() { + echo "Given a folder, and a model prefix, creates a folder that contains the reference transcriptions" + echo "and another folder containing the predicted transcriptions." + echo "usage: $0 [audio_dir] [model_prefix] [create_lab]" + echo " audio_dir The directory that contains the audio files and the transcription." + echo " model_prefix The model prefix (beginning of the files generated by the model)." + echo " create_lab (Optional, true or false) Indicates whether to create .lab files in the reference folder." + exit 1 + } + +if ! [[ $# =~ ^(2|3)$ ]]; then + display_usage +fi + +if [ -z "$3" ]; then + create_lab=false +fi + + +if ! [[ $model_prefix =~ ^(ldc_sad|noisemes_sad|tocombo_sad|opensmile_sad|lena_sad|lena|yunitator|\ +diartk_ldcSad|diartk_noisemesSad|diartk_tocomboSad|diartk_opensmileSad|diartk_goldSad|\ +yuniseg_ldcSad|yuniseg_noisemesSad|yuniseg_tocomboSad|yuniseg_opensmileSad|yuniseg_goldSad)$ ]]; then + echo "You're trying to create folders containing the reference transcriptions, and the predicted ones." + echo "However, you specified a wrong tool name." + echo "Please, check the name of the SAD/diarization tool." + exit 1; +fi + +# Create temp_ref folder +mkdir $audio_dir/temp_ref +for wav in `ls $audio_dir/*.wav`; do + base=$(basename $wav .wav) + cp $audio_dir/${base}.rttm $audio_dir/temp_ref/${base}.rttm + # Sort rttm by onset + sort --key 4 --numeric-sort $audio_dir/${base}.rttm -o $audio_dir/temp_ref/${base}.rttm + # Change tabulations to white-spaces + sed -i 's/\t/ /g' $audio_dir/temp_ref/${base}.rttm + # Replace two or more occurrences of whitespace by just one + sed -i 's/ \+/ /g' $audio_dir/temp_ref/${base}.rttm + if [ $create_lab == true ]; then + awk '{print $4" "($4+$5)" speech"}' $audio_dir/temp_ref/${base}.rttm > $audio_dir/temp_ref/${base}.lab + fi +done + +# Create temp_sys folder and copy all of the sys rttm inside of it +# Remove the model_prefix of it +mkdir $audio_dir/temp_sys +for rttm in `ls $audio_dir/${model_prefix}_*.rttm`; do + base=$(basename $rttm .rttm) + out=`echo $base | sed "s/${model_prefix}\_//g"` + cp $rttm $audio_dir/temp_sys/${out}.rttm + if [ $create_lab == true ]; then + echo "creating: " $audio_dir/temp_sys/${out}.lab + awk '{print $4" "($4+$5)" speech"}' $rttm > $audio_dir/temp_sys/${out}.lab + fi +done + +# check that temp_sys is not empty, otherwise exit and remove it. +if [ -z "$(ls -A $audio_dir/temp_sys)" ]; then + echo "Didn't find any transcription from the model prefix you specified. Please get the ${model_prefix}_my_file.rttm before" + rm -rf $audio_dir/temp_sys $audio_dir/temp_ref + exit +fi diff --git a/diarization.sh b/utils/diarization.sh similarity index 100% rename from diarization.sh rename to utils/diarization.sh diff --git a/utils/eaf2enriched_txt.sh b/utils/eaf2enriched_txt.sh new file mode 100755 index 0000000..5234516 --- /dev/null +++ b/utils/eaf2enriched_txt.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +INPUT_FOLDER=$1 +LANG=$2 +SCRIPT_DIR=$(dirname "$0") + +display_usage() { + echo "Given a folder containing eaf file, creates an enriched txt version of them." + echo "For each files, this script produces a txt version containing :" + echo -e "\t onset" + echo -e "\t off" + echo -e "\t speaker" + echo -e "\t cleaned up transcription" + echo -e "\t number of words" + echo -e "\t phonemized (or syllabified) version of the transcription" + echo -e "\t number of syllables" + + echo "usage: $0 [input] [language]" + echo " input The folder where to find the eaf files (REQUIRED)." + echo " output The language of the transcription : english, spanish or tzeltal (REQUIRED)." + exit 1 + } + +if [ -z "$1" ] || [ -z "$2" ] || ! [[ $LANG =~ ^(english|spanish|tzeltal)$ ]]; then + display_usage +fi + +for eaf_path in /vagrant/$1/*.eaf; do + eaf_path=${eaf_path#/vagrant/} + without_extension="${eaf_path%.*}" + echo "Converting $eaf_path files to ${without_extension}.txt ..." + python $SCRIPT_DIR/eaf2txt.py -i $eaf_path + + echo "Enriching ${without_extension}.txt" + $SCRIPT_DIR/selcha2clean.sh ${without_extension}.txt ${without_extension}_enriched.txt $LANG + + rm /vagrant/${without_extension}.txt +done \ No newline at end of file diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py new file mode 100755 index 0000000..c54a1b4 --- /dev/null +++ b/utils/eaf2txt.py @@ -0,0 +1,89 @@ +""" +This script converts an eaf file into a txt file containing the following information : + +onset offset transcription receiver speaker_tier + +It can be run either on a single eaf file, or on a whole folder containing eaf files. + +Example of use : + python tools/eaf2txt.py -i data/0396.eaf # One one file + python tools/eaf2txt.py -i data/ # On a whole folder + +About the naming convention of the output : + For each file called input_file.eaf, the result will be stored in input_file.txt +""" + +import pympi as pmp +import argparse +import os +import glob + + +def eaf2txt(path_to_eaf, output_folder, cleanup=False): + """ + Convert an eaf file to the txt format by extracting the onset, offset, ortho, + and the speaker tier. Note that the ortho field has been made by a human and needs + to be clean up. + + Parameters + ---------- + path_to_eaf : path to the eaf file. + + Write a txt whose name is the same than the eaf's one in output_folder + """ + basename = os.path.splitext(os.path.basename(path_to_eaf))[0] + output_path = os.path.join(output_folder, basename + '.txt') + output_file = open(output_path, 'w') + EAF = pmp.Elan.Eaf(path_to_eaf) + tiers = EAF.tiers + for tier in tiers: + try: + annotations = EAF.get_annotation_data_for_tier(tier) + except KeyError: + print("Tier %s ignored..." %tier) + for annotation in annotations: + parameters = EAF.get_parameters_for_tier(tier) + if 'PARTICIPANT' in parameters: + if len(annotation) == 4: + onset, offset, receiver, transcript = annotation[0], annotation[1], annotation[2], annotation[3] + elif len(annotation) == 3: + onset, offset, receiver, transcript = annotation[0], annotation[1], '', annotation[2] + else: + raise ValueError("Format unknown : %s\n" % annotation) + speaker = parameters['PARTICIPANT'] + + if cleanup: + transcript = clean_up_annotation(transcript) + output_file.write("%d\t%d\t%s\t%s\t%s\n" % (onset, offset, receiver, transcript, speaker)) + output_file.close() + +def main(): + parser = argparse.ArgumentParser(description="convert .eaf into .rttm") + parser.add_argument('-i', '--input', type=str, required=True, + help="path to the input .eaf file or the folder containing eaf files.") + args = parser.parse_args() + + # Initialize the output folder as the same folder than the input + # if not provided by the user. + if args.input[-4:] == '.eaf': + output = os.path.dirname(args.input) + else: + output = args.input + + data_dir = '/vagrant' + args.input = os.path.join(data_dir, args.input) + output = os.path.join(data_dir, output) + + if not os.path.isdir(output): + os.mkdir(output) + + if args.input[-4:] == '.eaf': # A single file has been provided by the user + eaf2txt(args.input, output) + else: # A whole folder has been provided + eaf_files = glob.iglob(os.path.join(args.input, '*.eaf')) + for eaf_path in eaf_files: + print("Processing %s" % eaf_path) + eaf2txt(eaf_path, output) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/utils/elan2rttm.py b/utils/elan2rttm.py new file mode 100755 index 0000000..0b917be --- /dev/null +++ b/utils/elan2rttm.py @@ -0,0 +1,75 @@ +""" +written in python3.5 + +script for translating .eaf annotation files into .rttm format + +WARNING: this version results in a loss of information since .rttm +only keeps speaker ID regardless of the nature of the speech (whereas +.eaf contains additional information such as speech nature e.g. MWU, VCM ...) + +This information might be recovered in an advanced version of this script + +""" + + +import pympi as pmp +import argparse +import os + + +def eaf2rttm(path_to_eaf, path_to_write_rttm): + """ + function to write a new .rttm file which is a transcription of the .eaf + given as input + + """ + + sampling_freq = 1000 + + print('\n') + EAF = pmp.Elan.Eaf(path_to_eaf) + + participants = [] + + for k in EAF.tiers.keys(): + + if 'PARTICIPANT' in EAF.tiers[k][2].keys(): + + if EAF.tiers[k][2]['PARTICIPANT'] not in participants: + + participants.append(EAF.tiers[k][2]['PARTICIPANT']) + + print('participants: {}'.format(participants)) + + base = os.path.basename(path_to_eaf) + name = os.path.splitext(base)[0] + + print('parsing file: {}'.format(name)) + + with open(os.path.join(path_to_write_rttm, name + ".rttm"), "w") as rttm: + + for participant in participants: + + for _, val in EAF.tiers[participant][0].items(): + + start = val[0] + end = val[1] + + t0 = float(EAF.timeslots[start]) / sampling_freq + length = float(EAF.timeslots[end]) / sampling_freq - t0 + + rttm.write(u"SPEAKER {} {} {} {} {} {} {} {}\n".format + (name, 1, "%.2f" % t0, "%.2f" % length, "", "", participant, 1 )) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="convert .eaf into .rttm") + parser.add_argument('-i', '--input', type=str, required=True, + help="path to the input .eaf file.") + parser.add_argument('-o', '--output', type=str, required=True, + help="path to the folder in which to write the output." + "The output .rttm file will have the same name as the " + "input file - except for the extension") + args = parser.parse_args() + +eaf2rttm(args.input, args.output) diff --git a/utils/empty_transcription.sh b/utils/empty_transcription.sh new file mode 100755 index 0000000..a5084ae --- /dev/null +++ b/utils/empty_transcription.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# +# author: the ACLEW team +# +# after all the transcriptions are extracted, +# look for wav file for which no transcription +# exist, and create empty file + +for wav in `ls $1/*.wav`; do + id=$(basename $wav .wav) + eaf=$1/$id.rttm + if [ ! -f $eaf ]; then + touch $eaf + fi +done diff --git a/utils/evalDiar.sh b/utils/evalDiar.sh new file mode 100644 index 0000000..65caef7 --- /dev/null +++ b/utils/evalDiar.sh @@ -0,0 +1,123 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to OpenSAT (go on folder up and to opensat) +DSCOREDIR=$(dirname $BASEDIR)/dscore + + +display_usage() { + echo "Usage: evalDiar.sh <>" + echo "where dirname is the name of the folder" + echo "containing the wav files, and transcription" + echo "specifies which transcription you want to use," + echo "only used if model == diartk." + echo "Model choices are :" + echo " - diartk" + echo " - yunitate" + echo "Transcription (mandatory for model == diartk) choices are:" + echo " -ldc_sad" + echo " -noisemes" + echo " -opensmile" + echo " -tocombosad" + echo " -textgrid" + echo " -eaf" + echo " -rttm" + exit 1; + +} + +if ! [[ $2 =~ ^(diartk|yunitate|lena)$ ]] || [ "$2" == "diartk" ] && [ $# -ne 3 ]; then + display_usage +fi + + +# data directory +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# Set CWD to path of Dscore +cd $DSCOREDIR + +model=$2 +if [[ $model =~ ^(diartk|yuniseg) ]]; then + trs_format=$3 + case $trs_format in + "ldc_sad") + sys_name=$model"_ldcSad" + ;; + "noisemes") + sys_name=$model"_noisemesSad" + ;; + "tocombosad") + sys_name=$model"_tocomboSad" + ;; + "opensmile") + sys_name=$model"_opensmileSad" + ;; + "textgrid") + sys_name=$model"_goldSad" + for wav in `ls $audio_dir/*.wav`; do + base=$(basename $wav .wav) + $conda_dir/python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid $audio_dir/${basename}.rttm + done + ;; + "eaf") + sys_name=$model"_goldSad" + for wav in `ls $audio_dir/*.wav`; do + base=$(basename $wav .wav) + $conda_dir/python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf $audio_dir/${basename}.rttm + done + ;; + "rttm") + sys_name=$model"_goldSad" + ;; + *) + echo "ERROR: You're trying to evaluate diartk, but the transcription system you specified is not recognized :" + echo " ldc_sad" + echo " noisemes" + echo " textgrid" + echo " eaf" + echo " rttm" + echo "Now exiting..." + exit 1 + ;; + esac +elif [ "$2" == "yunitate" ]; then + sys_name="yunitator" +elif [ "$2" == "lena" ]; then + sys_name="lena" +fi + +$BASEDIR/create_ref_sys.sh $audio_dir $sys_name + +echo "evaluating" + +$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $audio_dir/temp_ref $audio_dir/temp_sys + +# Check if some gold files are empty. If so, add a line in the eval dataframe +for fin in `ls $audio_dir/temp_ref/*.rttm`; do + base=$(basename $fin .rttm) + if [ ! -s $audio_dir/temp_ref/$base.rttm ]; then + if [ ! -s $audio_dir/temp_sys/$base.rttm ]; then + echo $base" 0 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + else + echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + fi + elif [ ! -s $audio_dir/temp_sys/$base.rttm ] && [ -s $audio_dir/temp_ref/$base.rttm ]; then + echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + fi +done + +echo "done evaluating, check $1/${sys_name}_eval.df for the results" +# remove temps +rm -rf $audio_dir/temp_ref $audio_dir/temp_sys diff --git a/utils/evalSAD.sh b/utils/evalSAD.sh new file mode 100644 index 0000000..509e5ed --- /dev/null +++ b/utils/evalSAD.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + + +### Read in variables from user +# data directory +audio_dir=$BASEDIR/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# check system to evaluate +system=$2 + + +### Other variables speicfic to this script +# Path to scoring tool NOTE: NOT dscore! +ldcSad_DIR=$REPOS/ldc_sad_hmm +# create temp dir +workdir=$audio_dir/temp/evalSad/ +mkdir -p $workdir + + +### SCRIPT STARTS +if [[ $system = "ldcSad" ]]; then + sys_name="ldcSad" +elif [[ $system = "noisemesSad" ]]; then + sys_name="noisemesSad" +elif [[ $system = "tocombosad" ]]; then + sys_name="tocombo_sad" +elif [[ $system = "opensmileSad" ]]; then + sys_name="opensmileSad" +elif [[ $system = "lenaSad" ]]; then + sys_name="lenaSad" + +else + echo "Please Specify the System you wish to evaluate." + echo "Choose between ldcSad, noisemeSad, tocomboSad, opensmileSad, lenaSad." + exit +fi + + +# Set CWD to path of scoring tool +cd $ldcSad_DIR + +mkdir + +$BASEDIR/create_ref_sys.sh $audio_dir $sys_name true + +echo "evaluating" +#$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys +# create /vagrant/results if it doesn't exist +echo "filename DCF FA MISS" > $audio_dir/${sys_name}_eval.df +for lab in `ls $workdir/temp_sys/*.lab`; do + base=$(basename $lab .lab) + if [ ! -s $workdir/temp_ref/$base.lab ]; then + if [ ! -s $workdir/temp_sys/$base.lab ]; then + echo $base" 0.00% 0.00% 0.00%" >> $audio_dir/${sys_name}_eval.df + else + echo $base" 25.00% 100.00% 0.00%" >> $audio_dir/${sys_name}_eval.df + fi + elif [ ! -s $workdir/temp_sys/$base.lab ] && [ -s $workdir/temp_ref/$base.lab ]; then + echo $base" 75.00% 0.00% 100.00%" >> $audio_dir/${sys_name}_eval.df + else + $conda_dir/python score.py $workdir/temp_ref $lab | awk -v var="$base" -F" " '{if ($1=="DCF:") {print var"\t"$2"\t"$4"\t"$6}}' >> $audio_dir/${sys_name}_eval.df + fi + +done +# small detail: remove the commas from the output +sed -i "s/,//g" $audio_dir/${sys_name}_eval.df +echo "done evaluating, check $1/${sys_name}_eval.df for the results" + +# remove temps +rm -rf $workdir/temp_ref $workdir/temp_sys + diff --git a/utils/extract_stats_chi.py b/utils/extract_stats_chi.py new file mode 100755 index 0000000..6ab3bb3 --- /dev/null +++ b/utils/extract_stats_chi.py @@ -0,0 +1,124 @@ +import sys +import argparse +import glob +import os +import re +from collections import OrderedDict + + +def detect_ad_chi_tt(previous_activity, curr_activity, last_silence_dur, chi, mal, fem): + if last_silence_dur <= 2.0: + if (previous_activity in mal and curr_activity in chi) or \ + (previous_activity in fem and curr_activity in chi) or \ + (previous_activity in chi and curr_activity in mal) or \ + (previous_activity in chi and curr_activity in fem): + return 1 + return 0 + + +def compute_statistics(rttm_path, chi, mal, fem): + chi_dur=0.0 + chi_utt=0 + ad_dur=0.0 + ad_utt=0 + ad_chi_tt=0 + + silence_dur = 0 + prev_activity = None + onset_prev = 0 + dur_prev = 0 + + with open(rttm_path,'r') as rttm: + for line in rttm: + line = line.replace('\t', ' ') + line = re.sub('\s+', ' ', line).strip() + anno_fields = line.split(' ') + curr_activity = anno_fields[7] + if curr_activity != 'SIL' and curr_activity != 'S': # We're managing things as if 'SIL' lines weren't exist + onset = float(anno_fields[3]) + dur = float(anno_fields[4]) + + if curr_activity in chi: + chi_dur += dur + chi_utt += 1 + elif curr_activity in mal or curr_activity in fem: + ad_dur += dur + ad_utt +=1 + else: + print("Activity %s not recognized" % (curr_activity)) + sys.exit(1) + + if onset_prev + dur_prev == onset: + silence_dur = 0.0 + else: + silence_dur = onset - onset_prev - dur_prev + + ad_chi_tt += detect_ad_chi_tt(prev_activity, curr_activity, silence_dur, chi, mal, fem) + + # We're managing things as if SIL lines weren't exist + + prev_activity=curr_activity + onset_prev=onset + dur_prev=dur + + filename = os.path.basename(rttm_path).split('.')[0] + res = [filename, chi_dur, chi_utt, ad_dur, ad_utt, ad_chi_tt] + return res + +def write_stats(list_stats, folder): + filename=os.path.join(folder,"stats.txt") + + with open(filename,'w') as fn: + fn.write("filename\tchi_dur\tchi_utt\tad_dur\tad_utt\tad_chi_tt\n") + for stats in list_stats: + fn.write('\t'.join(map(str,stats))+'\n') + +def main(): + parser = argparse.ArgumentParser(description="convert .txt into .rttm") + parser.add_argument('-f', '--folder', type=str, required=True, + help="path to the folder where to find the rttm to analyze." + "Note that all of the rttm are scanned.") + parser.add_argument('--chi', nargs='+', type=str, required=True, + help="labels that need to be considered as being child vocalization.") + parser.add_argument('--mal', nargs='+', type=str, required=True, + help="labels that need to be considered as being male adult speech.") + parser.add_argument('--fem', nargs='+', type=str, required=True, + help="labels that need to be considered as being female adult speech.") + args = parser.parse_args() + + # Below the values that need to be consider when evaluating tsi/lena folder + # prob C22_20170717_5640 + ## Gold files + # chi=['CHI*','C1', 'C2'] + # mal=['MA1','MA2'] + # fem=['MOT*','FA1','FA2'] + + ## Yunitator + # chi = ['CHI'] + # mal = ['MAL'] + # fem = ['FEM'] + + ## Lena N tag + # chi = ['CXN', 'CHN'] + # mal = ['MAN'] + # fem = ['FAN'] + + ## Lena MFC + # chi = ['C'] + # mal = ['M'] + # fem = ['F'] + + ## Lena N and F separated (should be the equivalent of MFC + # chi = ['CHN', 'CXN', 'CHF', 'CXF'] + # mal = ['MAN', 'MAF'] + # fem = ['FAN', 'FAF'] + args.folder=os.path.join('/vagrant', args.folder) + rttm_files = [fn for fn in glob.iglob(os.path.join(args.folder, '*.rttm')) + if 'cutted' not in fn] + list_stats=[] + for rttm_path in rttm_files: + list_stats.append(compute_statistics(rttm_path, args.chi, args.mal, args.fem)) + + write_stats(list_stats, args.folder) +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/utils/frame_cutter.py b/utils/frame_cutter.py new file mode 100755 index 0000000..b181e90 --- /dev/null +++ b/utils/frame_cutter.py @@ -0,0 +1,220 @@ +import sys +import os +import argparse +import re +import glob +import numpy as np +from scipy.io import wavfile + +def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): + """ + Given a rttm file, create a new file whose represents the same rttm cutted in frames. + If one frame has been classified as several classes in the original rttm, it concatenates classes. + Note that all of the frames that have not been classified in the original rttm are considered as being SIL. + Note that it will read the associated wav file to get the total duration of the recording. + + Parameters + ---------- + path_to_rttm : path to the rttm file. + frame_length : frame length. + output_file : path to the output file. + prefix : the prefix that needs to be remove (from rttm) to map the rttm to the wav file. + labels_map : to map the labels from original rttm (values) to the output rttm (keys). + + Write a rttm whose name is the same than the rttm's one suffixed by _cutted.rttm + """ + basename = os.path.splitext(os.path.basename(path_to_rttm))[0] + if prefix != "": + basename = basename.split(prefix)[1] + dirname = os.path.dirname(path_to_rttm) + wav_path = os.path.join(dirname,basename+'.wav') + if os.path.isfile(wav_path): + fs, data = wavfile.read(wav_path) + tot_dur_s = len(data)*1.0/fs + else: + print("Something went wrong while reading the wav file %s. Can not get total duration..." % wav_path) + sys.exit(1) + + frame_length_s = float(frame_length)/1000.0 + frames = np.arange(0.0, tot_dur_s, frame_length_s) + # We don't want to loose any data + if frames[-1] < tot_dur_s: + frames = np.append(frames, frames[-1]+frame_length_s) + + with open(path_to_rttm, 'r') as rttm: + with open(output_file, 'w') as output: + onset_prev_s = 0.0 + dur_prev_s = 0.0 + act_prev = None + append_prev = False + onset_s = None + + for line in rttm: + line = line.replace('\t', ' ') + line = re.sub('\s+', ' ', line).strip() + anno_fields = line.split(' ') + onset_s = float(anno_fields[3]) + dur_s = float(anno_fields[4]) + curr_activity = anno_fields[7] + + if onset_s > onset_prev_s + dur_prev_s : #There's been silence just before ! + sil_dur_s = onset_s - onset_prev_s - dur_prev_s + onset_sil_s = onset_prev_s + dur_prev_s + single_activity_cutter(basename, output, frame_length_s, + sil_dur_s, onset_sil_s, 'SIL', tot_dur_s, labels_map) + act_prev = 'SIL' + dur_prev_s = sil_dur_s + onset_prev_s = onset_sil_s + + single_activity_cutter(basename, output, frame_length_s, + dur_s, onset_s, curr_activity, tot_dur_s, labels_map) + + # Update previous fields + act_prev = curr_activity + dur_prev_s = dur_s + onset_prev_s = onset_s + + # Fill the last one by SILENCE + ## Handle empty rttm + if onset_s is None: + onset_s = 0.0 + dur_s = 0.0 + + if onset_s + dur_s < tot_dur_s: + sil_dur_s = tot_dur_s - onset_s-dur_s + onset_sil_s = onset_s + dur_s + single_activity_cutter(basename, output, frame_length_s, + sil_dur_s, onset_sil_s, 'SIL', tot_dur_s, labels_map) + + +def single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, curr_activity, tot_dur_s, labels_map): + """ + Given an activity, its onset and its duration, cut it into frames of length frame_length_s. + + Parameters + ---------- + basename The basename of the input rttm. + output The path of the output file. + frame_length_s The frame length (in s). + dur_s The duration of the current activity (in s). + onset_s The onset of the current activity (in s). + curr_activity The current activity. + labels_map : To map the labels from original rttm (values) to the output rttm (keys). + + """ + # We don't want to consider any fake labels generated after the duration of the wav file + if onset_s + dur_s > tot_dur_s: + dur_s = max(tot_dur_s - onset_s, 0) + if onset_s > tot_dur_s: + onset_s = 0.0 + + diff_s = onset_s - int(onset_s / frame_length_s) * frame_length_s + onset_s = int(onset_s / frame_length_s) * frame_length_s + n_frames = int((dur_s+diff_s) / frame_length_s) + # Get the output label (we want a full match or nothing) + activity = [k for k,v in labels_map.items() if re.match("("+v+")\Z", curr_activity) is not None] + if len(activity) != 1: + print("Can not map the input label to the output one : %s" % curr_activity) + sys.exit(1) + else: + activity = activity[0] + + for i in range(0, n_frames): + output.write("SPEAKER %s 1 %s %s %s \n" % \ + (basename, onset_s + frame_length_s * i, + str(frame_length_s), activity)) + + if not np.isclose(onset_s + frame_length_s * n_frames, onset_s+dur_s+diff_s, rtol=1e-05, atol=1e-08, equal_nan=False): + output.write("SPEAKER %s 1 %s %s %s \n" % \ + (basename, onset_s + frame_length_s * n_frames, + str(frame_length_s), activity)) + + +def aggregate_overlap(path_to_rttm, output_file): + """ + Given a cutted rttm file, aggregate the activities that happen in the same time. + The class of the generated frame will take the form of spkr1/spkr2 ... + + Parameters + ---------- + path_to_rttm Path to the input rttm file that have been previously cutted. + output_file Path to the output file. + """ + basename = os.path.splitext(os.path.basename(path_to_rttm))[0] + with open(path_to_rttm, 'r') as rttm: + with open(output_file, 'w') as output: + lines = rttm.readlines() + lines = sorted(lines, key=lambda line: float(line.split()[3])) + k = 0 + while k < len(lines): # Loop through the whole file + line_k = lines[k].split() + onset_k, dur_k, act_k = line_k[3], line_k[4], line_k[7] + frame_activity = [act_k] + j = k + 1 + while j < len(lines): # Loop through the activities that have the same onset + line_j = lines[j].split() + onset_j, dur_j, act_j = line_j[3], line_j[4], line_j[7] + if onset_k != onset_j: + output.write("SPEAKER %s 1 %s %s %s \n" % \ + (basename, onset_k, dur_k, '/'.join(frame_activity))) + break + else: # onset_k == onset_j: + if act_j not in frame_activity: + frame_activity.append(act_j) + frame_activity.sort() # Consider alphabetical order + k += 1 + j += 1 + k += 1 + + output.write("SPEAKER %s 1 %s %s %s \n" % \ + (basename, onset_k, dur_k, '/'.join(frame_activity))) + + + + +def main(): + parser = argparse.ArgumentParser(description="convert a rttm file into another rttm cutted in frames.") + parser.add_argument('-i', '--input', type=str, required=True, + help="path to the input .rttm file or the folder containing rttm files.") + parser.add_argument('-l', '--length', type=float, required=False, default=100.0, + help="the frame length in ms (Default to 100 ms).") + parser.add_argument('-p', '--prefix', type=str, default="", + help="the prefix that needs to be removed to map the rttm to the wav.") + args = parser.parse_args() + + labels_map = {"CHI": "CHI.?|CXN|CHN|C.?", + "FEM": "FAN|FAF|FEM|F|MOT.?|FA.?", + "MAL": "MAL|M|MAN|MA.?", + "SIL": "SIL|S"} + + # Initialize the output folder as the same folder than the input + # if not provided by the user. + if args.input[-5:] == '.rttm': + output = os.path.dirname(args.input) + else: + output = args.input + + data_dir = '/vagrant' + args.input = os.path.join(data_dir, args.input) + output = os.path.join(data_dir, output) + + if not os.path.isdir(output): + os.mkdir(output) + + if args.input[-5:] == '.rttm': # A single file has been provided by the user + output = os.path.splitext(args.input)[0]+'_cutted.rttm' + print(output) + cutter(args.input, args.length, output+'.tmp', args.prefix, labels_map) + aggregate_overlap(output+'.tmp', output) + os.remove(output+'.tmp') + else: # A whole folder has been provided + rttm_files = glob.iglob(os.path.join(args.input, '*.rttm')) + for rttm_path in rttm_files: + print("Processing %s" % rttm_path) + output = os.path.splitext(rttm_path)[0] + '_cutted.rttm' + cutter(rttm_path, args.length, output + '.tmp', args.prefix, labels_map) + aggregate_overlap(output + '.tmp', output) + os.remove(output + '.tmp') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/utils/generate_html.py b/utils/generate_html.py new file mode 100755 index 0000000..a5ab577 --- /dev/null +++ b/utils/generate_html.py @@ -0,0 +1,44 @@ +# generate_html.py +""" +Given a list of folders that have been fed to the different models, +generate a html file presenting the following results : + +wip + +Use case : + python tools/generate_html.py -f data/ -o data/html +It will scan folder data/ and generates the html interface at data/html. +""" + +import argparse +import os +import glob +from html_python.files_page import FilesPage +from html_python.models_page import ModelsPage +from html_python.style_css import StyleCSS +from html_python.page import Page + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-f', '--folder', type=str, + help=' Folder that needs to be analyzed', required=True) + parser.add_argument('-o', '--output', type = str, + help=' The folder where the html files will be generated.', required=True) + + args = parser.parse_args() + + # define data dir + data_dir = "/vagrant" + args.folder = os.path.join(data_dir, args.folder) + args.output = os.path.join(data_dir, args.output) + + style_css = StyleCSS(args.output) + files_html = FilesPage(args.output, args.folder) + files_html.write_statistics() + + models_html = ModelsPage(args.output, args.folder) + models_html.write_statistics() + models_html.close() + +if __name__ == '__main__': + main() diff --git a/get_aclewStarter.sh b/utils/get_aclewStarter.sh similarity index 100% rename from get_aclewStarter.sh rename to utils/get_aclewStarter.sh diff --git a/utils/high_volubility.py b/utils/high_volubility.py new file mode 100755 index 0000000..609ba5b --- /dev/null +++ b/utils/high_volubility.py @@ -0,0 +1,526 @@ +#!/usr/bin/env python +# +# author = The ACLEW Team +# +""" +This script extract short snippets of sound (approx. 10s long), +and runs them through a SAD or diarization tool to detect chunks of audio with : + +1) a lot of speech. +--> python tools/high_volubility.py file_path.wav --sad noisemes_sad + +2) a lot of child speech +--> python tools/high_volubility.py file_path.wav --diar yunitate --mode CHI + +3) a lot of parent-child conversations +--> python tools/high_volubility.py file_path.wav --diar yunitate --mode PCCONV + +4) a lot of adults conversations with a child minimally aware +--> python tools/high_volubility.py file_path.wav --diar yunitate --mode ACCA +""" + +import os +import sys +import re +import wave +import math +import numpy +import argparse +import subprocess + +from operator import itemgetter + + +def get_audio_length(wav): + """ Return duration of Wave file. + + Input: + wav: path to the wav file. + + Output: + dur: float, duration, in seconds, of wav file. + """ + + audio = wave.open(wav, 'r') + frames = audio.getnframes() + rate = audio.getframerate() + duration = frames / float(rate) + audio.close() + + return duration + + +def select_onsets(duration, step): + """ Return list of onsets on which this script will extract the chunks of + 10s + + Input: + duration: float, duration of the daylong recording + + Ouput: + onsets: list[floats], list the onsets on which this script will extract + the chunks of 10s to be run through the SAD tools + """ + return numpy.arange(0.0, duration, step) + + +def extract_chunks(wav, onset_list, chunk_size, temp): + """ Given a list of onset and a length in seconds, extract a snippet of + audio at each onset of this length. The extraction will be done using + SoX, called by subprocess. + + Input: + wav: path to the wav file. + onset_list: list[float], list of the onsets in the 'wav' file at which + we'll extract the segments + chunk_size: float, length in seconds of the chunks of audio this script + will extract. + + Output: + 'temp': the output of this function is the set of small wav file of + 'chunk_size' seconds in the temp folder. + The name of the wav files will be: + id_onset_length.wav + where id is the name of the original wav file, onset is the + onset at which the chunk occurs in the original wav file, and + length is the length of the chunk. + """ + + # for each onset, call SoX using subprocess to extract a chunk. + for on in onset_list: + + # get "id" basename of wav file + basename = os.path.splitext(os.path.basename(wav))[0] + + # create name of output + off = on + chunk_size + str_on = (6 - len(str(on))) * '0' + str(on) + str_off = (6 - len(str(off))) * '0' + str(off) + + chunk_name = '_'.join([basename, str_on, str_off]) + + # call subprocess + cmd = ['sox', wav, + os.path.join(temp, '{}.wav'.format(chunk_name)), + 'trim', str(on), str(chunk_size)] + subprocess.call(cmd) + + +def run_Model(temp_rel, temp_abs, sad, diar=None): + """ When all the snippets of sound are extracted, and stored in the temp + file, run them through a sad or diar tool, and keep + the 10%% that have the most speech. + By default, the function is on the SAD mode. That means that it will + run a SAD model (by default noiseme). However, if the diar parameter is + provided, this function will be on the diarization mode. + + Input: + temp_rel: relative path to the temp folder in which the snippets of + sounds are stored. Here we need the relative path, not the + abs path, since the SAD tool will add the "/vagrant/" part of + the path. + temp_abs: absolute path to the temp folder in which the snippets of + sounds are stored. + sad: name of the sad tool to be used to analyze the snippets of + sound + diar: name of the diar tool to be used to analyze the snippets of + sound. Note that it will use that sad parameter as a choice + of SAD provider. + + Output: + _: In temp, the SAD analyses will be written in RTTM format. + """ + if diar is not None: # Diarization mode + if diar == 'yunitate': + cmd = ['tools/{}.sh'.format(diar), '{}'.format(temp_rel)] + elif diar == 'diartk': + cmd = ['tools/{}.sh'.format(diar), '{}'.format(temp_rel), '{}'.format(sad)] + else: + cmd = ['exit 1'] + else: # SAD mode + cmd = ['tools/{}.sh'.format(sad), '{}'.format(temp_rel)] + + subprocess.call(cmd) + + # After the model has finished running, remove the wav files + for fin in os.listdir(temp_abs): + if fin.endswith('.wav'): + os.remove(os.path.join(temp_abs, fin)) + + +def extract_base_name(filename, diar): + """ + Giving a filename generated by a model and composed of : + model_name + wav_filename + tbeg + tdur + Extracts the base name composed of the three last elements. + + Input: + filename: a filename generated by a model + diar: a diarization model (if provided) + + Output: + base : wavfilename_tbeg_tdur + """ + if diar == 'yunitate': + base = filename.split('_')[1:] + else: + base = filename.split('_')[2:] + + base = os.path.splitext('_'.join(base))[0] + return base + + +def detect_parent_child_conv(previous_activity, curr_activity, last_silence_dur): + """ + Attempts to try if a turn-taking happened between a child and his/her parents + + Input: + previous_activity: the last activity amongst ['CHI', 'MAL', 'FEM'] + curr_activity: the current activity amongst ['CHI', 'MAL', 'FEM'] + last_silence_dur: the duration of the last silence + + Output: + A boolean indicating if a turn-taking happened between a child and his/her parents + True : a turn-taking happened + False : nothing happened + """ + if last_silence_dur <= 2.0: + if (previous_activity == 'MAL' and curr_activity == 'CHI') or \ + (previous_activity == 'FEM' and curr_activity == 'CHI') or \ + (previous_activity == 'CHI' and curr_activity == 'MAL') or \ + (previous_activity == 'CHI' and curr_activity == 'FEM'): + + return True + return False + +def detect_adults_conv(previous_activity, curr_activity, last_silence_dur): + """ + Attempts to try if a turn-taking happened between two adults + + Input: + previous_activity: the last activity amongst ['CHI', 'MAL', 'FEM'] + curr_activity: the current activity amongst ['CHI', 'MAL', 'FEM'] + last_silence_dur: the duration of the last silence + + Output: + A boolean indicating if a turn-taking happened between a child and his/her parents + True : a turn-taking happened + False : nothing happened + """ + if last_silence_dur <= 2.0: + if (previous_activity == 'MAL' and curr_activity == 'FEM') or \ + (previous_activity == 'FEM' and curr_activity == 'MAL') or \ + (previous_activity == 'FEM' and curr_activity == 'FEM') or \ + (previous_activity == 'MAL' and curr_activity == 'MAL'): + + return True + return False + +def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False): + """ When the model has finished producing its outputs, read all the + transcriptions and sort the files by the quantity of their speech + content or the quantity of their speech belonging to the noiseme_class. + + Input: + temp: path to the temp folder in which the snippets of sound are + stored. Here we need the relative path, not the absolute + path, since the SAD tool will add the "/vagrant/" part of + the path. + sad: name of the sad tool to be used to analyze the snippets of + sound. + perc: the percentage of speech to keep. + diar: the diarization model (if provided). + mode: the type of speech that needs to be kept (has to be amongst ['CHI']). + child_aware : (only used if mode == ACCA) Indicates, if we should filter the snippets + that don't present any child activity. + + Output: + sorted_files: list(str), list of the files, sorted by the quantity + of the speech content (as returned by the SAD tool) + or the quantity of the speech content classified as + belonging to the noiseme class (as returned by the + diarization tool). + only 10 %% of all files, that contain the most speech + """ + + # get list of model outputs + all_files = os.listdir(temp_abs) + diar_mode = diar is not None + if diar_mode: + model = diar + else: + model = sad + + # we consider only the annotations that have been generated by the model + annotations = [file for file in all_files if file.startswith(model[:-1])] + + # read all annotations and store duple in list (filename, speech_dur) + files_n_dur = [] + for file in annotations: + + # we extract the base name composed of wav_file_name + t_deg + t_dur + base = extract_base_name(file, diar) + + with open(os.path.join(temp_abs, file), 'r') as fin: + speech_activity = fin.readlines() + + # total duration of the speech of interest + tot_dur = 0.0 + # duration of the last silence + silence_dur = 0.0 + # type of the last activity + previous_activity = None + onset_prev = 0.0 + dur_prev = 0.0 + # variable to detect if the child is aware in ACCA mode. + chi_points = 0.0 + + for line in speech_activity: + anno_fields = line.split(' ') + dur = float(anno_fields[4]) + onset = float(anno_fields[3]) + curr_activity = anno_fields[7] + + + if onset_prev+dur_prev == onset: + silence_dur = 0.0 + else: + silence_dur = onset-onset_prev-dur_prev + + + if not diar_mode: # SAD mode + tot_dur += dur + elif diar_mode and mode == 'CHI' and curr_activity == 'CHI': # Child detection mode + tot_dur += 1 + elif diar_mode and mode == 'PCCONV': # Parent-child detection mode + if detect_parent_child_conv(previous_activity, curr_activity, silence_dur): + # Here we consider more an objective function (number of turn-taking) that + # we want to maximize. That comes from the fact that adults speak during a + # longer time while children speak only for few seconds. And we don't want + # to put too much weight on the adults speech. + tot_dur += 1 + elif diar_mode and mode == 'ACCA': # Adults conversation child aware detection + if detect_adults_conv(previous_activity, curr_activity, silence_dur): + tot_dur += 1 + elif curr_activity == 'CHI': + chi_points += 1 + + previous_activity = curr_activity + onset_prev = onset + dur_prev = dur + + files_n_dur.append((base, tot_dur, chi_points)) + + # remove annotation when finished reading + os.remove(os.path.join(temp_abs, file)) + + if child_aware and diar_mode == 'ACCA': + files_n_dur = [file for file in files_n_dur if file[2] > 3] + + if len(files_n_dur) == 0: + raise ValueError("No moments for the {} mode has been found.\n Try to decrease the step parameter or " + \ + "to increase the size of the chunks.") + + files_n_dur = sorted(files_n_dur, key=itemgetter(1), reverse=True) + + # return top 10%% of snippets + percent = max(1, int(math.ceil(perc * len(files_n_dur)))) + + sorted_files = files_n_dur[:percent] + + return sorted_files + +def new_onsets_two_minutes(sorted_files): + """ + Given a selection of file with lots of speech, + extract new 2minutes long chunks of audio in the original wav, + centered around the short 10s snippets that were analysed. + + Input: + sorted_files: list of the snippets that were selected + because they had lot of speech + temp_abs: absolute path to the temp folder that contains the + snippets + wav: path to the daylong recording + Ouput: + _: in the temp folder, new two minutes long chunks of + audio will be stored. + """ + + # loop over selected files and retrieve their onsets from their name + new_onset_list = [] + for snippet, speech_dur, chi_points in sorted_files: + onset = os.path.splitext(snippet)[0].split('_')[-2] + offset = os.path.splitext(snippet)[0].split('_')[-1] + + length = float(offset) - float(onset) + + # new segment is centered around snippet, so get middle of snippet + new_onset = length / 2 + float(onset) + + new_onset_list.append(new_onset) + + return new_onset_list + +def new_onsets_five_minutes(sorted_files): + """ + Given a selection of file with lots of speech, + extract new 5minutes long chunks of audio in the original wav, + by adding 2 minutes before and 1 minute after the 2minute chunks. + + Input: + sorted_files: list of the snippets that were selected + because they had lot of speech + temp_abs: absolute path to the temp folder that contains the + snippets + wav: path to the daylong recording + Ouput: + _: in the temp folder, new two minutes long chunks of + audio will be stored. + """ + # loop over selected files and retrieve their onsets from their name + new_onset_list = [] + for snippet, speech_dur, chi_points in sorted_files: + onset = os.path.splitext(snippet)[0].split('_')[-2] + offset = os.path.splitext(snippet)[0].split('_')[-1] + + # new segment starts 2 minute before the 2 minute chunk + new_onset = float(onset) - 120.0 + + new_onset_list.append(new_onset) + + return new_onset_list + + +def main(): + """ + Get duration of wav file + Given duration of wav file, extract list of onsets + Given list of onsets in wav file, extract chunks of wav + + Input: + daylong: path to the daylong recording + --step: (optional) step in seconds between each chunk. + By default 600 seconds. + --chunk_size: (optional) size of the chunks to extract. + --temp: (optional) path to a temporary folder to store the + extracted chunks. + --sad: (optional) name of the SAD tool to call to analyse + the chunks. By default noiseme + --diar: (optional) name of the diarization tool to call to analyse + the chunks. No default option + + """ + parser = argparse.ArgumentParser() + + parser.add_argument('daylong', metavar='AUDIO_FILE', + help='''Give RELATIVE path to the daylong recording''' + '''in wav format.''') + parser.add_argument('--step', default=600.0, type=float, + help='''(Optional) Step, in seconds, between each chunk of ''' + '''audio that will be extracted to be analysed by the SAD ''' + '''tool. By default, step=600 seconds (10 minutes)''') + parser.add_argument('--chunk_sizes', nargs=3, + default=[10.0, 120.0, 300.0], type=float, + help='''(Optional) Size of the chunks to extract and analyze. ''' + '''By default it's 10.0 120.0 300.0: \n''' + '''10s chunks are extracted, analyzed by the ''' + '''SAD tool, the 10%% chunks that contain the most speech ''' + '''are kept, than 120s chunks centered on the 10s chunks, ''' + '''these are again analysed by the SAD tool, the 10%% that ''' + ''' contain the most speech are kept, and 300.0s chunks ''' + ''' are finally extracted around these kept chunks.''') + parser.add_argument('--percentage', default=10, type=float, + help='''(Optional) Percentage of snippets to keep at each stage. ''' + '''By default, we keep 10%% of snippets each time.\n''' + '''For a 15h long recording, we have 90x10s snippets, ''' + '''we keep the 10%% with the most speech content, that ''' + '''lead to 9x120s snippets, we again keep the 10%% with the ''' + '''most speech content, so in the end we have 1x300 seconds ''' + '''segment.''') + parser.add_argument('--temp', default='tmp', + help='''(Optional) Path to a temp folder in which the small wav ''' + '''segments will be stored. If it doesn't exist, it will be ''' + '''created.''') + parser.add_argument('--sad', default='noisemes_sad', + help='''(Optional) name of the sad tool that will be used to ''' + '''analyze the snippets of sound''') + parser.add_argument('--diar', + help='''(Optional) name of the diar tool that will be used to ''' + '''analyze the snippets of sound. If this argument is provided by + the user, this script will be on the diarization mode. Otherwise, it will + be on the SAD mode.''') + parser.add_argument('--mode', default='CHI', choices=['CHI', 'PCCONV', 'ACCA'], + help='''(Optional) the noiseme class(es) of interest. ''' + '''Used only when the diar argument is provided.''') + + args = parser.parse_args() + + if args.diar == 'yunitate' and (args.mode == 'PCCONV' or args.mode == 'ACCA' or args.mode == 'CHI'): + if args.chunk_sizes[0] == 10.0: + print("Resetting chunk size at 20.0 seconds (more suitable for CHI/PCCONV/ACCA mode).") + args.chunk_sizes[0] = 20.0 + if args.step == 600.0: + print("Resetting step at 300.0 seconds (more suitable for CHI/PCCONV/ACCA mode).") + args.step = 300.0 + + # Define Data dir + data_dir = "/vagrant" + + # check if temp dir exist and create it if not + temp_abs = os.path.join(data_dir, args.temp) + temp_rel = args.temp # to launch SAD tool we need the relative path to temp + + if not os.path.isdir(temp_abs): + os.makedirs(temp_abs) + + # Define absolute path to wav file + wav_abs = os.path.join(data_dir, args.daylong) + + # get percentage + perc = args.percentage / 100.0 + + # get path to current (tools/) dir - useful to call the SAD tool + dir_path = os.path.dirname(os.path.realpath(__file__)) + + # get duration + duration = get_audio_length(wav_abs) + + # get list of onsets + onset_list = select_onsets(duration, args.step) + + # call subprocess to extract the chunks + extract_chunks(wav_abs, onset_list, args.chunk_sizes[0], temp_abs) + + # analyze using SAD tool + run_Model(temp_rel, temp_abs, args.sad, args.diar) + + # sort by speech duration + sorted_files = read_analyses(temp_abs, args.sad, perc, args.diar, args.mode) + + # get new onsets for two minutes chunks + new_onset_list = new_onsets_two_minutes(sorted_files) + + # extract two minutes chunks + extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[1], temp_abs) + + # analyze using SAD tool + run_Model(temp_rel, temp_abs, args.sad, args.diar) + + # sort by speech duration again + child_aware = False + if args.mode == 'ACCA': + child_aware = True + + sorted_files = read_analyses(temp_abs, args.sad, perc, args.diar, args.mode, child_aware) + + # get new onsets for five minutes chunks + new_onset_list = new_onsets_five_minutes(sorted_files) + + # extract final five minutes long chunks + output_dir = os.path.dirname(wav_abs) + extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[2], output_dir) + + +if __name__ == '__main__': + main() diff --git a/utils/html_python/__init__.py b/utils/html_python/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/utils/html_python/files_page.py b/utils/html_python/files_page.py new file mode 100755 index 0000000..bc56fdd --- /dev/null +++ b/utils/html_python/files_page.py @@ -0,0 +1,179 @@ +import html_python.page as page +import html_python.utils as utils +import html_python.style_css as style_css +import numpy as np +import os +import glob +import random +import numbers +from collections import OrderedDict + + +class FilesPage(page.Page): + + def __init__(self, output_folder, results_folder): + # Initialize self.output_folder & self.results_folder + page.Page.__init__(self, output_folder, results_folder) + + self.N_files = 20 # Fix the number of files to print in the table + + # List of gold files + self.gold_files = [fn for fn in glob.iglob(os.path.join(self.results_folder, '*.rttm')) + if not os.path.basename(fn).startswith(('ldc_sad', 'diartk', 'noisemes_sad', + 'opensmile', 'tocombo_sad', 'lena', 'yunitator'))] + # Name of the html that will be generated + self.name = 'files.html' + + # File descriptor + self.html = open(os.path.join(self.output_folder, self.name), 'w') + + tabs = '\n' + \ + '

' + self.html.write(tabs)#write tabs + + # Compute statistics + self._compute_statistics() + + if len(self.audio_stats) > self.N_files: + self.random_indices = np.sort(random.sample(range(0, len(self.audio_stats)), self.N_files)) + else: + self.random_indices = range(0, len(self.audio_stats)) + + def _compute_statistics(self): + + self.audio_stats = [] + self.gold_stats = [] + + # Empty OrderedDict that will contains the unique keys of the gold file + # We use only the keys, it's to fake an OrderedSet that doesn't exist natively in python. + # The difficulty here is that gold2.rttm could have some participants that gold1.rttm doesn't have. + # We still want to consider them in all of the rttm to present the results in a table. + self.gold_keys = OrderedDict({}) + for gold in self.gold_files: #for each reference rttm file + + wav_path = os.path.splitext(gold)[0]+'.wav' + + # Get .wav information + audio_stats_file = utils.analyze_wav(wav_path) + self.audio_stats.append(audio_stats_file) + + # Analyze gold + dur_wav = audio_stats_file['duration (s)'] + gold_stats_file = utils.analyze_rttm(gold, dur_wav) + self.gold_keys = OrderedDict.fromkeys(self.gold_keys.keys() + gold_stats_file.keys()) + self.gold_stats.append(gold_stats_file) + + self._compute_averages() + self.audio_stats = np.array(self.audio_stats) + self.gold_stats = np.array(self.gold_stats) + + def _compute_averages(self): + + # Get audio stats averages + self.averages_audio = OrderedDict(zip(self.audio_stats[0].keys()[2:], [0.0] * (len(self.audio_stats[0]) - 2))) + for line in self.audio_stats: + for key in line.keys(): + if isinstance(line[key], numbers.Number) and line[key] is not None: # None and non numbers are considered as being 0.0 + self.averages_audio[key] += line[key] + + for k, v in self.averages_audio.items(): + self.averages_audio[k] = v/len(self.audio_stats) + + # Get gold stats averages + self.averages_gold = OrderedDict(zip(self.gold_keys.keys()[1:], [0.0] * (len(self.gold_keys) - 1))) + for line in self.gold_stats: + for key in line.keys(): + if isinstance(line[key], numbers.Number) and line[key] is not None: # None and non numbers are considered as being 0.0 + self.averages_gold[key] += line[key] + + for k, v in self.averages_gold.items(): + self.averages_gold[k] = v/len(self.gold_stats) + + + def _write_value(self, value, number_of_digits = 4): + if isinstance(value, str): + self.html.write(' %s \n' % value) + elif isinstance(value, float) or isinstance(value, np.float64) or isinstance(value, np.float32): + self.html.write(' %.*f\n' % (number_of_digits,value)) + elif isinstance(value, int): + self.html.write(' %d \n' % value) + + def write_audio_stats(self): + keys = self.audio_stats[0].keys() + + # Open table + self.html.write('

Audio level statistics

\n\n') + + # Write first line of the table + self.html.write('\n') + for k in keys: + self.html.write('\n' % k) + self.html.write('\n') + + # Write audio statistics + for d in self.audio_stats[self.random_indices]: + self.html.write('\n') + for key, value in d.items(): + self._write_value(value, 4) + + self.html.write('\n') + + # Write averages + self.averages_audio["filename"] = "averages" + for k in keys: + if k in self.averages_audio: + self._write_value(self.averages_audio[k], 4) + else: + self._write_value("") + + # Close table + self.html.write('
%s
') + + + def write_gold_stats(self): + + keys = self.gold_stats[0].keys() + + # Open table + self.html.write('

Annotation level statistics

\n\n') + + # Write first line of the table + self.html.write('\n') + for k in self.gold_keys: + self.html.write('\n' % k) + self.html.write('\n') + + # Write gold statistics + for d in self.gold_stats[self.random_indices]: + self.html.write('\n') + for key in self.gold_keys: + if key in d: + self._write_value(d[key], 2) + else: + self._write_value("") + self.html.write('\n') + + # Write averages + self.averages_gold["filename"] = "averages" + for k in self.gold_keys: + if k in self.averages_gold: + self._write_value(self.averages_gold[k], 2) + else: + self._write_value("") + + # Close table + self.html.write('
%s
') + + def write_statistics(self): + self.write_audio_stats() + self.write_gold_stats() + if len(self.audio_stats) > self.N_files: + self.html.write("

Note : a random sample of %d files has been made to lighten the presentation." % self.N_files) + + def close(self): + self.html.close() \ No newline at end of file diff --git a/utils/html_python/models_page.py b/utils/html_python/models_page.py new file mode 100755 index 0000000..249872c --- /dev/null +++ b/utils/html_python/models_page.py @@ -0,0 +1,103 @@ +import html_python.page as page +import html_python.utils as utils +import numpy as np +import os +import glob +import html_python.style_css as style_css +from collections import OrderedDict + + +class ModelsPage(page.Page): + + def __init__(self, output_folder, results_folder): + # Initialize self.output_folder & self.results_folder + page.Page.__init__(self, output_folder, results_folder) + + # Name of the html that will be generated + self.name = 'models.html' + + # File descriptor + self.html = open(os.path.join(self.output_folder, self.name), 'w') + + tabs = '\n' + \ + '' + self.html.write(tabs) #write tabs + + # List of df files present in the results_folder + self.df_files = [fn for fn in glob.iglob(os.path.join(self.results_folder, '*.df'))] + + def _get_statistics(self): + self.sad_stats = [] + self.diar_stats = [] + for df_path in self.df_files: + basename = os.path.splitext(os.path.basename(df_path))[0] + if basename.startswith(('diartk','lena','yunitator')): + self.diar_stats.append(utils.get_averages(df_path)) + else: + self.sad_stats.append(utils.get_averages(df_path)) + + def _write_SAD_statistics(self): + # Write SAD table + if len(self.sad_stats) == 0: + self.html.write("No SAD model evaluations have been found.") + else: + # Open table + self.html.write('

SAD statistics

\n\n') + # Write first line of the table + self.html.write('\n') + keys = self.sad_stats[0].keys() + for k in keys: + self.html.write('\n' % k) + self.html.write('\n') + + # Write statistics + for d in self.sad_stats: + self.html.write('\n') + for key, value in d.items(): + utils.write_value(self.html, value, 4) + self.html.write('\n') + # Close table + self.html.write('
%s
') + + def _write_diar_statistics(self): + # Write SAD table + if len(self.diar_stats) == 0: + self.html.write("No diarization model evaluations have been found.") + else: + # Open table + self.html.write('

Diarization statistics

\n\n') + # Write first line of the table + self.html.write('\n') + keys = self.diar_stats[0].keys() + for k in keys: + self.html.write('\n' % k) + self.html.write('\n') + + # Write statistics + for d in self.diar_stats: + self.html.write('\n') + for key, value in d.items(): + utils.write_value(self.html, value, 2) + self.html.write('\n') + + # Close table + self.html.write('
%s
') + + def write_statistics(self): + if len(self.df_files) == 0: + self.html.write("No df files have been found... Please run the evaluation of choose another folder.") + else: + self._get_statistics() + self._write_SAD_statistics() + self._write_diar_statistics() + + + + + def close(self): + self.html.close() \ No newline at end of file diff --git a/utils/html_python/page.py b/utils/html_python/page.py new file mode 100755 index 0000000..0c59ba0 --- /dev/null +++ b/utils/html_python/page.py @@ -0,0 +1,30 @@ +from abc import ABCMeta, abstractmethod +import os + +# Used to read the rttm generated by all the different models. +# The first element '' is to handle gold rttm +sad_prefixes = ['ldc_sad_', 'noisemes_sad_', 'tocombo_sad_', 'opensmile_sad_'] +diar_prefixes = ['diartk_goldSad_', 'diartk_ldcSad_', 'diartk_tocomboSad_', + 'diartk_noisemesSad_', 'diartk_opensmileSad_'] + +class Page: + __metaclass__ = ABCMeta + + @abstractmethod + def __init__(self, output_folder, results_folder): + # The output folder where to store the html/css files. + self.output_folder = output_folder + + # The folders that we need to analyze/aggregate + self.results_folder = results_folder + + if not os.path.exists(self.output_folder): + os.makedirs(self.output_folder) + + @abstractmethod + def write_statistics(self): + raise NotImplementedError('subclasses must override write_statistics()!') + + @abstractmethod + def close(self): + raise NotImplementedError('subclasses must override close()!') diff --git a/utils/html_python/style_css.py b/utils/html_python/style_css.py new file mode 100755 index 0000000..db1bc75 --- /dev/null +++ b/utils/html_python/style_css.py @@ -0,0 +1,33 @@ +import os + +css_name = "style.css" # global variable + + +class StyleCSS: + + def __init__(self, output_folder): + # The output folder where to store the html/css files. + self.output_folder = output_folder + + if not os.path.exists(self.output_folder): + os.makedirs(self.output_folder) + + self.css = open(os.path.join(self.output_folder, 'style.css'), 'w') + + # tabs style + tabs_style = "ul {background: #333;list-style: none;overflow: hidden;text-align: center;}\n" + \ + "ul li {display: inline-block;}\n" + \ + "ul li a {padding: 5px 10px;background: #333;color: #fff;line-height: 3em;display: block; }\n" + \ + "ul li a:hover {background: #e4e4e4;color: #333;}\n" + \ + "li.active>a {background: #e4e4e4;color: #333;}\n" + \ + "a {display : block;color : #666;text-decoration : none;padding : 4px;}\n" + + # table style + table_style = "table {margin: 0 auto;}\n" +\ + "td, th {border: 1px solid #ddd;padding: 8px;text-align: center;}\n" +\ + "tr:nth-child(even){background-color: #f2f2f2;}\n" +\ + "tr:hover {background-color: #ddd;}\n" +\ + "th {padding-top: 12px;padding-bottom: 12px;text-align: center;background-color: #333;color: white;}\n" + self.css.write(tabs_style) + self.css.write(table_style) + self.css.close() \ No newline at end of file diff --git a/utils/html_python/utils.py b/utils/html_python/utils.py new file mode 100755 index 0000000..82a1678 --- /dev/null +++ b/utils/html_python/utils.py @@ -0,0 +1,164 @@ +from scipy.io import wavfile +import collections +import numpy as np +import os + + +# Utility functions +def write_value(fn, value, number_of_digits=4): + if isinstance(value, str): + fn.write(' %s \n' % value) + elif isinstance(value, float) or isinstance(value, np.float64) or isinstance(value, np.float32): + fn.write(' %.*f\n' % (number_of_digits, value)) + elif isinstance(value, int): + fn.write(' %d \n' % value) + + +def signaltonoise(a, axis=0, ddof=0): + """ + The signal-to-noise ratio of the input data. + Returns the signal-to-noise ratio of `a`, here defined as the mean + divided by the standard deviation. + Parameters + ---------- + a : array_like + An array_like object containing the sample data. + axis : int or None, optional + If axis is equal to None, the array is first ravel'd. If axis is an + integer, this is the axis over which to operate. Default is 0. + ddof : int, optional + Degrees of freedom correction for standard deviation. Default is 0. + Returns + ------- + s2n : ndarray + The mean to standard deviation ratio(s) along `axis`, or 0 where the + standard deviation is 0. + """ + a = np.asanyarray(a) + m = a.mean(axis) + sd = a.std(axis=axis, ddof=ddof) + return np.where(sd == 0, 0, m / sd) + +def analyze_wav(filepath): + """ + Analyzes a wav file and returns some audio statistics. + Parameters + ---------- + filepath + + Returns + ------- + statistics : + """ + basename = os.path.splitext(os.path.basename(filepath))[0] + + if os.path.splitext(filepath)[1] == '.wav' and os.path.isfile(filepath): + fs, data = wavfile.read(filepath) + data_type = type(data[0]) + if data_type == np.int16: + wav_format = '16-bit PCM' + MAX_WAV_AMP = 32767.0 + elif data_type == np.int32: + wav_format = '32-bit PCM' + MAX_WAV_AMP = 2147483647.0 + elif data_type == np.uint8: + wav_format = '8-bit PCM' + MAX_WAV_AMP = 255.0 + elif data_type == np.float32: + wav_format = '32-bit floating-point' + MAX_WAV_AMP = 1.0 + + # Normalization between -1 and 1 + data = data/MAX_WAV_AMP + + # Compute metrics + duration = len(data)*1.0/fs + mean_amplitude = np.mean(data) + max_amplitude = np.max(data) + snr = float(signaltonoise(data)) + statistics = collections.OrderedDict([("filename", basename), + ("wav format", wav_format), + ("duration (s)", duration), + ("mean amplitude", mean_amplitude), + ("max amplitude", max_amplitude), + ("signal to noise ratio", snr)]) + return statistics + + +def _detect_overlap(t_beg, dur, t_beg_prev, dur_prev): + + if t_beg_prev + dur_prev > t_beg: + if t_beg_prev+dur_prev > t_beg+dur: + return dur + else: + return t_beg_prev + dur_prev - t_beg + return 0.0 + + +def analyze_rttm(filepath, dur_wav): + basename = os.path.splitext(os.path.basename(filepath))[0] + dict = collections.OrderedDict([("filename", basename), + ("% total speech", 0.0), + ("% overlap", 0.0), + ("number of participants", 0)]) + + if os.path.splitext(filepath)[1] == '.rttm' and os.path.isfile(filepath): + fn = open(filepath) + t_beg_prev, dur_prev, participant_prev = 0.0, 0.0, None + for line in fn: + fields = line.split() + type, t_beg, dur, participant = fields[0], float(fields[3]), float(fields[4]), fields[7] + + # Add information about the participant + prop_key = "% of "+participant + if prop_key in dict: + dict[prop_key] += dur + else: + dict[prop_key] = dur + + # Add information about the overall speech + if type == 'SPEAKER': + dict["% total speech"] += dur + + # Compute overlap + dict["% overlap"] += _detect_overlap(t_beg, dur, t_beg_prev,dur_prev) + + # Update previous + t_beg_prev, dur_prev, participant_prev = t_beg, dur, participant + + # Normalization step + # Normalize participants speech duration by total speech + if dict["% total speech"]: + for k, v in dict.items(): + if k.startswith("% of "): + dict["number of participants"] += 1 + dict[k] /= dict["% total speech"] + # Normalize % overlap by total speech + dict["% overlap"] /= dict["% total speech"] + + # Normalize total speech by wav duration + dict["% total speech"] /= dur_wav + + fn.close() + return dict + +def get_averages(df_path): + column_sums = None + basename = os.path.splitext(os.path.basename(df_path))[0] + with open(df_path) as file: + header=file.readline() + header=header.replace('\n','').split('\t') + if header[0] == 'filename': + header=header[1:] + + lines = file.readlines() + rows_of_numbers = [map(float, line.replace('%','').replace('\n','').replace('NA','0.0').split('\t')[1:]) for line in lines] + sums = map(sum, zip(*rows_of_numbers)) + averages = [sum_item / len(lines) for sum_item in sums] + + # Add model name + header.insert(0, 'filename') + averages.insert(0, basename) + averages = collections.OrderedDict(zip(header, averages)) + return averages + diff --git a/toolbox/its2rttm.py b/utils/its2rttm.py similarity index 100% rename from toolbox/its2rttm.py rename to utils/its2rttm.py diff --git a/toolbox/its2rttm.sh b/utils/its2rttm.sh similarity index 100% rename from toolbox/its2rttm.sh rename to utils/its2rttm.sh diff --git a/toolbox/lab2rttm.sh b/utils/lab2rttm.sh similarity index 100% rename from toolbox/lab2rttm.sh rename to utils/lab2rttm.sh diff --git a/utils/make_big_corpus.sh b/utils/make_big_corpus.sh new file mode 100755 index 0000000..12d08a2 --- /dev/null +++ b/utils/make_big_corpus.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# this script takes as input, for $corpus, the folder containing the daylong recordings +# and the transcriptions in eaf format in a folder raw_$corpus. It reads the transcriptions +# in the eaf files and cuts the wav to only keep the transcribed part, and convert the transcribed +# part into rttm with the same names as the cut wavs. + +# take the name of the corpus as input and define the hard coded paths - they shall not change! +corpus=$1 # should be chosen between BER, WAR, SOD and CAS +working_dir=/DATA2T/aclew_data_update +daylong_dir=/DATA2T/aclew_daylong_data +temp_dir=$working_dir/temp # create temp dir to store wav. will be removed at end of script + +# Define function to check if all small wavs have an rttm. If not, create an empty one. +create_empty_rttm() { + # check the wav files and the talker_roles to see if the rttm exists + # if it doesn't, create an empty rttm file. + wav=$1 + rttms=$2 + for fin in `ls $wav/*.wav`; do + basename=$(basename $fin .wav) + if [[ ! -f $rttms/${basename}.rttm ]]; then + touch $rttms/${basename}.rttm + fi + done +} + +## Treat BER WAR the "simple way", add parameters to take into account the format of CAS and SOD/SOD2 +#if [[ $corpus == 'BER' ]] || [[ $corpus == 'WAR' ]] || [[ $corpus == 'CAS' ]]; then +if [[ $corpus != 'SOD2' ]] ; then + mkdir -p $temp_dir/$corpus/SAD + for wav in `ls $daylong_dir/$corpus/*.wav`; do + base=$(basename $wav .wav) + eaf=raw_$corpus/${base}.eaf + if [[ $corpus == 'CAS' ]]; then + python $working_dir/adjust_timestamps.py $working_dir/github_data/$eaf $wav $temp_dir --CAS + else + python $working_dir/adjust_timestamps.py $working_dir/github_data/$eaf $wav $temp_dir 2>&1 + fi + # now remove old wav and transcriptions: + + done + rm $working_dir/ACLEW_data/databrary_ACLEW/wavs/${corpus}_*wav $working_dir/ACLEW_data/databrary_ACLEW/talker_role/${corpus}_*rttm + mv $temp_dir/*.rttm $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ + mv $temp_dir/*.wav $working_dir/ACLEW_data/databrary_ACLEW/wavs/ + + # create empty rttms when the wav has no transcription (nobody's talking)' + #create_empty_rttm $corpus/treated $corpus/treated/talker_role + + # Now create the SAD + rm $working_dir/ACLEW_data/databrary_ACLEW/SAD/${corpus}_*rttm + python remove_overlap_rttm.py $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ $working_dir/ACLEW_data/databrary_ACLEW/SAD +fi + +# SOD : the eaf have the same name as the wav, but they added '-$name' where $name is the initials of the annotator +if [[ $corpus == 'SOD2' ]]; then + echo "treating SOD" 2>&1 + corpus=SOD + mkdir -p $temp_dir/$corpus/SAD + for wav in `ls $daylong_dir/$corpus/*.wav`; do + base=$(basename $wav .wav) + eaf=raw_$corpus/${base}-TS.eaf + if [ ! -f $working_dir/github_data/$eaf ]; then + eaf=raw_$corpus/${base}-JK.eaf + fi + python $working_dir/adjust_timestamps.py $working_dir/github_data/$eaf $wav $temp_dir 2>&1 + + done + mv $temp_dir/*.rttm $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ + mv $temp_dir/*.wav $working_dir/ACLEW_data/databrary_ACLEW/wavs/ + + # Now create the SAD + python remove_overlap_rttm.py $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ $working_dir/ACLEW_data/databrary_ACLEW/SAD + +fi +# create empty rttms when the wav has no transcription (nobody's talking)' + +#create_empty_rttm $corpus/treated $corpus/treated/talker_role + +# Now create the SAD +#python remove_overlap_rttm.py $corpus/treated/talker_role $corpus/treated/SAD + + +## CAS : the eaf don't have the 'on_off' tier to encode the segments, instead it's called "code" - this is taken +## into account in adjust_timestamps.py with the --CAS parameter +#if [[ $corpus == 'CAS' ]]; then +# #convert2wav $corpus +# mkdir -p $corpus/treated/SAD +# for wav in `ls $corpus/*.wav`; do +# base=$(basename $wav .wav) +# eaf=$corpus/raw_$corpus/${base}.eaf +# python $working_dir/adjust_timestamps.py $eaf $wav --CAS +# done +#fi +## create empty rttms when the wav has no transcription (nobody's talking)' +# +#create_empty_rttm $corpus/treated $corpus/treated/talker_role +# +## Now create the SAD +#python remove_overlap_rttm.py $corpus/treated/talker_role $corpus/treated/SAD +##done +# diff --git a/utils/noisemes_full.sh b/utils/noisemes_full.sh new file mode 100644 index 0000000..b93fcf5 --- /dev/null +++ b/utils/noisemes_full.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run OpenSAT with hard coded models & configs found here and in /vagrant +# assumes Python environment in /home/${user}/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to OpenSAT (go on folder up and to opensat) +OPENSATDIR=$(dirname $BASEDIR)/OpenSAT + +if [ $# -ne 1 ]; then + echo "Usage: noisemes_full.sh " + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of OpenSAT +cd $OPENSATDIR + +# first features +echo "extracting features for noisemes_full" +for file in `ls $audio_dir/*.wav`; do + SSSF/code/feature/extract-htk-vm2.sh $file +done + + + + +# then confidences +#/home/vagrant/anaconda/bin/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename +echo "predicting classes" +#$conda_dir/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename +$conda_dir/python SSSF/code/predict/1-confidence-vm4.py $audio_dir +echo "noisemes_full finished running" + +# take all the .rttm in /vagrant/data/hyp_sum and move them to /vagrant/data - move features and hyp_sum to another folder also. +for sad in `ls $audio_dir/hyp_sum/*.rttm`; do + _rttm=$(basename $sad) + rttm=$audio_dir/noiseme_full_${_rttm} + mv $sad $rttm +done + +# simply remove hyp and feature +rm -rf $audio_dir/feature $audio_dir/hyp_sum + +#if [ ! -d "$audio_dir/noiseme_full_temp" ]; then +# mkdir -p $audio_dir/noiseme_full_temp +#fi +# +#if [! -d "$audio_dir/noiseme_full_temp" ]; then +# mv $audio_dir/hyp_sum $audio_dir/noiseme_full_temp +#else +# echo "can't move hyp_sum/ folder to noiseme_full_temp/ because temp is already full" +#fi +# +#if [! -d "$audio_dir/noiseme_full_temp" ]; then +# mv $audio_dir/feature $audio_dir/noiseme_full_temp +#else +# echo "can't move features/ folder to noiseme_full_temp/ because temp is already full" +#fi +# diff --git a/utils/parse_cha_xml.py b/utils/parse_cha_xml.py new file mode 100755 index 0000000..f9a561f --- /dev/null +++ b/utils/parse_cha_xml.py @@ -0,0 +1,191 @@ +# parse_cha_xml.py +# +# Given CHATTER format xml (http://talkbank.org/software/chatter.html) +# supplied as an argument, or via a pipe, print out STM format text +# +# To toggle whether UNIBET words are printed out, or instead appear as "" +# set the switch --oov. To instead print their replacements, set the switch --replacment +# +# usage ./parse_cha_xml.py P1_6W_SE_C6.xml +# +# Change Log: +# 17 Jan 2018 - print plaintext utterances even if no timecode present +# - added handling of "happening" and formType elements +# to support things like "singing", yell, shout etc. +# - added metadata for speaker e.g. as +# found in 'participant' tags + +from xml.dom.minidom import parse +import sys,argparse,os + +reload(sys) +sys.setdefaultencoding("utf-8") + +parser=argparse.ArgumentParser(description="""Description""") +parser.add_argument('--oov', action='store_true', help='print symbols for nonwords') +parser.add_argument('--replacement', action='store_true', help='print replacement words') +parser.add_argument('--stm', action='store_true', help='produce STM format') +parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), help='CHATTER (xml) format input file', + default=sys.stdin) +args=parser.parse_args() + +# a table of speaker IDs and related metadata + +infile = args.infile.name +if infile == '': + dom = parse(sys.stdin) +else: + dom = parse(infile) +utts = dom.getElementsByTagName('u') # utterances +participants = dom.getElementsByTagName('participant') + +oov = args.oov +stm = args.stm +replace = args.replacement +#recording = infile[infile.rfind("/")+1:] +# get only base name (chop off .xml extension) +recording = os.path.splitext(os.path.basename(infile))[0] + +#utterance = "" + +parts = {} +for part in participants: + label = "<"; ident = "" + name = ""; role = ""; sex = "u" + for key in part.attributes.keys(): + if key == "id": + ident = part.attributes[key].nodeValue.encode('utf8') + if key == "name": + name = part.attributes[key].nodeValue.encode('utf8') + name = name.replace(" ","") + if key == "role": + role = part.attributes[key].nodeValue.encode('utf8') + role = role.replace(" ","") + if key == "sex": + sex = part.attributes[key].nodeValue.encode('utf8') + if sex == "male": sex = "m" + if sex == "female": sex = "f" + parts[ident]=("<"+name+","+sex+","+role+">").lower() +# print parts[ident] + +# add the word found inside node passed in as argument +def addWord( node ): + global utterance + for wordlet in node.childNodes: + if wordlet.nodeType == wordlet.TEXT_NODE: + unibet = False + s = wordlet.nodeValue + try: s.decode('ascii') + except UnicodeDecodeError: unibet = True + utterance += " " + if oov and unibet: + utterance += "" + else: + utterance += wordlet.nodeValue.encode('utf8') + + +def addReplacement ( group ): + added = False + for subword in group.childNodes: + if subword.nodeType == subword.ELEMENT_NODE and subword.tagName == 'replacement': + for replacement in subword.childNodes: + if replacement.nodeType == replacement.ELEMENT_NODE and replacement.tagName == 'w': + addWord( replacement ) + added = True + # didn't find a - just output the word + if not added: addWord( group ) + +def addUnibetOrReplacement( node ): + global utterance + for key in node.attributes.keys(): + if key == "untranscribed": + if oov: + utterance += " " + "" + else: + addWord( node ) + if key == "type" and (node.attributes[key].nodeValue == "fragment"): + utterance += " " + node.firstChild.nodeValue + if key == "formType": + if node.attributes[key].nodeValue == "UNIBET": + if replace: + addReplacement( node ) + else: + addWord( node ) + else: # for all other form types + # e.g. singing, babbling, kana, onomotapoeia, family-specific, letter, child-invented + # output word + addWord( node ) + +for utt in utts: + utterance = "" + start = 0 + has_timecode = False + # speaker + for key in utt.attributes.keys(): + if key == "who": + speaker=utt.attributes[key].nodeValue + spk_reco_clause = recording+" "+speaker+" "+recording+"_"+speaker + + for word in utt.childNodes: + # time code + if word.nodeType == word.ELEMENT_NODE and word.tagName == 'media': + has_timecode = True + for key in word.attributes.keys(): + if key == "start": + start = word.attributes[key].nodeValue + if key == "end": + end = word.attributes[key].nodeValue + if stm: + # Don't output if start == end; confuses downstream systems + if start != end: + print spk_reco_clause+" "+start+" "+end+" "+parts[speaker]+\ + utterance.lower().replace("_"," ").replace("-","") + sys.stdout.flush() + else: + print utterance.lower().replace("_"," ").replace("-","") + sys.stdout.flush() + utterance = "" + + # tb:wordType ("" tag) + if word.nodeType == word.ELEMENT_NODE and word.tagName == 'w': + if len(word.attributes.keys())==0: + if word.childNodes.length == 1: + addWord( word ) + else: + if replace: + addReplacement( word ) + else: + addWord( word ) + else: + addUnibetOrReplacement( word ) + # tb:element type ("" tag): + if word.nodeType == word.ELEMENT_NODE and word.tagName == 'e': + for wordlet in word.childNodes: + if wordlet.nodeType == wordlet.ELEMENT_NODE and wordlet.tagName == 'happening': + for txt in wordlet.childNodes: + thetxt = txt.nodeValue + utterance += " <" + thetxt.encode('utf8') + ">" + # tb:groupType or phoneticGroupType ("" or "" tag): + if word.nodeType == word.ELEMENT_NODE and (word.tagName == 'g' or word.tagName == 'pg'): + for group in word.childNodes: + if group.nodeType == group.ELEMENT_NODE and group.tagName == 'w': + if len(group.attributes.keys())==0: + if group.childNodes.length == 1: + addWord( group ) + else: + if replace: + addReplacement( group ) + else: + addWord( group ) + else: + # print oov (or unibet encoded word) + if oov: + utterance += " " + "" + else: + addUnibetOrReplacement( group ) + # done with utterance. if it had no timecode, was not printed(!) so + # print now + if not has_timecode: + print utterance.lower().replace("_"," ").replace("-","") + sys.stdout.flush() + utterance = "" diff --git a/toolbox/rttm2labels.py b/utils/rttm2labels.py similarity index 100% rename from toolbox/rttm2labels.py rename to utils/rttm2labels.py diff --git a/toolbox/rttm2scp.py b/utils/rttm2scp.py similarity index 100% rename from toolbox/rttm2scp.py rename to utils/rttm2scp.py diff --git a/toolbox/rttm2scp.sh b/utils/rttm2scp.sh similarity index 100% rename from toolbox/rttm2scp.sh rename to utils/rttm2scp.sh diff --git a/utils/runTALNet.sh b/utils/runTALNet.sh new file mode 100755 index 0000000..6da0d8d --- /dev/null +++ b/utils/runTALNet.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run 537 class classifier with hard coded models & configs found here +# assumes Python environment in /home/${user}/anaconda/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to classify tool (go one folder up and to 537cls) +CLASSIFY=$(dirname $BASEDIR)/TALNet + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "in /vagrant containing wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of TALNet +cd $CLASSIFY + +# Iterate over files +echo "Starting" +for f in `ls ${audio_dir}/*.wav`; do + ./runTALNet.sh $f + base=$(basename $f .wav) + mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat +done + +echo "$0 finished running" diff --git a/utils/selcha2clean.sh b/utils/selcha2clean.sh new file mode 100755 index 0000000..379a017 --- /dev/null +++ b/utils/selcha2clean.sh @@ -0,0 +1,169 @@ +#!/usr/bin/env bash +# Given a txt file containing the following fields : onset offset transcription receiver speaker_tier (Note that eaf2txt.py generates such kind of files) +# Returns an enriched version of it by cleaning the transcription field, syllabifying (or phonemizing it), counting the number of words, and the number of syllables + +LC_CTYPE=C +#########VARIABLES +#Variables that have been passed by the user +SELFILE=$1 +ORTHO=$2 +LANG=$3 +######### + + +display_usage() { + echo "Given a txt files containing the following fields : onset offset transcription receiver speaker_tier" + echo "and a language, returns an enriched version of this file by :" + echo -e "\t 1) Cleaning the transcription field (removing human-made errors)" + echo -e "\t 2) Counting the number of words" + echo -e "\t 3) Phonemizing (if english)/Syllabifying (if spanish or tzeltal) the transcription" + echo -e "\t 4) Counting the number of syllables" + echo "usage: $0 [input] [output] [language]" + echo " input The file path where to find the input txt file (REQUIRED)." + echo " output The output path (REQUIRED)." + echo " language The language of the transcription : english, spanish or tzeltal (REQUIRED)." + exit 1 + } + +if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || ! [[ $LANG =~ ^(english|spanish|tzeltal)$ ]]; then + display_usage +fi + +# Get relative and absolute paths that we need. +DATA_DIR=/vagrant +SELFILE_ABS="$DATA_DIR/$SELFILE" +ORTHO_ABS="$DATA_DIR/$ORTHO" +DIRNAME_ABS=$(dirname "${ORTHO_ABS}") +CLEAN_TRANSCRIPT_ABS=$DIRNAME_ABS"/clean_transcript.txt" +PHONEMIZED_ABS=$DIRNAME_ABS"/phonemized.txt" +DIRNAME_REL=$(dirname "${ORTHO}") +CLEAN_TRANSCRIPT_REL=$DIRNAME_REL"/clean_transcript.txt" +PHONEMIZED_REL=$DIRNAME_REL"/phonemized.txt" + +echo "Cleaning $SELFILE" + + +### HANDLING REPETITIONS ### +###  word [x2] ### +### or [x2]   ### +cut -f 4 -d$'\t' $SELFILE_ABS | +sed "s/\[ \+/\[/g" | +sed "s/ \+\[/\[/g" | +sed -r "s/\[X([0-9]+)/\[x\1/g" | +sed "s/> \+/>/g" > ${CLEAN_TRANSCRIPT_ABS}.tmp + +python -c " +import re +for line in open(\"${CLEAN_TRANSCRIPT_ABS}.tmp\"): + + if '<' in line and '>' in line: + newline = re.sub('<(.*)>\[x([0-9]+)\]', r'\1 \2', line) + if newline != line: + n = int(newline[-2:-1]) + newline = newline[:-2]*n + else: + newline = line + else: + reg = re.sub('(.*)\[x([0-9]+)\]', r'\1\2', line) + newline=[] + for word in reg.split(): + if word[-1].isdigit(): + newline += [word[:-1]]*int(word[-1]) + else: + newline += [word] + newline = ' '.join(newline) + newline = newline.rstrip() # Remove all \newline and let the print function puts only one of them + print(newline) +" > ${CLEAN_TRANSCRIPT_ABS}2.tmp + + +### CLEAN human-made inconsistencies + +cat ${CLEAN_TRANSCRIPT_ABS}2.tmp | +sed "s/\_/ /g" | +sed '/^0(.*) .$/d' | +sed 's/\..*$//g' | #this code deletes bulletpoints (Û+numbers +sed 's/\?.*$//g' | +sed 's/\!.*$//g' | +tr -d '\"' | +tr -d '\^' | #used to be identical to previous line +tr -d '\/' | +sed 's/\+/ /g' | +tr -d '\.' | +tr -d '\?' | +tr -d '!' | +tr -d ';' | +tr -d '\<' | +tr -d '\>' | +tr -d ',' | +tr -d ':' | +tr -d '~' | +sed 's/&=[^ ]*//g' | +sed 's/&[^ ]*//g' | #delete words beginning with & ##IMPORTANT CHOICE COULD HAVE CHOSEN TO NOT DELETE SUCH NEOLOGISMS/NONWORDS +sed 's/\[[^[]*\]//g' | #delete comments +#sed 's/([^(]*)//g' | #IMPORTANT CHOICE -- UNCOMMENT THIS LINE AND COMMENT OUT THE NEXT TO DELETE MATERIAL NOTED AS NOT PRONOUNCED +sed 's/(//g' | sed 's/)//g' | #IMPORTANT CHOICE -- UNCOMMENT THIS LINE AND COMMENT OUT THE PRECEDING TO REMOVE PARENTHESES TAGGING UNPRONOUNCED MATERIAL +sed 's/xxx//g' | +sed 's/www//g' | +sed 's/XXX//g' | +sed 's/yyy//g' | +sed 's/0*//g' | +sed 's/[^ ]*@s:[^ ]*//g' | #delete words tagged as being a switch into another language +#sed 's/[^ ]*@o//g' | #delete words tagged as onomatopeic +sed 's/@[^ ]*//g' | #delete tags beginning with @ IMPORTANT CHOICE, COULD HAVE CHOSEN TO DELETE FAMILIAR/ONOMAT WORDS +sed "s/\'/ /g" | +tr -s ' ' | +sed 's/ $//g' | +sed 's/^ //g' | +sed 's/^[ ]*//g' | +sed 's/ $//g' | +#sed '/^$/d' | # We don't want to remove end lines here +sed '/^ $/d' | +sed 's/\^//g' | +sed 's/\-//g' | +sed 's/\[\=//g' | # We observed [= occurrences that we're not interested in. Has to be careful about that one +sed 's/[0-9]//g' | # We remove all of the remaining numbers +#tr -d '\t' | +awk '{gsub("\"",""); print}' > ${CLEAN_TRANSCRIPT_ABS}3.tmp + +SCRIPT_DIR=$(dirname "$0") +$SCRIPT_DIR/syllabify.sh ${CLEAN_TRANSCRIPT_REL}3.tmp ${PHONEMIZED_REL} $LANG + +## Append number of words to the clean transcription +cat ${CLEAN_TRANSCRIPT_ABS}3.tmp | awk -F'[ ]' '{print $0"\t"NF}' > ${CLEAN_TRANSCRIPT_ABS} + +## Concatenate those 2 files +python -c " +import re +transcript_f = open(\"${CLEAN_TRANSCRIPT_ABS}\") +phonemized_f = open(\"${PHONEMIZED_ABS}\") + +for transcript_l in transcript_f.readlines(): + nb_words = transcript_l.split('\t')[1] + if int(nb_words) == 0: + x=2 + print(\"\t0\t\t0\") + else: + phoneme_l = phonemized_f.readline() + transcript_l = transcript_l.rstrip() + phoneme_l = phoneme_l.rstrip() + print(transcript_l+'\t'+phoneme_l) +" > $ORTHO_ABS.tmp + +## Now we concatenate the original csv files and the clean ortho (by column) +### Extract everything except transcript column from the original file +cut -f1,2,3,5 -d$'\t' $SELFILE_ABS > ${ORTHO_ABS}2.tmp + +### Concatenate the latter columns to the clean one contained in _tmp3.txt +paste -d$'\t' ${ORTHO_ABS}2.tmp ${ORTHO_ABS}.tmp > $ORTHO_ABS + +##This is to process all the "junk" that were generated when making the +##changes from included to ortho. For e.g., the cleaning process +##generated double spaces between 2 words (while not present in +##included) +sed -i -e 's/ $//g' $ORTHO_ABS + +# Remove temporary files +rm ${DIRNAME_ABS}/*.tmp +rm ${CLEAN_TRANSCRIPT_ABS} +rm ${PHONEMIZED_ABS} \ No newline at end of file diff --git a/utils/sum-rttm.sh b/utils/sum-rttm.sh new file mode 100755 index 0000000..056d831 --- /dev/null +++ b/utils/sum-rttm.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# sum-rttm.sh +# +# Compute and print the number of lines in an RTTM, and the sum of durations +# for use in comparing system outputs +# +# Takes 1 argument: path to an RTTM file + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "where RTTMfile is an RTTM filename" + exit 1 +fi + +LINES=`cat $1 | wc -l` +SUM=`awk '{SUM+=$5} END {print SUM}' $1` + +echo -e 'LINES: '$LINES'\tDURATION SUM: '$SUM'\tFILE: '$1 diff --git a/utils/syllabify.sh b/utils/syllabify.sh new file mode 100755 index 0000000..0c3444f --- /dev/null +++ b/utils/syllabify.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Given an input file (containing raw text), an output one, and a language (english, spanish or tzeltal) +# Write in the output file the phonemization (if english) or the syllabification (if spanish or tzeltal) of it, +# and count the number of syllables +### Script parameters +INPUT=$1 +OUTPUT=$2 +LANG=$3 +VOWELS=$4 +### +DATA_DIR="/vagrant" +INPUT=$DATA_DIR"/"$INPUT +OUTPUT=$DATA_DIR"/"$OUTPUT +DIRNAME=${INPUT%/*} +EXTENSION=${INPUT##*.} + +display_usage() { + echo "Given the path to a file (.tmp or .txt) containing sentences, a language (english, spanish or tzeltal)," + echo "and a list of vowels, create a .syll file containing the original sentence, the phonemized/syllabified" + echo "version of it, and the number of syllables present in the original sentence." + echo "usage: $0 [input] [output] [language] [vowels]" + echo " input The file path where to find the transcription. Has to be txt or tmp extension. (REQUIRED)" + echo " output The output path. (REQUIRED)" + echo " language The language of the transcription (OPTIONAL, default = english)" + echo " vowels The list of vowels of the language if language set on spanish or tzeltal (OPTIONAL, default = aeiou)" + exit 1 + } + +if [ -z "$1" ] || [ -z "$2" ] || ! [[ $EXTENSION =~ ^(txt|tmp)$ ]]; then + display_usage +fi + +if [ -z "$3" ]; then + echo "No languages has been provided. Setting this parameter to english." + LANG="english" +fi + +if [ "$3" == "spanish" ] || [ "$3" == "tzeltal" ]; then + if [ -z "$4" ]; then + VOWELS="aeiouáéíóúü" + echo "Language set on spanish or tzeltal. But no vowels have been provided." + echo "Setting this parameter to $VOWELS" + echo $VOWELS > $DIRNAME"/"$LANG"-Vowels.txt" + fi +fi + +if [ "$3" == "english" ]; then + echo "Pĥonemizing $INPUT ..." + # Phonemize the clean version + phonemize ${INPUT} -o ${OUTPUT}.tmp -s - + + ## Append number of syllables to the phonemized transcription + cat ${OUTPUT}.tmp | awk -F- '{print $0"\t"NF-1}' > ${OUTPUT} +elif [ "$3" == "spanish" ] || [ "$3" == "tzeltal" ]; then + # Changing upper case to lower case + cat $INPUT | tr '[:upper:]' '[:lower:]' | tr 'A-ZÂÁÀÄÊÉÈËÏÍÎÖÓÔÖÚÙÛÑÇ' 'a-zâáàäêéèëïíîöóôöúùûñç' > $INPUT.tmp + # Get all the different words in the corpus + # and get the different onsets by removing what follows the first vowel + cat $INPUT.tmp | tr ' ' '\n' | sort | uniq | + sed 's/[aeiou].*//g' | grep .| uniq > $DIRNAME"/"$LANG"-ValidOnsets.txt" + SCRIPT_DIR=$(dirname "$0") + perl $SCRIPT_DIR/catspa-syllabify-corpus.pl $LANG $INPUT.tmp $OUTPUT.tmp + + ## Append number of syllables + cat $OUTPUT.tmp | awk -F'/' '{print $0"\t"NF-1}' > $OUTPUT + + rm $INPUT.tmp $DIRNAME"/"$LANG"-ValidOnsets.txt" $DIRNAME"/"$LANG"-Vowels.txt" +else + echo "Language unknown." + exit 1 +fi + +echo "Done." + +rm $OUTPUT.tmp + + diff --git a/utils/textgrid2rttm.py b/utils/textgrid2rttm.py new file mode 100755 index 0000000..ea7e35f --- /dev/null +++ b/utils/textgrid2rttm.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# +# author = julien karadayi +# +# This script converts transcription in Text Grid / Praat format +# to RTTM format. This is useful for evaluating performances of +# Speech detection algorithms with the *dscore* package, +# in the DiarizationVM virtual machine. +# The 1 and 0 labels are sent to " speech ", and no label / "x" label +# are not written in output (which means it is described as "non speech") + +import os +import argparse +# from praatio import tgio +import tgt # tgt is better thant praatio for our application + # because it allows to manipulate the timestamps, + # which is something we cannot do with praatio. + + + +def textgrid2rttm(textgrid): + ''' + Take in input the path to a text grid, + and output a dictionary of lists *{spkr: [ (onset, duration) ]}* + that can easily be written in rttm format. + ''' + # init output + rttm_out = dict() + + # open textgrid + #tg = tgio.openTextgrid(textgrid) + tg = tgt.read_textgrid(textgrid) + + # loop over all speakers in this text grid + #for spkr in tg.tierNameList: + for spkr in tg.get_tier_names(): + + spkr_timestamps = [] + # loop over all annotations for this speaker + #for interval in tg.tierDict[spkr].entryList: + for _interval in tg.get_tiers_by_name(spkr): + for interval in _interval: + + bg, ed, label = interval.start_time,\ + interval.end_time,\ + interval.text + + #if label == "x": + # continue + #elif label == "1" or label == "2": + # spkr_timestamps.append((bg, ed-bg)) + spkr_timestamps.append((bg, ed-bg)) + + # add list of onsets, durations for each speakers + rttm_out[spkr] = spkr_timestamps + return rttm_out + + +def write_rttm(rttm_out, basename_whole): + ''' + take a dictionary {spkr:[ (onset, duration) ]} as input + and write on rttm output by speaker + ''' + # write one rttm file for the whole wav, indicating + # only regions of speech, and not the speaker + with open(basename_whole + '.rttm', 'w') as fout: + for spkr in rttm_out: + for bg, dur in rttm_out[spkr]: + fout.write(u'SPEAKER {} 1 {} {} ' + ' {} \n'.format( + basename_whole.split('/')[-1], bg, dur, spkr)) + + +if __name__ == '__main__': + command_example = "python textgrid2rttm.py /folder/" + parser = argparse.ArgumentParser(epilog=command_example) + parser.add_argument('input_file', + help=''' Input File ''') + parser.add_argument('output_file', + help='''Name of the output file in which to write''') + + args = parser.parse_args() + + rttm_out = textgrid2rttm(args.input_file) + write_rttm(rttm_out, args.output_file) + #if not os.path.isdir(args.output_folder_whole): + # os.makedirs(args.output_folder_whole) + + #for fold in os.listdir(args.input_folder): + # for fin in os.listdir(os.path.join(args.input_folder, fold)): + # if not fin.endswith('m1.TextGrid'): + # # read only text grids with full anotation + # # in this folder + # continue + + # tg_in = os.path.join(args.input_folder, fold, fin) + # basename_whole = os.path.join(args.output_folder_whole, + # '_'.join(fin.split('_')[0:3])) + + # # extract begining/durations of speech intervals + # rttm_out = textgrid2rttm(tg_in) + # # write 1 rttm per spkr transcribed in this text grid + # write_rttm(rttm_out, basename_whole) diff --git a/toolbox/tocombo2rttm.py b/utils/tocombo2rttm.py similarity index 100% rename from toolbox/tocombo2rttm.py rename to utils/tocombo2rttm.py diff --git a/utils/train_test_split.py b/utils/train_test_split.py new file mode 100755 index 0000000..64ad008 --- /dev/null +++ b/utils/train_test_split.py @@ -0,0 +1,146 @@ +import os +import glob +import shutil +import numpy as np +import argparse +from math import floor, ceil + +### GLOBAL VARIABLE +default_test_prop = 0.5 + +def _create_empty_train_test(input_folder): + """ + Given an input folder, create a train and test folder. + If these folders already exist, move their content to the input folder before creating new train and test folders. + + Parameters + ---------- + input_folder path to the input folder + + Returns + ------- + path of the train folder and path of the test folder + """ + train_folder, test_folder = os.path.join(input_folder, 'train'), os.path.join(input_folder, 'test') + + # Bring back files to the parent directory + files = glob.glob(os.path.join(train_folder, '*'))+glob.glob(os.path.join(test_folder, '*')) + for path_f in files: + basename = os.path.basename(path_f) + shutil.move(path_f, os.path.join(input_folder, basename)) + + # Delete train and test folder + if os.path.isdir(train_folder): + shutil.rmtree(train_folder) + + if os.path.isdir(test_folder): + shutil.rmtree(test_folder) + + # Create new ones + os.makedirs(train_folder) + os.makedirs(test_folder) + + return train_folder, test_folder + + +def split(input_folder, test_prop, train_prop): + """ + Given an input folder, a proportion for the test set, a proportion for the training set, split the pairs + (.wav/.rttm) into a training folder and a test folder. + + Parameters + ---------- + input_folder the path to the input folder (containing wav and rttm files) + test_prop the proportion of the data that will be included in the test set + train_prop the proportion of the data that will be included in the training set + """ + # Create empty train and test directories. + # Move their content to the parent directory if they already exist + train_folder, test_folder = _create_empty_train_test(input_folder) + + # Check for all the wav into the the input_folder + wav = np.array(glob.glob(os.path.join(input_folder, "*.wav"))) + np.random.shuffle(wav) + + n_samples = len(wav) + n_train, n_test = np.int(floor(train_prop*n_samples)), np.int(ceil(test_prop*n_samples)) + + training_idx = np.arange(n_train) + test_idx = np.arange(n_train, n_train + n_test) + + train, test = wav[training_idx], wav[test_idx] + + # Move wav files ONLY if an associated rttm is found + for train_f in train: + basename = os.path.splitext(os.path.basename(train_f))[0] + old_path = os.path.join(input_folder, basename) + new_path = os.path.join(train_folder, basename) + if os.path.exists(old_path+'.rttm'): + os.rename(old_path+'.rttm', new_path+'.rttm') + os.rename(old_path+'.wav', new_path+'.wav') + else: + print("Ignoring file %s whose rttm has not been found." % (basename+'.wav')) + + for test_f in test: + basename = os.path.splitext(os.path.basename(test_f))[0] + old_path = os.path.join(input_folder, basename) + new_path = os.path.join(test_folder, basename) + if os.path.exists(old_path+'.rttm'): + os.rename(old_path+'.rttm', new_path+'.rttm') + os.rename(old_path+'.wav', new_path+'.wav') + else: + print("Ignoring file %s whose rttm has not been found." % (basename+'.wav')) + + n_real_train = len([f for f in glob.glob(os.path.join(train_folder, '*')) if os.path.isfile(f)]) / 2 + n_real_test = len([f for f in glob.glob(os.path.join(test_folder, '*')) if os.path.isfile(f)]) / 2 + + if n_real_train == 0: + print("Warning : The training set that you generated is empty !") + if n_real_test == 0: + print("Warning : The test set that you generated is empty !") + + + + + +def main(): + parser = argparse.ArgumentParser(description="Split a folder into a train set and a test set.") + parser.add_argument('-f', '--folder', type=str, required=True, + help='path to the folder that needs to be splitted.') + parser.add_argument('--test_prop', type=float, default=None, + help='''a float between 0.0 and 1.0 representing the proportion of the + dataset to include in the test set. If not specfied, the + value is automatically set to the complement of the + --train_prop. If --train_prop is not specified, --test_prop is set to + {}'''.format(default_test_prop)) + parser.add_argument('--train_prop', default=None, type=float, + help='''a float between 0.0 and 1.0 representing the proportion of the + dataset to include in the train set. If not specified, the + value is automatically set to the complement of --test_prop''') + parser.add_argument('-r', '--random_seed', default=None, type=int, + help='Seed the generator (for reproducible results)') + args = parser.parse_args() + + if args.train_prop is None: + test_prop = default_test_prop if args.test_prop is None else args.test_prop + else: + test_prop = 1.0-args.train_prop if args.test_prop is None else args.test_prop + train_prop = args.train_prop + + if test_prop < 0.0 or test_prop > 1.0 or train_prop < 0.0 or train_prop > 1.0: + raise ValueError("The test proportion and the train proportion must be between 0 and 1") + + data_dir = "/vagrant" + input_folder = os.path.join(data_dir, args.folder) + if not os.path.isdir(input_folder): + raise ValueError("The folder that you want to split is not found. Please check the path that you provided.") + + # Set the random seed + if args.random_seed is not None: + np.random.seed(args.random_seed) + + split(input_folder, test_prop, train_prop) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/utils/txt2rttm.py b/utils/txt2rttm.py new file mode 100755 index 0000000..cba1ae4 --- /dev/null +++ b/utils/txt2rttm.py @@ -0,0 +1,140 @@ +""" +This script converts an txt file into a rttm one. +The txt file must contain : class onset offset. +It can be run either on a single txt file, or on a whole folder containing txt files. + +Example of use : + python tools/txt2rttm.py -i data/my_file.txt # One one file + python tools/txt2rttm.py -i data/ # On a whole folder + python tools/txt2rttm.py -i data/ -l True # On a whole folder + lena mode activated + +If the lena mode is activated, it will look for a file called tsi_key_info.xlsx in the input folder +that contains a column file_lena (storing lena names, ex : e20170722_093015_009456_2040_2100_lena) +and a column key (containg the associated ACLEW name) +About the naming convention of the output : + For each file called input_file.txt, the result will be stored in input_file.rttm +""" + +import pympi as pmp +import argparse +import os +import sys +import glob +from openpyxl import load_workbook + +def lena_to_aclew_name(tsi_key_info, basename): + """ + Convert lena names to ACLEW names. + + Parameters + ---------- + tsi_key_info : the path to the tsi_key_infos.xlsx file + basename : the basename of the txt file that needs to be converted. This name follows the LENA naming convention. + + Returns + ------- + The name respecting the ACLEW naming convention + """ + onset = basename.split('_')[3] + basename_beg = '_'.join(basename.split('_')[0:3]) # Get the first 3 elements + wb = load_workbook(tsi_key_info,data_only=True) + wb = wb.worksheets[0] + first_row = wb.rows[0] + file_lena_num_col = None + key_num_col = None + + # Get num of the column + for idx in range(0, len(first_row)): + cell = first_row[idx] + if cell.value == "file_lena": + file_lena_num_col = idx + if cell.value == "key": + key_num_col = idx + + # Loop through the cells to look for the basename + if file_lena_num_col is not None and key_num_col is not None: + for row in wb.rows[1:]: + file_lena = row[file_lena_num_col].value + key_num = row[key_num_col].value + if file_lena == basename_beg: + child, good_date = key_num.split('_') + return '_'.join(['lena',child,good_date,onset]) + + +def txt2rttm(path_to_txt, output_folder, labels_to_keep, lena_mode=False, only_first_letter=False): + """ + Convert an txt file to the rttm format by extracting the + Parameters + ---------- + path_to_txt : path to the txt file. + output_folder : where to store the output files + + Write a rttm whose name is the same than the txt's one in output_folder + """ + basename = os.path.splitext(os.path.basename(path_to_txt))[0] + if lena_mode: + dirname = os.path.dirname(path_to_txt) + output_basename = lena_to_aclew_name(os.path.join(dirname, 'tsi_key_info.xlsx'), basename) + output_path = os.path.join(dirname, output_basename + '.rttm') + # Change the output_basename because we don't want to write the model prefix lena_ + # in the rttm fil + output_basename = '_'.join(output_basename.split('_')[1:]) + else: + output_path = os.path.join(output_folder, basename + '.rttm') + output_basename = os.path.splitext(os.path.basename(output_path))[0] + + with open(path_to_txt, 'r') as txt: + with open(output_path, 'w') as rttm: + for line in txt: + activity, onset, offset = line.rstrip().split('\t') + dur = float(offset)-float(onset) + + if lena_mode and activity in labels_to_keep: + if only_first_letter: + activity = activity[0] + rttm.write("SPEAKER %s 1 %s %s %s \n" % (output_basename, onset, str(dur), activity)) + elif not lena_mode: + rttm.write("SPEAKER %s 1 %s %s %s \n" % (output_basename, onset, str(dur), activity)) + + +def main(): + parser = argparse.ArgumentParser(description="convert .txt into .rttm") + parser.add_argument('-i', '--input', type=str, required=True, + help="path to the input .txt file or the folder containing txt files.") + parser.add_argument('-l', '--lena_mode', type=bool, required=False, default=False, + help="indicates whether to use this script in the lena mode or not. If the lena mode" + "is activated, it will read the table tsi_key_info.xlsx in the input folder and" + "will change the naming convention of the output in consequences") + parser.add_argument('-t', '--to_keep', nargs='+', type=str, required=True, + help='List of labels that needs to be kept.') + parser.add_argument('-fl', '--only_first_letter', type=bool, default=False, + help='Indicates if the output labels will be produced by keeping only the first letter' + 'of the original labels.') + args = parser.parse_args() + + + # Initialize the output folder as the same folder than the input + # if not provided by the user. + if args.input[-4:] == '.txt': + output = os.path.dirname(args.input) + else: + output = args.input + + data_dir = '/vagrant' + args.input = os.path.join(data_dir, args.input) + output = os.path.join(data_dir, output) + + if not os.path.isdir(output): + os.mkdir(output) + + if args.input[-4:] == '.txt': # A single file has been provided by the user + txt2rttm(args.input, output, args.to_keep, args.lena_mode, args.only_first_letter) + else: # A whole folder has been provided + txt_files = glob.iglob(os.path.join(args.input, '*.txt')) + for txt_path in txt_files: + print("Processing %s" % txt_path) + txt2rttm(txt_path, output, args.to_keep, args.lena_mode, args.only_first_letter) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/conf/vad/vad_segmenter_aclew.conf b/utils/vad_segmenter_aclew.conf.txt old mode 100755 new mode 100644 similarity index 100% rename from conf/vad/vad_segmenter_aclew.conf rename to utils/vad_segmenter_aclew.conf.txt diff --git a/utils/yuniSeg.sh b/utils/yuniSeg.sh new file mode 100644 index 0000000..976b135 --- /dev/null +++ b/utils/yuniSeg.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run YuniSeg with hard coded models & configs found here and in /vagrant +# assumes Python environment in /home/${user}/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to YuniSeg (go one folder up and to Yunitator) +YUNITATDIR=$(dirname $BASEDIR)/Yunitator +# let's get our bearings: set CWD to the path of Yunitator +cd $YUNITATDIR + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "containing the wav and rttm files" + echo "and SADtoolname is the SAD to use." + echo "Choices are:" + echo " ldc_sad" + echo " noisemes" + echo " tocombosad" + echo " opensmile" + echo " textgrid" + echo " eaf" + echo " rttm" + exit 1 +fi + +audio_dir=/vagrant/$1 +trs_format=$2 + +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc, but may not be if run from outside VM +export PATH=/home/${user}/anaconda/bin:$PATH + + +# Iterate over files +echo "Starting" +for f in `ls $audio_dir/*.wav`; do + filename=$(basename "$f") + basename="${filename%.*}" + echo "treating $basename" + + # output filename produced by runYuniSegs + outfile=$audio_dir/$basename.yuniSeg.rttm + + case $trs_format in + "ldc_sad") + sys="ldcSad" + model_prefix="ldc_sad_" + ;; + "") + # add default case + echo "Warning: no SAD source specified, using Noisemes by default, at your own risk." + echo "Next time, please specify SAD." + sys="noisemesSad" + model_prefix="noisemes_sad_" + ;; + "noisemes") + sys="noisemesSad" + model_prefix="noisemes_sad_" + ;; + "tocombosad") + sys="tocomboSad" + model_prefix="tocombo_sad_" + ;; + "opensmile") + sys="opensmileSad" + model_prefix="opensmile_sad_" + ;; + "textgrid") + sys="goldSad" + model_prefix=${trs_format}_ + $conda_dir/python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid ${trs_format}_${basename}.rttm + ;; + "eaf") + sys="goldSad" + model_prefix=${trs_format}_ + $conda_dir/python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf ${trs_format}_${basename}.rttm + ;; + "rttm") + sys="goldSad" + model_prefix="" + ;; + *) + echo "ERROR: please choose SAD system between:" + echo " ldc_sad" + echo " noisemes" + echo " tocombosad" + echo " opensmile" + echo " textgrid" + echo " eaf" + echo " rttm" + echo "Now exiting..." + exit 1 + ;; + esac + + ./runYuniSegs.sh $f $audio_dir/${model_prefix}${basename}.rttm + cp $outfile $audio_dir/yuniseg_${sys}_${basename}.rttm + + if [ ! -s $audio_dir/yuniseg_${sys}_${basename}.rttm ]; then + # if diarization failed, still write an empty file... + touch $audio_dir/yuniseg_${sys}_${basename}.rttm + fi +done + +echo "$0 finished running" + +# simply remove hyp and feature +rm $outfile +rm -rf $audio_dir/Yunitemp From a2f01357e0be4c5a8274a6695711fe699e8ede74 Mon Sep 17 00:00:00 2001 From: alecristia Date: Fri, 9 Nov 2018 13:27:59 +0100 Subject: [PATCH 041/299] second wave of changes, still not tested --- .gitignore | 4 + Vagrantfile | 10 +- docs/source/diartk.md | 2 +- docs/source/extra-tools.md | 60 +- docs/source/initial_questions.md | 26 +- docs/source/install.md | 51 +- docs/source/instructions_for_contributors.md | 2 +- docs/source/{ldc_sad.md => ldcSad.md} | 2 +- .../{noisemes_sad.md => noisemesSad.md} | 6 +- .../{opensmile_sad.md => opensmileSad.md} | 4 +- docs/source/references.md | 17 + docs/source/{tocombo_sad.md => tocomboSad.md} | 0 docs/source/tool_doc.md | 3 + docs/source/troubleshoot.md | 8 +- docs/source/usage.md | 34 +- launcher/.DS_Store | Bin 6148 -> 0 bytes launcher/537classify.sh | 48 -- launcher/diartk.sh | 117 ---- launcher/eval.sh | 59 -- launcher/ldcSad.sh | 47 -- launcher/noisemesSad.sh | 80 --- launcher/opensmileSad.sh | 60 -- launcher/test.sh | 249 --------- launcher/tocomboSad.sh | 78 --- launcher/yunitate.sh | 57 -- utils/.DS_Store | Bin 6148 -> 0 bytes utils/README.md | 105 ---- utils/adjust_timestamps.py | 308 ---------- utils/catspa-syllabify-corpus.pl | 93 ---- utils/change_tsi_lena_names.py | 43 -- utils/chat2stm.sh | 53 -- utils/check_folder.sh | 35 -- utils/chunk.sh | 61 -- utils/create_ref_sys.sh | 75 --- utils/diarization.sh | 184 ------ utils/eaf2enriched_txt.sh | 37 -- utils/eaf2txt.py | 89 --- utils/elan2rttm.py | 75 --- utils/empty_transcription.sh | 15 - utils/evalDiar.sh | 123 ---- utils/evalSAD.sh | 83 --- utils/extract_stats_chi.py | 124 ----- utils/frame_cutter.py | 220 -------- utils/generate_html.py | 44 -- utils/get_aclewStarter.sh | 58 -- utils/high_volubility.py | 526 ------------------ utils/html_python/__init__.py | 0 utils/html_python/files_page.py | 179 ------ utils/html_python/models_page.py | 103 ---- utils/html_python/page.py | 30 - utils/html_python/style_css.py | 33 -- utils/html_python/utils.py | 164 ------ utils/its2rttm.py | 80 --- utils/its2rttm.sh | 23 - utils/lab2rttm.sh | 30 - utils/make_big_corpus.sh | 101 ---- utils/noisemes_full.sh | 80 --- utils/parse_cha_xml.py | 191 ------- utils/rttm2labels.py | 41 -- utils/rttm2scp.py | 102 ---- utils/rttm2scp.sh | 17 - utils/runTALNet.sh | 47 -- utils/selcha2clean.sh | 169 ------ utils/sum-rttm.sh | 19 - utils/syllabify.sh | 77 --- utils/textgrid2rttm.py | 103 ---- utils/tocombo2rttm.py | 52 -- utils/train_test_split.py | 146 ----- utils/txt2rttm.py | 140 ----- utils/vad_segmenter_aclew.conf.txt | 62 --- utils/yuniSeg.sh | 121 ---- 71 files changed, 135 insertions(+), 5350 deletions(-) rename docs/source/{ldc_sad.md => ldcSad.md} (97%) rename docs/source/{noisemes_sad.md => noisemesSad.md} (98%) rename docs/source/{opensmile_sad.md => opensmileSad.md} (97%) rename docs/source/{tocombo_sad.md => tocomboSad.md} (100%) create mode 100644 docs/source/tool_doc.md delete mode 100644 launcher/.DS_Store delete mode 100644 launcher/537classify.sh delete mode 100644 launcher/diartk.sh delete mode 100644 launcher/eval.sh delete mode 100644 launcher/ldcSad.sh delete mode 100644 launcher/noisemesSad.sh delete mode 100644 launcher/opensmileSad.sh delete mode 100644 launcher/test.sh delete mode 100644 launcher/tocomboSad.sh delete mode 100644 launcher/yunitate.sh delete mode 100644 utils/.DS_Store delete mode 100755 utils/README.md delete mode 100755 utils/adjust_timestamps.py delete mode 100755 utils/catspa-syllabify-corpus.pl delete mode 100755 utils/change_tsi_lena_names.py delete mode 100755 utils/chat2stm.sh delete mode 100755 utils/check_folder.sh delete mode 100755 utils/chunk.sh delete mode 100755 utils/create_ref_sys.sh delete mode 100755 utils/diarization.sh delete mode 100755 utils/eaf2enriched_txt.sh delete mode 100755 utils/eaf2txt.py delete mode 100755 utils/elan2rttm.py delete mode 100755 utils/empty_transcription.sh delete mode 100644 utils/evalDiar.sh delete mode 100644 utils/evalSAD.sh delete mode 100755 utils/extract_stats_chi.py delete mode 100755 utils/frame_cutter.py delete mode 100755 utils/generate_html.py delete mode 100755 utils/get_aclewStarter.sh delete mode 100755 utils/high_volubility.py delete mode 100755 utils/html_python/__init__.py delete mode 100755 utils/html_python/files_page.py delete mode 100755 utils/html_python/models_page.py delete mode 100755 utils/html_python/page.py delete mode 100755 utils/html_python/style_css.py delete mode 100755 utils/html_python/utils.py delete mode 100644 utils/its2rttm.py delete mode 100755 utils/its2rttm.sh delete mode 100755 utils/lab2rttm.sh delete mode 100755 utils/make_big_corpus.sh delete mode 100644 utils/noisemes_full.sh delete mode 100755 utils/parse_cha_xml.py delete mode 100644 utils/rttm2labels.py delete mode 100755 utils/rttm2scp.py delete mode 100755 utils/rttm2scp.sh delete mode 100755 utils/runTALNet.sh delete mode 100755 utils/selcha2clean.sh delete mode 100755 utils/sum-rttm.sh delete mode 100755 utils/syllabify.sh delete mode 100755 utils/textgrid2rttm.py delete mode 100644 utils/tocombo2rttm.py delete mode 100755 utils/train_test_split.py delete mode 100755 utils/txt2rttm.py delete mode 100644 utils/vad_segmenter_aclew.conf.txt delete mode 100644 utils/yuniSeg.sh diff --git a/.gitignore b/.gitignore index dd723a7..fcf347b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ # Generally ignore data directories data* docs/build/* +.DS_Store +docs/.DS_Store +ldc_sad_hmm/ +HTK.tar.gz diff --git a/Vagrantfile b/Vagrantfile index bd67238..1a1d5ea 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -140,7 +140,7 @@ Vagrant.configure("2") do |config| # Install OpenSMILE echo "Installing OpenSMILE" - mkdir -p repos/ + mkdir -p /home/${user}/repos/ cd /home/${user}/repos/ wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz tar zxvf OpenSMILE-2.1.tar.gz @@ -204,7 +204,13 @@ Vagrant.configure("2") do |config| python setup.py build sudo apt-get install -y python-setuptools sudo python setup.py install - cd .. + + #install launcher and utils + cd /home/${user}/ + git clone https://github.com/aclew/launcher.git + chmod +x launcher/* + git clone https://github.com/aclew/utils.git + chmod +x utils/* # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) diff --git a/docs/source/diartk.md b/docs/source/diartk.md index ed94fdc..4ac5160 100644 --- a/docs/source/diartk.md +++ b/docs/source/diartk.md @@ -18,4 +18,4 @@ We use this tool with the following parameter values: ## Main references: -D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. https://pdfs.semanticscholar.org/71e3/9d42aadd9ec44a42aa5cd21202fedb5eaec5.pdf \ No newline at end of file +D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. https://pdfs.semanticscholar.org/71e3/9d42aadd9ec44a42aa5cd21202fedb5eaec5.pdf diff --git a/docs/source/extra-tools.md b/docs/source/extra-tools.md index 73f0a21..5f7738a 100644 --- a/docs/source/extra-tools.md +++ b/docs/source/extra-tools.md @@ -6,15 +6,71 @@ The ACLEW Starter dataset is freely available, and can be downloaded in order to test the tools. To download it, using your terminal, as explained before, go in the DiViMe folder and do: -```$ vagrant ssh -c "tools/get_aclewStarter.sh data/aclewStarter/"``` +```$ vagrant ssh -c "launcher/get_aclewStarter.sh data/aclewStarter/"``` This will create a folder called aclewStarter inside data, in which you will find the audio files from the public dataset and their corresponding .rttm annotations. At the present time, there are only two matched annotation-wav files, totalling 10 minutes of running recordings You can then use the tools mentioned before, by replacing the "data/" folder in the command given in the previous paragraph by "aclewStarter/", E.G for noisemes: -```$ vagrant ssh -c "tools/noisemes_sad.sh /"``` +```$ vagrant ssh -c "launcher/noisemesSad.sh /"``` #### Reference for the ACLEW Starter dataset: Bergelson, E., Warlaumont, A., Cristia, A., Casillas, M., Rosemberg, C., Soderstrom, M., Rowland, C., Durrant, S. & Bunce, J. (2017). Starter-ACLEW. Databrary. Retrieved August 15, 2018 from http://doi.org/10.17910/B7.390. + +## Using scripts in the Utilities + + + +### elan2rttm.py + +Convert annotations made using the ELAN tool, in .eaf format, into rttm transcriptions. Please note that, using this script, some information is lost, notably +the vocal maturity annotation (coded in tier vcm@CHI), does not appear in the RTTM format. These information could be retrieved and put in the rttm. If you need this information in the RTTM, please raise an issue on github. + +### textgrid2rttm.py + +Convert annotations made using Praat, in .TextGrid format, into rttm transcriptions. Requires: + +* [pympi](https://github.com/dopefishh/pympi) +* [tgt](https://github.com/hbuschme/TextGridTools/) + +We provide code to translate annotations from other formats into RTTM: + +**ELAN .eaf format** + +WARNING: the current version does not handle subtypes when parsing annotations e.g. TIER\_ID 'CHI' would be written in the RTTM output file but 'vmc@CHI' would not. This is due to the time references being based on other TIER\_ID's annotations for subtypes. + +From within the machine, you would run the script as follows: + +``` +python utils/elan2rttm.py -i my_file.eaf -o my_output_folder +``` + +**Praat TextGrid format** + +From within the machine, you would run the script as follows: + +``` +python utils/textgrid2rttm.py my_input_folder +``` + + +### adjust_timestamps.py + +This script is specific to the data in ACLEW, with the ACLEW annotations conventions. It takes as input a daylong recording in wav format (available on databrary), and a transcription in .eaf format that contains annotated segment coded in an "on_off" tier (or "code" tier for some corpora that were annotated before the new convention). +It then takes each annotated segment of 2 minutes, extract it from the daylong recording to output a small wav file of 2 minutes, with the name: +corpus_id_onset_offset.wav +where corpus is the name of the original corpus, id is the name of the daylong recording (which is itself the id given to the recorded child), onset is where the segment starts in the daylong recording (in seconds, with 6 digits padded with 0's if necessary), offset is where the segment ends in the daylong recording (with the same convention). +For each of these segments extracted, it also writes the annotations in rttm format, with the timestamps adapted to correspond to the small wav, and with the same name as the small wav previously written. + +### remove_overlap_rttm.py + +Take a transcription in RTTM format, and convert it to a SAD annotation in RTTM format. The SAD annotation contains less information, as it only indicated "speech" segment (i.e. the talker is written as "speech", no matter who the original talker is), and there are no overlap between speech segments. + +### make_big_corpus.sh + +This script is called to treat all the daylong recording with their annotations, using the previous adjust_timestamps.py script. It also creates gold SAD rttm using the remove_overlap_rttm.py script previously described. + + + diff --git a/docs/source/initial_questions.md b/docs/source/initial_questions.md index 3be985e..2d3029f 100644 --- a/docs/source/initial_questions.md +++ b/docs/source/initial_questions.md @@ -8,6 +8,8 @@ It is a collection of diarization tools, i.e., it allows users to add annotation 2) Talker diarization (answers the question: who is talking?) +3) Role diarization (answers the question: what kind of person is talking?) + We are hoping to add more tools in the future, including register detection, syllable quantification, and vocal maturity estimation. ## Who is the ACLEW DiViMe for? @@ -20,25 +22,15 @@ We are hoping to make the use of these tools as easy as possible, but some comma A virtual machine is actually a mini-computer that gets set up inside your computer. This creates a virtual environment within which we can be sure that our tools run, and run in the same way across all computers (Windows, Mac, Linux). -Inside this mini-computer, we have put the following tools: - -1) Speech activity detection (answers the question: when is someone talking?) - - * [LDC Speech Activity Detection](https://github.com/aclew/DiViMe#ldc_sad)(coming soon) - * [Speech Activity Detection Using Noisemes](#noisemes_sad) - * [OpenSmile SAD](#opensmile_sad) - * [Threshold Optimized Combo SAD](#tocombo_sad) - - -2) Talker diarization (answers the question: who is talking?) - - * [DiarTK](#diartk) - -3) Evaluation +Inside this mini-computer, we have tried to put several tools for each one of our three questions. Please note that some of the tools are developed by fellow researchers and programmers, and since we do not control them, we cannot be absolutely certain they will work. Therefore, we provide a general introduction to the contents in the usage section, and a specific list of tools in dedicated Detailed instructions sections. -If a user has some annotations, they may want to know how good the ACLEW DiViMe parsed their audio recordings. In that case, you can use one tool we soon paln to provide to evaluate: - * [LDC Diarization Scoring](https://github.com/aclew/DiViMe#ldc-diarization-scoring) +## How should I cite ACLEW DiViMe? +The main citation is this paper, which explains the structure and idea, and provides some evaluation: +Adrien Le Franc, Eric Riebling, Julien Karadayi, Yun Wang, Camila Scaff, Florian Metze, and Alejandrina Cristia. +The ACLEW DiViMe: An easy-to-use diarization tool. In Proc. INTERSPEECH, Hyderabad; India, September 2018. +The idea of using virtual machines to package speech tools comes from this work: +Florian Metze, Eric Fosler-Lussier, and Rebecca Bates. The speech recognition virtual kitchen. In Proc. INTERSPEECH, Lyon; France, August 2013. https://github.org/srvk. \ No newline at end of file diff --git a/docs/source/install.md b/docs/source/install.md index eada5a1..a704903 100644 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -14,7 +14,7 @@ Try the following first: - In it, navigate to the directory in which you want the VM to be hosted - type in: -`$ git clone https://github.com/aclew/DiViMe` +`$ git clone https://github.com/srvk/DiViMe` 3. Change into it by @@ -44,14 +44,14 @@ Advanced topic: [Installing With Docker](https://github.com/srvk/DiViMe/wiki/Ins ## Checking your installation -The very first time you use DiViMe, it is a good idea to run a quickstart test, which will be performed using the public files from the ACLEW Starter set (Bergelson et al., 2017): +The very first time you use DiViMe, it is a good idea to run a quick start test, which will be performed using data from the [VanDam Public Daylong](https://homebank.talkbank.org/access/Public/VanDam-Daylong.html) [HomeBank](homebank.talkbank.org) corpus (VanDam et al., 2015): 1. Open a terminal 2. Navigate inside the DiViMe folder 3. Do `$ vagrant up` 4. Do -`$ vagrant ssh -c "tools/test.sh"` +`$ vagrant ssh -c "launcher/test.sh"` This should produce the output: @@ -73,52 +73,13 @@ DiarTK passed the test. Congratulations, everything is OK! -This is the simple test with a few short files. If you would like to run a test for use with daylong recordings, please run $ vagrant ssh -c "tools/test-daylong.sh". Note that this will download a very large recording. +This is the simple test with a few short files. If you would like to run a test for use with daylong recordings, please run $ vagrant ssh -c "launcher/test-daylong.sh". Note that this will download a very large recording. ``` -## Checking your installation for daylong files - -Many of our users have very long files that they want to analyze. To check that our tools are working in your environment, we will test them using the one of the public files from the vanDam corpus (vanDam & Tully, 2016): - -1. Open a terminal -2. Navigate inside the DiViMe folder -3. Do -`$ vagrant up` -4. Do -`$ vagrant ssh -c "tools/test-daylong.sh"` - -This test will take quite some time. It will proceed to download that daylong file, and then process it with all of our tools. Afterwards, it should produce the output: - -``` -Downloading the daylong file... -Download complete. - -Processing annotations... -Annotations processed. - -Testing LDC SAD... -LDC SAD passed the test. - -Testing Speech Activity Detection Using Noisemes... -Noisemes passed the test. - -Testing OpenSmile SAD... -OpenSmile SAD passed the test. - -Testing Threshold Optimized Combo SAD... -Threshold Optimized Combo SAD passed the test. - -Testing DiarTK... -DiarTK passed the test. - -Congratulations, everything is OK! - -``` - ## Common installation errors and fixes -- For LDC SAD, you may get an error "LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include LDC SAD. This error means that you cannot use LDC SAD, but you can use any other SAD/VAD. (For example, noisemes.) +- For LDC SAD, you may get an error "LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include LDC SAD. This error means that you cannot use LDC SAD, but you can use any other SAD/VAD. (For example, noisemesSad.) - For LDC SAD, Noisemes, and DiarTK, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. The easiest way to fix it is to install HTK (again). If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. @@ -144,4 +105,6 @@ $ cd .. $ rm -r -f divime ``` +## References +VanDam, M., De Palma, P., Strong, W. E. (2015, May). Fundamental frequency of speech directed to children who have hearing loss. Poster presented at the 169th Meeting of the Acoustical Society of America, Pittsburgh, PA. diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index 6c1a6cd..17babd0 100644 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -45,7 +45,7 @@ SPEAKER file17 1 3.52 0.82 nonspeech The columns are: Type file chnl tbeg tdur ortho stype name conf Slat -8. If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named toolname_sad_filename.rttm, which will look like this: +8. If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named toolnameSad_filename.rttm, which will look like this: ``` SPEAKER file17 1 0.00 0.77 speech diff --git a/docs/source/ldc_sad.md b/docs/source/ldcSad.md similarity index 97% rename from docs/source/ldc_sad.md rename to docs/source/ldcSad.md index 9849933..d8d33b5 100644 --- a/docs/source/ldc_sad.md +++ b/docs/source/ldcSad.md @@ -11,4 +11,4 @@ Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, access ## Associated references: Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. -Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. \ No newline at end of file +Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. diff --git a/docs/source/noisemes_sad.md b/docs/source/noisemesSad.md similarity index 98% rename from docs/source/noisemes_sad.md rename to docs/source/noisemesSad.md index 366d427..21ecbe6 100644 --- a/docs/source/noisemes_sad.md +++ b/docs/source/noisemesSad.md @@ -1,4 +1,4 @@ -# Noisemes_sad +# NoisemesSad ## General intro @@ -71,7 +71,7 @@ The 18 classes are as follows: 2 speech_ne 3 mumble 4 singing -5 music_sing +5 musicSing 6 music 7 human 8 cheer @@ -112,4 +112,4 @@ Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event det S.Burger,Q.Jin,P.F.Schulam,andF.Metze,“Noisemes:Man- ual annotation of environmental noise in audio streams,” Carnegie Mellon University, Pittsburgh, PA; U.S.A., Tech. Rep. CMU-LTI- 12-07, 2012. S.Strassel,A.Morris,J.G.Fiscus,C.Caruso,H.Lee,P.D.Over, J. Fiumara, B. L. Shaw, B. Antonishek, and M. Michel, “Creating havic: Heterogeneous audio visual internet collection,” in Proc. LREC. Istanbul, Turkey: ELRA, May 2012. -F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia fea- ture extractor,” in Proceedings of the 21st ACM international con- ference on Multimedia. ACM, 2013, pp. 835–838. \ No newline at end of file +F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia fea- ture extractor,” in Proceedings of the 21st ACM international con- ference on Multimedia. ACM, 2013, pp. 835–838. diff --git a/docs/source/opensmile_sad.md b/docs/source/opensmileSad.md similarity index 97% rename from docs/source/opensmile_sad.md rename to docs/source/opensmileSad.md index 3d106d8..0994e4c 100644 --- a/docs/source/opensmile_sad.md +++ b/docs/source/opensmileSad.md @@ -21,7 +21,7 @@ from the turn detector component."; we use a tighter criterion than the default You can change these parameters locally by doing: ``` $ vagrant ssh -$ nano /vagrant/conf/vad/vad_segmenter_aclew.conf +$ nano /vagrant/conf/vad/vadSegmenter_aclew.conf ``` openSMILE manuals consulted: @@ -34,4 +34,4 @@ openSMILE manuals consulted: Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. -Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. \ No newline at end of file +Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. diff --git a/docs/source/references.md b/docs/source/references.md index 98b6c13..74f4f46 100644 --- a/docs/source/references.md +++ b/docs/source/references.md @@ -1,3 +1,20 @@ +# Further information on the formats + +### RTTM + +RTTM is an annotaion format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) +This format is used by the [DiViMe](https://github.com/srvk/DiViMe). + +### TextGrid + +TextGrid is a standard format for speech annotation, used by the Praat software. + +### Eaf + +Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. + + + # References Our work builds directly on that of others. The main references for tools currently included and/or data currently used to perform tests are: diff --git a/docs/source/tocombo_sad.md b/docs/source/tocomboSad.md similarity index 100% rename from docs/source/tocombo_sad.md rename to docs/source/tocomboSad.md diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md new file mode 100644 index 0000000..1290bfc --- /dev/null +++ b/docs/source/tool_doc.md @@ -0,0 +1,3 @@ +# Documentation of individual tools + +This section of the documentation gets populated with information from the different working tools. diff --git a/docs/source/troubleshoot.md b/docs/source/troubleshoot.md index ea71bda..7fa47b8 100644 --- a/docs/source/troubleshoot.md +++ b/docs/source/troubleshoot.md @@ -3,7 +3,7 @@ ## Installation issues ### Virtual Machine creation If your computer freezes after `vagrant up`, it may be due to several things. -If your OS is ubuntu 16.04, there's a known incompatibility between VirtualBox and the 4.13 Linux kernel on ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installation_simple), or install the latest version of virtualbox which should fix the problem. +If your OS is ubuntu 16.04, there's a known incompatibility between VirtualBox and the 4.13 Linux kernel on ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installationSimple), or install the latest version of virtualbox which should fix the problem. If you are not on ubuntu 16.04, or if the previous fix didn't work, it may also be due to the fact that Vagrant is trying to create a Virtual Machine that asks for too much resources. Please ensure that you have enough space on your computer (you should have at least 15Gb of free space) and check that the memory asked for is okay. If not, you can lower the memory of the VM by changing line 25 of the VagrantFile, ``` vbox.memory = 3072 @@ -28,14 +28,14 @@ You can now try again with `vagrant up` ## Problems with some of the Tools ### LDC SAD, OpenSmile, DiarTK -If ldc_sad, OpenSmile, DiarTK don't seem to work after vagrant up, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: +If ldcSad, OpenSmile, DiarTK don't seem to work after vagrant up, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: ``` vagrant up --provision ``` -This step will install HTK inside the VM, which is used by several tools including ldc_sad. +This step will install HTK inside the VM, which is used by several tools including ldcSad. ### Noisemes -If you use the noisemes_sad or the noisemes_full tool, one problem you may encounter is that it doesn't treat all of your files and gives you an error that looks like this: +If you use the noisemesSad or the noisemes_full tool, one problem you may encounter is that it doesn't treat all of your files and gives you an error that looks like this: ``` Traceback (most recent call last): File "SSSF/code/predict/1-confidence-vm5.py", line 59, in diff --git a/docs/source/usage.md b/docs/source/usage.md index 6038751..191d058 100644 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -24,42 +24,42 @@ Next we provide instructions for all tools. More detailed information about each 3. For the SAD tools, type a command like this one: -`$ vagrant ssh -c "tools/noisemes_sad.sh data/"` +`$ vagrant ssh -c "launcher/noisemesSad.sh data/"` This will create a set of new rttm files, with the name of the tool added at the beginning. For example, imagine you have a file called participant23.wav, and you decide to run two SADs: ``` -$ vagrant ssh -c "tools/opensmile_sad.sh data/" -$ vagrant ssh -c "tools/noisemes_sad.sh data/" +$ vagrant ssh -c "launcher/opensmileSad.sh data/" +$ vagrant ssh -c "launcher/noisemesSad.sh data/" ``` This will result in your having the following three files in your /data/ folder: - participant23.wav -- opensmile_sad_participant23.rttm -- noisemes_sad_participant23.rttm +- opensmileSad_participant23.rttm +- noisemesSad_participant23.rttm -If you look inside one of these .rttm's, say the opensmile_sad one, it will look as follows: +If you look inside one of these .rttm's, say the opensmileSad one, it will look as follows: ``` SPEAKER participant23 1 0.00 0.77 speech SPEAKER participant23 1 1.38 2.14 speech ``` -This means that opensmile_sad considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. +This means that opensmileSad considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. 4. There is one **pure diarization** tool: diartk. Here is the command to run, for the data/ input folder: -`$ vagrant ssh -c "tools/diartk.sh data/ noisemes_sad"` +`$ vagrant ssh -c "launcher/diartk.sh data/ noisemesSad"` Pure diarization tools only perform talker diarization (i.e., *who* speaks) but not speech activity detection (*when* is someone speaking). Therefore, this system requires some form of SAD. The third parameter ('noisemes') tells the system which SAD annotation to use, from among the list: -- ldc_sad: this means you want the system to use the output of the LDC_SAD system. If you have not run LDC_SAD, the system will run it for you. -- noisemes_sad: this means you want the system to use the output of the noisemes_sad system. If you have not run LDC_SAD, the system will run it for you. -- opensmile_sad: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. -- tocombo_sad: this means you want the system to use the output of the tocombo_sad system. If you have not ran tocombosad, the system will run it for you. +- ldcSad: this means you want the system to use the output of the LDC_SAD system. If you have not run LDC_SAD, the system will run it for you. +- noisemesSad: this means you want the system to use the output of the noisemesSad system. If you have not run LDC_SAD, the system will run it for you. +- opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. +- tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran tocombosad, the system will run it for you. - textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. - eaf: this means you want the system to use your eaf annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your eaf files before you start. Please note that the system will convert your eafs into .rttm in the process. - rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. @@ -70,12 +70,12 @@ Finally, if no parameter is provided, the system will give an error. The version we call "yunitator" takes the raw recording as input. To call this one, do -`$ vagrant ssh -c "tools/yunitator.sh data/"` +`$ vagrant ssh -c "launcher/yunitator.sh data/"` The version we call "yuniSeg" takes the raw recording as well as a SAD as input. To call this one, do -`$ vagrant ssh -c "tools/yuniSeg.sh data/ noisemes_sad"` +`$ vagrant ssh -c "launcher/yuniSeg.sh data/ noisemesSad"` Both of them return one rttm per sound file, with an estimation of where there are vocalizations by children, female adults, and male adults. @@ -83,11 +83,11 @@ For more information on the model underlying them, see the Yunitator section bel 6. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: -`$ vagrant ssh -c "tools/eval.sh data/ noisemes_sad"` +`$ vagrant ssh -c "launcher/eval.sh data/ noisemesSad"` -Notice there are 2 parameters provided to the evaluation suite. The first parameter tells the system which folder to analyze (in this case, the whole data/ folder). The second parameter indicates which tool's output to evaluate (in this case, noisemes_sad). The system will use the .rttm annotations if they exist; or the .eaf ones if the former are missing; or the .textgrid of neither .rttm nor .eaf are found. +Notice there are 2 parameters provided to the evaluation suite. The first parameter tells the system which folder to analyze (in this case, the whole data/ folder). The second parameter indicates which tool's output to evaluate (in this case, noisemesSad). The system will use the .rttm annotations if they exist; or the .eaf ones if the former are missing; or the .textgrid of neither .rttm nor .eaf are found. If you want to evaluate a diarization produced by the diartk tool, you will have to specify a third parameter, to tell the system which SAD was used to compute the diartk outputs you want to evaluate. E.G. : -`$ vagrant ssh -c "tools/eval.sh data/ diartk noisemes_sad` +`$ vagrant ssh -c "launcher/eval.sh data/ diartk noisemesSad` 7. Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: diff --git a/launcher/.DS_Store b/launcher/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0" - echo "where dirname is the name of the folder" - echo "containing the wav files" - exit 1 -fi - -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" -# Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir - - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - -# let's get our bearings: set CWD to the path of Yunitator -cd $CLASSIFY - -# Iterate over files -echo "Starting" -for f in `ls ${audio_dir}/*.wav`; do - ./run537classify.sh $f - base=$(basename $f .wav) - mv $audio_dir/${base}.rttm ${audio_dir}/537cls_${base}.rttm - mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/537cls_${base}.frame_prob.mat -done - -echo "$0 finished running" diff --git a/launcher/diartk.sh b/launcher/diartk.sh deleted file mode 100644 index 1b01eb5..0000000 --- a/launcher/diartk.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/bash -# Launcher onset routine -source ~/.bashrc -SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` -conda_dir=$BASEDIR/anaconda/bin -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -# end of launcher onset routine - - -### Read in variables from user -audio_dir=$BASEDIR/1 -trs_format=$2 - - -### Other variables speicfic to this script -# create temp dir -workdir=$audio_dir/temp/diartk -mkdir -p $workdir - -### SCRIPT STARTS -cd $BASEDIR/repos/ib_diarization_toolkit - - -# Check audio_dir to see if empty or if contains empty wav -bash $UTILS/check_folder.sh $audio_dir - - -for fin in `ls $audio_dir/*.wav`; do - filename=$(basename "$fin") - basename="${filename%.*}" - echo "treating $basename" - - featfile=$workdir/$basename.fea - scpfile=$workdir/$basename.scp - - # first-first convert RTTM to DiarTK's version of a .scp file - # SCP format: - # __=[start,end] - # RTTM format: - # Type file chan tbeg tdur ortho stype name conf Slat - # math: convert RTTM seconds to HTK (10ms default) frames = multiply by 100 - case $trs_format in - "ldcSad") - sys="ldcSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/ldcSad_${basename}.rttm $scpfile - ;; - "noisemesSad") - sys="noisemesSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile - ;; - "tocomboSad") - sys="tocomboSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/tocombo_sad_${basename}.rttm $scpfile - ;; - "opensmileSad") - sys="opensmileSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/opensmile_sad_${basename}.rttm $scpfile - ;; - "textgrid") - sys="goldSad" - $conda_dir/python /home$UTILS/textgrid2rttm.py $audio_dir/${basename}.TextGrid $workdir/${basename}.rttm - $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile - rm $workdir/$basename.rttm - ;; - "eaf") - sys="goldSad" - $conda_dir/python /home$UTILS/elan2rttm.py $audio_dir/${basename}.eaf $workdir/${basename}.rttm - $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile - rm $workdir/$basename.rttm - ;; - "rttm") - sys="goldSad" - # Since some reference rttm files are spaced rather than tabbed, we need to - # tab them before using them. - cp $audio_dir/${basename}.rttm $workdir/${basename}.rttm - sed -i 's/ \+/\t/g' $workdir//${basename}.rttm - $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile - ;; - *) - echo "ERROR: please choose SAD system between:" - echo " ldcSad" - echo " noisemesSad" - echo " tocomboSad" - echo " opensmileSad" - echo " textgrid" - echo " eaf" - echo " rttm" - echo "Now exiting..." - exit 1 - ;; - esac - - # don't process files with empty transcription - if [ -s $scpfile ]; then - # first generate HTK features - HCopy -T 2 -C htkconfig $fin $featfile - - # next run DiarTK - scripts/run.diarizeme.sh $featfile $scpfile $workdir $basename - - # print results - #cat $workdir/$basename.out - cp $workdir/$basename.rttm $audio_dir/diartk_${sys}_${basename}.rttm - fi - if [ ! -s $audio_dir/diartk_${sys}_${basename}.rttm ]; then - # if diarization failed, still write an empty file... - touch $audio_dir/diartk_${sys}_${basename}.rttm - fi - - - -done - -# Delete temporary folder -rm -rf $workdir \ No newline at end of file diff --git a/launcher/eval.sh b/launcher/eval.sh deleted file mode 100644 index ac5e864..0000000 --- a/launcher/eval.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -# Launcher onset routine -source ~/.bashrc -SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` -conda_dir=$BASEDIR/anaconda/bin -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -# end of launcher onset routine - -### Read in variables from user -audio_dir=$BASEDIR/$1 -system=$2 - -### Other variables speicfic to this script -#none - -display_usage() { - echo "Usage: eval.sh <>" - echo "where data is the folder containing the data" - echo "and system is the system you want" - echo "to evaluate. Choices are:" - echo " ldcSad" - echo " noisemesSad" - echo " tocomboSad" - echo " opensmileSad" - echo " lenaSad" - echo " diartk" - echo " yunitate" - echo " lenaDiar" - echo "If evaluating diartk, please give which flavour" - echo "of SAD you used to produce the transcription" - echo "you want to evaluate" - exit 1 -} - -if [ $# -lt 2 ] ; then - display_usage -fi - - - -### SCRIPT STARTS -case $system in -"tocomboSad"|"opensmileSad"|"ldcSad"|"noisemesSad|lenaSad") - sh $UTILS/evalSAD.sh $audio_dir $system - ;; -"yunitate"|"lenaDiar") - sh $UTILS/evalDiar.sh $audio_dir $system - ;; -"diartk") - sad=$3 - sh $UTILS/evalDiar.sh $audio_dir $system $sad - ;; -*) - display_usage - ;; - -esac diff --git a/launcher/ldcSad.sh b/launcher/ldcSad.sh deleted file mode 100644 index 83a42ce..0000000 --- a/launcher/ldcSad.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash -# Launcher onset routine -source ~/.bashrc -SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` -conda_dir=$BASEDIR/anaconda/bin -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -# end of launcher onset routine - -### Read in variables from user -audio_dir=$BASEDIR/$1 - -### Other variables speicfic to this script -LDC_SAD_DIR=$REPOS/ldc_sad_hmm -workdir=$audio_dir/temp/diartk -mkdir -p $workdir - -### SCRIPT STARTS -if [ $# -ne 1 ]; then - echo "Usage: ldcSad.sh " - echo "where dirname is the name of the folder" - echo "containing the wav files" - exit 1 -fi - -# Check audio_dir to see if empty or if contains empty wav -bash $UTILS/check_folder.sh $audio_dir - -# Set CWD as LDC_SAD_HMM -cd $LDC_SAD_DIR - -# launch ldc -$conda_dir/python perform_sad.py -L $workdir $audio_dir/*.wav -echo "finished using ldcSad_hmm. Please look inside $1 to see the output in *.rttm format" - -# move all files to name them correctly -for wav in `ls $audio_dir/*.wav`; do - # retrieve filename and remove .wav - base=$(basename $wav .wav) - rttm_out=$workdir/ldcSad_${base}.rttm - if [ -s $workdir/${base}.lab ]; then - grep ' speech' $workdir/${base}.lab | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $rttm_out - else - touch $rttm_out - fi -done diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh deleted file mode 100644 index 2fd5bc2..0000000 --- a/launcher/noisemesSad.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash -# noisemes_sad.sh -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin - -# run OpenSAT with hard coded models & configs found here and in /vagrant - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to OpenSAT (go on folder up and to opensat) -OPENSATDIR=$(dirname $BASEDIR)/OpenSAT - -if [ $# -ne 1 ]; then - echo "Usage: noisemes_sad.sh " - echo "where dirname is a folder on the host" - echo "containing the wav files (/vagrant/dirname/ in the VM)" - exit 1 -fi - -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" - -# Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir - -# let's get our bearings: set CWD to path of OpenSAT -cd $OPENSATDIR - -# make output folder for features, below input folder -mkdir -p $audio_dir/feature - -# first features -echo "extracting features for speech activity detection" -for file in `ls $audio_dir/*.wav`; do - SSSF/code/feature/extract-htk-vm2.sh $file -done - -# then confidences -#python SSSF/code/predict/1-confidence-vm3.py $1 -echo "detecting speech and non speech segments" -$conda_dir/python SSSF/code/predict/1-confidence-vm5.py $audio_dir -echo "finished detecting speech and non speech segments" - -# take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. -for sad in `ls $audio_dir/hyp_sum/*.lab`; do - base=$(basename $sad .lab) - rttm_out=noisemes_sad_${base}.rttm - if [ -s $sad ]; then - grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out - else - touch $audio_dir/$rttm_out - fi -done - -# simple remove hyp and feature -rm -rf $audio_dir/hyp_sum $audio_dir/feature -# mv hyp and features folders to a temp that the user can delete. -#if [ ! -d "$audio_dir/noiseme_sad_temp" ]; then -# mkdir -p $audio_dir/noiseme_sad_temp -#fi -# -#if [! -d "$audio_dir/noiseme_sad_temp" ]; then -# mv $audio_dir/hyp_sum $audio_dir/noiseme_sad_temp -#else -# echo "can't move hyp_sum/ folder to noiseme_sad_temp/ because temp is already full" -#fi -# -#if [! -d "$audio_dir/noiseme_sad_temp" ]; then -# mv $audio_dir/feature $audio_dir/noiseme_sad_temp -#else -# echo "can't move features/ folder to noiseme_sad_temp/ because temp is already full" -#fi -# diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh deleted file mode 100644 index 5e60b5a..0000000 --- a/launcher/opensmileSad.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -# Launcher onset routine -source ~/.bashrc -SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` -conda_dir=$BASEDIR/anaconda/bin -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -# end of launcher onset routine - -### Read in variables from user -audio_dir=$BASEDIR/$1 - -### Other variables speicfic to this script -OSHOME=$REPOS/openSMILE-2.1.0/ -CONFIG_FILE=$UTILS/vad_segmenter_aclew.conf -OPENSMILE=$OSHOME/bin/linux_x64_standalone_static/SMILExtract -workdir=$audio_dir/temp/opensmileSad -mkdir -p $workdir - -### SCRIPT STARTS - -if [ $# -lt 1 ]; then - echo "USAGE: $0 " - exit 1 -fi - -filename=$(basename "$1") -dirname=$(dirname "$1") -extension="${filename##*.}" -basename="${filename%.*}" - - -cd $OSHOME/scripts/vad - -# Use OpenSMILE 2.1.0 -for sad in `ls $audio_dir/*.wav`; do - - file=$sad - id=`basename $file` - id=${id%.wav} - > $audio_dir/${id}.txt #Make it empty if already present - echo "Processing $id ..." - LD_LIBRARY_PATH=$BASEDIR/usr/local/lib \ - $OPENSMILE \ - -C $CONFIG_FILE \ - -I $file \ - -turndebug 1 \ - -noconsoleoutput 1 \ - -saveSegmentTimes $workdir/${id}.txt \ - -logfile $workdir/opensmile-vad.log > /dev/null -done - -for output in $(ls $workdir/*.txt); do - id=$(basename $output .txt) - awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > $audio_dir/opensmileSad_$id.rttm -done - -# Delete temporary folder -rm -rf $workdir \ No newline at end of file diff --git a/launcher/test.sh b/launcher/test.sh deleted file mode 100644 index b293cce..0000000 --- a/launcher/test.sh +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/bash -# -# This script tests numerous tools -# from a downloaded 5 minute section of the HomeBank VanDam daylong audio sample -# ("ACLEW Starter" data) - -# this doesn't work because .bashrc exits immediately if not running interactively -#source /home/vagrant/.bashrc -i -# instead: -export PATH=/home/vagrant/anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin -LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH" - -conda_dir=/home/vagrant/anaconda/bin - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/vagrant/tools -BASEDIR=`dirname $SCRIPT` - -# Paths to Tools -LDC_SAD_DIR=$(dirname $BASEDIR)/ldcSad_hmm -OPENSATDIR=$(dirname $BASEDIR)/OpenSAT # noisemes -OPENSMILEDIR=$(dirname $BASEDIR)/openSMILE-2.1.0/ -TOCOMBOSAD=$(dirname $BASEDIR)/To-Combo-SAD -DIARTKDIR=$(dirname $BASEDIR)/ib_diarization_toolkit -#TALNETDIR=$(dirname $BASEDIR)/TALNet -DSCOREDIR=$(dirname $BASEDIR)/dscore -YUNITATORDIR=$(dirname $BASEDIR)/Yunitator - -FAILURES=false - -echo "Starting tests" -echo "Downloading test audio..." - -cd /vagrant/data -# get transcript -wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip -unzip -q -o VanDam-Daylong.zip - -# This is the working directory for the tests; right beside the input -cd VanDam-Daylong/BN32/ -# Get daylong recording from the web -wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 - -WORKDIR=`pwd` -DATADIR=data/VanDam-Daylong/BN32 # relative to /vagrant, used by launcher scripts -BASE=BN32_010007 # base filename for test input file, minus .wav or .rttm suffix -BASETEST=${BASE}_test -START=2513 # 41:53 in seconds -STOP=2813 # 46:53 in seconds - -# get 5 minute subset of audio -sox $BASE.mp3 $BASETEST.wav trim $START 5:00 >& /dev/null 2>1 - -# convert CHA to reliable STM -/home/vagrant/tools/chat2stm.sh $BASE.cha > $BASE.stm 2>/dev/null -# convert STM to RTTM as e.g. BN32_010007.rttm -# shift audio offsets to be 0-relative -cat $BASE.stm | awk -v start=$START -v stop=$STOP -v file=$BASE -e '{if (($4 > start) && ($4 < stop)) print "SPEAKER",file,"1",($4 - start),($5 - $4),"","","","","" }' > $BASETEST.rttm -TEST_RTTM=$WORKDIR/$BASETEST.rttm -TEST_WAV=$WORKDIR/$BASETEST.wav - - -# Check for HTK -echo "Checking for HTK..." -if [ -s /usr/local/bin/HCopy ]; then - echo "HTK is installed." -else - echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" - echo " and rename it to HTK.tar.gz ?" -fi - -# First test in ldcSad_hmm -echo "Testing LDC SAD..." -if [ -s $LDC_SAD_DIR/perform_sad.py ]; then - cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/ldcSad-test - rm -rf $TESTDIR; mkdir -p $TESTDIR - $conda_dir/python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldcSad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} - # convert output to rttm, for diartk. - grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm - if [ -s $TESTDIR/$BASETEST.rttm ]; then - echo "LDC SAD passed the test." - else - FAILURES=true - echo " LDC SAD failed - no output RTTM" - fi -else - echo " LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" -fi - - -# now test Noisemes -echo "Testing noisemes..." -cd $OPENSATDIR -TESTDIR=$WORKDIR/noisemes-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -<<<<<<< HEAD -./runDiarNoisemes.sh $TESTDIR > $TESTDIR/nosiemes-test.log 2>&1 || (echo "Noisemes failed - dependencies" && FAILURES=true) -cp $TESTDIR/hyp_sum/$BASETEST.rttm $TESTDIR -======= -./runDiarNoisemes.sh $TESTDIR > $TESTDIR/nosiemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} ->>>>>>> 053a3d0b196066a04d60bf41fbc2b62843374814 - -if [ -s $TESTDIR/hyp_sum/$BASETEST.rttm ]; then - echo "Noisemes passed the test." -else - FAILURES=true - echo " Noisemes failed - no RTTM output" -fi -# clean up -rm -rf $OPENSATDIR/SSSF/data/feature $OPENSATDIR/SSSF/data/hyp - - -# now test OPENSMILEDIR -echo "Testing OpenSmile SAD..." -cd $OPENSMILEDIR -TESTDIR=$WORKDIR/opensmile-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -<<<<<<< HEAD -/home/vagrant/tools/opensmile_sad.sh $DATADIR/opensmile-test >$TESTDIR/opensmile-test.log || (echo "OpenSmile SAD failed - dependencies" && FAILURES=true) -======= -/home/vagrant/tools/opensmile_sad.sh data/VanDam-Daylong/BN32/opensmile-test >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} ->>>>>>> 053a3d0b196066a04d60bf41fbc2b62843374814 - -if [ -s $TESTDIR/opensmile_sad_$BASETEST.rttm ]; then - echo "OpenSmile SAD passed the test." -else - FAILURES=true - echo " OpenSmile SAD failed - no RTTM output" -fi - -# now test TOCOMBOSAD -echo "Testing ToCombo SAD..." -cd $TOCOMBOSAD -TESTDIR=$WORKDIR/tocombo_sad-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -<<<<<<< HEAD -/home/vagrant/tools/tocombo_sad.sh $DATADIR/tocombo_sad-test > $TESTDIR/tocombo_sad_test.log 2>&1 || (echo "TOCOMBO SAD failed - dependencies" && FAILURES=true) -======= -/home/vagrant/tools/tocombo_sad.sh data/VanDam-Daylong/BN32/tocombo_sad-test > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} ->>>>>>> 053a3d0b196066a04d60bf41fbc2b62843374814 - -if [ -s $TESTDIR/tocombo_sad_$BASETEST.rttm ]; then - echo "TOCOMBO SAD passed the test." -else - FAILURES=true - echo " TOCOMBO SAD failed - no output RTTM" -fi - - -# finally test DIARTK -echo "Testing DIARTK..." -cd $DIARTKDIR -TESTDIR=$WORKDIR/diartk-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -# run like the wind -./run-rttm.sh $TEST_WAV $TEST_RTTM $TESTDIR > $TESTDIR/diartk-test.log 2>&1 -if grep -q "command not found" $TESTDIR/diartk-test.log; then - echo " Diartk failed - dependencies (probably HTK)" - FAILURES=true -else - if [ -s $TESTDIR/$BASETEST.rttm ]; then - echo "DiarTK passed the test." - else - FAILURES=true - echo " Diartk failed - no output RTTM" - fi -fi - -# finally test Yunitator -echo "Testing Yunitator..." -cd $YUNITATORDIR -TESTDIR=$WORKDIR/yunitator-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -# let 'er rip -./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/Yunitemp/$BASETEST.rttm ]; then - echo "Yunitator passed the test." -else - FAILURES=true - echo " Yunitator failed - no output RTTM" -fi - - -# Test DSCORE -echo "Testing Dscore..." -cd $DSCOREDIR -TESTDIR=$WORKDIR/dscore-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -cp -r test_ref test_sys $TESTDIR -rm -f test.df -python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/test.df ]; then - echo "DScore passed the test." -else - echo " DScore failed the test - output does not match expected" - FAILURES=true -fi - - -# testing LDC evalSAD (on opensmile) -echo "Testing LDC evalSAD" -<<<<<<< HEAD -cd $LDC_SAD_DIR -TESTDIR=$WORKDIR/opensmile-test -cp $WORKDIR/$BASETEST.rttm $TESTDIR -~/tools/eval.sh $TESTDIR opensmile > $WORKDIR/ldcSad-test/ldc_evalSAD.log 2>&1 || (echo "LDC evalSAD failed - dependencies" && FAILURES=true) -# clean up -rm $TESTDIR/$BASETEST.rttm -if [ -s $TESTDIR/opensmile_sad_eval.df ]; then - echo "LDC evalSAD passed the test" -======= -if [ -d $LDC_SAD_DIR ]; then - cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/opensmile-test - cp $WORKDIR/$BASETEST.rttm $TESTDIR - ~/tools/eval.sh $DATADIR/opensmile-test opensmile > $WORKDIR/ldcSad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} - if [ -s $TESTDIR/opensmile_sad_eval.df ]; then - echo "LDC evalSAD passed the test" - else - echo " LDC evalSAD failed - no output .df" - FAILURES=true - fi ->>>>>>> 053a3d0b196066a04d60bf41fbc2b62843374814 -else - echo " LDC evalSAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" - FAILURES=true -fi - - -# test finished -if $FAILURES; then - echo "Some tools did not pass the test, but you can still use others" -else - echo "Congratulations, everything is OK!" -fi - -# results -echo "RESULTS:" -for f in /vagrant/$DATADIR/*-test/*.rttm; do $BASEDIR/sum-rttm.sh $f; done -echo "DSCORE:" -cat /vagrant/data/VanDam-Daylong/BN32/dscore-test/test.df -echo "EVAL_SAD:" -cat $TESTDIR/opensmile_sad_eval.df diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh deleted file mode 100644 index 8eba2d0..0000000 --- a/launcher/tocomboSad.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash -# Launcher onset routine -source ~/.bashrc -SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` -conda_dir=$BASEDIR/anaconda/bin -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -# end of launcher onset routine - - -### Read in variables from user -audio_dir=$BASEDIR/1 -trs_format=$2 - - -### Other variables speicfic to this script -# create temp dir -workdir=$audio_dir/temp/tocomboSad -mkdir -p $workdir -TOCOMBOSADDIR=$REPOS/To-Combo-SAD -MCR=/usr/local/MATLAB/MATLAB_Runtime/v93 - -### SCRIPT STARTS - -if [ $# -ne 1 ]; then - echo "Usage: tocombo_sad.sh " - echo "where dirname is a folder on the host" - echo "containing the wav files (/vagrant/dirname/ in the VM)" - exit 1 -fi - -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" - -# Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir - -# let's get our bearings: set CWD to path of ToComboSAD -cd $TOCOMBOSADDIR - -mkdir -p $workdir/feat -rm -f $workdir/filelist.txt -touch $workdir/filelist.txt - -# create temp dir to store audio files with 1 channels, if needed (i.e. if audio to treat has 2 or more channels.) -# Indeed, To Combo Sad Fails when there are more than 1 channels. -for f in $audio_dir/*.wav; do - # Check if audio has 1 channel or more. If it has more, use sox to create a temp audio file w/ 1 channel. - n_chan=$(soxi $f | grep Channels | cut -d ':' -f 2) - if [[ $n_chan -gt 1 ]]; then - base=$(basename $f) - sox -c $n_chan $f -c 1 $workdir/$base - f=$workdir/$base - fi - - echo $f >> $workdir/filelist.txt - -done -echo "finished" - -export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64: - -./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt - -# Retrieve the outputs from the temp folder -mv $workdir/*ToCombo.txt $audio_dir - -#convert to rttms -for f in $audio_dir/*.ToCombo.txt; do - bn=`basename $f .wav.ToCombo.txt` - python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > $audio_dir/tocombo_sad_$bn.rttm -done - -# Delete temporary folder -rm -rf $workdir \ No newline at end of file diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh deleted file mode 100644 index 01d58f2..0000000 --- a/launcher/yunitate.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin - -# run OpenSAT with hard coded models & configs found here and in /vagrant -# assumes Python environment in /home/${user}/ - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to Yunitator (go one folder up and to Yunitator) -YUNITATDIR=$(dirname $BASEDIR)/Yunitator - -if [ $# -ne 1 ]; then - echo "Usage: $0 " - echo "where dirname is the name of the folder" - echo "containing the wav files" - exit 1 -fi - -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" -# Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir - - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - -# let's get our bearings: set CWD to the path of Yunitator -cd $YUNITATDIR - -# Iterate over files -echo "Starting" -for f in `ls $audio_dir/*.wav`; do - ./runYunitator.sh $f -done - -echo "$0 finished running" - -# take all the .rttm in $audio_dir/Yunitemp/ and move them to /vagrant/data -for sad in `ls $audio_dir/Yunitemp/*.rttm`; do - _rttm=$(basename $sad) - rttm=$audio_dir/yunitator_${_rttm} - # Remove not needed SIL lines - # sed -i '/ SIL /d' $sad - mv $sad $rttm -done - -# simply remove hyp and feature -rm -rf $audio_dir/Yunitemp diff --git a/utils/.DS_Store b/utils/.DS_Store deleted file mode 100644 index 17c15323e9fc7e01f36bd4b08d901ca2dd7b15cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyH3ME5S)b+kAHDXxOnQv9s3#Y`S!)o}jI@xMMu{fRYZ&42GiHcG{ z3d|L_%t0>C4=4(Fhg;QeCnGZTqKLf6dObYz90$;G87Bm0= diff --git a/utils/README.md b/utils/README.md deleted file mode 100755 index 5d3acd0..0000000 --- a/utils/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# WUT -This repository contains wrappers to use all the tools available inside the ACLEW Diarization VM. -These wrappers were created in order to create a more simple user experience - -## Overall summary - -### SAD tools -``` -ldc_sad.sh -noisemes_sad.sh -noisemes_full.sh -opensmile_sad.sh -tocombo_sad.sh -``` -### Talker Diarization tools -``` -diartk.sh -yunitate.sh -yuniSeg.sh -``` -### Scoring tools -``` -eval.sh -evalDiar.sh -evalSAD.sh -``` -### VM Self-test -``` -test.sh -``` -### Utilities -``` -chat2stm.sh -check_folder.sh -chunk.sh -high_volubility.py -parse_cha_xml.py -``` - - -## Further information about some of these - - - -### elan2rttm.py - -Convert annotations made using the ELAN tool, in .eaf format, into rttm transcriptions. Please note that, using this script, some information is lost, notably -the vocal maturity annotation (coded in tier vcm@CHI), does not appear in the RTTM format. These information could be retrieved and put in the rttm. If you need this information in the RTTM, please raise an issue on github. - -### textgrid2rttm.py - -Convert annotations made using Praat, in .TextGrid format, into rttm transcriptions. Requires: - -* [pympi](https://github.com/dopefishh/pympi) -* [tgt](https://github.com/hbuschme/TextGridTools/) - -### adjust_timestamps.py - -This script is specific to the data in ACLEW, with the ACLEW annotations conventions. It takes as input a daylong recording in wav format (available on databrary), and a transcription in .eaf format that contains annotated segment coded in an "on_off" tier (or "code" tier for some corpora that were annotated before the new convention). -It then takes each annotated segment of 2 minutes, extract it from the daylong recording to output a small wav file of 2 minutes, with the name: -corpus_id_onset_offset.wav -where corpus is the name of the original corpus, id is the name of the daylong recording (which is itself the id given to the recorded child), onset is where the segment starts in the daylong recording (in seconds, with 6 digits padded with 0's if necessary), offset is where the segment ends in the daylong recording (with the same convention). -For each of these segments extracted, it also writes the annotations in rttm format, with the timestamps adapted to correspond to the small wav, and with the same name as the small wav previously written. - -### remove_overlap_rttm.py - -Take a transcription in RTTM format, and convert it to a SAD annotation in RTTM format. The SAD annotation contains less information, as it only indicated "speech" segment (i.e. the talker is written as "speech", no matter who the original talker is), and there are no overlap between speech segments. - -### make_big_corpus.sh - -This script is called to treat all the daylong recording with their annotations, using the previous adjust_timestamps.py script. It also creates gold SAD rttm using the remove_overlap_rttm.py script previously described. - -## Further info on the formats - -### RTTM - -RTTM is an annotaion format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) -This format is used by the [DiViMe](https://github.com/srvk/DiViMe). - -We provide code to translate annotations from other formats into RTTM: - -**ELAN .eaf fromat** - -WARNING: the current version does not handle subtypes when parsing annotations e.g. TIER\_ID 'CHI' would be written in the RTTM output file but 'vmc@CHI' would not. This is due to the time references being based on other TIER\_ID's annotations for subtypes. - -You should run the script as follows: - -``` -python elan2rttm.py -i my_file.eaf -o my_output_folder -``` - -**Praat TextGrid format** - -You should run the script as follows: - -``` -python textgrid2rttm.py my_input_folder -``` -### TextGrid - -TextGrid is a standard format for speech annotation, used by the Praat software. - -### Eaf - -Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. diff --git a/utils/adjust_timestamps.py b/utils/adjust_timestamps.py deleted file mode 100755 index c598301..0000000 --- a/utils/adjust_timestamps.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env python -# -# -import pympi as pmp -import shutil -import os -import argparse -import subprocess -from collections import defaultdict -from operator import itemgetter - - -def eaf2rttm(path_to_eaf): - """ - function to write a new .rttm file which is a transcription of the .eaf - given as input - - """ - - # in EAF, timestamps are in milliseconds, convert them to seconds - # TODO read scale from header of EAF - sampling_freq = 1000.0 - - print('\n') - # read eaf file - EAF = pmp.Elan.Eaf(path_to_eaf) - - participants = [] - - # gather all the talker's names - for k in EAF.tiers.keys(): - - if 'PARTICIPANT' in EAF.tiers[k][2].keys(): - - if EAF.tiers[k][2]['PARTICIPANT'] not in participants: - - participants.append(EAF.tiers[k][2]['PARTICIPANT']) - - print('participants: {}'.format(participants)) - - base = os.path.basename(path_to_eaf) - name = os.path.splitext(base)[0] - - print('parsing file: {}'.format(name)) - - # get the begining, ending and transcription for each annotation of - # each tier - rttm = [] - for participant in participants: - if participant not in EAF.tiers: - continue - for _, val in EAF.tiers[participant][0].items(): - # Get timestamps - start = val[0] - end = val[1] - - t0 = EAF.timeslots[start] / sampling_freq - length = EAF.timeslots[end] / sampling_freq - t0 - - # get transcription - transcript = val[2] - - rttm.append((name, t0, length, transcript, participant)) - - return rttm - -def eaf2rttm_CAS(path_to_eaf): - """ - function to write a new .rttm file which is a transcription of the .eaf - given as input - - """ - - sampling_freq = 1000.0 - - print('\n') - EAF = pmp.Elan.Eaf(path_to_eaf) - - participants = [] - - for k in EAF.tiers.keys(): - - if 'PARTICIPANT' in EAF.tiers[k][2].keys(): - - if EAF.tiers[k][2]['PARTICIPANT'] not in participants: - - participants.append(EAF.tiers[k][2]['PARTICIPANT']) - - print('participants: {}'.format(participants)) - - base = os.path.basename(path_to_eaf) - name = os.path.splitext(base)[0] - - print('parsing file: {}'.format(name)) - - # get the begining, ending and transcription for each annotation of - # each tier - rttm = [] - for participant in participants: - - for _, val in EAF.tiers[participant][0].items(): - # Get timestamps - start = val[0] - end = val[1] - - t0 = EAF.timeslots[start] / sampling_freq - length = EAF.timeslots[end] / sampling_freq - t0 - - # get transcription - transcript = val[2] - - rttm.append((name, t0, length, transcript, participant)) - return rttm - -def write_rttm(output, rttm_path, annotations): - """ write annotations to rttm_path""" - - with open(os.path.join(output, rttm_path), 'w') as fout: - rttm_name = rttm_path.split('.')[0] - print len(annotations) - for name, t0, length, transcript, participant in annotations: - fout.write(u"SPEAKER\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n".format - (rttm_name, 1, "%.3f" %t0, "%.3f" %length, transcript, - "", participant, 1 )) - -def get_all_on_offs(eaf): - """ - Return all the annotated intervals from the current file - """ - EAF = pmp.Elan.Eaf(eaf) - - all_intervals = EAF.tiers['on_off'][0] - - # get the segments delimited for "on_off" tier, - # as those give the timestamps between which are the annotations - on_offs = [] - for key in all_intervals: - interv = all_intervals[key] - beg_end = interv[2] - beg, end = [float(time) for time in beg_end.split('_')] - # store in seconds, not milliseconds - on_offs.append((beg/1000.0, end/1000.0)) - - return on_offs - -def get_all_on_offs_CAS(eaf): - """ - Return all the annotated intervals from the current file - """ - EAF = pmp.Elan.Eaf(eaf) - - all_intervals = EAF.tiers['code'][0] - - on_offs = [] - for key in all_intervals: - interv = all_intervals[key] - beg_end = interv[2] - _beg = interv[0] - _end = interv[1] - beg = EAF.timeslots[_beg] - end = EAF.timeslots[_end] - - # store in seconds, not milliseconds - on_offs.append((beg/1000.0, end/1000.0)) - - return on_offs - -def cut_audio(on_offs, input_audio, dest): - """ - Extract from the daylong recordings the small parts that have - been annotated - """ - - # for each annotated segment, call sox to extract the part from the - # wav file - # Also, write each onset/offset with 6 digits - for on, off in on_offs: - audio_base = os.path.splitext(input_audio)[0] - wav_name = os.path.basename(audio_base) - dir_name = os.path.split(os.path.dirname(audio_base))[-1] - - # add the necessary number of 0's to the onsets/offsets - # to have 6 digits - str_on = str(int(on)) - str_off = str(int(off)) - - str_on = (6 - len(str_on)) * '0' + str_on - str_off = (6 - len(str_off)) * '0' + str_off - output_audio = '_'.join([dir_name, wav_name, - str_on, str_off]) + '.wav' - cmd = ['sox', input_audio, os.path.join(dest, output_audio), - 'trim', str(on), str(off - on)] - print " ".join(cmd) - subprocess.call(cmd) - -def extract_from_rttm(on_offs, rttm): - """ - For each minute of annotation, extract the annotation of that minute - from the transcription and write a distinct .rttm file with all the - timestamps with reference to the begining of that segment. - """ - sorted_rttm = sorted(rttm, key=itemgetter(1)) - - # create dict { (annotated segments) -> [annotation] } - extract_rttm = defaultdict(list) - for on, off in on_offs: - for name, t0, length, transcript, participant in sorted_rttm: - end = t0 + length - if (on <= t0 < off) or (on <= end < off): - # if the current annotation is (at least partially) - # contained in the current segment, append it. - # Adjust the segment to strictly fit in on-off - t0 = max(t0, on) - end = min(end, off) - length = end - t0 - extract_rttm[(on, off)].append((name, t0 - on, - length, - transcript, participant)) - elif (on > t0) and (end >= off): - # if the current annotation completely contains the annotated - # segment, add it also. This shouldn't happen, so print a - # warning also. - print('Warning: speaker speaks longer than annotated segment.\n' - 'Please check annotation from speaker {},' - 'between {} {}, segment {} {}.\n'.format(name, t0, - end, on, off)) - extract_rttm[(on, off)].append((name, 0, off - on, - transcript, participant)) - elif (end < on): - # wait until reach segment - continue - elif (t0 >= off): - # no point in continuing further since the rttm is sorted. - break - - return extract_rttm - -def main(): - """ - Take as input one eaf and wav file, and extract the segments from the - wav that have been annotated. - """ - parser = argparse.ArgumentParser(description="extract annotated segments") - parser.add_argument('eaf', type=str, - help='''Path to the transcription of the wave file, ''' - ''' in eaf format.''') - parser.add_argument('wav', type=str, - help='''Path to the wave file to treat''') - parser.add_argument('output', type=str) - parser.add_argument('-c', '--CAS', action='store_true', - help='''By default the script detects the segments''' - ''' using the "on_off" tier. For the CAS corpus,''' - ''' we should use the "code" tier.\n''' - ''' Enable this option when treating the CAS corpus''') - args = parser.parse_args() - - output = args.output - print output - #if not os.path.isdir( os.path.join(output, 'treated')): - # os.makedirs(os.path.join(output, 'treated')) - #if not os.path.isdir( os.path.join(output, 'treated', 'talker_role')): - # os.makedirs(os.path.join(output, 'treated', 'talker_role')) - - if args.CAS: - # read transcriptions - complete_rttm = eaf2rttm_CAS(args.eaf) - - # extract annotated segments - on_offs = get_all_on_offs_CAS(args.eaf) - else: - # read transcriptions - complete_rttm = eaf2rttm(args.eaf) - - # extract annotated segments - on_offs = get_all_on_offs(args.eaf) - - # cut audio files according to on_off/code tier in eaf annotations - cut_audio(on_offs, args.wav, output) - - # store in dict the annotations to write in rttm format - extract_rttm = extract_from_rttm(on_offs, complete_rttm) - - # write one rttm file per on_off/tier segment - for key in extract_rttm: - base = os.path.basename(args.eaf) - - # get the name of the corpus by taking the name of the folder and removing "raw" - dir_name = os.path.split( os.path.dirname(args.eaf) )[-1].split('_')[-1] - - name = os.path.splitext(base)[0] - # check is initials of annotator are in eaf name - if '-' in name: - name = name.split('-')[0] - - # add 0's to have exactly 6 digits (i.e. 1 second is 000001 s) - str_on = str(int(key[0])) - str_off = str(int(key[1])) - - str_on = (6 - len(str_on)) * '0' + str_on - str_off = (6 - len(str_off)) * '0' + str_off - - rttm_path = '_'.join([dir_name, name, - str_on, str_off]) + '.rttm' - write_rttm(output, rttm_path, extract_rttm[key]) - - -if __name__ == '__main__': - main() diff --git a/utils/catspa-syllabify-corpus.pl b/utils/catspa-syllabify-corpus.pl deleted file mode 100755 index 36a8c4a..0000000 --- a/utils/catspa-syllabify-corpus.pl +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/perl - -# Alex Cristia alecristia@gmail.com 2015-07-13 adapted VERY MINIMALLY this code from scripts -# distributed by Lawrence Phillips & Lisa Pearl, 12/23/13 (UCI-Brent-Syllabic Corpus) - credit is owed mainly to those authors - -# Uses the maximum onset principle to fully syllabify a corpus -use File::Basename; - -$language=$ARGV[0]; -$filecorpus=$ARGV[1]; -$output=$ARGV[2]; -$dirname=dirname($filecorpus); - -#print "\n the language is $language\n"; -# /input/ OR /scripts/ ? -# Save valid onsets from ValidOnsets.txt -%onsets = {}; -open(ONSETS, "<$dirname/$language-ValidOnsets.txt") or die("Couldn't open $dirname/$language-ValidOnsets.txt\n"); -while(defined($fileline = )){ - chomp($fileline); - #print "$fileline\n"; - $onsets{$fileline} = 1; #This is an odd way of stating things - #print "added"; -} -#print "out of the while"; -close(ONSETS); - -# Save valid vowels from Vowels.txt -%vowels = {}; -open(VOWELS, "<$dirname/$language-Vowels.txt") or die("Couldn't open $dirname/$language-Vowels.txt\n"); -my $vowels = ; -close(VOWELS); -#print "$vowels\n"; - -# Go through CORPUS.txt, -# for nonsyllabified words: for each syllable, find its vowel, and its maximum onset, given acceptable onsets and beginning of word. -# print syllabified version to syllabified-CORPUS.txt. -open(SYLLABIFIED, ">$output") or die("Couldn't open $output for writing\n"); -open(CORPUS, "<$filecorpus") or die("Couldn't open $filecorpus for reading"); - - - -while(defined($fileline = )){ - #print "entered first while\n"; - chomp($fileline); - $currline = $fileline; - @wordarray = split(" ", $currline); # divide the line into a set of words - $syllline="";#we start with a clean slate for each line - while(@wordarray > 0){ - $currword = pop(@wordarray); # cut out the last word in the word array & put it in currword - #print "now looking at $currword\n"; - @chararray = split(//, $currword); - - $syllword="";#we start with a clean slate for each word - $currsyllable=""; #and for the syllable - - while(@chararray > 0){ - $currchar = pop(@chararray); # cut out the last char in the char array for this word & put it in currchar - $currsyllable = $currchar.$currsyllable; # append currchar to current syllable - that will be necessary regardless of whether it's a vowel or a coda - # if hit a vowel.. - #if($currchar =~ /[ae3EiOo0u]/){ - if($currchar =~ /[$vowels]/){ - # print "$currchar\n"; - #if(@chararray[@chararray-1] !=~ /[ae3EiOo0u]/){ - if(@chararray[@chararray-1] !=~ /[$vowels]/){ - # print "@chararray[@chararray-1]\n"; - #if this char is a vowel and the previous one is not, then we need to make the onset - $onset = ""; #we start with nothing as the onset - #then we want to take one letter at a time and check whether their concatenation makes a good onset - while(@chararray > 0 && exists($onsets{@chararray[@chararray-1] . $onset})){ - #print "$onsets{@chararray[@chararray-1] . $onset}\n"; - $currchar = pop(@chararray); - $onset = $currchar . $onset; - } - #we get here either because we've concatenated the onset+rest or because there was no onset and the preceding element is a vowel, so this is the end of the syllable - $currsyllable = $onset . $currsyllable; - # add syllable to word entry - } - $syllword = "\/" . $currsyllable . $syllword; - $currsyllable = ""; - }#we end the if we are looking at a vowel - }#when we end this while there are no more characters in this word, so we can add it - $syllline=$syllword. " " . $syllline; - #print "$syllword\n"; - - } #while we work our way through the words in the line -- so when we exit this, we are ready to print out a syllabified line - if($syllline){ - print SYLLABIFIED "$syllline\n"; - } -}#while there are lines in this file - -close(SYLLABIFIED); -close(CORPUS); \ No newline at end of file diff --git a/utils/change_tsi_lena_names.py b/utils/change_tsi_lena_names.py deleted file mode 100755 index 88134ce..0000000 --- a/utils/change_tsi_lena_names.py +++ /dev/null @@ -1,43 +0,0 @@ -import glob -import os -import re -import argparse - -parser = argparse.ArgumentParser(description="Convert the old naming convention of tsi/lena files into the new one.") -parser.add_argument('-f', '--folder', type=str, required=True, - help="path to the input folder tsi/lena (containing C25_NA_M14_20170719_56040.{wav|rttm} files).") -args = parser.parse_args() - -path_tsi_lena=os.path.join("/vagrant", args.folder) -rttm_files = glob.iglob(os.path.join(path_tsi_lena, '*.rttm')) - -for rttm in rttm_files: - dirname = os.path.dirname(rttm) - basename = os.path.splitext(os.path.basename(rttm))[0] - basename_splitted = basename.split('_') - - old_name = os.path.splitext(basename)[0] - if basename[0] == 'C' and len(basename_splitted) == 5: - new_name = '_'.join([basename_splitted[0], - basename_splitted[3], - basename_splitted[4]]) - - # Modify rttm name - new_path_rttm = os.path.join(dirname, new_name+'.rttm') - os.rename(rttm ,new_path_rttm) - - # Modify wav name - old_path_wav = os.path.join(dirname, old_name+'.wav') - new_path_wav = os.path.join(dirname, new_name+'.wav') - os.rename(old_path_wav, new_path_wav) - - # Do the change within the rttm (column 2 containing the filename) - new_name = os.path.splitext(new_name)[0] - f = open(new_path_rttm, 'r+b') - f_content = f.read() - f_content = re.sub(old_name, new_name, f_content) - f.seek(0) - f.truncate() - f.write(f_content) - f.close() - diff --git a/utils/chat2stm.sh b/utils/chat2stm.sh deleted file mode 100755 index 90285d6..0000000 --- a/utils/chat2stm.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -# -# Shell script to convert .CHA format to .STM format -# -# ./cha2stm.sh .cha produces .stm -# -# To have this use replacement words instead of marking OOV words as "" -# swap (uncomment) the last line to change the arguments to parse_cha_xml.sh - -BASEDIR=$(dirname $0) - -if [ $# -ne 1 ]; then - echo "Usage: cha2stm.sh .cha" - echo - exit 1; -fi - -filename=$(basename "$1") -dirname=$(dirname "$1") -extension="${filename##*.}" -basename="${filename%.*}" - -# Install Java 8 and CHATTER -# First get chatter -mkdir -p ~/bin/lib -( -cd ~/bin/lib -if [ ! -f chatter.jar ]; then - wget http://talkbank.org/software/chatter.jar || exit 1 -fi - -# now get java 8 -if [ -d zulu8.17.0.3-jdk8.0.102-linux_x64 ]; then - : - #echo "Not installing Java 8 since it is already there." 1>&2 -else - echo "Downloading and installing Java 8" 1>&2 - wget http://cdn.azul.com/zulu/bin/zulu8.17.0.3-jdk8.0.102-linux_x64.tar.gz 1>&2 || exit 1 - tar -zxvf zulu8.17.0.3-jdk8.0.102-linux_x64.tar.gz 1>&2 - rm zulu8.17.0.3-jdk8.0.102-linux_x64.tar.gz 1>&2 - echo "Done installing Java 8" 1>&2 -fi -) - -if [ -f $dirname/$basename.cha ]; then - # - # First convert CHA to CHATTER xml - ~/bin/lib/zulu8.17.0.3-jdk8.0.102-linux_x64/bin/java -cp ~/bin/lib/chatter.jar org.talkbank.chatter.App -inputFormat cha -outputFormat xml -output $dirname/$basename.xml $dirname/$basename.cha - - # Convert CHATTER xml to STM - #python scripts/parse_cha_xml.py $dirname/$basename.xml --stm --replacement - python $BASEDIR/../tools/parse_cha_xml.py $dirname/$basename.xml --stm --oov -fi diff --git a/utils/check_folder.sh b/utils/check_folder.sh deleted file mode 100755 index d7be677..0000000 --- a/utils/check_folder.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -check_folder=$(readlink -f $1) - -# First check that the folder is not empty -if [[ -z "$(ls -A $check_folder)" ]]; then - echo "data folder is empty!" - exit -else - echo "wavs and transcriptions found !" -fi - -# Then, check the consistency of all the files -> check if -# the wav have no amplitude -# (credit to http://decided.ly/2013/02/06/find-silent-audio-files/) -## A quick hack like script to list all the files that have -## a low amplitude. - -Max=0.0 # Any amplitude greater than this will NOT be listed -#OutList=~/output.list # The name of the file that contains a -# list of file names only of all the -# low-amplitude files. - -# rm $OutList -for each in `ls $check_folder/*.wav` -do - amplitude=$(sox "$each" -n stat 2>&1 | grep "Maximum amplitude" | cut -d ":" -f 2 | sed 's/ //g') - if [[ $(echo "if (${amplitude} > ${Max}) 1 else 0" | bc) -eq 0 ]] - then - echo "$each --> $amplitude" >&2 - echo "$each seems empty !" - fi -done - -echo "Tests finished" diff --git a/utils/chunk.sh b/utils/chunk.sh deleted file mode 100755 index 572e163..0000000 --- a/utils/chunk.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -# chunk.sh - break files into 5 minute segments in a special folder -# then run a processing script on the folder of chunks -# then merge the resulting RTTMs back together into the -# folder where the input file resides -# -# assumes $1 is full path to a large WAV file -# assumes $2 is path to script to run (such as are found in tools/ -# that takes a folder name in /vagrant, and processes all WAVs in it) -# -# produces a single .rttm in the same folder $1 was found in -# -# uses /vagrant/chunk/ for temporary results - -if [[ $# < 2 ]]; then - echo "Usage: " $0 " " - echo " e.g. tools/chunk.sh /vagrant/ami.wav tools/yunitate.sh" - exit -fi - -WORKFOLDER="/vagrant/chunk" - -# remember basename for later ;) -filename=$(basename "$1") -basename="${filename%.*}" # name without extension -dirname=`dirname $1` # input folder - -if [[ -f $WORKFOLDER ]]; then - # clean out the folder first - rm -rf $WORKFOLDER/* -else - # create the folder - mkdir -p $WORKFOLDER -fi - -# Create 5 minute (except for last piece) named chunk-001.wav chunk-002.wav etc. -sox $1 $WORKFOLDER/chunk-.wav trim 0 300 : newfile : restart - -# run whichever tool you were going to run over the $WORKFOLDER folder -# assume tools are like in ~/tools and assume path is /vagrant/ -# but are only given -$2 chunk - -# assume output is in $WORKFOLDER/chunk-00x.rttm - rename/ rejoin - -OUTFILE=$dirname/$basename.rttm -rm -f $OUTFILE # don't want to append to existing one! -touch $OUTFILE - -COUNT=0 -for f in `ls $WORKFOLDER/*chunk-*.rttm`; do - - # add $COUNT seconds to start time (column 4) of RTTM, and concatenate to $OUTFILE - cat $f | awk -v ADDME=$COUNT '{print $1,$2,$3,($4+ADDME),$5,$6,$7,$8,$9}' >> $OUTFILE - - # increment COUNT in 5 minutes' worth of secons (300) - COUNT=$(($COUNT + 300)) - -done - diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh deleted file mode 100755 index 47e5a9e..0000000 --- a/utils/create_ref_sys.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env bash - -audio_dir=$1 -model_prefix=$2 -create_lab=$3 - -base_directory=$(echo "$audio_dir" | awk -F "/" '{print $2}') - -if [ "$base_directory" != "vagrant" ]; then - audio_dir=/vagrant/$1 -fi - -display_usage() { - echo "Given a folder, and a model prefix, creates a folder that contains the reference transcriptions" - echo "and another folder containing the predicted transcriptions." - echo "usage: $0 [audio_dir] [model_prefix] [create_lab]" - echo " audio_dir The directory that contains the audio files and the transcription." - echo " model_prefix The model prefix (beginning of the files generated by the model)." - echo " create_lab (Optional, true or false) Indicates whether to create .lab files in the reference folder." - exit 1 - } - -if ! [[ $# =~ ^(2|3)$ ]]; then - display_usage -fi - -if [ -z "$3" ]; then - create_lab=false -fi - - -if ! [[ $model_prefix =~ ^(ldc_sad|noisemes_sad|tocombo_sad|opensmile_sad|lena_sad|lena|yunitator|\ -diartk_ldcSad|diartk_noisemesSad|diartk_tocomboSad|diartk_opensmileSad|diartk_goldSad|\ -yuniseg_ldcSad|yuniseg_noisemesSad|yuniseg_tocomboSad|yuniseg_opensmileSad|yuniseg_goldSad)$ ]]; then - echo "You're trying to create folders containing the reference transcriptions, and the predicted ones." - echo "However, you specified a wrong tool name." - echo "Please, check the name of the SAD/diarization tool." - exit 1; -fi - -# Create temp_ref folder -mkdir $audio_dir/temp_ref -for wav in `ls $audio_dir/*.wav`; do - base=$(basename $wav .wav) - cp $audio_dir/${base}.rttm $audio_dir/temp_ref/${base}.rttm - # Sort rttm by onset - sort --key 4 --numeric-sort $audio_dir/${base}.rttm -o $audio_dir/temp_ref/${base}.rttm - # Change tabulations to white-spaces - sed -i 's/\t/ /g' $audio_dir/temp_ref/${base}.rttm - # Replace two or more occurrences of whitespace by just one - sed -i 's/ \+/ /g' $audio_dir/temp_ref/${base}.rttm - if [ $create_lab == true ]; then - awk '{print $4" "($4+$5)" speech"}' $audio_dir/temp_ref/${base}.rttm > $audio_dir/temp_ref/${base}.lab - fi -done - -# Create temp_sys folder and copy all of the sys rttm inside of it -# Remove the model_prefix of it -mkdir $audio_dir/temp_sys -for rttm in `ls $audio_dir/${model_prefix}_*.rttm`; do - base=$(basename $rttm .rttm) - out=`echo $base | sed "s/${model_prefix}\_//g"` - cp $rttm $audio_dir/temp_sys/${out}.rttm - if [ $create_lab == true ]; then - echo "creating: " $audio_dir/temp_sys/${out}.lab - awk '{print $4" "($4+$5)" speech"}' $rttm > $audio_dir/temp_sys/${out}.lab - fi -done - -# check that temp_sys is not empty, otherwise exit and remove it. -if [ -z "$(ls -A $audio_dir/temp_sys)" ]; then - echo "Didn't find any transcription from the model prefix you specified. Please get the ${model_prefix}_my_file.rttm before" - rm -rf $audio_dir/temp_sys $audio_dir/temp_ref - exit -fi diff --git a/utils/diarization.sh b/utils/diarization.sh deleted file mode 100755 index 3c02186..0000000 --- a/utils/diarization.sh +++ /dev/null @@ -1,184 +0,0 @@ -#!/bin/bash - -set -o errexit - -if [ $# -ne 2 ]; then - echo "Usage: ./diarization.sh " - exit -fi - -#define the directory where the results will be saved -datadir=$2 - -# make output folder -mkdir -p $2 -echo "$1 1 0 1000000000 U U U 1" > $datadir/show.uem.seg - -if [ -z $LOCALCLASSPATH ]; then -#LOCALCLASSPATH=lib/LIUM_SpkDiarization-4.2.jar -LOCALCLASSPATH=lium_spkdiarization-8.4.1.jar -fi - -#turn off tracing -trace="--trace" -#trace="" -#turn off help text -#help="--help" -help="" - -#the MFCC file -features="$1 1 0 1000000000 U U U 1" - -#the MFCC corresponds to sphinx 12 MFCC + Energy -# sphinx=the mfcc was computed by the sphinx tools -# 1: static coefficients are present in the file -# 1: energy coefficient is present in the file -# 0: delta coefficients are not present in the file -# 0: delta energy coefficient is not present in the file -# 0: delta delta coefficients are not present in the file -# 0: delta delta energy coefficient is not present in the file -# 13: total size of a feature vector in the mfcc file -# 0:0:0: no feature normalization -fInputDesc="sphinx,1:1:0:0:0:0,13,0:0:0" -fInputDesc="audio2sphinx,1:1:0:0:0:0,13,0:0:0" - -#this variable is use in CLR/NCLR clustering and gender detection -#the MFCC corresponds to sphinx 12 MFCC + E -# sphinx=the mfcc is computed by sphinx tools -# 1: static coefficients are present in the file -# 3: energy coefficient is present in the file but will not be used -# 2: delta coefficients are not present in the file and will be computed on the fly -# 0: delta energy coefficient is not present in the file -# 0: delta delta coefficients are not present in the file -# 0: delta delta energy coefficient is not present in the file -# 13: size of a feature vector in the mfcc file -# 1:1:300:4: the MFCC are wrapped (feature warping using a sliding windows of 300 features), -# next the features are centered and reduced: mean and variance are computed by segment -fInputDescCLR="sphinx,1:3:2:0:0:0,13,1:1:300:4" -fInputDescCLR="audio2sphinx,1:3:2:0:0:0,13,1:1:300:4" - - -show="show" - -#get the initial segmentation file -#uem="$2" -uem=$datadir/show.uem.seg - -#set the java virtual machine program -java="java" -#if [ -n $JAVA_BIN ]; then -# java=$JAVA_BIN -#fi - - -#define where the UBM GMM is -ubm=models/ubm.gmm - - -#define where the speech / non-speech set of GMMs is -#pmsgmm=./model/sms.gmms -pmsgmm=models/sms.gmms - -#define where the silence set of GMMs is -sgmm=models/s.gmms - -#define where the gender and bandwidth set of GMMs (4 models) is -#(female studio, male studio, female telephone, male telephone) -ggmm=models/gender.gmms - - -echo "#####################################################" -echo "# $show" -echo "#####################################################" - - - -iseg=./$datadir/$show.i.seg -pmsseg=./$datadir/$show.pms.seg - - -adjseg=./$datadir/$show.adj.h.seg - -# Check the validity of the MFCC -$java -Xmx1024m -classpath $LOCALCLASSPATH fr.lium.spkDiarization.programs.MSegInit $trace $help \ - --fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=$uem --sOutputMask=./$datadir/show.i.seg $show - -# Speech / non-speech segmentation using a set of GMMs -$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MDecode $trace $help \ - --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,0:0:0 --fInputMask=$features --sInputMask=$iseg \ ---sOutputMask=$pmsseg --dPenality=500,500,10 --tInputMask=$pmsgmm $show - -# GLR-based segmentation, make small segments -$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MSeg $trace $help \ - --kind=FULL --sMethod=GLR --fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.i.seg \ ---sOutputMask=./$datadir/show.s.seg $show - -# Linear clustering, fuse consecutive segments of the same speaker from the start to the end -$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MClust $trace $help \ ---fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.s.seg \ ---sOutputMask=./$datadir/show.l.seg --cMethod=l --cThr=2.5 $show - -# Hierarchical bottom-up BIC clustering - $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MClust $trace $help \ ---fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.l.seg \ ---sOutputMask=./$datadir/show.h.seg --cMethod=h --cThr=6 $show - -# Initialize one speaker GMM with 8 diagonal Gaussian components for each cluster - $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MTrainInit $help $trace \ ---nbComp=8 --kind=DIAG --fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.h.seg \ ---tOutputMask=./$datadir/show.init.gmms $show - -# EM computation for each GMM - $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MTrainEM $help $trace \ ---nbComp=8 --kind=DIAG --fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.h.seg \ ---tOutputMask=./$datadir/show.gmms --tInputMask=./$datadir/show.init.gmms $show - - # Viterbi decoding using the set of GMMs trained by EM - $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MDecode $trace $help \ ---fInputMask=${features} --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.h.seg \ ---sOutputMask=./$datadir/show.d.seg --dPenality=250 --tInputMask=$datadir/show.gmms $show - - # Adjust segment boundaries near silence sections - $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.tools.SAdjSeg $help $trace \ - --fInputMask=$features --fInputDesc=audio2sphinx,1:1:0:0:0:0,13,0:0:0 --sInputMask=./$datadir/show.d.seg \ ---sOutputMask=$adjseg $show - - # Filter speaker segmentation according to speech / non-speech segmentation -flt1seg=./$datadir/$show.flt1.seg -$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.tools.SFilter $help $trace \ - --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,0:0:0 --fInputMask=$features --fltSegMinLenSpeech=150 --fltSegMinLenSil=25 \ ---sFilterClusterName=music --fltSegPadding=25 --sFilterMask=$pmsseg --sInputMask=$adjseg --sOutputMask=$flt1seg $show - -flt2seg=./$datadir/$show.flt2.seg -$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.tools.SFilter $help $trace \ - --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,0:0:0 --fInputMask=$features --fltSegMinLenSpeech=150 --fltSegMinLenSil=25 \ ---sFilterClusterName=jingle --fltSegPadding=25 --sFilterMask=$pmsseg --sInputMask=$flt1seg --sOutputMask=$flt2seg $show - - - # Split segments longer than 20s (useful for transcription) - splseg=./$datadir/$show.spl.seg - $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.tools.SSplitSeg $help \ - --sFilterMask=$pmsseg --sFilterClusterName=iS,iT,j --sInputMask=$flt2seg --sSegMaxLen=2000 --sSegMaxLenModel=2000 \ ---sOutputMask=$splseg --fInputMask=$features --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,0:0:0 --tInputMask=$sgmm $show - - - - -#------------------------------------------------------------------------------- -# Set gender and bandwidth -gseg=./$datadir/$show.g.seg -$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MScore $help \ - --sGender --sByCluster --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,1:1:0 --fInputMask=$features --sInputMask=$splseg \ ---sOutputMask=$gseg --tInputMask=$ggmm $show - - - -# NCLR clustering -# Features contain static and delta and are centered and reduced (--fInputDesc) -c=1.7 -spkseg=./$datadir/$show.c.seg -$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MClust $help $trace \ - --fInputMask=$features --fInputDesc=$fInputDescCLR --sInputMask=$gseg \ ---sOutputMask=./$datadir/show.seg --cMethod=ce --cThr=$c --tInputMask=$ubm \ ---emCtrl=1,5,0.01 --sTop=5,$ubm --tOutputMask=./$datadir/$show.c.gmm $show - diff --git a/utils/eaf2enriched_txt.sh b/utils/eaf2enriched_txt.sh deleted file mode 100755 index 5234516..0000000 --- a/utils/eaf2enriched_txt.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -INPUT_FOLDER=$1 -LANG=$2 -SCRIPT_DIR=$(dirname "$0") - -display_usage() { - echo "Given a folder containing eaf file, creates an enriched txt version of them." - echo "For each files, this script produces a txt version containing :" - echo -e "\t onset" - echo -e "\t off" - echo -e "\t speaker" - echo -e "\t cleaned up transcription" - echo -e "\t number of words" - echo -e "\t phonemized (or syllabified) version of the transcription" - echo -e "\t number of syllables" - - echo "usage: $0 [input] [language]" - echo " input The folder where to find the eaf files (REQUIRED)." - echo " output The language of the transcription : english, spanish or tzeltal (REQUIRED)." - exit 1 - } - -if [ -z "$1" ] || [ -z "$2" ] || ! [[ $LANG =~ ^(english|spanish|tzeltal)$ ]]; then - display_usage -fi - -for eaf_path in /vagrant/$1/*.eaf; do - eaf_path=${eaf_path#/vagrant/} - without_extension="${eaf_path%.*}" - echo "Converting $eaf_path files to ${without_extension}.txt ..." - python $SCRIPT_DIR/eaf2txt.py -i $eaf_path - - echo "Enriching ${without_extension}.txt" - $SCRIPT_DIR/selcha2clean.sh ${without_extension}.txt ${without_extension}_enriched.txt $LANG - - rm /vagrant/${without_extension}.txt -done \ No newline at end of file diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py deleted file mode 100755 index c54a1b4..0000000 --- a/utils/eaf2txt.py +++ /dev/null @@ -1,89 +0,0 @@ -""" -This script converts an eaf file into a txt file containing the following information : - -onset offset transcription receiver speaker_tier - -It can be run either on a single eaf file, or on a whole folder containing eaf files. - -Example of use : - python tools/eaf2txt.py -i data/0396.eaf # One one file - python tools/eaf2txt.py -i data/ # On a whole folder - -About the naming convention of the output : - For each file called input_file.eaf, the result will be stored in input_file.txt -""" - -import pympi as pmp -import argparse -import os -import glob - - -def eaf2txt(path_to_eaf, output_folder, cleanup=False): - """ - Convert an eaf file to the txt format by extracting the onset, offset, ortho, - and the speaker tier. Note that the ortho field has been made by a human and needs - to be clean up. - - Parameters - ---------- - path_to_eaf : path to the eaf file. - - Write a txt whose name is the same than the eaf's one in output_folder - """ - basename = os.path.splitext(os.path.basename(path_to_eaf))[0] - output_path = os.path.join(output_folder, basename + '.txt') - output_file = open(output_path, 'w') - EAF = pmp.Elan.Eaf(path_to_eaf) - tiers = EAF.tiers - for tier in tiers: - try: - annotations = EAF.get_annotation_data_for_tier(tier) - except KeyError: - print("Tier %s ignored..." %tier) - for annotation in annotations: - parameters = EAF.get_parameters_for_tier(tier) - if 'PARTICIPANT' in parameters: - if len(annotation) == 4: - onset, offset, receiver, transcript = annotation[0], annotation[1], annotation[2], annotation[3] - elif len(annotation) == 3: - onset, offset, receiver, transcript = annotation[0], annotation[1], '', annotation[2] - else: - raise ValueError("Format unknown : %s\n" % annotation) - speaker = parameters['PARTICIPANT'] - - if cleanup: - transcript = clean_up_annotation(transcript) - output_file.write("%d\t%d\t%s\t%s\t%s\n" % (onset, offset, receiver, transcript, speaker)) - output_file.close() - -def main(): - parser = argparse.ArgumentParser(description="convert .eaf into .rttm") - parser.add_argument('-i', '--input', type=str, required=True, - help="path to the input .eaf file or the folder containing eaf files.") - args = parser.parse_args() - - # Initialize the output folder as the same folder than the input - # if not provided by the user. - if args.input[-4:] == '.eaf': - output = os.path.dirname(args.input) - else: - output = args.input - - data_dir = '/vagrant' - args.input = os.path.join(data_dir, args.input) - output = os.path.join(data_dir, output) - - if not os.path.isdir(output): - os.mkdir(output) - - if args.input[-4:] == '.eaf': # A single file has been provided by the user - eaf2txt(args.input, output) - else: # A whole folder has been provided - eaf_files = glob.iglob(os.path.join(args.input, '*.eaf')) - for eaf_path in eaf_files: - print("Processing %s" % eaf_path) - eaf2txt(eaf_path, output) - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/utils/elan2rttm.py b/utils/elan2rttm.py deleted file mode 100755 index 0b917be..0000000 --- a/utils/elan2rttm.py +++ /dev/null @@ -1,75 +0,0 @@ -""" -written in python3.5 - -script for translating .eaf annotation files into .rttm format - -WARNING: this version results in a loss of information since .rttm -only keeps speaker ID regardless of the nature of the speech (whereas -.eaf contains additional information such as speech nature e.g. MWU, VCM ...) - -This information might be recovered in an advanced version of this script - -""" - - -import pympi as pmp -import argparse -import os - - -def eaf2rttm(path_to_eaf, path_to_write_rttm): - """ - function to write a new .rttm file which is a transcription of the .eaf - given as input - - """ - - sampling_freq = 1000 - - print('\n') - EAF = pmp.Elan.Eaf(path_to_eaf) - - participants = [] - - for k in EAF.tiers.keys(): - - if 'PARTICIPANT' in EAF.tiers[k][2].keys(): - - if EAF.tiers[k][2]['PARTICIPANT'] not in participants: - - participants.append(EAF.tiers[k][2]['PARTICIPANT']) - - print('participants: {}'.format(participants)) - - base = os.path.basename(path_to_eaf) - name = os.path.splitext(base)[0] - - print('parsing file: {}'.format(name)) - - with open(os.path.join(path_to_write_rttm, name + ".rttm"), "w") as rttm: - - for participant in participants: - - for _, val in EAF.tiers[participant][0].items(): - - start = val[0] - end = val[1] - - t0 = float(EAF.timeslots[start]) / sampling_freq - length = float(EAF.timeslots[end]) / sampling_freq - t0 - - rttm.write(u"SPEAKER {} {} {} {} {} {} {} {}\n".format - (name, 1, "%.2f" % t0, "%.2f" % length, "", "", participant, 1 )) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description="convert .eaf into .rttm") - parser.add_argument('-i', '--input', type=str, required=True, - help="path to the input .eaf file.") - parser.add_argument('-o', '--output', type=str, required=True, - help="path to the folder in which to write the output." - "The output .rttm file will have the same name as the " - "input file - except for the extension") - args = parser.parse_args() - -eaf2rttm(args.input, args.output) diff --git a/utils/empty_transcription.sh b/utils/empty_transcription.sh deleted file mode 100755 index a5084ae..0000000 --- a/utils/empty_transcription.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# -# author: the ACLEW team -# -# after all the transcriptions are extracted, -# look for wav file for which no transcription -# exist, and create empty file - -for wav in `ls $1/*.wav`; do - id=$(basename $wav .wav) - eaf=$1/$id.rttm - if [ ! -f $eaf ]; then - touch $eaf - fi -done diff --git a/utils/evalDiar.sh b/utils/evalDiar.sh deleted file mode 100644 index 65caef7..0000000 --- a/utils/evalDiar.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to OpenSAT (go on folder up and to opensat) -DSCOREDIR=$(dirname $BASEDIR)/dscore - - -display_usage() { - echo "Usage: evalDiar.sh <>" - echo "where dirname is the name of the folder" - echo "containing the wav files, and transcription" - echo "specifies which transcription you want to use," - echo "only used if model == diartk." - echo "Model choices are :" - echo " - diartk" - echo " - yunitate" - echo "Transcription (mandatory for model == diartk) choices are:" - echo " -ldc_sad" - echo " -noisemes" - echo " -opensmile" - echo " -tocombosad" - echo " -textgrid" - echo " -eaf" - echo " -rttm" - exit 1; - -} - -if ! [[ $2 =~ ^(diartk|yunitate|lena)$ ]] || [ "$2" == "diartk" ] && [ $# -ne 3 ]; then - display_usage -fi - - -# data directory -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" - -# Set CWD to path of Dscore -cd $DSCOREDIR - -model=$2 -if [[ $model =~ ^(diartk|yuniseg) ]]; then - trs_format=$3 - case $trs_format in - "ldc_sad") - sys_name=$model"_ldcSad" - ;; - "noisemes") - sys_name=$model"_noisemesSad" - ;; - "tocombosad") - sys_name=$model"_tocomboSad" - ;; - "opensmile") - sys_name=$model"_opensmileSad" - ;; - "textgrid") - sys_name=$model"_goldSad" - for wav in `ls $audio_dir/*.wav`; do - base=$(basename $wav .wav) - $conda_dir/python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid $audio_dir/${basename}.rttm - done - ;; - "eaf") - sys_name=$model"_goldSad" - for wav in `ls $audio_dir/*.wav`; do - base=$(basename $wav .wav) - $conda_dir/python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf $audio_dir/${basename}.rttm - done - ;; - "rttm") - sys_name=$model"_goldSad" - ;; - *) - echo "ERROR: You're trying to evaluate diartk, but the transcription system you specified is not recognized :" - echo " ldc_sad" - echo " noisemes" - echo " textgrid" - echo " eaf" - echo " rttm" - echo "Now exiting..." - exit 1 - ;; - esac -elif [ "$2" == "yunitate" ]; then - sys_name="yunitator" -elif [ "$2" == "lena" ]; then - sys_name="lena" -fi - -$BASEDIR/create_ref_sys.sh $audio_dir $sys_name - -echo "evaluating" - -$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $audio_dir/temp_ref $audio_dir/temp_sys - -# Check if some gold files are empty. If so, add a line in the eval dataframe -for fin in `ls $audio_dir/temp_ref/*.rttm`; do - base=$(basename $fin .rttm) - if [ ! -s $audio_dir/temp_ref/$base.rttm ]; then - if [ ! -s $audio_dir/temp_sys/$base.rttm ]; then - echo $base" 0 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df - else - echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df - fi - elif [ ! -s $audio_dir/temp_sys/$base.rttm ] && [ -s $audio_dir/temp_ref/$base.rttm ]; then - echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df - fi -done - -echo "done evaluating, check $1/${sys_name}_eval.df for the results" -# remove temps -rm -rf $audio_dir/temp_ref $audio_dir/temp_sys diff --git a/utils/evalSAD.sh b/utils/evalSAD.sh deleted file mode 100644 index 509e5ed..0000000 --- a/utils/evalSAD.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/bash -# Launcher onset routine -source ~/.bashrc -SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` -conda_dir=$BASEDIR/anaconda/bin -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -# end of launcher onset routine - - -### Read in variables from user -# data directory -audio_dir=$BASEDIR/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" - -# check system to evaluate -system=$2 - - -### Other variables speicfic to this script -# Path to scoring tool NOTE: NOT dscore! -ldcSad_DIR=$REPOS/ldc_sad_hmm -# create temp dir -workdir=$audio_dir/temp/evalSad/ -mkdir -p $workdir - - -### SCRIPT STARTS -if [[ $system = "ldcSad" ]]; then - sys_name="ldcSad" -elif [[ $system = "noisemesSad" ]]; then - sys_name="noisemesSad" -elif [[ $system = "tocombosad" ]]; then - sys_name="tocombo_sad" -elif [[ $system = "opensmileSad" ]]; then - sys_name="opensmileSad" -elif [[ $system = "lenaSad" ]]; then - sys_name="lenaSad" - -else - echo "Please Specify the System you wish to evaluate." - echo "Choose between ldcSad, noisemeSad, tocomboSad, opensmileSad, lenaSad." - exit -fi - - -# Set CWD to path of scoring tool -cd $ldcSad_DIR - -mkdir - -$BASEDIR/create_ref_sys.sh $audio_dir $sys_name true - -echo "evaluating" -#$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys -# create /vagrant/results if it doesn't exist -echo "filename DCF FA MISS" > $audio_dir/${sys_name}_eval.df -for lab in `ls $workdir/temp_sys/*.lab`; do - base=$(basename $lab .lab) - if [ ! -s $workdir/temp_ref/$base.lab ]; then - if [ ! -s $workdir/temp_sys/$base.lab ]; then - echo $base" 0.00% 0.00% 0.00%" >> $audio_dir/${sys_name}_eval.df - else - echo $base" 25.00% 100.00% 0.00%" >> $audio_dir/${sys_name}_eval.df - fi - elif [ ! -s $workdir/temp_sys/$base.lab ] && [ -s $workdir/temp_ref/$base.lab ]; then - echo $base" 75.00% 0.00% 100.00%" >> $audio_dir/${sys_name}_eval.df - else - $conda_dir/python score.py $workdir/temp_ref $lab | awk -v var="$base" -F" " '{if ($1=="DCF:") {print var"\t"$2"\t"$4"\t"$6}}' >> $audio_dir/${sys_name}_eval.df - fi - -done -# small detail: remove the commas from the output -sed -i "s/,//g" $audio_dir/${sys_name}_eval.df -echo "done evaluating, check $1/${sys_name}_eval.df for the results" - -# remove temps -rm -rf $workdir/temp_ref $workdir/temp_sys - diff --git a/utils/extract_stats_chi.py b/utils/extract_stats_chi.py deleted file mode 100755 index 6ab3bb3..0000000 --- a/utils/extract_stats_chi.py +++ /dev/null @@ -1,124 +0,0 @@ -import sys -import argparse -import glob -import os -import re -from collections import OrderedDict - - -def detect_ad_chi_tt(previous_activity, curr_activity, last_silence_dur, chi, mal, fem): - if last_silence_dur <= 2.0: - if (previous_activity in mal and curr_activity in chi) or \ - (previous_activity in fem and curr_activity in chi) or \ - (previous_activity in chi and curr_activity in mal) or \ - (previous_activity in chi and curr_activity in fem): - return 1 - return 0 - - -def compute_statistics(rttm_path, chi, mal, fem): - chi_dur=0.0 - chi_utt=0 - ad_dur=0.0 - ad_utt=0 - ad_chi_tt=0 - - silence_dur = 0 - prev_activity = None - onset_prev = 0 - dur_prev = 0 - - with open(rttm_path,'r') as rttm: - for line in rttm: - line = line.replace('\t', ' ') - line = re.sub('\s+', ' ', line).strip() - anno_fields = line.split(' ') - curr_activity = anno_fields[7] - if curr_activity != 'SIL' and curr_activity != 'S': # We're managing things as if 'SIL' lines weren't exist - onset = float(anno_fields[3]) - dur = float(anno_fields[4]) - - if curr_activity in chi: - chi_dur += dur - chi_utt += 1 - elif curr_activity in mal or curr_activity in fem: - ad_dur += dur - ad_utt +=1 - else: - print("Activity %s not recognized" % (curr_activity)) - sys.exit(1) - - if onset_prev + dur_prev == onset: - silence_dur = 0.0 - else: - silence_dur = onset - onset_prev - dur_prev - - ad_chi_tt += detect_ad_chi_tt(prev_activity, curr_activity, silence_dur, chi, mal, fem) - - # We're managing things as if SIL lines weren't exist - - prev_activity=curr_activity - onset_prev=onset - dur_prev=dur - - filename = os.path.basename(rttm_path).split('.')[0] - res = [filename, chi_dur, chi_utt, ad_dur, ad_utt, ad_chi_tt] - return res - -def write_stats(list_stats, folder): - filename=os.path.join(folder,"stats.txt") - - with open(filename,'w') as fn: - fn.write("filename\tchi_dur\tchi_utt\tad_dur\tad_utt\tad_chi_tt\n") - for stats in list_stats: - fn.write('\t'.join(map(str,stats))+'\n') - -def main(): - parser = argparse.ArgumentParser(description="convert .txt into .rttm") - parser.add_argument('-f', '--folder', type=str, required=True, - help="path to the folder where to find the rttm to analyze." - "Note that all of the rttm are scanned.") - parser.add_argument('--chi', nargs='+', type=str, required=True, - help="labels that need to be considered as being child vocalization.") - parser.add_argument('--mal', nargs='+', type=str, required=True, - help="labels that need to be considered as being male adult speech.") - parser.add_argument('--fem', nargs='+', type=str, required=True, - help="labels that need to be considered as being female adult speech.") - args = parser.parse_args() - - # Below the values that need to be consider when evaluating tsi/lena folder - # prob C22_20170717_5640 - ## Gold files - # chi=['CHI*','C1', 'C2'] - # mal=['MA1','MA2'] - # fem=['MOT*','FA1','FA2'] - - ## Yunitator - # chi = ['CHI'] - # mal = ['MAL'] - # fem = ['FEM'] - - ## Lena N tag - # chi = ['CXN', 'CHN'] - # mal = ['MAN'] - # fem = ['FAN'] - - ## Lena MFC - # chi = ['C'] - # mal = ['M'] - # fem = ['F'] - - ## Lena N and F separated (should be the equivalent of MFC - # chi = ['CHN', 'CXN', 'CHF', 'CXF'] - # mal = ['MAN', 'MAF'] - # fem = ['FAN', 'FAF'] - args.folder=os.path.join('/vagrant', args.folder) - rttm_files = [fn for fn in glob.iglob(os.path.join(args.folder, '*.rttm')) - if 'cutted' not in fn] - list_stats=[] - for rttm_path in rttm_files: - list_stats.append(compute_statistics(rttm_path, args.chi, args.mal, args.fem)) - - write_stats(list_stats, args.folder) -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/utils/frame_cutter.py b/utils/frame_cutter.py deleted file mode 100755 index b181e90..0000000 --- a/utils/frame_cutter.py +++ /dev/null @@ -1,220 +0,0 @@ -import sys -import os -import argparse -import re -import glob -import numpy as np -from scipy.io import wavfile - -def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): - """ - Given a rttm file, create a new file whose represents the same rttm cutted in frames. - If one frame has been classified as several classes in the original rttm, it concatenates classes. - Note that all of the frames that have not been classified in the original rttm are considered as being SIL. - Note that it will read the associated wav file to get the total duration of the recording. - - Parameters - ---------- - path_to_rttm : path to the rttm file. - frame_length : frame length. - output_file : path to the output file. - prefix : the prefix that needs to be remove (from rttm) to map the rttm to the wav file. - labels_map : to map the labels from original rttm (values) to the output rttm (keys). - - Write a rttm whose name is the same than the rttm's one suffixed by _cutted.rttm - """ - basename = os.path.splitext(os.path.basename(path_to_rttm))[0] - if prefix != "": - basename = basename.split(prefix)[1] - dirname = os.path.dirname(path_to_rttm) - wav_path = os.path.join(dirname,basename+'.wav') - if os.path.isfile(wav_path): - fs, data = wavfile.read(wav_path) - tot_dur_s = len(data)*1.0/fs - else: - print("Something went wrong while reading the wav file %s. Can not get total duration..." % wav_path) - sys.exit(1) - - frame_length_s = float(frame_length)/1000.0 - frames = np.arange(0.0, tot_dur_s, frame_length_s) - # We don't want to loose any data - if frames[-1] < tot_dur_s: - frames = np.append(frames, frames[-1]+frame_length_s) - - with open(path_to_rttm, 'r') as rttm: - with open(output_file, 'w') as output: - onset_prev_s = 0.0 - dur_prev_s = 0.0 - act_prev = None - append_prev = False - onset_s = None - - for line in rttm: - line = line.replace('\t', ' ') - line = re.sub('\s+', ' ', line).strip() - anno_fields = line.split(' ') - onset_s = float(anno_fields[3]) - dur_s = float(anno_fields[4]) - curr_activity = anno_fields[7] - - if onset_s > onset_prev_s + dur_prev_s : #There's been silence just before ! - sil_dur_s = onset_s - onset_prev_s - dur_prev_s - onset_sil_s = onset_prev_s + dur_prev_s - single_activity_cutter(basename, output, frame_length_s, - sil_dur_s, onset_sil_s, 'SIL', tot_dur_s, labels_map) - act_prev = 'SIL' - dur_prev_s = sil_dur_s - onset_prev_s = onset_sil_s - - single_activity_cutter(basename, output, frame_length_s, - dur_s, onset_s, curr_activity, tot_dur_s, labels_map) - - # Update previous fields - act_prev = curr_activity - dur_prev_s = dur_s - onset_prev_s = onset_s - - # Fill the last one by SILENCE - ## Handle empty rttm - if onset_s is None: - onset_s = 0.0 - dur_s = 0.0 - - if onset_s + dur_s < tot_dur_s: - sil_dur_s = tot_dur_s - onset_s-dur_s - onset_sil_s = onset_s + dur_s - single_activity_cutter(basename, output, frame_length_s, - sil_dur_s, onset_sil_s, 'SIL', tot_dur_s, labels_map) - - -def single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, curr_activity, tot_dur_s, labels_map): - """ - Given an activity, its onset and its duration, cut it into frames of length frame_length_s. - - Parameters - ---------- - basename The basename of the input rttm. - output The path of the output file. - frame_length_s The frame length (in s). - dur_s The duration of the current activity (in s). - onset_s The onset of the current activity (in s). - curr_activity The current activity. - labels_map : To map the labels from original rttm (values) to the output rttm (keys). - - """ - # We don't want to consider any fake labels generated after the duration of the wav file - if onset_s + dur_s > tot_dur_s: - dur_s = max(tot_dur_s - onset_s, 0) - if onset_s > tot_dur_s: - onset_s = 0.0 - - diff_s = onset_s - int(onset_s / frame_length_s) * frame_length_s - onset_s = int(onset_s / frame_length_s) * frame_length_s - n_frames = int((dur_s+diff_s) / frame_length_s) - # Get the output label (we want a full match or nothing) - activity = [k for k,v in labels_map.items() if re.match("("+v+")\Z", curr_activity) is not None] - if len(activity) != 1: - print("Can not map the input label to the output one : %s" % curr_activity) - sys.exit(1) - else: - activity = activity[0] - - for i in range(0, n_frames): - output.write("SPEAKER %s 1 %s %s %s \n" % \ - (basename, onset_s + frame_length_s * i, - str(frame_length_s), activity)) - - if not np.isclose(onset_s + frame_length_s * n_frames, onset_s+dur_s+diff_s, rtol=1e-05, atol=1e-08, equal_nan=False): - output.write("SPEAKER %s 1 %s %s %s \n" % \ - (basename, onset_s + frame_length_s * n_frames, - str(frame_length_s), activity)) - - -def aggregate_overlap(path_to_rttm, output_file): - """ - Given a cutted rttm file, aggregate the activities that happen in the same time. - The class of the generated frame will take the form of spkr1/spkr2 ... - - Parameters - ---------- - path_to_rttm Path to the input rttm file that have been previously cutted. - output_file Path to the output file. - """ - basename = os.path.splitext(os.path.basename(path_to_rttm))[0] - with open(path_to_rttm, 'r') as rttm: - with open(output_file, 'w') as output: - lines = rttm.readlines() - lines = sorted(lines, key=lambda line: float(line.split()[3])) - k = 0 - while k < len(lines): # Loop through the whole file - line_k = lines[k].split() - onset_k, dur_k, act_k = line_k[3], line_k[4], line_k[7] - frame_activity = [act_k] - j = k + 1 - while j < len(lines): # Loop through the activities that have the same onset - line_j = lines[j].split() - onset_j, dur_j, act_j = line_j[3], line_j[4], line_j[7] - if onset_k != onset_j: - output.write("SPEAKER %s 1 %s %s %s \n" % \ - (basename, onset_k, dur_k, '/'.join(frame_activity))) - break - else: # onset_k == onset_j: - if act_j not in frame_activity: - frame_activity.append(act_j) - frame_activity.sort() # Consider alphabetical order - k += 1 - j += 1 - k += 1 - - output.write("SPEAKER %s 1 %s %s %s \n" % \ - (basename, onset_k, dur_k, '/'.join(frame_activity))) - - - - -def main(): - parser = argparse.ArgumentParser(description="convert a rttm file into another rttm cutted in frames.") - parser.add_argument('-i', '--input', type=str, required=True, - help="path to the input .rttm file or the folder containing rttm files.") - parser.add_argument('-l', '--length', type=float, required=False, default=100.0, - help="the frame length in ms (Default to 100 ms).") - parser.add_argument('-p', '--prefix', type=str, default="", - help="the prefix that needs to be removed to map the rttm to the wav.") - args = parser.parse_args() - - labels_map = {"CHI": "CHI.?|CXN|CHN|C.?", - "FEM": "FAN|FAF|FEM|F|MOT.?|FA.?", - "MAL": "MAL|M|MAN|MA.?", - "SIL": "SIL|S"} - - # Initialize the output folder as the same folder than the input - # if not provided by the user. - if args.input[-5:] == '.rttm': - output = os.path.dirname(args.input) - else: - output = args.input - - data_dir = '/vagrant' - args.input = os.path.join(data_dir, args.input) - output = os.path.join(data_dir, output) - - if not os.path.isdir(output): - os.mkdir(output) - - if args.input[-5:] == '.rttm': # A single file has been provided by the user - output = os.path.splitext(args.input)[0]+'_cutted.rttm' - print(output) - cutter(args.input, args.length, output+'.tmp', args.prefix, labels_map) - aggregate_overlap(output+'.tmp', output) - os.remove(output+'.tmp') - else: # A whole folder has been provided - rttm_files = glob.iglob(os.path.join(args.input, '*.rttm')) - for rttm_path in rttm_files: - print("Processing %s" % rttm_path) - output = os.path.splitext(rttm_path)[0] + '_cutted.rttm' - cutter(rttm_path, args.length, output + '.tmp', args.prefix, labels_map) - aggregate_overlap(output + '.tmp', output) - os.remove(output + '.tmp') - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/utils/generate_html.py b/utils/generate_html.py deleted file mode 100755 index a5ab577..0000000 --- a/utils/generate_html.py +++ /dev/null @@ -1,44 +0,0 @@ -# generate_html.py -""" -Given a list of folders that have been fed to the different models, -generate a html file presenting the following results : - -wip - -Use case : - python tools/generate_html.py -f data/ -o data/html -It will scan folder data/ and generates the html interface at data/html. -""" - -import argparse -import os -import glob -from html_python.files_page import FilesPage -from html_python.models_page import ModelsPage -from html_python.style_css import StyleCSS -from html_python.page import Page - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('-f', '--folder', type=str, - help=' Folder that needs to be analyzed', required=True) - parser.add_argument('-o', '--output', type = str, - help=' The folder where the html files will be generated.', required=True) - - args = parser.parse_args() - - # define data dir - data_dir = "/vagrant" - args.folder = os.path.join(data_dir, args.folder) - args.output = os.path.join(data_dir, args.output) - - style_css = StyleCSS(args.output) - files_html = FilesPage(args.output, args.folder) - files_html.write_statistics() - - models_html = ModelsPage(args.output, args.folder) - models_html.write_statistics() - models_html.close() - -if __name__ == '__main__': - main() diff --git a/utils/get_aclewStarter.sh b/utils/get_aclewStarter.sh deleted file mode 100755 index a1909bf..0000000 --- a/utils/get_aclewStarter.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -# -# author = the ACLEW Team -# -# Use this script to download the aclew Starter from databrary and start using -# it with the DiViMe. -# This script should be launched from the DiViMe folder, which also contains -# the VagrantFile. - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` - -# url to dataset in zip format -aclewStarter_url=https://nyu.databrary.org/volume/390/zip/true -aclewStarter_folder=databrary390-Bergelson-Warlaumont-Cristia-Casillas-Rosemberg-Soderstrom-Rowland-Durrant-Bunce-Starter-ACLEW - -# create data directory to store dataset and download zip file -if [[ ! -d "aclewStarter" ]]; then - mkdir $BASEDIR/aclewStarter -fi - -cd $BASEDIR/aclewStarter - -echo "downloading the ACLEW Starter Dataset..." -wget $aclewStarter_url - -# unzip archive and keep data when there is both the audio file and -# the transcription. Delete the archive file -unzip true -rm true - -# regroup wavs and transcriptions and remove those that don't have a match -cd $aclewStarter_folder -mkdir transcript -mkdir wav - -mv sessions/*/*.wav wav/ -mv materials*/*.eaf transcript/ - -echo "processing all the ACLEW Starter files..." -for eaf in $(ls transcript/); do - base=$(echo $eaf | cut -d '-' -f 1) - if [[ -f wav/${base}.wav ]]; then - mv transcript/$eaf transcript/${base}.eaf - vagrant ssh -c "python varia/elan2rttm.py -i /vagrant/aclewStarter/$aclewStarter_folder/transcript/${base}.eaf -o /vagrant/aclewStarter/" - mv wav/${base}.wav ../ - else - rm transcript/$eaf - fi -done - -# When all the files are seen, delete the extracted raw folder -cd ../ -rm -rf $aclewStarter_folder - -echo "You can now use the ACLEW Starter dataset!" diff --git a/utils/high_volubility.py b/utils/high_volubility.py deleted file mode 100755 index 609ba5b..0000000 --- a/utils/high_volubility.py +++ /dev/null @@ -1,526 +0,0 @@ -#!/usr/bin/env python -# -# author = The ACLEW Team -# -""" -This script extract short snippets of sound (approx. 10s long), -and runs them through a SAD or diarization tool to detect chunks of audio with : - -1) a lot of speech. ---> python tools/high_volubility.py file_path.wav --sad noisemes_sad - -2) a lot of child speech ---> python tools/high_volubility.py file_path.wav --diar yunitate --mode CHI - -3) a lot of parent-child conversations ---> python tools/high_volubility.py file_path.wav --diar yunitate --mode PCCONV - -4) a lot of adults conversations with a child minimally aware ---> python tools/high_volubility.py file_path.wav --diar yunitate --mode ACCA -""" - -import os -import sys -import re -import wave -import math -import numpy -import argparse -import subprocess - -from operator import itemgetter - - -def get_audio_length(wav): - """ Return duration of Wave file. - - Input: - wav: path to the wav file. - - Output: - dur: float, duration, in seconds, of wav file. - """ - - audio = wave.open(wav, 'r') - frames = audio.getnframes() - rate = audio.getframerate() - duration = frames / float(rate) - audio.close() - - return duration - - -def select_onsets(duration, step): - """ Return list of onsets on which this script will extract the chunks of - 10s - - Input: - duration: float, duration of the daylong recording - - Ouput: - onsets: list[floats], list the onsets on which this script will extract - the chunks of 10s to be run through the SAD tools - """ - return numpy.arange(0.0, duration, step) - - -def extract_chunks(wav, onset_list, chunk_size, temp): - """ Given a list of onset and a length in seconds, extract a snippet of - audio at each onset of this length. The extraction will be done using - SoX, called by subprocess. - - Input: - wav: path to the wav file. - onset_list: list[float], list of the onsets in the 'wav' file at which - we'll extract the segments - chunk_size: float, length in seconds of the chunks of audio this script - will extract. - - Output: - 'temp': the output of this function is the set of small wav file of - 'chunk_size' seconds in the temp folder. - The name of the wav files will be: - id_onset_length.wav - where id is the name of the original wav file, onset is the - onset at which the chunk occurs in the original wav file, and - length is the length of the chunk. - """ - - # for each onset, call SoX using subprocess to extract a chunk. - for on in onset_list: - - # get "id" basename of wav file - basename = os.path.splitext(os.path.basename(wav))[0] - - # create name of output - off = on + chunk_size - str_on = (6 - len(str(on))) * '0' + str(on) - str_off = (6 - len(str(off))) * '0' + str(off) - - chunk_name = '_'.join([basename, str_on, str_off]) - - # call subprocess - cmd = ['sox', wav, - os.path.join(temp, '{}.wav'.format(chunk_name)), - 'trim', str(on), str(chunk_size)] - subprocess.call(cmd) - - -def run_Model(temp_rel, temp_abs, sad, diar=None): - """ When all the snippets of sound are extracted, and stored in the temp - file, run them through a sad or diar tool, and keep - the 10%% that have the most speech. - By default, the function is on the SAD mode. That means that it will - run a SAD model (by default noiseme). However, if the diar parameter is - provided, this function will be on the diarization mode. - - Input: - temp_rel: relative path to the temp folder in which the snippets of - sounds are stored. Here we need the relative path, not the - abs path, since the SAD tool will add the "/vagrant/" part of - the path. - temp_abs: absolute path to the temp folder in which the snippets of - sounds are stored. - sad: name of the sad tool to be used to analyze the snippets of - sound - diar: name of the diar tool to be used to analyze the snippets of - sound. Note that it will use that sad parameter as a choice - of SAD provider. - - Output: - _: In temp, the SAD analyses will be written in RTTM format. - """ - if diar is not None: # Diarization mode - if diar == 'yunitate': - cmd = ['tools/{}.sh'.format(diar), '{}'.format(temp_rel)] - elif diar == 'diartk': - cmd = ['tools/{}.sh'.format(diar), '{}'.format(temp_rel), '{}'.format(sad)] - else: - cmd = ['exit 1'] - else: # SAD mode - cmd = ['tools/{}.sh'.format(sad), '{}'.format(temp_rel)] - - subprocess.call(cmd) - - # After the model has finished running, remove the wav files - for fin in os.listdir(temp_abs): - if fin.endswith('.wav'): - os.remove(os.path.join(temp_abs, fin)) - - -def extract_base_name(filename, diar): - """ - Giving a filename generated by a model and composed of : - model_name + wav_filename + tbeg + tdur - Extracts the base name composed of the three last elements. - - Input: - filename: a filename generated by a model - diar: a diarization model (if provided) - - Output: - base : wavfilename_tbeg_tdur - """ - if diar == 'yunitate': - base = filename.split('_')[1:] - else: - base = filename.split('_')[2:] - - base = os.path.splitext('_'.join(base))[0] - return base - - -def detect_parent_child_conv(previous_activity, curr_activity, last_silence_dur): - """ - Attempts to try if a turn-taking happened between a child and his/her parents - - Input: - previous_activity: the last activity amongst ['CHI', 'MAL', 'FEM'] - curr_activity: the current activity amongst ['CHI', 'MAL', 'FEM'] - last_silence_dur: the duration of the last silence - - Output: - A boolean indicating if a turn-taking happened between a child and his/her parents - True : a turn-taking happened - False : nothing happened - """ - if last_silence_dur <= 2.0: - if (previous_activity == 'MAL' and curr_activity == 'CHI') or \ - (previous_activity == 'FEM' and curr_activity == 'CHI') or \ - (previous_activity == 'CHI' and curr_activity == 'MAL') or \ - (previous_activity == 'CHI' and curr_activity == 'FEM'): - - return True - return False - -def detect_adults_conv(previous_activity, curr_activity, last_silence_dur): - """ - Attempts to try if a turn-taking happened between two adults - - Input: - previous_activity: the last activity amongst ['CHI', 'MAL', 'FEM'] - curr_activity: the current activity amongst ['CHI', 'MAL', 'FEM'] - last_silence_dur: the duration of the last silence - - Output: - A boolean indicating if a turn-taking happened between a child and his/her parents - True : a turn-taking happened - False : nothing happened - """ - if last_silence_dur <= 2.0: - if (previous_activity == 'MAL' and curr_activity == 'FEM') or \ - (previous_activity == 'FEM' and curr_activity == 'MAL') or \ - (previous_activity == 'FEM' and curr_activity == 'FEM') or \ - (previous_activity == 'MAL' and curr_activity == 'MAL'): - - return True - return False - -def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False): - """ When the model has finished producing its outputs, read all the - transcriptions and sort the files by the quantity of their speech - content or the quantity of their speech belonging to the noiseme_class. - - Input: - temp: path to the temp folder in which the snippets of sound are - stored. Here we need the relative path, not the absolute - path, since the SAD tool will add the "/vagrant/" part of - the path. - sad: name of the sad tool to be used to analyze the snippets of - sound. - perc: the percentage of speech to keep. - diar: the diarization model (if provided). - mode: the type of speech that needs to be kept (has to be amongst ['CHI']). - child_aware : (only used if mode == ACCA) Indicates, if we should filter the snippets - that don't present any child activity. - - Output: - sorted_files: list(str), list of the files, sorted by the quantity - of the speech content (as returned by the SAD tool) - or the quantity of the speech content classified as - belonging to the noiseme class (as returned by the - diarization tool). - only 10 %% of all files, that contain the most speech - """ - - # get list of model outputs - all_files = os.listdir(temp_abs) - diar_mode = diar is not None - if diar_mode: - model = diar - else: - model = sad - - # we consider only the annotations that have been generated by the model - annotations = [file for file in all_files if file.startswith(model[:-1])] - - # read all annotations and store duple in list (filename, speech_dur) - files_n_dur = [] - for file in annotations: - - # we extract the base name composed of wav_file_name + t_deg + t_dur - base = extract_base_name(file, diar) - - with open(os.path.join(temp_abs, file), 'r') as fin: - speech_activity = fin.readlines() - - # total duration of the speech of interest - tot_dur = 0.0 - # duration of the last silence - silence_dur = 0.0 - # type of the last activity - previous_activity = None - onset_prev = 0.0 - dur_prev = 0.0 - # variable to detect if the child is aware in ACCA mode. - chi_points = 0.0 - - for line in speech_activity: - anno_fields = line.split(' ') - dur = float(anno_fields[4]) - onset = float(anno_fields[3]) - curr_activity = anno_fields[7] - - - if onset_prev+dur_prev == onset: - silence_dur = 0.0 - else: - silence_dur = onset-onset_prev-dur_prev - - - if not diar_mode: # SAD mode - tot_dur += dur - elif diar_mode and mode == 'CHI' and curr_activity == 'CHI': # Child detection mode - tot_dur += 1 - elif diar_mode and mode == 'PCCONV': # Parent-child detection mode - if detect_parent_child_conv(previous_activity, curr_activity, silence_dur): - # Here we consider more an objective function (number of turn-taking) that - # we want to maximize. That comes from the fact that adults speak during a - # longer time while children speak only for few seconds. And we don't want - # to put too much weight on the adults speech. - tot_dur += 1 - elif diar_mode and mode == 'ACCA': # Adults conversation child aware detection - if detect_adults_conv(previous_activity, curr_activity, silence_dur): - tot_dur += 1 - elif curr_activity == 'CHI': - chi_points += 1 - - previous_activity = curr_activity - onset_prev = onset - dur_prev = dur - - files_n_dur.append((base, tot_dur, chi_points)) - - # remove annotation when finished reading - os.remove(os.path.join(temp_abs, file)) - - if child_aware and diar_mode == 'ACCA': - files_n_dur = [file for file in files_n_dur if file[2] > 3] - - if len(files_n_dur) == 0: - raise ValueError("No moments for the {} mode has been found.\n Try to decrease the step parameter or " + \ - "to increase the size of the chunks.") - - files_n_dur = sorted(files_n_dur, key=itemgetter(1), reverse=True) - - # return top 10%% of snippets - percent = max(1, int(math.ceil(perc * len(files_n_dur)))) - - sorted_files = files_n_dur[:percent] - - return sorted_files - -def new_onsets_two_minutes(sorted_files): - """ - Given a selection of file with lots of speech, - extract new 2minutes long chunks of audio in the original wav, - centered around the short 10s snippets that were analysed. - - Input: - sorted_files: list of the snippets that were selected - because they had lot of speech - temp_abs: absolute path to the temp folder that contains the - snippets - wav: path to the daylong recording - Ouput: - _: in the temp folder, new two minutes long chunks of - audio will be stored. - """ - - # loop over selected files and retrieve their onsets from their name - new_onset_list = [] - for snippet, speech_dur, chi_points in sorted_files: - onset = os.path.splitext(snippet)[0].split('_')[-2] - offset = os.path.splitext(snippet)[0].split('_')[-1] - - length = float(offset) - float(onset) - - # new segment is centered around snippet, so get middle of snippet - new_onset = length / 2 + float(onset) - - new_onset_list.append(new_onset) - - return new_onset_list - -def new_onsets_five_minutes(sorted_files): - """ - Given a selection of file with lots of speech, - extract new 5minutes long chunks of audio in the original wav, - by adding 2 minutes before and 1 minute after the 2minute chunks. - - Input: - sorted_files: list of the snippets that were selected - because they had lot of speech - temp_abs: absolute path to the temp folder that contains the - snippets - wav: path to the daylong recording - Ouput: - _: in the temp folder, new two minutes long chunks of - audio will be stored. - """ - # loop over selected files and retrieve their onsets from their name - new_onset_list = [] - for snippet, speech_dur, chi_points in sorted_files: - onset = os.path.splitext(snippet)[0].split('_')[-2] - offset = os.path.splitext(snippet)[0].split('_')[-1] - - # new segment starts 2 minute before the 2 minute chunk - new_onset = float(onset) - 120.0 - - new_onset_list.append(new_onset) - - return new_onset_list - - -def main(): - """ - Get duration of wav file - Given duration of wav file, extract list of onsets - Given list of onsets in wav file, extract chunks of wav - - Input: - daylong: path to the daylong recording - --step: (optional) step in seconds between each chunk. - By default 600 seconds. - --chunk_size: (optional) size of the chunks to extract. - --temp: (optional) path to a temporary folder to store the - extracted chunks. - --sad: (optional) name of the SAD tool to call to analyse - the chunks. By default noiseme - --diar: (optional) name of the diarization tool to call to analyse - the chunks. No default option - - """ - parser = argparse.ArgumentParser() - - parser.add_argument('daylong', metavar='AUDIO_FILE', - help='''Give RELATIVE path to the daylong recording''' - '''in wav format.''') - parser.add_argument('--step', default=600.0, type=float, - help='''(Optional) Step, in seconds, between each chunk of ''' - '''audio that will be extracted to be analysed by the SAD ''' - '''tool. By default, step=600 seconds (10 minutes)''') - parser.add_argument('--chunk_sizes', nargs=3, - default=[10.0, 120.0, 300.0], type=float, - help='''(Optional) Size of the chunks to extract and analyze. ''' - '''By default it's 10.0 120.0 300.0: \n''' - '''10s chunks are extracted, analyzed by the ''' - '''SAD tool, the 10%% chunks that contain the most speech ''' - '''are kept, than 120s chunks centered on the 10s chunks, ''' - '''these are again analysed by the SAD tool, the 10%% that ''' - ''' contain the most speech are kept, and 300.0s chunks ''' - ''' are finally extracted around these kept chunks.''') - parser.add_argument('--percentage', default=10, type=float, - help='''(Optional) Percentage of snippets to keep at each stage. ''' - '''By default, we keep 10%% of snippets each time.\n''' - '''For a 15h long recording, we have 90x10s snippets, ''' - '''we keep the 10%% with the most speech content, that ''' - '''lead to 9x120s snippets, we again keep the 10%% with the ''' - '''most speech content, so in the end we have 1x300 seconds ''' - '''segment.''') - parser.add_argument('--temp', default='tmp', - help='''(Optional) Path to a temp folder in which the small wav ''' - '''segments will be stored. If it doesn't exist, it will be ''' - '''created.''') - parser.add_argument('--sad', default='noisemes_sad', - help='''(Optional) name of the sad tool that will be used to ''' - '''analyze the snippets of sound''') - parser.add_argument('--diar', - help='''(Optional) name of the diar tool that will be used to ''' - '''analyze the snippets of sound. If this argument is provided by - the user, this script will be on the diarization mode. Otherwise, it will - be on the SAD mode.''') - parser.add_argument('--mode', default='CHI', choices=['CHI', 'PCCONV', 'ACCA'], - help='''(Optional) the noiseme class(es) of interest. ''' - '''Used only when the diar argument is provided.''') - - args = parser.parse_args() - - if args.diar == 'yunitate' and (args.mode == 'PCCONV' or args.mode == 'ACCA' or args.mode == 'CHI'): - if args.chunk_sizes[0] == 10.0: - print("Resetting chunk size at 20.0 seconds (more suitable for CHI/PCCONV/ACCA mode).") - args.chunk_sizes[0] = 20.0 - if args.step == 600.0: - print("Resetting step at 300.0 seconds (more suitable for CHI/PCCONV/ACCA mode).") - args.step = 300.0 - - # Define Data dir - data_dir = "/vagrant" - - # check if temp dir exist and create it if not - temp_abs = os.path.join(data_dir, args.temp) - temp_rel = args.temp # to launch SAD tool we need the relative path to temp - - if not os.path.isdir(temp_abs): - os.makedirs(temp_abs) - - # Define absolute path to wav file - wav_abs = os.path.join(data_dir, args.daylong) - - # get percentage - perc = args.percentage / 100.0 - - # get path to current (tools/) dir - useful to call the SAD tool - dir_path = os.path.dirname(os.path.realpath(__file__)) - - # get duration - duration = get_audio_length(wav_abs) - - # get list of onsets - onset_list = select_onsets(duration, args.step) - - # call subprocess to extract the chunks - extract_chunks(wav_abs, onset_list, args.chunk_sizes[0], temp_abs) - - # analyze using SAD tool - run_Model(temp_rel, temp_abs, args.sad, args.diar) - - # sort by speech duration - sorted_files = read_analyses(temp_abs, args.sad, perc, args.diar, args.mode) - - # get new onsets for two minutes chunks - new_onset_list = new_onsets_two_minutes(sorted_files) - - # extract two minutes chunks - extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[1], temp_abs) - - # analyze using SAD tool - run_Model(temp_rel, temp_abs, args.sad, args.diar) - - # sort by speech duration again - child_aware = False - if args.mode == 'ACCA': - child_aware = True - - sorted_files = read_analyses(temp_abs, args.sad, perc, args.diar, args.mode, child_aware) - - # get new onsets for five minutes chunks - new_onset_list = new_onsets_five_minutes(sorted_files) - - # extract final five minutes long chunks - output_dir = os.path.dirname(wav_abs) - extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[2], output_dir) - - -if __name__ == '__main__': - main() diff --git a/utils/html_python/__init__.py b/utils/html_python/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/utils/html_python/files_page.py b/utils/html_python/files_page.py deleted file mode 100755 index bc56fdd..0000000 --- a/utils/html_python/files_page.py +++ /dev/null @@ -1,179 +0,0 @@ -import html_python.page as page -import html_python.utils as utils -import html_python.style_css as style_css -import numpy as np -import os -import glob -import random -import numbers -from collections import OrderedDict - - -class FilesPage(page.Page): - - def __init__(self, output_folder, results_folder): - # Initialize self.output_folder & self.results_folder - page.Page.__init__(self, output_folder, results_folder) - - self.N_files = 20 # Fix the number of files to print in the table - - # List of gold files - self.gold_files = [fn for fn in glob.iglob(os.path.join(self.results_folder, '*.rttm')) - if not os.path.basename(fn).startswith(('ldc_sad', 'diartk', 'noisemes_sad', - 'opensmile', 'tocombo_sad', 'lena', 'yunitator'))] - # Name of the html that will be generated - self.name = 'files.html' - - # File descriptor - self.html = open(os.path.join(self.output_folder, self.name), 'w') - - tabs = '\n' + \ - '' - self.html.write(tabs)#write tabs - - # Compute statistics - self._compute_statistics() - - if len(self.audio_stats) > self.N_files: - self.random_indices = np.sort(random.sample(range(0, len(self.audio_stats)), self.N_files)) - else: - self.random_indices = range(0, len(self.audio_stats)) - - def _compute_statistics(self): - - self.audio_stats = [] - self.gold_stats = [] - - # Empty OrderedDict that will contains the unique keys of the gold file - # We use only the keys, it's to fake an OrderedSet that doesn't exist natively in python. - # The difficulty here is that gold2.rttm could have some participants that gold1.rttm doesn't have. - # We still want to consider them in all of the rttm to present the results in a table. - self.gold_keys = OrderedDict({}) - for gold in self.gold_files: #for each reference rttm file - - wav_path = os.path.splitext(gold)[0]+'.wav' - - # Get .wav information - audio_stats_file = utils.analyze_wav(wav_path) - self.audio_stats.append(audio_stats_file) - - # Analyze gold - dur_wav = audio_stats_file['duration (s)'] - gold_stats_file = utils.analyze_rttm(gold, dur_wav) - self.gold_keys = OrderedDict.fromkeys(self.gold_keys.keys() + gold_stats_file.keys()) - self.gold_stats.append(gold_stats_file) - - self._compute_averages() - self.audio_stats = np.array(self.audio_stats) - self.gold_stats = np.array(self.gold_stats) - - def _compute_averages(self): - - # Get audio stats averages - self.averages_audio = OrderedDict(zip(self.audio_stats[0].keys()[2:], [0.0] * (len(self.audio_stats[0]) - 2))) - for line in self.audio_stats: - for key in line.keys(): - if isinstance(line[key], numbers.Number) and line[key] is not None: # None and non numbers are considered as being 0.0 - self.averages_audio[key] += line[key] - - for k, v in self.averages_audio.items(): - self.averages_audio[k] = v/len(self.audio_stats) - - # Get gold stats averages - self.averages_gold = OrderedDict(zip(self.gold_keys.keys()[1:], [0.0] * (len(self.gold_keys) - 1))) - for line in self.gold_stats: - for key in line.keys(): - if isinstance(line[key], numbers.Number) and line[key] is not None: # None and non numbers are considered as being 0.0 - self.averages_gold[key] += line[key] - - for k, v in self.averages_gold.items(): - self.averages_gold[k] = v/len(self.gold_stats) - - - def _write_value(self, value, number_of_digits = 4): - if isinstance(value, str): - self.html.write(' %s \n' % value) - elif isinstance(value, float) or isinstance(value, np.float64) or isinstance(value, np.float32): - self.html.write(' %.*f\n' % (number_of_digits,value)) - elif isinstance(value, int): - self.html.write(' %d \n' % value) - - def write_audio_stats(self): - keys = self.audio_stats[0].keys() - - # Open table - self.html.write('

Audio level statistics

\n\n') - - # Write first line of the table - self.html.write('\n') - for k in keys: - self.html.write('\n' % k) - self.html.write('\n') - - # Write audio statistics - for d in self.audio_stats[self.random_indices]: - self.html.write('\n') - for key, value in d.items(): - self._write_value(value, 4) - - self.html.write('\n') - - # Write averages - self.averages_audio["filename"] = "averages" - for k in keys: - if k in self.averages_audio: - self._write_value(self.averages_audio[k], 4) - else: - self._write_value("") - - # Close table - self.html.write('
%s
') - - - def write_gold_stats(self): - - keys = self.gold_stats[0].keys() - - # Open table - self.html.write('

Annotation level statistics

\n\n') - - # Write first line of the table - self.html.write('\n') - for k in self.gold_keys: - self.html.write('\n' % k) - self.html.write('\n') - - # Write gold statistics - for d in self.gold_stats[self.random_indices]: - self.html.write('\n') - for key in self.gold_keys: - if key in d: - self._write_value(d[key], 2) - else: - self._write_value("") - self.html.write('\n') - - # Write averages - self.averages_gold["filename"] = "averages" - for k in self.gold_keys: - if k in self.averages_gold: - self._write_value(self.averages_gold[k], 2) - else: - self._write_value("") - - # Close table - self.html.write('
%s
') - - def write_statistics(self): - self.write_audio_stats() - self.write_gold_stats() - if len(self.audio_stats) > self.N_files: - self.html.write("

Note : a random sample of %d files has been made to lighten the presentation." % self.N_files) - - def close(self): - self.html.close() \ No newline at end of file diff --git a/utils/html_python/models_page.py b/utils/html_python/models_page.py deleted file mode 100755 index 249872c..0000000 --- a/utils/html_python/models_page.py +++ /dev/null @@ -1,103 +0,0 @@ -import html_python.page as page -import html_python.utils as utils -import numpy as np -import os -import glob -import html_python.style_css as style_css -from collections import OrderedDict - - -class ModelsPage(page.Page): - - def __init__(self, output_folder, results_folder): - # Initialize self.output_folder & self.results_folder - page.Page.__init__(self, output_folder, results_folder) - - # Name of the html that will be generated - self.name = 'models.html' - - # File descriptor - self.html = open(os.path.join(self.output_folder, self.name), 'w') - - tabs = '\n' + \ - '' - self.html.write(tabs) #write tabs - - # List of df files present in the results_folder - self.df_files = [fn for fn in glob.iglob(os.path.join(self.results_folder, '*.df'))] - - def _get_statistics(self): - self.sad_stats = [] - self.diar_stats = [] - for df_path in self.df_files: - basename = os.path.splitext(os.path.basename(df_path))[0] - if basename.startswith(('diartk','lena','yunitator')): - self.diar_stats.append(utils.get_averages(df_path)) - else: - self.sad_stats.append(utils.get_averages(df_path)) - - def _write_SAD_statistics(self): - # Write SAD table - if len(self.sad_stats) == 0: - self.html.write("No SAD model evaluations have been found.") - else: - # Open table - self.html.write('

SAD statistics

\n\n') - # Write first line of the table - self.html.write('\n') - keys = self.sad_stats[0].keys() - for k in keys: - self.html.write('\n' % k) - self.html.write('\n') - - # Write statistics - for d in self.sad_stats: - self.html.write('\n') - for key, value in d.items(): - utils.write_value(self.html, value, 4) - self.html.write('\n') - # Close table - self.html.write('
%s
') - - def _write_diar_statistics(self): - # Write SAD table - if len(self.diar_stats) == 0: - self.html.write("No diarization model evaluations have been found.") - else: - # Open table - self.html.write('

Diarization statistics

\n\n') - # Write first line of the table - self.html.write('\n') - keys = self.diar_stats[0].keys() - for k in keys: - self.html.write('\n' % k) - self.html.write('\n') - - # Write statistics - for d in self.diar_stats: - self.html.write('\n') - for key, value in d.items(): - utils.write_value(self.html, value, 2) - self.html.write('\n') - - # Close table - self.html.write('
%s
') - - def write_statistics(self): - if len(self.df_files) == 0: - self.html.write("No df files have been found... Please run the evaluation of choose another folder.") - else: - self._get_statistics() - self._write_SAD_statistics() - self._write_diar_statistics() - - - - - def close(self): - self.html.close() \ No newline at end of file diff --git a/utils/html_python/page.py b/utils/html_python/page.py deleted file mode 100755 index 0c59ba0..0000000 --- a/utils/html_python/page.py +++ /dev/null @@ -1,30 +0,0 @@ -from abc import ABCMeta, abstractmethod -import os - -# Used to read the rttm generated by all the different models. -# The first element '' is to handle gold rttm -sad_prefixes = ['ldc_sad_', 'noisemes_sad_', 'tocombo_sad_', 'opensmile_sad_'] -diar_prefixes = ['diartk_goldSad_', 'diartk_ldcSad_', 'diartk_tocomboSad_', - 'diartk_noisemesSad_', 'diartk_opensmileSad_'] - -class Page: - __metaclass__ = ABCMeta - - @abstractmethod - def __init__(self, output_folder, results_folder): - # The output folder where to store the html/css files. - self.output_folder = output_folder - - # The folders that we need to analyze/aggregate - self.results_folder = results_folder - - if not os.path.exists(self.output_folder): - os.makedirs(self.output_folder) - - @abstractmethod - def write_statistics(self): - raise NotImplementedError('subclasses must override write_statistics()!') - - @abstractmethod - def close(self): - raise NotImplementedError('subclasses must override close()!') diff --git a/utils/html_python/style_css.py b/utils/html_python/style_css.py deleted file mode 100755 index db1bc75..0000000 --- a/utils/html_python/style_css.py +++ /dev/null @@ -1,33 +0,0 @@ -import os - -css_name = "style.css" # global variable - - -class StyleCSS: - - def __init__(self, output_folder): - # The output folder where to store the html/css files. - self.output_folder = output_folder - - if not os.path.exists(self.output_folder): - os.makedirs(self.output_folder) - - self.css = open(os.path.join(self.output_folder, 'style.css'), 'w') - - # tabs style - tabs_style = "ul {background: #333;list-style: none;overflow: hidden;text-align: center;}\n" + \ - "ul li {display: inline-block;}\n" + \ - "ul li a {padding: 5px 10px;background: #333;color: #fff;line-height: 3em;display: block; }\n" + \ - "ul li a:hover {background: #e4e4e4;color: #333;}\n" + \ - "li.active>a {background: #e4e4e4;color: #333;}\n" + \ - "a {display : block;color : #666;text-decoration : none;padding : 4px;}\n" - - # table style - table_style = "table {margin: 0 auto;}\n" +\ - "td, th {border: 1px solid #ddd;padding: 8px;text-align: center;}\n" +\ - "tr:nth-child(even){background-color: #f2f2f2;}\n" +\ - "tr:hover {background-color: #ddd;}\n" +\ - "th {padding-top: 12px;padding-bottom: 12px;text-align: center;background-color: #333;color: white;}\n" - self.css.write(tabs_style) - self.css.write(table_style) - self.css.close() \ No newline at end of file diff --git a/utils/html_python/utils.py b/utils/html_python/utils.py deleted file mode 100755 index 82a1678..0000000 --- a/utils/html_python/utils.py +++ /dev/null @@ -1,164 +0,0 @@ -from scipy.io import wavfile -import collections -import numpy as np -import os - - -# Utility functions -def write_value(fn, value, number_of_digits=4): - if isinstance(value, str): - fn.write(' %s \n' % value) - elif isinstance(value, float) or isinstance(value, np.float64) or isinstance(value, np.float32): - fn.write(' %.*f\n' % (number_of_digits, value)) - elif isinstance(value, int): - fn.write(' %d \n' % value) - - -def signaltonoise(a, axis=0, ddof=0): - """ - The signal-to-noise ratio of the input data. - Returns the signal-to-noise ratio of `a`, here defined as the mean - divided by the standard deviation. - Parameters - ---------- - a : array_like - An array_like object containing the sample data. - axis : int or None, optional - If axis is equal to None, the array is first ravel'd. If axis is an - integer, this is the axis over which to operate. Default is 0. - ddof : int, optional - Degrees of freedom correction for standard deviation. Default is 0. - Returns - ------- - s2n : ndarray - The mean to standard deviation ratio(s) along `axis`, or 0 where the - standard deviation is 0. - """ - a = np.asanyarray(a) - m = a.mean(axis) - sd = a.std(axis=axis, ddof=ddof) - return np.where(sd == 0, 0, m / sd) - -def analyze_wav(filepath): - """ - Analyzes a wav file and returns some audio statistics. - Parameters - ---------- - filepath - - Returns - ------- - statistics : - """ - basename = os.path.splitext(os.path.basename(filepath))[0] - - if os.path.splitext(filepath)[1] == '.wav' and os.path.isfile(filepath): - fs, data = wavfile.read(filepath) - data_type = type(data[0]) - if data_type == np.int16: - wav_format = '16-bit PCM' - MAX_WAV_AMP = 32767.0 - elif data_type == np.int32: - wav_format = '32-bit PCM' - MAX_WAV_AMP = 2147483647.0 - elif data_type == np.uint8: - wav_format = '8-bit PCM' - MAX_WAV_AMP = 255.0 - elif data_type == np.float32: - wav_format = '32-bit floating-point' - MAX_WAV_AMP = 1.0 - - # Normalization between -1 and 1 - data = data/MAX_WAV_AMP - - # Compute metrics - duration = len(data)*1.0/fs - mean_amplitude = np.mean(data) - max_amplitude = np.max(data) - snr = float(signaltonoise(data)) - statistics = collections.OrderedDict([("filename", basename), - ("wav format", wav_format), - ("duration (s)", duration), - ("mean amplitude", mean_amplitude), - ("max amplitude", max_amplitude), - ("signal to noise ratio", snr)]) - return statistics - - -def _detect_overlap(t_beg, dur, t_beg_prev, dur_prev): - - if t_beg_prev + dur_prev > t_beg: - if t_beg_prev+dur_prev > t_beg+dur: - return dur - else: - return t_beg_prev + dur_prev - t_beg - return 0.0 - - -def analyze_rttm(filepath, dur_wav): - basename = os.path.splitext(os.path.basename(filepath))[0] - dict = collections.OrderedDict([("filename", basename), - ("% total speech", 0.0), - ("% overlap", 0.0), - ("number of participants", 0)]) - - if os.path.splitext(filepath)[1] == '.rttm' and os.path.isfile(filepath): - fn = open(filepath) - t_beg_prev, dur_prev, participant_prev = 0.0, 0.0, None - for line in fn: - fields = line.split() - type, t_beg, dur, participant = fields[0], float(fields[3]), float(fields[4]), fields[7] - - # Add information about the participant - prop_key = "% of "+participant - if prop_key in dict: - dict[prop_key] += dur - else: - dict[prop_key] = dur - - # Add information about the overall speech - if type == 'SPEAKER': - dict["% total speech"] += dur - - # Compute overlap - dict["% overlap"] += _detect_overlap(t_beg, dur, t_beg_prev,dur_prev) - - # Update previous - t_beg_prev, dur_prev, participant_prev = t_beg, dur, participant - - # Normalization step - # Normalize participants speech duration by total speech - if dict["% total speech"]: - for k, v in dict.items(): - if k.startswith("% of "): - dict["number of participants"] += 1 - dict[k] /= dict["% total speech"] - # Normalize % overlap by total speech - dict["% overlap"] /= dict["% total speech"] - - # Normalize total speech by wav duration - dict["% total speech"] /= dur_wav - - fn.close() - return dict - -def get_averages(df_path): - column_sums = None - basename = os.path.splitext(os.path.basename(df_path))[0] - with open(df_path) as file: - header=file.readline() - header=header.replace('\n','').split('\t') - if header[0] == 'filename': - header=header[1:] - - lines = file.readlines() - rows_of_numbers = [map(float, line.replace('%','').replace('\n','').replace('NA','0.0').split('\t')[1:]) for line in lines] - sums = map(sum, zip(*rows_of_numbers)) - averages = [sum_item / len(lines) for sum_item in sums] - - # Add model name - header.insert(0, 'filename') - averages.insert(0, basename) - averages = collections.OrderedDict(zip(header, averages)) - return averages - diff --git a/utils/its2rttm.py b/utils/its2rttm.py deleted file mode 100644 index f3e190a..0000000 --- a/utils/its2rttm.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python -# -# author: The ACLEW Team -# -# This script takes as input its file -# and convert it to rttm file. - -import os -import re -import argparse - - -def its_line_2_rttm_line(its_line, rttm_name): - """ - < Segment spkr = "TVF" average_dB = "-49.61" peak_dB = "-38.96" startTime = "PT31819.24S" endTime = "PT31820.61S" / > - to - SPEAKER rttm_name 1 t_beg dur class - """ - its_line = its_line[its_line.find("<"):] - - rttm_line = "" - if its_line[:8] == " " +\ - " " +\ - spkr + " " +\ - " " +\ - "\n" - - return rttm_line - - -def its_2_rttm(input_path, output_path): - """Read a RTTM file indicating gold diarization""" - rttm_name = os.path.splitext(os.path.basename(output_path))[0] - - with open(input_path, 'r') as its: - with open(output_path, 'w') as rttm: - for its_line in its: - rttm_line = its_line_2_rttm_line(its_line, rttm_name) - rttm.write(rttm_line) - -def main(): - """Take transcription file in its format as input, and write """ - """it into rttm format.""" - parser = argparse.ArgumentParser( - description='Take transcription file in its format as input, and write ' - 'it into rttm format.', - add_help=True, - usage='%(prog)s [its] [rttm]') - parser.add_argument( - 'its', type=str, metavar='PATH', - help='Path to the its input') - parser.add_argument( - 'rttm', type=str, metavar='PATH', - help='Path to the rttm output') - - args = parser.parse_args() - - its_2_rttm(args.its, args.rttm) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/utils/its2rttm.sh b/utils/its2rttm.sh deleted file mode 100755 index 7f54580..0000000 --- a/utils/its2rttm.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# Given a folder, convert all of the its files to rttm - -SCRIPT_PATH=$(dirname "$(readlink -f "$0")") - -folder=$1 - -if [ -z "$folder" ]; then - echo "You must specify a folder containing its files." - exit -fi - -if [ ! -n "$(ls -A $folder/*.its 2>/dev/null)" ] -then - echo "The folder you specified does not contain any its files." - -fi - -for its_file in $folder/*.its -do - rttm_name=${its_file%.its}.rttm - python $SCRIPT_PATH/its2rttm.py $its_file $rttm_name -done diff --git a/utils/lab2rttm.sh b/utils/lab2rttm.sh deleted file mode 100755 index 57f8103..0000000 --- a/utils/lab2rttm.sh +++ /dev/null @@ -1,30 +0,0 @@ -#sample rttm file -#SPEAKER NDAR_TC217KM7 1 0.01 0.12 spk7 -# structure is blah filename blah onset dur blah blah speakerid blah -#times are in seconds - -#sample min file -#0 6031 S0 -#structure is onset offset speakerid -#numbers are in seconds - -#takes as input a folder that contains txts -#and will receive the rttm files -#eg ./min2rttm.sh /pylon2/ci560op/acrsta/data/starterACLEW/ - -folder=$1 - -for j in $folder/*.lab -do -#echo $j -#echo "$folder/${subf}_ref.rttm" - subf=`basename ${j} | sed "s/.lab//"` - type=${subf: -5} - - if [ $type != "_lena" ] - then - type="" - fi - subf=`echo $subf | sed "s/_lena//"` - grep ' speech' $j | awk '{print "SPEAKER" " " "'$subf'" " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $folder/${subf}${type}.rttm -done diff --git a/utils/make_big_corpus.sh b/utils/make_big_corpus.sh deleted file mode 100755 index 12d08a2..0000000 --- a/utils/make_big_corpus.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash -# this script takes as input, for $corpus, the folder containing the daylong recordings -# and the transcriptions in eaf format in a folder raw_$corpus. It reads the transcriptions -# in the eaf files and cuts the wav to only keep the transcribed part, and convert the transcribed -# part into rttm with the same names as the cut wavs. - -# take the name of the corpus as input and define the hard coded paths - they shall not change! -corpus=$1 # should be chosen between BER, WAR, SOD and CAS -working_dir=/DATA2T/aclew_data_update -daylong_dir=/DATA2T/aclew_daylong_data -temp_dir=$working_dir/temp # create temp dir to store wav. will be removed at end of script - -# Define function to check if all small wavs have an rttm. If not, create an empty one. -create_empty_rttm() { - # check the wav files and the talker_roles to see if the rttm exists - # if it doesn't, create an empty rttm file. - wav=$1 - rttms=$2 - for fin in `ls $wav/*.wav`; do - basename=$(basename $fin .wav) - if [[ ! -f $rttms/${basename}.rttm ]]; then - touch $rttms/${basename}.rttm - fi - done -} - -## Treat BER WAR the "simple way", add parameters to take into account the format of CAS and SOD/SOD2 -#if [[ $corpus == 'BER' ]] || [[ $corpus == 'WAR' ]] || [[ $corpus == 'CAS' ]]; then -if [[ $corpus != 'SOD2' ]] ; then - mkdir -p $temp_dir/$corpus/SAD - for wav in `ls $daylong_dir/$corpus/*.wav`; do - base=$(basename $wav .wav) - eaf=raw_$corpus/${base}.eaf - if [[ $corpus == 'CAS' ]]; then - python $working_dir/adjust_timestamps.py $working_dir/github_data/$eaf $wav $temp_dir --CAS - else - python $working_dir/adjust_timestamps.py $working_dir/github_data/$eaf $wav $temp_dir 2>&1 - fi - # now remove old wav and transcriptions: - - done - rm $working_dir/ACLEW_data/databrary_ACLEW/wavs/${corpus}_*wav $working_dir/ACLEW_data/databrary_ACLEW/talker_role/${corpus}_*rttm - mv $temp_dir/*.rttm $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ - mv $temp_dir/*.wav $working_dir/ACLEW_data/databrary_ACLEW/wavs/ - - # create empty rttms when the wav has no transcription (nobody's talking)' - #create_empty_rttm $corpus/treated $corpus/treated/talker_role - - # Now create the SAD - rm $working_dir/ACLEW_data/databrary_ACLEW/SAD/${corpus}_*rttm - python remove_overlap_rttm.py $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ $working_dir/ACLEW_data/databrary_ACLEW/SAD -fi - -# SOD : the eaf have the same name as the wav, but they added '-$name' where $name is the initials of the annotator -if [[ $corpus == 'SOD2' ]]; then - echo "treating SOD" 2>&1 - corpus=SOD - mkdir -p $temp_dir/$corpus/SAD - for wav in `ls $daylong_dir/$corpus/*.wav`; do - base=$(basename $wav .wav) - eaf=raw_$corpus/${base}-TS.eaf - if [ ! -f $working_dir/github_data/$eaf ]; then - eaf=raw_$corpus/${base}-JK.eaf - fi - python $working_dir/adjust_timestamps.py $working_dir/github_data/$eaf $wav $temp_dir 2>&1 - - done - mv $temp_dir/*.rttm $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ - mv $temp_dir/*.wav $working_dir/ACLEW_data/databrary_ACLEW/wavs/ - - # Now create the SAD - python remove_overlap_rttm.py $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ $working_dir/ACLEW_data/databrary_ACLEW/SAD - -fi -# create empty rttms when the wav has no transcription (nobody's talking)' - -#create_empty_rttm $corpus/treated $corpus/treated/talker_role - -# Now create the SAD -#python remove_overlap_rttm.py $corpus/treated/talker_role $corpus/treated/SAD - - -## CAS : the eaf don't have the 'on_off' tier to encode the segments, instead it's called "code" - this is taken -## into account in adjust_timestamps.py with the --CAS parameter -#if [[ $corpus == 'CAS' ]]; then -# #convert2wav $corpus -# mkdir -p $corpus/treated/SAD -# for wav in `ls $corpus/*.wav`; do -# base=$(basename $wav .wav) -# eaf=$corpus/raw_$corpus/${base}.eaf -# python $working_dir/adjust_timestamps.py $eaf $wav --CAS -# done -#fi -## create empty rttms when the wav has no transcription (nobody's talking)' -# -#create_empty_rttm $corpus/treated $corpus/treated/talker_role -# -## Now create the SAD -#python remove_overlap_rttm.py $corpus/treated/talker_role $corpus/treated/SAD -##done -# diff --git a/utils/noisemes_full.sh b/utils/noisemes_full.sh deleted file mode 100644 index b93fcf5..0000000 --- a/utils/noisemes_full.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin - -# run OpenSAT with hard coded models & configs found here and in /vagrant -# assumes Python environment in /home/${user}/ - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to OpenSAT (go on folder up and to opensat) -OPENSATDIR=$(dirname $BASEDIR)/OpenSAT - -if [ $# -ne 1 ]; then - echo "Usage: noisemes_full.sh " - echo "where dirname is the name of the folder" - echo "containing the wav files" - exit 1 -fi - -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" -# Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir - - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - -# let's get our bearings: set CWD to the path of OpenSAT -cd $OPENSATDIR - -# first features -echo "extracting features for noisemes_full" -for file in `ls $audio_dir/*.wav`; do - SSSF/code/feature/extract-htk-vm2.sh $file -done - - - - -# then confidences -#/home/vagrant/anaconda/bin/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename -echo "predicting classes" -#$conda_dir/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename -$conda_dir/python SSSF/code/predict/1-confidence-vm4.py $audio_dir -echo "noisemes_full finished running" - -# take all the .rttm in /vagrant/data/hyp_sum and move them to /vagrant/data - move features and hyp_sum to another folder also. -for sad in `ls $audio_dir/hyp_sum/*.rttm`; do - _rttm=$(basename $sad) - rttm=$audio_dir/noiseme_full_${_rttm} - mv $sad $rttm -done - -# simply remove hyp and feature -rm -rf $audio_dir/feature $audio_dir/hyp_sum - -#if [ ! -d "$audio_dir/noiseme_full_temp" ]; then -# mkdir -p $audio_dir/noiseme_full_temp -#fi -# -#if [! -d "$audio_dir/noiseme_full_temp" ]; then -# mv $audio_dir/hyp_sum $audio_dir/noiseme_full_temp -#else -# echo "can't move hyp_sum/ folder to noiseme_full_temp/ because temp is already full" -#fi -# -#if [! -d "$audio_dir/noiseme_full_temp" ]; then -# mv $audio_dir/feature $audio_dir/noiseme_full_temp -#else -# echo "can't move features/ folder to noiseme_full_temp/ because temp is already full" -#fi -# diff --git a/utils/parse_cha_xml.py b/utils/parse_cha_xml.py deleted file mode 100755 index f9a561f..0000000 --- a/utils/parse_cha_xml.py +++ /dev/null @@ -1,191 +0,0 @@ -# parse_cha_xml.py -# -# Given CHATTER format xml (http://talkbank.org/software/chatter.html) -# supplied as an argument, or via a pipe, print out STM format text -# -# To toggle whether UNIBET words are printed out, or instead appear as "" -# set the switch --oov. To instead print their replacements, set the switch --replacment -# -# usage ./parse_cha_xml.py P1_6W_SE_C6.xml -# -# Change Log: -# 17 Jan 2018 - print plaintext utterances even if no timecode present -# - added handling of "happening" and formType elements -# to support things like "singing", yell, shout etc. -# - added metadata for speaker e.g. as -# found in 'participant' tags - -from xml.dom.minidom import parse -import sys,argparse,os - -reload(sys) -sys.setdefaultencoding("utf-8") - -parser=argparse.ArgumentParser(description="""Description""") -parser.add_argument('--oov', action='store_true', help='print symbols for nonwords') -parser.add_argument('--replacement', action='store_true', help='print replacement words') -parser.add_argument('--stm', action='store_true', help='produce STM format') -parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), help='CHATTER (xml) format input file', - default=sys.stdin) -args=parser.parse_args() - -# a table of speaker IDs and related metadata - -infile = args.infile.name -if infile == '': - dom = parse(sys.stdin) -else: - dom = parse(infile) -utts = dom.getElementsByTagName('u') # utterances -participants = dom.getElementsByTagName('participant') - -oov = args.oov -stm = args.stm -replace = args.replacement -#recording = infile[infile.rfind("/")+1:] -# get only base name (chop off .xml extension) -recording = os.path.splitext(os.path.basename(infile))[0] - -#utterance = "" - -parts = {} -for part in participants: - label = "<"; ident = "" - name = ""; role = ""; sex = "u" - for key in part.attributes.keys(): - if key == "id": - ident = part.attributes[key].nodeValue.encode('utf8') - if key == "name": - name = part.attributes[key].nodeValue.encode('utf8') - name = name.replace(" ","") - if key == "role": - role = part.attributes[key].nodeValue.encode('utf8') - role = role.replace(" ","") - if key == "sex": - sex = part.attributes[key].nodeValue.encode('utf8') - if sex == "male": sex = "m" - if sex == "female": sex = "f" - parts[ident]=("<"+name+","+sex+","+role+">").lower() -# print parts[ident] - -# add the word found inside node passed in as argument -def addWord( node ): - global utterance - for wordlet in node.childNodes: - if wordlet.nodeType == wordlet.TEXT_NODE: - unibet = False - s = wordlet.nodeValue - try: s.decode('ascii') - except UnicodeDecodeError: unibet = True - utterance += " " - if oov and unibet: - utterance += "" - else: - utterance += wordlet.nodeValue.encode('utf8') - - -def addReplacement ( group ): - added = False - for subword in group.childNodes: - if subword.nodeType == subword.ELEMENT_NODE and subword.tagName == 'replacement': - for replacement in subword.childNodes: - if replacement.nodeType == replacement.ELEMENT_NODE and replacement.tagName == 'w': - addWord( replacement ) - added = True - # didn't find a - just output the word - if not added: addWord( group ) - -def addUnibetOrReplacement( node ): - global utterance - for key in node.attributes.keys(): - if key == "untranscribed": - if oov: - utterance += " " + "" - else: - addWord( node ) - if key == "type" and (node.attributes[key].nodeValue == "fragment"): - utterance += " " + node.firstChild.nodeValue - if key == "formType": - if node.attributes[key].nodeValue == "UNIBET": - if replace: - addReplacement( node ) - else: - addWord( node ) - else: # for all other form types - # e.g. singing, babbling, kana, onomotapoeia, family-specific, letter, child-invented - # output word - addWord( node ) - -for utt in utts: - utterance = "" - start = 0 - has_timecode = False - # speaker - for key in utt.attributes.keys(): - if key == "who": - speaker=utt.attributes[key].nodeValue - spk_reco_clause = recording+" "+speaker+" "+recording+"_"+speaker - - for word in utt.childNodes: - # time code - if word.nodeType == word.ELEMENT_NODE and word.tagName == 'media': - has_timecode = True - for key in word.attributes.keys(): - if key == "start": - start = word.attributes[key].nodeValue - if key == "end": - end = word.attributes[key].nodeValue - if stm: - # Don't output if start == end; confuses downstream systems - if start != end: - print spk_reco_clause+" "+start+" "+end+" "+parts[speaker]+\ - utterance.lower().replace("_"," ").replace("-","") - sys.stdout.flush() - else: - print utterance.lower().replace("_"," ").replace("-","") - sys.stdout.flush() - utterance = "" - - # tb:wordType ("" tag) - if word.nodeType == word.ELEMENT_NODE and word.tagName == 'w': - if len(word.attributes.keys())==0: - if word.childNodes.length == 1: - addWord( word ) - else: - if replace: - addReplacement( word ) - else: - addWord( word ) - else: - addUnibetOrReplacement( word ) - # tb:element type ("" tag): - if word.nodeType == word.ELEMENT_NODE and word.tagName == 'e': - for wordlet in word.childNodes: - if wordlet.nodeType == wordlet.ELEMENT_NODE and wordlet.tagName == 'happening': - for txt in wordlet.childNodes: - thetxt = txt.nodeValue - utterance += " <" + thetxt.encode('utf8') + ">" - # tb:groupType or phoneticGroupType ("" or "" tag): - if word.nodeType == word.ELEMENT_NODE and (word.tagName == 'g' or word.tagName == 'pg'): - for group in word.childNodes: - if group.nodeType == group.ELEMENT_NODE and group.tagName == 'w': - if len(group.attributes.keys())==0: - if group.childNodes.length == 1: - addWord( group ) - else: - if replace: - addReplacement( group ) - else: - addWord( group ) - else: - # print oov (or unibet encoded word) - if oov: - utterance += " " + "" - else: - addUnibetOrReplacement( group ) - # done with utterance. if it had no timecode, was not printed(!) so - # print now - if not has_timecode: - print utterance.lower().replace("_"," ").replace("-","") - sys.stdout.flush() - utterance = "" diff --git a/utils/rttm2labels.py b/utils/rttm2labels.py deleted file mode 100644 index 0cca5f4..0000000 --- a/utils/rttm2labels.py +++ /dev/null @@ -1,41 +0,0 @@ -#! /usr/bin/python -''' -Created on Oct 4, 2014 -@author: fmetze,er1k -convert RTTM (segmented) to Audacity labels format -''' - -import sys -import datetime -import re - -def printbuf (begin, end, text): - datetime1 = datetime.datetime.utcfromtimestamp(begin) - datetime2 = datetime.datetime.utcfromtimestamp(end) - allseconds1 = 60 * datetime1.minute + 3600 * datetime1.hour + datetime1.second - allseconds2 = 60 * datetime2.minute + 3600 * datetime2.hour + datetime2.second - print "%s.%s\t%s.%s\t%s" % (allseconds1, datetime1.strftime('%f'), allseconds2, datetime2.strftime('%f'), text) - - -for l in sys.stdin: - - m = re.match("^(.*) (.*) (.*) (\S+) (\S+) (.*) (.*) (.*) (.*)$", l) - if m: - type, file = m.group(1, 2) - channel = int(m.group(3)) - starttime = float(m.group(4)) - duration = float(m.group(5)) - ortho = m.group(6) - stype = m.group(7) - name = m.group(8) - conf = m.group(9) - - printbuf (starttime, starttime+duration, name) - begin = starttime - - elif re.match(";.*", l) or re.match("#.*", l): - pass - - else: - raise Exception("cannot process line: " + l) - diff --git a/utils/rttm2scp.py b/utils/rttm2scp.py deleted file mode 100755 index f7b0008..0000000 --- a/utils/rttm2scp.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -# author: The ACLEW Team -# -# This script takes as input gold rttm file -# that transcribes a diarization, and converts it -# to a gold scp file indicating Speech Activity. -# It is necessary, to avoid overlaps between speech intervals -# and to sort the intervals by onsets. - -import os -import sys -import argparse -from intervaltree import IntervalTree, Interval -from operator import itemgetter - -def read_rttm(input_path): - """Read a RTTM file indicating gold diarization""" - with open(input_path, 'r') as fin: - # RTTM format is - # SPEAKER fname 1 onset duration spkr - rttm = fin.readlines() - #sad = IntervalTree() - all_intervals = [] - fname = "" - for line in rttm: - row = line.strip('\n').split() - fname, onset, dur = row[1], row[3], row[4] - if float(dur) == 0: - # Remove empty intervals - continue - elif float(dur) < 0: - print("{} shows an interval with negative duration." - " Please inspect file, this shouldn't happen".format( - line)) - continue - - # add interval to list - all_intervals.append((float(onset), float(onset) + float(dur))) - - # sort intervals by their onset - all_intervals.sort() - - # look at each interval, add them in growing order of onset, - # trim the beginning if it overlaps with previous interval, - # and completely delete if it is contained by the previous interval. - sad = [] - prev_on = 0 - prev_off = 0 - for onset, offset in all_intervals: - if len(sad) == 0: - # don't check anything for first interval - sad.append((onset, offset)) - prev_on = onset - prev_off = offset - continue - - if onset < prev_off: - if offset <= prev_off: - # interval is completely contained in the previous one - continue - onset = prev_off - - sad.append((onset, offset)) - prev_on = onset - prev_off = offset - - return sad, fname - -def write_scp(out_intervals, fname, output): - """Write output in SCP format""" - - with open(output, 'w') as fout: - fout.write(u'') # write empty string in case out_intervals is empty - for onset, offset in out_intervals: - fout.write(u'{fname}_{on}_{off}={fname}.fea[{on},{off}]\n'.format( - fname=fname, - on=int(onset*100), - off=int(offset*100))) - -def main(): - """Take diarization in RTTM format as input, and write """ - """SAD in scp format, with ordered intervals, as output.""" - parser = argparse.ArgumentParser( - description='Take diarization in RTTM format as input, and write ' - 'SAD in scp format, with ordered intervals, as output.', - add_help=True, - usage='%(prog)s [RTTM] [SCP]') - parser.add_argument( - 'rttm', type=str, metavar='PATH', - help='Path to the RTTM input') - parser.add_argument( - 'scp', type=str, metavar='PATH', - help='Path to the SCP output') - - args = parser.parse_args() - - sad_tree, fname = read_rttm(args.rttm) - write_scp(sad_tree, fname, args.scp) - -if __name__ == "__main__": - main() diff --git a/utils/rttm2scp.sh b/utils/rttm2scp.sh deleted file mode 100755 index 6dc3176..0000000 --- a/utils/rttm2scp.sh +++ /dev/null @@ -1,17 +0,0 @@ -#sample rttm file -#SPEAKER NDAR_TC217KM7 1 0.01 0.12 spk7 -# structure is blah filename blah onset dur blah blah speakerid blah -# -#sample scp file: -#BER_0713_07_02_21041_-1_60=BER_0713_07_02_21041.scp[-1,60] -#structure of scp file is: -#filename_begining_end=features[begining,end] - -rttm_in=$1 -basename=$2 -featfile=$3 -scp_out=$4 - - -grep SPEAKER $rttm_in | awk -v base="$basename" -v feats="$featfile" '{begg=$4*100;endd=($4+$5)*100; print base "_" begg "_" endd "="feats "[" begg "," endd "]"}' > $scp_out - diff --git a/utils/runTALNet.sh b/utils/runTALNet.sh deleted file mode 100755 index 6da0d8d..0000000 --- a/utils/runTALNet.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin - -# run 537 class classifier with hard coded models & configs found here -# assumes Python environment in /home/${user}/anaconda/ - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to classify tool (go one folder up and to 537cls) -CLASSIFY=$(dirname $BASEDIR)/TALNet - -if [ $# -ne 1 ]; then - echo "Usage: $0 " - echo "where dirname is the name of the folder" - echo "in /vagrant containing wav files" - exit 1 -fi - -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" -# Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir - - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - -# let's get our bearings: set CWD to the path of TALNet -cd $CLASSIFY - -# Iterate over files -echo "Starting" -for f in `ls ${audio_dir}/*.wav`; do - ./runTALNet.sh $f - base=$(basename $f .wav) - mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat -done - -echo "$0 finished running" diff --git a/utils/selcha2clean.sh b/utils/selcha2clean.sh deleted file mode 100755 index 379a017..0000000 --- a/utils/selcha2clean.sh +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env bash -# Given a txt file containing the following fields : onset offset transcription receiver speaker_tier (Note that eaf2txt.py generates such kind of files) -# Returns an enriched version of it by cleaning the transcription field, syllabifying (or phonemizing it), counting the number of words, and the number of syllables - -LC_CTYPE=C -#########VARIABLES -#Variables that have been passed by the user -SELFILE=$1 -ORTHO=$2 -LANG=$3 -######### - - -display_usage() { - echo "Given a txt files containing the following fields : onset offset transcription receiver speaker_tier" - echo "and a language, returns an enriched version of this file by :" - echo -e "\t 1) Cleaning the transcription field (removing human-made errors)" - echo -e "\t 2) Counting the number of words" - echo -e "\t 3) Phonemizing (if english)/Syllabifying (if spanish or tzeltal) the transcription" - echo -e "\t 4) Counting the number of syllables" - echo "usage: $0 [input] [output] [language]" - echo " input The file path where to find the input txt file (REQUIRED)." - echo " output The output path (REQUIRED)." - echo " language The language of the transcription : english, spanish or tzeltal (REQUIRED)." - exit 1 - } - -if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || ! [[ $LANG =~ ^(english|spanish|tzeltal)$ ]]; then - display_usage -fi - -# Get relative and absolute paths that we need. -DATA_DIR=/vagrant -SELFILE_ABS="$DATA_DIR/$SELFILE" -ORTHO_ABS="$DATA_DIR/$ORTHO" -DIRNAME_ABS=$(dirname "${ORTHO_ABS}") -CLEAN_TRANSCRIPT_ABS=$DIRNAME_ABS"/clean_transcript.txt" -PHONEMIZED_ABS=$DIRNAME_ABS"/phonemized.txt" -DIRNAME_REL=$(dirname "${ORTHO}") -CLEAN_TRANSCRIPT_REL=$DIRNAME_REL"/clean_transcript.txt" -PHONEMIZED_REL=$DIRNAME_REL"/phonemized.txt" - -echo "Cleaning $SELFILE" - - -### HANDLING REPETITIONS ### -###  word [x2] ### -### or [x2]   ### -cut -f 4 -d$'\t' $SELFILE_ABS | -sed "s/\[ \+/\[/g" | -sed "s/ \+\[/\[/g" | -sed -r "s/\[X([0-9]+)/\[x\1/g" | -sed "s/> \+/>/g" > ${CLEAN_TRANSCRIPT_ABS}.tmp - -python -c " -import re -for line in open(\"${CLEAN_TRANSCRIPT_ABS}.tmp\"): - - if '<' in line and '>' in line: - newline = re.sub('<(.*)>\[x([0-9]+)\]', r'\1 \2', line) - if newline != line: - n = int(newline[-2:-1]) - newline = newline[:-2]*n - else: - newline = line - else: - reg = re.sub('(.*)\[x([0-9]+)\]', r'\1\2', line) - newline=[] - for word in reg.split(): - if word[-1].isdigit(): - newline += [word[:-1]]*int(word[-1]) - else: - newline += [word] - newline = ' '.join(newline) - newline = newline.rstrip() # Remove all \newline and let the print function puts only one of them - print(newline) -" > ${CLEAN_TRANSCRIPT_ABS}2.tmp - - -### CLEAN human-made inconsistencies - -cat ${CLEAN_TRANSCRIPT_ABS}2.tmp | -sed "s/\_/ /g" | -sed '/^0(.*) .$/d' | -sed 's/\..*$//g' | #this code deletes bulletpoints (Û+numbers -sed 's/\?.*$//g' | -sed 's/\!.*$//g' | -tr -d '\"' | -tr -d '\^' | #used to be identical to previous line -tr -d '\/' | -sed 's/\+/ /g' | -tr -d '\.' | -tr -d '\?' | -tr -d '!' | -tr -d ';' | -tr -d '\<' | -tr -d '\>' | -tr -d ',' | -tr -d ':' | -tr -d '~' | -sed 's/&=[^ ]*//g' | -sed 's/&[^ ]*//g' | #delete words beginning with & ##IMPORTANT CHOICE COULD HAVE CHOSEN TO NOT DELETE SUCH NEOLOGISMS/NONWORDS -sed 's/\[[^[]*\]//g' | #delete comments -#sed 's/([^(]*)//g' | #IMPORTANT CHOICE -- UNCOMMENT THIS LINE AND COMMENT OUT THE NEXT TO DELETE MATERIAL NOTED AS NOT PRONOUNCED -sed 's/(//g' | sed 's/)//g' | #IMPORTANT CHOICE -- UNCOMMENT THIS LINE AND COMMENT OUT THE PRECEDING TO REMOVE PARENTHESES TAGGING UNPRONOUNCED MATERIAL -sed 's/xxx//g' | -sed 's/www//g' | -sed 's/XXX//g' | -sed 's/yyy//g' | -sed 's/0*//g' | -sed 's/[^ ]*@s:[^ ]*//g' | #delete words tagged as being a switch into another language -#sed 's/[^ ]*@o//g' | #delete words tagged as onomatopeic -sed 's/@[^ ]*//g' | #delete tags beginning with @ IMPORTANT CHOICE, COULD HAVE CHOSEN TO DELETE FAMILIAR/ONOMAT WORDS -sed "s/\'/ /g" | -tr -s ' ' | -sed 's/ $//g' | -sed 's/^ //g' | -sed 's/^[ ]*//g' | -sed 's/ $//g' | -#sed '/^$/d' | # We don't want to remove end lines here -sed '/^ $/d' | -sed 's/\^//g' | -sed 's/\-//g' | -sed 's/\[\=//g' | # We observed [= occurrences that we're not interested in. Has to be careful about that one -sed 's/[0-9]//g' | # We remove all of the remaining numbers -#tr -d '\t' | -awk '{gsub("\"",""); print}' > ${CLEAN_TRANSCRIPT_ABS}3.tmp - -SCRIPT_DIR=$(dirname "$0") -$SCRIPT_DIR/syllabify.sh ${CLEAN_TRANSCRIPT_REL}3.tmp ${PHONEMIZED_REL} $LANG - -## Append number of words to the clean transcription -cat ${CLEAN_TRANSCRIPT_ABS}3.tmp | awk -F'[ ]' '{print $0"\t"NF}' > ${CLEAN_TRANSCRIPT_ABS} - -## Concatenate those 2 files -python -c " -import re -transcript_f = open(\"${CLEAN_TRANSCRIPT_ABS}\") -phonemized_f = open(\"${PHONEMIZED_ABS}\") - -for transcript_l in transcript_f.readlines(): - nb_words = transcript_l.split('\t')[1] - if int(nb_words) == 0: - x=2 - print(\"\t0\t\t0\") - else: - phoneme_l = phonemized_f.readline() - transcript_l = transcript_l.rstrip() - phoneme_l = phoneme_l.rstrip() - print(transcript_l+'\t'+phoneme_l) -" > $ORTHO_ABS.tmp - -## Now we concatenate the original csv files and the clean ortho (by column) -### Extract everything except transcript column from the original file -cut -f1,2,3,5 -d$'\t' $SELFILE_ABS > ${ORTHO_ABS}2.tmp - -### Concatenate the latter columns to the clean one contained in _tmp3.txt -paste -d$'\t' ${ORTHO_ABS}2.tmp ${ORTHO_ABS}.tmp > $ORTHO_ABS - -##This is to process all the "junk" that were generated when making the -##changes from included to ortho. For e.g., the cleaning process -##generated double spaces between 2 words (while not present in -##included) -sed -i -e 's/ $//g' $ORTHO_ABS - -# Remove temporary files -rm ${DIRNAME_ABS}/*.tmp -rm ${CLEAN_TRANSCRIPT_ABS} -rm ${PHONEMIZED_ABS} \ No newline at end of file diff --git a/utils/sum-rttm.sh b/utils/sum-rttm.sh deleted file mode 100755 index 056d831..0000000 --- a/utils/sum-rttm.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# sum-rttm.sh -# -# Compute and print the number of lines in an RTTM, and the sum of durations -# for use in comparing system outputs -# -# Takes 1 argument: path to an RTTM file - -if [ $# -ne 1 ]; then - echo "Usage: $0 " - echo "where RTTMfile is an RTTM filename" - exit 1 -fi - -LINES=`cat $1 | wc -l` -SUM=`awk '{SUM+=$5} END {print SUM}' $1` - -echo -e 'LINES: '$LINES'\tDURATION SUM: '$SUM'\tFILE: '$1 diff --git a/utils/syllabify.sh b/utils/syllabify.sh deleted file mode 100755 index 0c3444f..0000000 --- a/utils/syllabify.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash -# Given an input file (containing raw text), an output one, and a language (english, spanish or tzeltal) -# Write in the output file the phonemization (if english) or the syllabification (if spanish or tzeltal) of it, -# and count the number of syllables -### Script parameters -INPUT=$1 -OUTPUT=$2 -LANG=$3 -VOWELS=$4 -### -DATA_DIR="/vagrant" -INPUT=$DATA_DIR"/"$INPUT -OUTPUT=$DATA_DIR"/"$OUTPUT -DIRNAME=${INPUT%/*} -EXTENSION=${INPUT##*.} - -display_usage() { - echo "Given the path to a file (.tmp or .txt) containing sentences, a language (english, spanish or tzeltal)," - echo "and a list of vowels, create a .syll file containing the original sentence, the phonemized/syllabified" - echo "version of it, and the number of syllables present in the original sentence." - echo "usage: $0 [input] [output] [language] [vowels]" - echo " input The file path where to find the transcription. Has to be txt or tmp extension. (REQUIRED)" - echo " output The output path. (REQUIRED)" - echo " language The language of the transcription (OPTIONAL, default = english)" - echo " vowels The list of vowels of the language if language set on spanish or tzeltal (OPTIONAL, default = aeiou)" - exit 1 - } - -if [ -z "$1" ] || [ -z "$2" ] || ! [[ $EXTENSION =~ ^(txt|tmp)$ ]]; then - display_usage -fi - -if [ -z "$3" ]; then - echo "No languages has been provided. Setting this parameter to english." - LANG="english" -fi - -if [ "$3" == "spanish" ] || [ "$3" == "tzeltal" ]; then - if [ -z "$4" ]; then - VOWELS="aeiouáéíóúü" - echo "Language set on spanish or tzeltal. But no vowels have been provided." - echo "Setting this parameter to $VOWELS" - echo $VOWELS > $DIRNAME"/"$LANG"-Vowels.txt" - fi -fi - -if [ "$3" == "english" ]; then - echo "Pĥonemizing $INPUT ..." - # Phonemize the clean version - phonemize ${INPUT} -o ${OUTPUT}.tmp -s - - - ## Append number of syllables to the phonemized transcription - cat ${OUTPUT}.tmp | awk -F- '{print $0"\t"NF-1}' > ${OUTPUT} -elif [ "$3" == "spanish" ] || [ "$3" == "tzeltal" ]; then - # Changing upper case to lower case - cat $INPUT | tr '[:upper:]' '[:lower:]' | tr 'A-ZÂÁÀÄÊÉÈËÏÍÎÖÓÔÖÚÙÛÑÇ' 'a-zâáàäêéèëïíîöóôöúùûñç' > $INPUT.tmp - # Get all the different words in the corpus - # and get the different onsets by removing what follows the first vowel - cat $INPUT.tmp | tr ' ' '\n' | sort | uniq | - sed 's/[aeiou].*//g' | grep .| uniq > $DIRNAME"/"$LANG"-ValidOnsets.txt" - SCRIPT_DIR=$(dirname "$0") - perl $SCRIPT_DIR/catspa-syllabify-corpus.pl $LANG $INPUT.tmp $OUTPUT.tmp - - ## Append number of syllables - cat $OUTPUT.tmp | awk -F'/' '{print $0"\t"NF-1}' > $OUTPUT - - rm $INPUT.tmp $DIRNAME"/"$LANG"-ValidOnsets.txt" $DIRNAME"/"$LANG"-Vowels.txt" -else - echo "Language unknown." - exit 1 -fi - -echo "Done." - -rm $OUTPUT.tmp - - diff --git a/utils/textgrid2rttm.py b/utils/textgrid2rttm.py deleted file mode 100755 index ea7e35f..0000000 --- a/utils/textgrid2rttm.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -# -# author = julien karadayi -# -# This script converts transcription in Text Grid / Praat format -# to RTTM format. This is useful for evaluating performances of -# Speech detection algorithms with the *dscore* package, -# in the DiarizationVM virtual machine. -# The 1 and 0 labels are sent to " speech ", and no label / "x" label -# are not written in output (which means it is described as "non speech") - -import os -import argparse -# from praatio import tgio -import tgt # tgt is better thant praatio for our application - # because it allows to manipulate the timestamps, - # which is something we cannot do with praatio. - - - -def textgrid2rttm(textgrid): - ''' - Take in input the path to a text grid, - and output a dictionary of lists *{spkr: [ (onset, duration) ]}* - that can easily be written in rttm format. - ''' - # init output - rttm_out = dict() - - # open textgrid - #tg = tgio.openTextgrid(textgrid) - tg = tgt.read_textgrid(textgrid) - - # loop over all speakers in this text grid - #for spkr in tg.tierNameList: - for spkr in tg.get_tier_names(): - - spkr_timestamps = [] - # loop over all annotations for this speaker - #for interval in tg.tierDict[spkr].entryList: - for _interval in tg.get_tiers_by_name(spkr): - for interval in _interval: - - bg, ed, label = interval.start_time,\ - interval.end_time,\ - interval.text - - #if label == "x": - # continue - #elif label == "1" or label == "2": - # spkr_timestamps.append((bg, ed-bg)) - spkr_timestamps.append((bg, ed-bg)) - - # add list of onsets, durations for each speakers - rttm_out[spkr] = spkr_timestamps - return rttm_out - - -def write_rttm(rttm_out, basename_whole): - ''' - take a dictionary {spkr:[ (onset, duration) ]} as input - and write on rttm output by speaker - ''' - # write one rttm file for the whole wav, indicating - # only regions of speech, and not the speaker - with open(basename_whole + '.rttm', 'w') as fout: - for spkr in rttm_out: - for bg, dur in rttm_out[spkr]: - fout.write(u'SPEAKER {} 1 {} {} ' - ' {} \n'.format( - basename_whole.split('/')[-1], bg, dur, spkr)) - - -if __name__ == '__main__': - command_example = "python textgrid2rttm.py /folder/" - parser = argparse.ArgumentParser(epilog=command_example) - parser.add_argument('input_file', - help=''' Input File ''') - parser.add_argument('output_file', - help='''Name of the output file in which to write''') - - args = parser.parse_args() - - rttm_out = textgrid2rttm(args.input_file) - write_rttm(rttm_out, args.output_file) - #if not os.path.isdir(args.output_folder_whole): - # os.makedirs(args.output_folder_whole) - - #for fold in os.listdir(args.input_folder): - # for fin in os.listdir(os.path.join(args.input_folder, fold)): - # if not fin.endswith('m1.TextGrid'): - # # read only text grids with full anotation - # # in this folder - # continue - - # tg_in = os.path.join(args.input_folder, fold, fin) - # basename_whole = os.path.join(args.output_folder_whole, - # '_'.join(fin.split('_')[0:3])) - - # # extract begining/durations of speech intervals - # rttm_out = textgrid2rttm(tg_in) - # # write 1 rttm per spkr transcribed in this text grid - # write_rttm(rttm_out, basename_whole) diff --git a/utils/tocombo2rttm.py b/utils/tocombo2rttm.py deleted file mode 100644 index 1479bdc..0000000 --- a/utils/tocombo2rttm.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/bash -# - -import os -import sys -import ipdb - -tocombo = sys.argv[1] -output = sys.argv[2] - -# read VAD input -with open(tocombo, 'r') as fin: - - trs = fin.readlines() - shortened_trs = [] - - # there's one line per 0.1 second, so aggregate to get the whole segment - # with constant state of speech/nonspeech - for i, line in enumerate(trs): - on, off, state = line.strip('\n').split(' ') - if i == 0: - first_on = on - prev_off = off - prev_state = state - elif i > 0 and i < len(trs) - 1: - if not state == prev_state: - shortened_trs.append((first_on, prev_off, prev_state)) - first_on = on - prev_off = off - prev_state = state - elif state == prev_state: - prev_off = off - prev_state = state - elif i == len(trs) - 1: - if not state == prev_state: - shortened_trs.append((first_on, prev_off, prev_state)) - shortened_trs.append((on, off, state)) - elif state == prev_state: - shortened_trs.append((first_on, off, state)) - -shortened_trs = [(float(on), float(off), int(state)) for on, off, state in shortened_trs] - -# write rttm output -fname = os.path.basename(tocombo).split('.')[0] -with open(output, 'w') as fout: - for on, off, state in shortened_trs: - if state == 1: - vad = "speech" - else: - continue - fout.write(u"SPEAKER {} {} {} {} {} {} {} {}\n".format - (fname, 1, on, off - on, "", "", vad, 1 )) diff --git a/utils/train_test_split.py b/utils/train_test_split.py deleted file mode 100755 index 64ad008..0000000 --- a/utils/train_test_split.py +++ /dev/null @@ -1,146 +0,0 @@ -import os -import glob -import shutil -import numpy as np -import argparse -from math import floor, ceil - -### GLOBAL VARIABLE -default_test_prop = 0.5 - -def _create_empty_train_test(input_folder): - """ - Given an input folder, create a train and test folder. - If these folders already exist, move their content to the input folder before creating new train and test folders. - - Parameters - ---------- - input_folder path to the input folder - - Returns - ------- - path of the train folder and path of the test folder - """ - train_folder, test_folder = os.path.join(input_folder, 'train'), os.path.join(input_folder, 'test') - - # Bring back files to the parent directory - files = glob.glob(os.path.join(train_folder, '*'))+glob.glob(os.path.join(test_folder, '*')) - for path_f in files: - basename = os.path.basename(path_f) - shutil.move(path_f, os.path.join(input_folder, basename)) - - # Delete train and test folder - if os.path.isdir(train_folder): - shutil.rmtree(train_folder) - - if os.path.isdir(test_folder): - shutil.rmtree(test_folder) - - # Create new ones - os.makedirs(train_folder) - os.makedirs(test_folder) - - return train_folder, test_folder - - -def split(input_folder, test_prop, train_prop): - """ - Given an input folder, a proportion for the test set, a proportion for the training set, split the pairs - (.wav/.rttm) into a training folder and a test folder. - - Parameters - ---------- - input_folder the path to the input folder (containing wav and rttm files) - test_prop the proportion of the data that will be included in the test set - train_prop the proportion of the data that will be included in the training set - """ - # Create empty train and test directories. - # Move their content to the parent directory if they already exist - train_folder, test_folder = _create_empty_train_test(input_folder) - - # Check for all the wav into the the input_folder - wav = np.array(glob.glob(os.path.join(input_folder, "*.wav"))) - np.random.shuffle(wav) - - n_samples = len(wav) - n_train, n_test = np.int(floor(train_prop*n_samples)), np.int(ceil(test_prop*n_samples)) - - training_idx = np.arange(n_train) - test_idx = np.arange(n_train, n_train + n_test) - - train, test = wav[training_idx], wav[test_idx] - - # Move wav files ONLY if an associated rttm is found - for train_f in train: - basename = os.path.splitext(os.path.basename(train_f))[0] - old_path = os.path.join(input_folder, basename) - new_path = os.path.join(train_folder, basename) - if os.path.exists(old_path+'.rttm'): - os.rename(old_path+'.rttm', new_path+'.rttm') - os.rename(old_path+'.wav', new_path+'.wav') - else: - print("Ignoring file %s whose rttm has not been found." % (basename+'.wav')) - - for test_f in test: - basename = os.path.splitext(os.path.basename(test_f))[0] - old_path = os.path.join(input_folder, basename) - new_path = os.path.join(test_folder, basename) - if os.path.exists(old_path+'.rttm'): - os.rename(old_path+'.rttm', new_path+'.rttm') - os.rename(old_path+'.wav', new_path+'.wav') - else: - print("Ignoring file %s whose rttm has not been found." % (basename+'.wav')) - - n_real_train = len([f for f in glob.glob(os.path.join(train_folder, '*')) if os.path.isfile(f)]) / 2 - n_real_test = len([f for f in glob.glob(os.path.join(test_folder, '*')) if os.path.isfile(f)]) / 2 - - if n_real_train == 0: - print("Warning : The training set that you generated is empty !") - if n_real_test == 0: - print("Warning : The test set that you generated is empty !") - - - - - -def main(): - parser = argparse.ArgumentParser(description="Split a folder into a train set and a test set.") - parser.add_argument('-f', '--folder', type=str, required=True, - help='path to the folder that needs to be splitted.') - parser.add_argument('--test_prop', type=float, default=None, - help='''a float between 0.0 and 1.0 representing the proportion of the - dataset to include in the test set. If not specfied, the - value is automatically set to the complement of the - --train_prop. If --train_prop is not specified, --test_prop is set to - {}'''.format(default_test_prop)) - parser.add_argument('--train_prop', default=None, type=float, - help='''a float between 0.0 and 1.0 representing the proportion of the - dataset to include in the train set. If not specified, the - value is automatically set to the complement of --test_prop''') - parser.add_argument('-r', '--random_seed', default=None, type=int, - help='Seed the generator (for reproducible results)') - args = parser.parse_args() - - if args.train_prop is None: - test_prop = default_test_prop if args.test_prop is None else args.test_prop - else: - test_prop = 1.0-args.train_prop if args.test_prop is None else args.test_prop - train_prop = args.train_prop - - if test_prop < 0.0 or test_prop > 1.0 or train_prop < 0.0 or train_prop > 1.0: - raise ValueError("The test proportion and the train proportion must be between 0 and 1") - - data_dir = "/vagrant" - input_folder = os.path.join(data_dir, args.folder) - if not os.path.isdir(input_folder): - raise ValueError("The folder that you want to split is not found. Please check the path that you provided.") - - # Set the random seed - if args.random_seed is not None: - np.random.seed(args.random_seed) - - split(input_folder, test_prop, train_prop) - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/utils/txt2rttm.py b/utils/txt2rttm.py deleted file mode 100755 index cba1ae4..0000000 --- a/utils/txt2rttm.py +++ /dev/null @@ -1,140 +0,0 @@ -""" -This script converts an txt file into a rttm one. -The txt file must contain : class onset offset. -It can be run either on a single txt file, or on a whole folder containing txt files. - -Example of use : - python tools/txt2rttm.py -i data/my_file.txt # One one file - python tools/txt2rttm.py -i data/ # On a whole folder - python tools/txt2rttm.py -i data/ -l True # On a whole folder + lena mode activated - -If the lena mode is activated, it will look for a file called tsi_key_info.xlsx in the input folder -that contains a column file_lena (storing lena names, ex : e20170722_093015_009456_2040_2100_lena) -and a column key (containg the associated ACLEW name) -About the naming convention of the output : - For each file called input_file.txt, the result will be stored in input_file.rttm -""" - -import pympi as pmp -import argparse -import os -import sys -import glob -from openpyxl import load_workbook - -def lena_to_aclew_name(tsi_key_info, basename): - """ - Convert lena names to ACLEW names. - - Parameters - ---------- - tsi_key_info : the path to the tsi_key_infos.xlsx file - basename : the basename of the txt file that needs to be converted. This name follows the LENA naming convention. - - Returns - ------- - The name respecting the ACLEW naming convention - """ - onset = basename.split('_')[3] - basename_beg = '_'.join(basename.split('_')[0:3]) # Get the first 3 elements - wb = load_workbook(tsi_key_info,data_only=True) - wb = wb.worksheets[0] - first_row = wb.rows[0] - file_lena_num_col = None - key_num_col = None - - # Get num of the column - for idx in range(0, len(first_row)): - cell = first_row[idx] - if cell.value == "file_lena": - file_lena_num_col = idx - if cell.value == "key": - key_num_col = idx - - # Loop through the cells to look for the basename - if file_lena_num_col is not None and key_num_col is not None: - for row in wb.rows[1:]: - file_lena = row[file_lena_num_col].value - key_num = row[key_num_col].value - if file_lena == basename_beg: - child, good_date = key_num.split('_') - return '_'.join(['lena',child,good_date,onset]) - - -def txt2rttm(path_to_txt, output_folder, labels_to_keep, lena_mode=False, only_first_letter=False): - """ - Convert an txt file to the rttm format by extracting the - Parameters - ---------- - path_to_txt : path to the txt file. - output_folder : where to store the output files - - Write a rttm whose name is the same than the txt's one in output_folder - """ - basename = os.path.splitext(os.path.basename(path_to_txt))[0] - if lena_mode: - dirname = os.path.dirname(path_to_txt) - output_basename = lena_to_aclew_name(os.path.join(dirname, 'tsi_key_info.xlsx'), basename) - output_path = os.path.join(dirname, output_basename + '.rttm') - # Change the output_basename because we don't want to write the model prefix lena_ - # in the rttm fil - output_basename = '_'.join(output_basename.split('_')[1:]) - else: - output_path = os.path.join(output_folder, basename + '.rttm') - output_basename = os.path.splitext(os.path.basename(output_path))[0] - - with open(path_to_txt, 'r') as txt: - with open(output_path, 'w') as rttm: - for line in txt: - activity, onset, offset = line.rstrip().split('\t') - dur = float(offset)-float(onset) - - if lena_mode and activity in labels_to_keep: - if only_first_letter: - activity = activity[0] - rttm.write("SPEAKER %s 1 %s %s %s \n" % (output_basename, onset, str(dur), activity)) - elif not lena_mode: - rttm.write("SPEAKER %s 1 %s %s %s \n" % (output_basename, onset, str(dur), activity)) - - -def main(): - parser = argparse.ArgumentParser(description="convert .txt into .rttm") - parser.add_argument('-i', '--input', type=str, required=True, - help="path to the input .txt file or the folder containing txt files.") - parser.add_argument('-l', '--lena_mode', type=bool, required=False, default=False, - help="indicates whether to use this script in the lena mode or not. If the lena mode" - "is activated, it will read the table tsi_key_info.xlsx in the input folder and" - "will change the naming convention of the output in consequences") - parser.add_argument('-t', '--to_keep', nargs='+', type=str, required=True, - help='List of labels that needs to be kept.') - parser.add_argument('-fl', '--only_first_letter', type=bool, default=False, - help='Indicates if the output labels will be produced by keeping only the first letter' - 'of the original labels.') - args = parser.parse_args() - - - # Initialize the output folder as the same folder than the input - # if not provided by the user. - if args.input[-4:] == '.txt': - output = os.path.dirname(args.input) - else: - output = args.input - - data_dir = '/vagrant' - args.input = os.path.join(data_dir, args.input) - output = os.path.join(data_dir, output) - - if not os.path.isdir(output): - os.mkdir(output) - - if args.input[-4:] == '.txt': # A single file has been provided by the user - txt2rttm(args.input, output, args.to_keep, args.lena_mode, args.only_first_letter) - else: # A whole folder has been provided - txt_files = glob.iglob(os.path.join(args.input, '*.txt')) - for txt_path in txt_files: - print("Processing %s" % txt_path) - txt2rttm(txt_path, output, args.to_keep, args.lena_mode, args.only_first_letter) - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/utils/vad_segmenter_aclew.conf.txt b/utils/vad_segmenter_aclew.conf.txt deleted file mode 100644 index 35f1636..0000000 --- a/utils/vad_segmenter_aclew.conf.txt +++ /dev/null @@ -1,62 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -///////// > openSMILE LSTM-RNN voice activity detector< ////////////////// -///////// ////////////////// -///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// -///////// All rights reserverd. ////////////////// -/////////////////////////////////////////////////////////////////////////////////////// - - -[componentInstances:cComponentManager] -instance[dataMemory].type = cDataMemory -instance[waveSource].type = cWaveSource - -[waveSource:cWaveSource] -writer.dmLevel = wave -filename = \cm[inputfile(I){input.wav}:name of input file] -monoMixdown = 1 -start = 0 -end = -1 -endrel = 0 -noHeader = 0 -buffersize_sec = 10 - - - ; inculdes a VAD module -\{vad_opensource.conf.inc} - ; and a turn detector module -\{turnDetector.conf.inc} -;\{\cm[turnDetector(T){turnDetector.conf}:filename of turn detector config file]} - - -[componentInstances:cComponentManager] - ; the wave file segmenter -instance[waveSinkCut].type = cWaveSinkCut - ; optional: CSV output -instance[csvSink].type = cCsvSink -printLevelStats = 0 - -[waveSinkCut:cWaveSinkCut] -reader.dmLevel = frames -fileBase = \cm[waveoutput(W){?}:prefix of WAV output files] -fileExtension = .wav -fileNameFormatString = %s%04d%s -startIndex = 1 -preSil = 0.1 -postSil = 0.1 -multiOut = 1 -sampleFormat = 16bit -; sample rate should be read from the input level -; automatically. In some cases this does not work due to -; round-off errors, so you can force it manually here: -;forceSampleRate = 44100 -;forceSampleRate = 16000 -saveSegmentTimes = \cm[saveSegmentTimes{times.dat}:file to save segment times to] -showSegmentTimes = 1 - -[csvSink:cCsvSink] -reader.dmLevel=vad_VAD_voice -filename= \cm[csvoutput{?}:name of VAD output file] -printHeader = 0 -timestamp = 1 -number = 0 - diff --git a/utils/yuniSeg.sh b/utils/yuniSeg.sh deleted file mode 100644 index 976b135..0000000 --- a/utils/yuniSeg.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin - -# run YuniSeg with hard coded models & configs found here and in /vagrant -# assumes Python environment in /home/${user}/ - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to YuniSeg (go one folder up and to Yunitator) -YUNITATDIR=$(dirname $BASEDIR)/Yunitator -# let's get our bearings: set CWD to the path of Yunitator -cd $YUNITATDIR - -if [ $# -ne 2 ]; then - echo "Usage: $0 " - echo "where dirname is the name of the folder" - echo "containing the wav and rttm files" - echo "and SADtoolname is the SAD to use." - echo "Choices are:" - echo " ldc_sad" - echo " noisemes" - echo " tocombosad" - echo " opensmile" - echo " textgrid" - echo " eaf" - echo " rttm" - exit 1 -fi - -audio_dir=/vagrant/$1 -trs_format=$2 - -# Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir - - -# this is set in user's login .bashrc, but may not be if run from outside VM -export PATH=/home/${user}/anaconda/bin:$PATH - - -# Iterate over files -echo "Starting" -for f in `ls $audio_dir/*.wav`; do - filename=$(basename "$f") - basename="${filename%.*}" - echo "treating $basename" - - # output filename produced by runYuniSegs - outfile=$audio_dir/$basename.yuniSeg.rttm - - case $trs_format in - "ldc_sad") - sys="ldcSad" - model_prefix="ldc_sad_" - ;; - "") - # add default case - echo "Warning: no SAD source specified, using Noisemes by default, at your own risk." - echo "Next time, please specify SAD." - sys="noisemesSad" - model_prefix="noisemes_sad_" - ;; - "noisemes") - sys="noisemesSad" - model_prefix="noisemes_sad_" - ;; - "tocombosad") - sys="tocomboSad" - model_prefix="tocombo_sad_" - ;; - "opensmile") - sys="opensmileSad" - model_prefix="opensmile_sad_" - ;; - "textgrid") - sys="goldSad" - model_prefix=${trs_format}_ - $conda_dir/python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid ${trs_format}_${basename}.rttm - ;; - "eaf") - sys="goldSad" - model_prefix=${trs_format}_ - $conda_dir/python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf ${trs_format}_${basename}.rttm - ;; - "rttm") - sys="goldSad" - model_prefix="" - ;; - *) - echo "ERROR: please choose SAD system between:" - echo " ldc_sad" - echo " noisemes" - echo " tocombosad" - echo " opensmile" - echo " textgrid" - echo " eaf" - echo " rttm" - echo "Now exiting..." - exit 1 - ;; - esac - - ./runYuniSegs.sh $f $audio_dir/${model_prefix}${basename}.rttm - cp $outfile $audio_dir/yuniseg_${sys}_${basename}.rttm - - if [ ! -s $audio_dir/yuniseg_${sys}_${basename}.rttm ]; then - # if diarization failed, still write an empty file... - touch $audio_dir/yuniseg_${sys}_${basename}.rttm - fi -done - -echo "$0 finished running" - -# simply remove hyp and feature -rm $outfile -rm -rf $audio_dir/Yunitemp From 068e074aa55b37e60aa98b02655c7531370d1460 Mon Sep 17 00:00:00 2001 From: alecristia Date: Tue, 13 Nov 2018 16:36:51 +0100 Subject: [PATCH 042/299] skeleton --- docs/source/instructions_for_contributors.md | 83 +++++++++++--------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index 17babd0..c73f5f2 100644 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -3,49 +3,36 @@ ## Before you start -1. Install DiViMe as per the installation instructions. +Before you start, you'll just generate the VM environment to check you can get your tool working as expected. -2. Run the test.sh routine and the test-daylong.sh routine. They will each download audio recordings and annotations that you will need to make sure your tool is compatible with the rest of the work flow. +1. Install DiViMe as per the installation instructions, including the `vagrant up` that wakes the machine up. -3. Open Vagrantfile in any text editor and add there what needs to be installed to get your tool to work in this environment. Typically, you'll have something like - -`$ git clone http://github.com/srvk/OpenSAT` +2. Run the test.sh routine routine. It downloads audio recordings and annotations that you will need to make sure your tool is compatible with the rest of the work flow. Additionally, it will help you spot any issues there may be. ## Adapting your tool to the VM environment -4. STEPS MISSING HERE -- EXPLAIN HOW TO TEST THAT TOOL WORKS IN ENVIRONMENT - -## Integrating your tool into the DiViMe workflow - -6. Write a wrapper allowing users to call on your tool. - -- The wrapper should be written in bash, and it should be called TOOLNAME_STAGE.sh. -- You choose your own tool's name. Use anything you want except the other names already in use. -- The fixed stages names are: sad (for both speech activity detection and voice activity detection), diar (for speaker diarization and role assignment), and add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use sad) or the talker role input (then use add type). -- Read on for input/output requirements depending on stage. -- This flowchart may help: https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9 - +1. For this section, you'll be working entirely within the machine. So start by doing `vagrant ssh` to log in. -5. All tools should read in all .wav files inside data/ and, optionally, associated annotation files, which are in rttm format. +2. Ideally, you will put your tool somewhere public, so that anyone rebuilding the machine will get access to it. You don't need to make your code open source. You can also share a binary executable version (ask us for instructions if you need them). -6. All tools should write into the data/ folder an annotation file for each .wav file; this annotation file should respect the rttm format. - -6. Your tool may generate two types of ancillary files: Intermediary representation files, such as features extracted from the wav files; and log files, with detailed information of what was done and how. Intermediary representation files should be deleted. Log files may be stored in the temp/ folder, which will only be accessible from within the VM, and should be deleted if they are large (>5MB). As a reminder, our target user may not be technically advanced, and thus including long technical logs may do more to confuse than to help. - -7. For all annotations, we are using the following rttm format throughout (From NIST's 2009 eval plan https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf): - -** todo: this example is bad: cells are not intelligible and the example in fact violates rttm recommendations** +3. Install your code in the location where it will be within the machine: ``` -SPEAKER file17 1 0.00 0.77 speech -SPEAKER file17 1 0.77 0.61 nonspeech -SPEAKER file17 1 1.38 2.14 speech -SPEAKER file17 1 3.52 0.82 nonspeech +cd repos +git clone http://github.com/srvk/OpenSAT ``` -The columns are: Type file chnl tbeg tdur ortho stype name conf Slat +4. Write a wrapper allowing users to call on your tool. -8. If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named toolnameSad_filename.rttm, which will look like this: +- The wrapper should be written in bash, and it should be called toolnameStage.sh. +- You choose your own tool's name. Use anything you want except the other names already in use. +- The fixed stages names are: sad (for both speech activity detection and voice activity detection), diar (for speaker diarization and role assignment), and add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use sad) or the talker role input (then use add). +- Read on for input/output requirements depending on stage. +- This flowchart may help: https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9 +- The wrapper should process all .wav files inside data/ and, optionally, associated annotation files, which are in rttm format. (For more information on the rttm output, read [NIST's 2009 eval plan](https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf)) +- The wrapper should write its main output into the data/ folder. Typically, this will be one annotation file for each .wav file. If so, this annotation file should respect the rttm format. Additionally, it should be named as follows: toolnameStage_file_original_name.rttm +- You probably also generate two types of ancillary files: Intermediary representation files, such as features extracted from the wav files; and log files, with detailed information of what was done and how. Both should be stored in the /vagrant/data/temp/ folder. At the end of the process, Intermediary representation files should be deleted at the end of your wrapper. Log files should also be deleted if they are large (>5MB). As a reminder, our target user may not be technically advanced, and thus including long technical logs may do more to confuse than to help. +- If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named toolnameSad_filename.rttm, which will look like this: ``` SPEAKER file17 1 0.00 0.77 speech @@ -53,13 +40,20 @@ SPEAKER file17 1 1.38 2.14 speech ``` -9. If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the immediately previous step. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then use the default sad/vad (see end of instructions for list of default tools). In both cases, your wrapper should first check these sad/vad exist and if not, execute a command to generate them (see Instructions for use for instructions on how to use DiViMe's included tools). +- If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the previous bulletpoint. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then use the default sad/vad (see end of instructions for list of default tools). In both cases, your wrapper should first check these sad/vad exist and if not, execute a command to generate them (see Instructions for use for instructions on how to use DiViMe's included tools). Your diarization-type tool should return one rttm per audio file, named toolnameDiar_filename.rttm, which must look like this: -10. Your SAD-type tool should return one rttm per audio file, named toolname_diar_filename.rttm, which must look like this: - -** todo: copy-paste the example above, remove all information not present at diar or role stage ** +** FIX this table ** +``` +SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 +SPEAKER family 1 4.6 1.2 background 0.327808111906 +SPEAKER family 1 5.8 1.1 speech 0.430758684874 +SPEAKER family 1 6.9 1.2 background 0.401730179787 +SPEAKER family 1 8.1 0.7 speech 0.407463937998 +SPEAKER family 1 8.8 1.1 background 0.37258502841 +SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +``` -10. If your tool is not a VAD/SAD but it is a classifier that assumes only raw acoustic input, then declare it as a sad/vad, and follow the instructions for vad/sad above, except that you'll adapt the rttm output to the classes you typically have. For example, one tool classifies audio into noiseme categories. It returns rttm's like this one: +- If your tool is not a VAD/SAD but it is a classifier that assumes only raw acoustic input, then declare it as a sad/vad, and follow the instructions for vad/sad above, except that you'll adapt the rttm output to the classes you typically have. For example, one tool classifies audio into noiseme categories. It returns rttm's like this one: ** todo: put example here, but make sure that the "type" class is not violated by the contents of the subtype column. For example, this is bad (noise should not be class SPEAKER):** @@ -73,8 +67,23 @@ SPEAKER family 1 8.8 1.1 background 0.37258502 SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 ``` -11. If your tool is a classifier that works only on a subtype of speaker (e.g., only on children's speech), then assume that each wav is accompanied by an rttm that has this information noted in column XX. +- If your tool is a classifier that works only on a subtype of speaker (e.g., only on children's speech), then assume that each wav is accompanied by an rttm that has this information noted in column XX. ** todo: add default tool section** ** todo: address "process multiple files in parallel, if possible (like using sbatch?)"** + + +## Integrating your tool into DiViMe for real + +fork our divime repo +add a line to clone your repo +add lines to add to the environment any dependencies needed +add an md with short description, citation, and instructions for use +pull request + +fork our launcher repo +add your wrapper +add a section to the test specific to your tool +pull request + From b6b891ed07399f35e23970299f10ff88eb4abb1a Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 13 Nov 2018 13:11:38 -0500 Subject: [PATCH 043/299] example +consistent capitalization -> wrapper name --- docs/source/instructions_for_contributors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index c73f5f2..fbac3a6 100644 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -26,7 +26,7 @@ git clone http://github.com/srvk/OpenSAT - The wrapper should be written in bash, and it should be called toolnameStage.sh. - You choose your own tool's name. Use anything you want except the other names already in use. -- The fixed stages names are: sad (for both speech activity detection and voice activity detection), diar (for speaker diarization and role assignment), and add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use sad) or the talker role input (then use add). +- The fixed stages names are: Sad (for both speech activity detection and voice activity detection), Diar (for speaker diarization and role assignment), and Add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use sad) or the talker role input (then use add). So for a tool with the toolname 'noisemes' for example, that performs speech activity detection, it's wrapper would be called `noisemesSad.sh` - Read on for input/output requirements depending on stage. - This flowchart may help: https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9 - The wrapper should process all .wav files inside data/ and, optionally, associated annotation files, which are in rttm format. (For more information on the rttm output, read [NIST's 2009 eval plan](https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf)) From 0f50bebf746034d539c1e0e44e7255d1f9e7941d Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 13 Nov 2018 14:40:53 -0500 Subject: [PATCH 044/299] Add more naming convention examples --- docs/source/instructions_for_contributors.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index fbac3a6..9491064 100644 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -26,13 +26,14 @@ git clone http://github.com/srvk/OpenSAT - The wrapper should be written in bash, and it should be called toolnameStage.sh. - You choose your own tool's name. Use anything you want except the other names already in use. -- The fixed stages names are: Sad (for both speech activity detection and voice activity detection), Diar (for speaker diarization and role assignment), and Add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use sad) or the talker role input (then use add). So for a tool with the toolname 'noisemes' for example, that performs speech activity detection, it's wrapper would be called `noisemesSad.sh` +- The fixed stages names are: Sad (for both speech activity detection and voice activity detection), Diar (for speaker diarization and role assignment), and Add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use Sad) or the talker role input (then use Add). So for a tool with the toolname 'noisemes' for example, that performs speech activity detection, it's wrapper would be called `noisemesSad.sh` - Read on for input/output requirements depending on stage. - This flowchart may help: https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9 - The wrapper should process all .wav files inside data/ and, optionally, associated annotation files, which are in rttm format. (For more information on the rttm output, read [NIST's 2009 eval plan](https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf)) -- The wrapper should write its main output into the data/ folder. Typically, this will be one annotation file for each .wav file. If so, this annotation file should respect the rttm format. Additionally, it should be named as follows: toolnameStage_file_original_name.rttm +- The wrapper should write its main output into the data/ folder. Typically, this will be one annotation file for each .wav file. If so, this annotation file should respect the rttm format, in particular using the space character (not tab) as a field separator. +- Output files should be named as follows: toolnameStage_basename.rttm. So for example a tool named "noisemes" (toolname="noisemes") that does speech activity (Stage="Sad"), and an input file "RTM20.wav" (basename="RTM20" like the output of the linux command `basename RTM20.wav .wav`), the output filename would be `noisemesSad_RTM20.rttm` - You probably also generate two types of ancillary files: Intermediary representation files, such as features extracted from the wav files; and log files, with detailed information of what was done and how. Both should be stored in the /vagrant/data/temp/ folder. At the end of the process, Intermediary representation files should be deleted at the end of your wrapper. Log files should also be deleted if they are large (>5MB). As a reminder, our target user may not be technically advanced, and thus including long technical logs may do more to confuse than to help. -- If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named toolnameSad_filename.rttm, which will look like this: +- If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named according to the convention above, which will look like this: ``` SPEAKER file17 1 0.00 0.77 speech @@ -40,7 +41,7 @@ SPEAKER file17 1 1.38 2.14 speech ``` -- If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the previous bulletpoint. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then use the default sad/vad (see end of instructions for list of default tools). In both cases, your wrapper should first check these sad/vad exist and if not, execute a command to generate them (see Instructions for use for instructions on how to use DiViMe's included tools). Your diarization-type tool should return one rttm per audio file, named toolnameDiar_filename.rttm, which must look like this: +- If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the previous bulletpoint. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then use the default sad/vad (see end of instructions for list of default tools). In both cases, your wrapper should first check these sad/vad exist and if not, execute a command to generate them (see Instructions for use for instructions on how to use DiViMe's included tools). Your diarization-type tool should return one rttm per audio file, following the naming convention toolnameDiar_basename.rttm. For example a diarization tool named "talker" with input file "RTM20.wav" would produce the output filename `talkerDiar_RTM20.rttm`. The output RTTM must look like this: ** FIX this table ** ``` From ab6134cf09158a98a5cb913ef98ff9b2a56de192 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 14 Nov 2018 10:24:11 -0500 Subject: [PATCH 045/299] Add double spaces as line breaks in last section --- docs/source/instructions_for_contributors.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index 9491064..8862f54 100644 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -77,14 +77,14 @@ SPEAKER family 1 9.9 1.7 noise_ongoing 0.31518515 ## Integrating your tool into DiViMe for real -fork our divime repo -add a line to clone your repo -add lines to add to the environment any dependencies needed -add an md with short description, citation, and instructions for use -pull request - -fork our launcher repo -add your wrapper -add a section to the test specific to your tool -pull request +fork our divime repo +add a line to clone your repo +add lines to add to the environment any dependencies needed +add an md with short description, citation, and instructions for use +pull request + +fork our launcher repo +add your wrapper +add a section to the test specific to your tool +pull request From 6f9c307a45deb67c8152582218cb23dd2721287e Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 14 Nov 2018 12:52:29 -0500 Subject: [PATCH 046/299] Fix permissions on ~/repos This allows 'vagrant up' provisioning to complete. --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 1a1d5ea..1a70bb4 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -140,7 +140,7 @@ Vagrant.configure("2") do |config| # Install OpenSMILE echo "Installing OpenSMILE" - mkdir -p /home/${user}/repos/ + su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz tar zxvf OpenSMILE-2.1.tar.gz From 941df11c87f54c7fc3c4cb5854c4a125d93549b6 Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 14 Nov 2018 19:14:06 +0100 Subject: [PATCH 047/299] in progress --- docs/source/instructions_for_contributors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index c73f5f2..cfce04d 100644 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -27,8 +27,8 @@ git clone http://github.com/srvk/OpenSAT - The wrapper should be written in bash, and it should be called toolnameStage.sh. - You choose your own tool's name. Use anything you want except the other names already in use. - The fixed stages names are: sad (for both speech activity detection and voice activity detection), diar (for speaker diarization and role assignment), and add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use sad) or the talker role input (then use add). -- Read on for input/output requirements depending on stage. - This flowchart may help: https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9 +- The wrapper will take at least one argument, namely the name of the folder where the data are stored. Most users will pass "data/" - The wrapper should process all .wav files inside data/ and, optionally, associated annotation files, which are in rttm format. (For more information on the rttm output, read [NIST's 2009 eval plan](https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf)) - The wrapper should write its main output into the data/ folder. Typically, this will be one annotation file for each .wav file. If so, this annotation file should respect the rttm format. Additionally, it should be named as follows: toolnameStage_file_original_name.rttm - You probably also generate two types of ancillary files: Intermediary representation files, such as features extracted from the wav files; and log files, with detailed information of what was done and how. Both should be stored in the /vagrant/data/temp/ folder. At the end of the process, Intermediary representation files should be deleted at the end of your wrapper. Log files should also be deleted if they are large (>5MB). As a reminder, our target user may not be technically advanced, and thus including long technical logs may do more to confuse than to help. From cc60658014f94681284346d9a0c01d77777d3139 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Thu, 15 Nov 2018 19:22:49 +0000 Subject: [PATCH 048/299] make tests work --- Vagrantfile | 26 ++++++++++++++++++-------- conf/.theanorc | 13 +++++++++++++ 2 files changed, 31 insertions(+), 8 deletions(-) mode change 100644 => 100755 Vagrantfile create mode 100755 conf/.theanorc diff --git a/Vagrantfile b/Vagrantfile old mode 100644 new mode 100755 index 1a70bb4..14d2ac4 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,3 +1,4 @@ +# coding: utf-8 # -*- mode: ruby -*- # vi: set ft=ruby @@ -140,10 +141,13 @@ Vagrant.configure("2") do |config| # Install OpenSMILE echo "Installing OpenSMILE" - su ${user} -c "mkdir -p /home/${user}/repos/" + su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz tar zxvf OpenSMILE-2.1.tar.gz + # install SMILExtract system-wide + cp openSMILE-2.1.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin + chmod +x /usr/local/bin/SMILExtract rm OpenSMILE-2.1.tar.gz # optionally Install HTK (without it, some other tools will not work) @@ -166,22 +170,21 @@ Vagrant.configure("2") do |config| cd /home/${user}/repos/ # Get OpenSAT=noisemes and dependencies - git clone http://github.com/srvk/OpenSAT --branch v1.0 - git clone http://github.com/yajiemiao/pdnn - git clone http://github.com/srvk/coconut + git clone http://github.com/srvk/OpenSAT # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" - cp /vagrant/.theanorc /home/${user}/ + cp /vagrant/conf/.theanorc /home/${user}/ export PATH=/home/${user}/anaconda/bin:$PATH su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install ldc-sad - #git clone http://github.com/srvk/ldc_sad_hmm --branch v1.0 + # run this version 'by hand' in the VM in repos/ using your github username and password + #git clone http://github.com/aclew/ldc_sad_hmm # Install Yunitator and dependencies - git clone https://github.com/srvk/Yunitator --branch v1.0 + git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" @@ -195,7 +198,7 @@ Vagrant.configure("2") do |config| # Install eval - git clone http://github.com/srvk/dscore --branch v1.0 + git clone http://github.com/srvk/dscore #--branch v1.0 # Phonemizer installation sudo apt-get install -y festival espeak @@ -218,6 +221,13 @@ Vagrant.configure("2") do |config| # and recommonmark (needed to make html in docs/) su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" + # OpenSAT (noisemes) and possibly other tools depend on tools ~/G/. + # So let's not do away with it. +# cd /home/${user} +# mkdir -p G +# cd G +# ln -s /home/vagrant/repos/pdnn . +# ln -s /home/vagrant/repos/coconut . # Some cleanup sudo apt-get autoremove -y diff --git a/conf/.theanorc b/conf/.theanorc new file mode 100755 index 0000000..af1aa2a --- /dev/null +++ b/conf/.theanorc @@ -0,0 +1,13 @@ +[global] +floatX = float32 +device = cpu + +[nvcc] +#fastmath = True + +[lib] +cnmem = 0.9 + +[cuda] +root = /opt/cuda-8.0 +#root = /usr/local/cuda-7.0 From b776be2e36616d4c352865b364a07f0f6f0dda82 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 19 Nov 2018 16:28:40 +0100 Subject: [PATCH 049/299] combining 3 repos in one --- .gitignore | 35 +++++++++++++++++++++++++++++++++++ launcher | 1 + utils | 1 + 3 files changed, 37 insertions(+) create mode 160000 launcher create mode 160000 utils diff --git a/.gitignore b/.gitignore index fcf347b..e6f8acd 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,38 @@ docs/build/* docs/.DS_Store ldc_sad_hmm/ HTK.tar.gz + + +# History files +.Rhistory +.Rapp.history + +# Session Data files +.RData + +# Example code in package build process +*-Ex.R + +# Output files from R CMD build +/*.tar.gz + +# Output files from R CMD check +/*.Rcheck/ + +# RStudio files +.Rproj.user/ + +# produced vignettes +vignettes/*.html +vignettes/*.pdf + +# OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 +.httr-oauth + +# knitr and R markdown default cache directories +/*_cache/ +/cache/ + +# Temporary files created by R markdown +*.utf8.md +*.knit.md diff --git a/launcher b/launcher new file mode 160000 index 0000000..f2a820c --- /dev/null +++ b/launcher @@ -0,0 +1 @@ +Subproject commit f2a820c01966bf11df501077b0de89d5bd3b0dd1 diff --git a/utils b/utils new file mode 160000 index 0000000..0ed7abd --- /dev/null +++ b/utils @@ -0,0 +1 @@ +Subproject commit 0ed7abd67daac8a46bff31e66e8f83475fce3bea From 97025f81582596b531b7cba7c58d3be44f69f21d Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 19 Nov 2018 18:24:59 +0000 Subject: [PATCH 050/299] populate launcher & utils --- .gitignore | 0 .theanorc | 0 Dockerfile | 0 LICENSE | 0 README.md | 0 Vagrantfile | 10 +- data/.gitignore | 0 docs/Makefile | 0 docs/make.bat | 0 docs/source/conf.py | 0 docs/source/diartk.md | 0 docs/source/eval.md | 0 docs/source/extra-tools.md | 0 docs/source/index.rst | 0 docs/source/initial_questions.md | 0 docs/source/install.md | 0 docs/source/instructions_for_contributors.md | 0 docs/source/ldcSad.md | 0 docs/source/noisemesSad.md | 0 docs/source/opensmileSad.md | 0 docs/source/references.md | 0 docs/source/tocomboSad.md | 0 docs/source/tool_doc.md | 0 docs/source/troubleshoot.md | 0 docs/source/usage.md | 0 docs/source/yunitator.md | 0 launcher | 1 - launcher/537classify.sh | 48 ++ launcher/README.md | 37 ++ launcher/diartk.sh | 117 +++++ launcher/eval.sh | 61 +++ launcher/evalDiar.sh | 123 +++++ launcher/evalSAD.sh | 83 +++ launcher/ldcSad.sh | 47 ++ launcher/noisemesSad.sh | 80 +++ launcher/opensmileSad.sh | 60 +++ launcher/test.sh | 229 ++++++++ launcher/tocomboSad.sh | 78 +++ launcher/yunitate.sh | 57 ++ test.wav | Bin test2.mp3 | Bin test2.rttm | 0 utils | 1 - utils/.gitignore | 33 ++ utils/README.md | 4 + utils/adjust_timestamps.py | 308 +++++++++++ utils/catspa-syllabify-corpus.pl | 93 ++++ utils/change_tsi_lena_names.py | 43 ++ utils/chat2stm.sh | 53 ++ utils/check_folder.sh | 35 ++ utils/chunk.sh | 61 +++ utils/create_ref_sys.sh | 76 +++ utils/diarization.sh | 184 +++++++ utils/eaf2enriched_txt.sh | 37 ++ utils/eaf2txt.py | 89 ++++ utils/elan2rttm.py | 75 +++ utils/empty_transcription.sh | 15 + utils/extract_stats_chi.py | 124 +++++ utils/frame_cutter.py | 220 ++++++++ utils/generate_html.py | 44 ++ utils/get_aclewStarter.sh | 58 ++ utils/high_volubility.py | 526 +++++++++++++++++++ utils/html_python/__init__.py | 0 utils/html_python/files_page.py | 179 +++++++ utils/html_python/models_page.py | 103 ++++ utils/html_python/page.py | 30 ++ utils/html_python/style_css.py | 33 ++ utils/html_python/utils.py | 164 ++++++ utils/its2rttm.py | 80 +++ utils/its2rttm.sh | 23 + utils/lab2rttm.sh | 30 ++ utils/make_big_corpus.sh | 101 ++++ utils/noisemes_full.sh | 80 +++ utils/parse_cha_xml.py | 191 +++++++ utils/rttm2labels.py | 41 ++ utils/rttm2scp.py | 102 ++++ utils/rttm2scp.sh | 17 + utils/runTALNet.sh | 47 ++ utils/selcha2clean.sh | 169 ++++++ utils/sum-rttm.sh | 19 + utils/syllabify.sh | 77 +++ utils/textgrid2rttm.py | 103 ++++ utils/tocombo2rttm.py | 52 ++ utils/train_test_split.py | 146 +++++ utils/txt2rttm.py | 140 +++++ utils/vad_segmenter_aclew.conf.txt | 62 +++ utils/yuniSeg.sh | 121 +++++ 87 files changed, 5211 insertions(+), 9 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 .theanorc mode change 100644 => 100755 Dockerfile mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 data/.gitignore mode change 100644 => 100755 docs/Makefile mode change 100644 => 100755 docs/make.bat mode change 100644 => 100755 docs/source/conf.py mode change 100644 => 100755 docs/source/diartk.md mode change 100644 => 100755 docs/source/eval.md mode change 100644 => 100755 docs/source/extra-tools.md mode change 100644 => 100755 docs/source/index.rst mode change 100644 => 100755 docs/source/initial_questions.md mode change 100644 => 100755 docs/source/install.md mode change 100644 => 100755 docs/source/instructions_for_contributors.md mode change 100644 => 100755 docs/source/ldcSad.md mode change 100644 => 100755 docs/source/noisemesSad.md mode change 100644 => 100755 docs/source/opensmileSad.md mode change 100644 => 100755 docs/source/references.md mode change 100644 => 100755 docs/source/tocomboSad.md mode change 100644 => 100755 docs/source/tool_doc.md mode change 100644 => 100755 docs/source/troubleshoot.md mode change 100644 => 100755 docs/source/usage.md mode change 100644 => 100755 docs/source/yunitator.md delete mode 160000 launcher create mode 100755 launcher/537classify.sh create mode 100755 launcher/README.md create mode 100755 launcher/diartk.sh create mode 100755 launcher/eval.sh create mode 100755 launcher/evalDiar.sh create mode 100755 launcher/evalSAD.sh create mode 100755 launcher/ldcSad.sh create mode 100755 launcher/noisemesSad.sh create mode 100755 launcher/opensmileSad.sh create mode 100755 launcher/test.sh create mode 100755 launcher/tocomboSad.sh create mode 100755 launcher/yunitate.sh mode change 100644 => 100755 test.wav mode change 100644 => 100755 test2.mp3 mode change 100644 => 100755 test2.rttm delete mode 160000 utils create mode 100755 utils/.gitignore create mode 100755 utils/README.md create mode 100755 utils/adjust_timestamps.py create mode 100755 utils/catspa-syllabify-corpus.pl create mode 100755 utils/change_tsi_lena_names.py create mode 100755 utils/chat2stm.sh create mode 100755 utils/check_folder.sh create mode 100755 utils/chunk.sh create mode 100755 utils/create_ref_sys.sh create mode 100755 utils/diarization.sh create mode 100755 utils/eaf2enriched_txt.sh create mode 100755 utils/eaf2txt.py create mode 100755 utils/elan2rttm.py create mode 100755 utils/empty_transcription.sh create mode 100755 utils/extract_stats_chi.py create mode 100755 utils/frame_cutter.py create mode 100755 utils/generate_html.py create mode 100755 utils/get_aclewStarter.sh create mode 100755 utils/high_volubility.py create mode 100755 utils/html_python/__init__.py create mode 100755 utils/html_python/files_page.py create mode 100755 utils/html_python/models_page.py create mode 100755 utils/html_python/page.py create mode 100755 utils/html_python/style_css.py create mode 100755 utils/html_python/utils.py create mode 100755 utils/its2rttm.py create mode 100755 utils/its2rttm.sh create mode 100755 utils/lab2rttm.sh create mode 100755 utils/make_big_corpus.sh create mode 100755 utils/noisemes_full.sh create mode 100755 utils/parse_cha_xml.py create mode 100755 utils/rttm2labels.py create mode 100755 utils/rttm2scp.py create mode 100755 utils/rttm2scp.sh create mode 100755 utils/runTALNet.sh create mode 100755 utils/selcha2clean.sh create mode 100755 utils/sum-rttm.sh create mode 100755 utils/syllabify.sh create mode 100755 utils/textgrid2rttm.py create mode 100755 utils/tocombo2rttm.py create mode 100755 utils/train_test_split.py create mode 100755 utils/txt2rttm.py create mode 100755 utils/vad_segmenter_aclew.conf.txt create mode 100755 utils/yuniSeg.sh diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.theanorc b/.theanorc old mode 100644 new mode 100755 diff --git a/Dockerfile b/Dockerfile old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/Vagrantfile b/Vagrantfile index 14d2ac4..f2d07cf 100755 --- a/Vagrantfile +++ b/Vagrantfile @@ -221,13 +221,9 @@ Vagrant.configure("2") do |config| # and recommonmark (needed to make html in docs/) su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" - # OpenSAT (noisemes) and possibly other tools depend on tools ~/G/. - # So let's not do away with it. -# cd /home/${user} -# mkdir -p G -# cd G -# ln -s /home/vagrant/repos/pdnn . -# ln -s /home/vagrant/repos/coconut . + # Link /vagrant/launcher and /vagrant/utils to home folder where scripts expect them + ln -s /vagrant/launcher /home/${user}/ + ln -s /vagrant/utils /home/${user}/ # Some cleanup sudo apt-get autoremove -y diff --git a/data/.gitignore b/data/.gitignore old mode 100644 new mode 100755 diff --git a/docs/Makefile b/docs/Makefile old mode 100644 new mode 100755 diff --git a/docs/make.bat b/docs/make.bat old mode 100644 new mode 100755 diff --git a/docs/source/conf.py b/docs/source/conf.py old mode 100644 new mode 100755 diff --git a/docs/source/diartk.md b/docs/source/diartk.md old mode 100644 new mode 100755 diff --git a/docs/source/eval.md b/docs/source/eval.md old mode 100644 new mode 100755 diff --git a/docs/source/extra-tools.md b/docs/source/extra-tools.md old mode 100644 new mode 100755 diff --git a/docs/source/index.rst b/docs/source/index.rst old mode 100644 new mode 100755 diff --git a/docs/source/initial_questions.md b/docs/source/initial_questions.md old mode 100644 new mode 100755 diff --git a/docs/source/install.md b/docs/source/install.md old mode 100644 new mode 100755 diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md old mode 100644 new mode 100755 diff --git a/docs/source/ldcSad.md b/docs/source/ldcSad.md old mode 100644 new mode 100755 diff --git a/docs/source/noisemesSad.md b/docs/source/noisemesSad.md old mode 100644 new mode 100755 diff --git a/docs/source/opensmileSad.md b/docs/source/opensmileSad.md old mode 100644 new mode 100755 diff --git a/docs/source/references.md b/docs/source/references.md old mode 100644 new mode 100755 diff --git a/docs/source/tocomboSad.md b/docs/source/tocomboSad.md old mode 100644 new mode 100755 diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md old mode 100644 new mode 100755 diff --git a/docs/source/troubleshoot.md b/docs/source/troubleshoot.md old mode 100644 new mode 100755 diff --git a/docs/source/usage.md b/docs/source/usage.md old mode 100644 new mode 100755 diff --git a/docs/source/yunitator.md b/docs/source/yunitator.md old mode 100644 new mode 100755 diff --git a/launcher b/launcher deleted file mode 160000 index f2a820c..0000000 --- a/launcher +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f2a820c01966bf11df501077b0de89d5bd3b0dd1 diff --git a/launcher/537classify.sh b/launcher/537classify.sh new file mode 100755 index 0000000..a88185e --- /dev/null +++ b/launcher/537classify.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run 537 class classifier with hard coded models & configs found here +# assumes Python environment in /home/${user}/anaconda/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to classify tool (go one folder up and to 537cls) +CLASSIFY=$(dirname $BASEDIR)/537cls + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of Yunitator +cd $CLASSIFY + +# Iterate over files +echo "Starting" +for f in `ls ${audio_dir}/*.wav`; do + ./run537classify.sh $f + base=$(basename $f .wav) + mv $audio_dir/${base}.rttm ${audio_dir}/537cls_${base}.rttm + mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/537cls_${base}.frame_prob.mat +done + +echo "$0 finished running" diff --git a/launcher/README.md b/launcher/README.md new file mode 100755 index 0000000..a81e2ae --- /dev/null +++ b/launcher/README.md @@ -0,0 +1,37 @@ +# Launcher +This repository contains scripts that launch tools in the ACLEW Diarization VM. + +## Overall summary + +### SAD tools +``` +ldcSad.sh +noisemesSad.sh +opensmileSad.sh +tocomboSad.sh +``` +### Talker Diarization tools +``` +diartk.sh + +``` + +### Role assignment tools + +``` +yunitate.sh + +``` + +### Scoring tools +``` +evalDiar.sh +evalSAD.sh +``` + +### VM Self-test +``` +test.sh +``` + + diff --git a/launcher/diartk.sh b/launcher/diartk.sh new file mode 100755 index 0000000..e053de3 --- /dev/null +++ b/launcher/diartk.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + + +### Read in variables from user +audio_dir=/vagrant/$1 +trs_format=$2 + + +### Other variables specific to this script +# create temp dir +workdir=$audio_dir/temp/diartk +mkdir -p $workdir + +### SCRIPT STARTS +cd $BASEDIR/repos/ib_diarization_toolkit + + +# Check audio_dir to see if empty or if contains empty wav +bash $UTILS/check_folder.sh $audio_dir + + +for fin in `ls $audio_dir/*.wav`; do + filename=$(basename "$fin") + basename="${filename%.*}" + echo "treating $basename" + + featfile=$workdir/$basename.fea + scpfile=$workdir/$basename.scp + + # first-first convert RTTM to DiarTK's version of a .scp file + # SCP format: + # __=[start,end] + # RTTM format: + # Type file chan tbeg tdur ortho stype name conf Slat + # math: convert RTTM seconds to HTK (10ms default) frames = multiply by 100 + case $trs_format in + "ldcSad") + sys="ldcSad" + $conda_dir/python $UTILS/rttm2scp.py $audio_dir/ldcSad_${basename}.rttm $scpfile + ;; + "noisemesSad") + sys="noisemesSad" + $conda_dir/python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile + ;; + "tocomboSad") + sys="tocomboSad" + $conda_dir/python $UTILS/rttm2scp.py $audio_dir/tocombo_sad_${basename}.rttm $scpfile + ;; + "opensmileSad") + sys="opensmileSad" + $conda_dir/python $UTILS/rttm2scp.py $audio_dir/opensmile_sad_${basename}.rttm $scpfile + ;; + "textgrid") + sys="goldSad" + $conda_dir/python /home$UTILS/textgrid2rttm.py $audio_dir/${basename}.TextGrid $workdir/${basename}.rttm + $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + rm $workdir/$basename.rttm + ;; + "eaf") + sys="goldSad" + $conda_dir/python /home$UTILS/elan2rttm.py $audio_dir/${basename}.eaf $workdir/${basename}.rttm + $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + rm $workdir/$basename.rttm + ;; + "rttm") + sys="goldSad" + # Since some reference rttm files are spaced rather than tabbed, we need to + # tab them before using them. + cp $audio_dir/${basename}.rttm $workdir/${basename}.rttm + sed -i 's/ \+/\t/g' $workdir//${basename}.rttm + $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + ;; + *) + echo "ERROR: please choose SAD system between:" + echo " ldcSad" + echo " noisemesSad" + echo " tocomboSad" + echo " opensmileSad" + echo " textgrid" + echo " eaf" + echo " rttm" + echo "Now exiting..." + exit 1 + ;; + esac + + # don't process files with empty transcription + if [ -s $scpfile ]; then + # first generate HTK features + HCopy -T 2 -C htkconfig $fin $featfile + + # next run DiarTK + scripts/run.diarizeme.sh $featfile $scpfile $workdir $basename + + # print results + #cat $workdir/$basename.out + cp $workdir/$basename.rttm $audio_dir/diartk_${sys}_${basename}.rttm + fi + if [ ! -s $audio_dir/diartk_${sys}_${basename}.rttm ]; then + # if diarization failed, still write an empty file... + touch $audio_dir/diartk_${sys}_${basename}.rttm + fi + + + +done + +# Delete temporary folder +rm -rf $workdir diff --git a/launcher/eval.sh b/launcher/eval.sh new file mode 100755 index 0000000..a218022 --- /dev/null +++ b/launcher/eval.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=/home/vagrant +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +LAUNCHER=$BASEDIR/launcher +# end of launcher onset routine + +### Read in variables from user +#audio_dir=/vagrant/$1 +audio_dir=$1 +system=$2 + +### Other variables specific to this script +#none + +display_usage() { + echo "Usage: eval.sh <>" + echo "where data is the folder containing the data" + echo "and system is the system you want" + echo "to evaluate. Choices are:" + echo " ldcSad" + echo " noisemesSad" + echo " tocomboSad" + echo " opensmileSad" + echo " lenaSad" + echo " diartk" + echo " yunitate" + echo " lenaDiar" + echo "If evaluating diartk, please give which flavour" + echo "of SAD you used to produce the transcription" + echo "you want to evaluate" + exit 1 +} + +if [ $# -lt 2 ] ; then + display_usage +fi + +echo "audio_dir in eval.sh is: " $audio_dir + +### SCRIPT STARTS +case $system in +"tocomboSad"|"opensmileSad"|"ldcSad"|"noisemesSad|lenaSad") + sh $LAUNCHER/evalSAD.sh $audio_dir $system + ;; +"yunitate"|"lenaDiar") + sh $LAUNCHER/evalDiar.sh $audio_dir $system + ;; +"diartk") + sad=$3 + sh $LAUNCHER/evalDiar.sh $audio_dir $system $sad + ;; +*) + display_usage + ;; + +esac diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh new file mode 100755 index 0000000..65caef7 --- /dev/null +++ b/launcher/evalDiar.sh @@ -0,0 +1,123 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to OpenSAT (go on folder up and to opensat) +DSCOREDIR=$(dirname $BASEDIR)/dscore + + +display_usage() { + echo "Usage: evalDiar.sh <>" + echo "where dirname is the name of the folder" + echo "containing the wav files, and transcription" + echo "specifies which transcription you want to use," + echo "only used if model == diartk." + echo "Model choices are :" + echo " - diartk" + echo " - yunitate" + echo "Transcription (mandatory for model == diartk) choices are:" + echo " -ldc_sad" + echo " -noisemes" + echo " -opensmile" + echo " -tocombosad" + echo " -textgrid" + echo " -eaf" + echo " -rttm" + exit 1; + +} + +if ! [[ $2 =~ ^(diartk|yunitate|lena)$ ]] || [ "$2" == "diartk" ] && [ $# -ne 3 ]; then + display_usage +fi + + +# data directory +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# Set CWD to path of Dscore +cd $DSCOREDIR + +model=$2 +if [[ $model =~ ^(diartk|yuniseg) ]]; then + trs_format=$3 + case $trs_format in + "ldc_sad") + sys_name=$model"_ldcSad" + ;; + "noisemes") + sys_name=$model"_noisemesSad" + ;; + "tocombosad") + sys_name=$model"_tocomboSad" + ;; + "opensmile") + sys_name=$model"_opensmileSad" + ;; + "textgrid") + sys_name=$model"_goldSad" + for wav in `ls $audio_dir/*.wav`; do + base=$(basename $wav .wav) + $conda_dir/python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid $audio_dir/${basename}.rttm + done + ;; + "eaf") + sys_name=$model"_goldSad" + for wav in `ls $audio_dir/*.wav`; do + base=$(basename $wav .wav) + $conda_dir/python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf $audio_dir/${basename}.rttm + done + ;; + "rttm") + sys_name=$model"_goldSad" + ;; + *) + echo "ERROR: You're trying to evaluate diartk, but the transcription system you specified is not recognized :" + echo " ldc_sad" + echo " noisemes" + echo " textgrid" + echo " eaf" + echo " rttm" + echo "Now exiting..." + exit 1 + ;; + esac +elif [ "$2" == "yunitate" ]; then + sys_name="yunitator" +elif [ "$2" == "lena" ]; then + sys_name="lena" +fi + +$BASEDIR/create_ref_sys.sh $audio_dir $sys_name + +echo "evaluating" + +$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $audio_dir/temp_ref $audio_dir/temp_sys + +# Check if some gold files are empty. If so, add a line in the eval dataframe +for fin in `ls $audio_dir/temp_ref/*.rttm`; do + base=$(basename $fin .rttm) + if [ ! -s $audio_dir/temp_ref/$base.rttm ]; then + if [ ! -s $audio_dir/temp_sys/$base.rttm ]; then + echo $base" 0 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + else + echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + fi + elif [ ! -s $audio_dir/temp_sys/$base.rttm ] && [ -s $audio_dir/temp_ref/$base.rttm ]; then + echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + fi +done + +echo "done evaluating, check $1/${sys_name}_eval.df for the results" +# remove temps +rm -rf $audio_dir/temp_ref $audio_dir/temp_sys diff --git a/launcher/evalSAD.sh b/launcher/evalSAD.sh new file mode 100755 index 0000000..1ae74e7 --- /dev/null +++ b/launcher/evalSAD.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + + +### Read in variables from user +# data directory +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# check system to evaluate +system=$2 + + +### Other variables specific to this script +# Path to scoring tool NOTE: NOT dscore! +ldcSad_DIR=$REPOS/ldc_sad_hmm +# create temp dir +workdir=$audio_dir +mkdir -p $workdir + + +### SCRIPT STARTS +if [[ $system = "ldcSad" ]]; then + sys_name="ldcSad" +elif [[ $system = "noisemesSad" ]]; then + sys_name="noisemesSad" +elif [[ $system = "tocombosad" ]]; then + sys_name="tocombo_sad" +elif [[ $system = "opensmileSad" ]]; then + sys_name="opensmileSad" +elif [[ $system = "lenaSad" ]]; then + sys_name="lenaSad" + +else + echo "Please Specify the System you wish to evaluate." + echo "Choose between ldcSad, noisemeSad, tocomboSad, opensmileSad, lenaSad." + exit +fi + + +# Set CWD to path of scoring tool +cd $ldcSad_DIR + +#mkdir + +$UTILS/create_ref_sys.sh $audio_dir $sys_name true + +echo "evaluating" +#$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys +# create /vagrant/results if it doesn't exist +echo "filename DCF FA MISS" > $audio_dir/${sys_name}_eval.df +for lab in `ls $workdir/temp_sys/*.lab`; do + base=$(basename $lab .lab) + if [ ! -s $workdir/temp_ref/$base.lab ]; then + if [ ! -s $workdir/temp_sys/$base.lab ]; then + echo $base" 0.00% 0.00% 0.00%" >> $audio_dir/${sys_name}_eval.df + else + echo $base" 25.00% 100.00% 0.00%" >> $audio_dir/${sys_name}_eval.df + fi + elif [ ! -s $workdir/temp_sys/$base.lab ] && [ -s $workdir/temp_ref/$base.lab ]; then + echo $base" 75.00% 0.00% 100.00%" >> $audio_dir/${sys_name}_eval.df + else + $conda_dir/python score.py $workdir/temp_ref $lab | awk -v var="$base" -F" " '{if ($1=="DCF:") {print var"\t"$2"\t"$4"\t"$6}}' >> $audio_dir/${sys_name}_eval.df + fi + +done +# small detail: remove the commas from the output +sed -i "s/,//g" $audio_dir/${sys_name}_eval.df +echo "done evaluating, check $1/${sys_name}_eval.df for the results" + +# remove temps +rm -rf $workdir/temp_ref $workdir/temp_sys + diff --git a/launcher/ldcSad.sh b/launcher/ldcSad.sh new file mode 100755 index 0000000..590ff8d --- /dev/null +++ b/launcher/ldcSad.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=/home/vagrant +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + +### Read in variables from user +audio_dir=/vagrant/$1 + +### Other variables specific to this script +LDC_SAD_DIR=$REPOS/ldc_sad_hmm +workdir=$audio_dir/temp/diartk +mkdir -p $workdir + +### SCRIPT STARTS +if [ $# -ne 1 ]; then + echo "Usage: ldcSad.sh " + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +# Check audio_dir to see if empty or if contains empty wav +bash $UTILS/check_folder.sh $audio_dir + +# Set CWD as LDC_SAD_HMM +cd $LDC_SAD_DIR + +# launch ldc +$conda_dir/python perform_sad.py -L $workdir $audio_dir/*.wav +echo "finished using ldcSad_hmm. Please look inside $1 to see the output in *.rttm format" + +# move all files to name them correctly +for wav in `ls $audio_dir/*.wav`; do + # retrieve filename and remove .wav + base=$(basename $wav .wav) + rttm_out=$workdir/ldcSad_${base}.rttm + if [ -s $workdir/${base}.lab ]; then + grep ' speech' $workdir/${base}.lab | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $rttm_out + else + touch $rttm_out + fi +done diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh new file mode 100755 index 0000000..2fd5bc2 --- /dev/null +++ b/launcher/noisemesSad.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# noisemes_sad.sh +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run OpenSAT with hard coded models & configs found here and in /vagrant + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to OpenSAT (go on folder up and to opensat) +OPENSATDIR=$(dirname $BASEDIR)/OpenSAT + +if [ $# -ne 1 ]; then + echo "Usage: noisemes_sad.sh " + echo "where dirname is a folder on the host" + echo "containing the wav files (/vagrant/dirname/ in the VM)" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + +# let's get our bearings: set CWD to path of OpenSAT +cd $OPENSATDIR + +# make output folder for features, below input folder +mkdir -p $audio_dir/feature + +# first features +echo "extracting features for speech activity detection" +for file in `ls $audio_dir/*.wav`; do + SSSF/code/feature/extract-htk-vm2.sh $file +done + +# then confidences +#python SSSF/code/predict/1-confidence-vm3.py $1 +echo "detecting speech and non speech segments" +$conda_dir/python SSSF/code/predict/1-confidence-vm5.py $audio_dir +echo "finished detecting speech and non speech segments" + +# take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. +for sad in `ls $audio_dir/hyp_sum/*.lab`; do + base=$(basename $sad .lab) + rttm_out=noisemes_sad_${base}.rttm + if [ -s $sad ]; then + grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out + else + touch $audio_dir/$rttm_out + fi +done + +# simple remove hyp and feature +rm -rf $audio_dir/hyp_sum $audio_dir/feature +# mv hyp and features folders to a temp that the user can delete. +#if [ ! -d "$audio_dir/noiseme_sad_temp" ]; then +# mkdir -p $audio_dir/noiseme_sad_temp +#fi +# +#if [! -d "$audio_dir/noiseme_sad_temp" ]; then +# mv $audio_dir/hyp_sum $audio_dir/noiseme_sad_temp +#else +# echo "can't move hyp_sum/ folder to noiseme_sad_temp/ because temp is already full" +#fi +# +#if [! -d "$audio_dir/noiseme_sad_temp" ]; then +# mv $audio_dir/feature $audio_dir/noiseme_sad_temp +#else +# echo "can't move features/ folder to noiseme_sad_temp/ because temp is already full" +#fi +# diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh new file mode 100755 index 0000000..9d48927 --- /dev/null +++ b/launcher/opensmileSad.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + +### Read in variables from user +audio_dir=/vagrant/$1 + +### Other variables specific to this script +OSHOME=$REPOS/openSMILE-2.1.0/ +CONFIG_FILE=$UTILS/vad_segmenter_aclew.conf.txt +OPENSMILE=$OSHOME/bin/linux_x64_standalone_static/SMILExtract +workdir=$audio_dir/temp/opensmileSad +mkdir -p $workdir + +### SCRIPT STARTS + +if [ $# -lt 1 ]; then + echo "USAGE: $0 " + exit 1 +fi + +filename=$(basename "$1") +dirname=$(dirname "$1") +extension="${filename##*.}" +basename="${filename%.*}" + + +cd $OSHOME/scripts/vad + +# Use OpenSMILE 2.1.0 +for sad in `ls $audio_dir/*.wav`; do + + file=$sad + id=`basename $file` + id=${id%.wav} + > $audio_dir/${id}.txt #Make it empty if already present + echo "Processing $id ..." + LD_LIBRARY_PATH=/usr/local/lib \ + $OPENSMILE \ + -C $CONFIG_FILE \ + -I $file \ + -turndebug 1 \ + -noconsoleoutput 1 \ + -saveSegmentTimes $workdir/${id}.txt \ + -logfile $workdir/opensmile-vad.log > /dev/null +done + +for output in $(ls $workdir/*.txt); do + id=$(basename $output .txt) + awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > $audio_dir/opensmileSad_$id.rttm +done + +# Delete temporary folder +rm -rf $workdir diff --git a/launcher/test.sh b/launcher/test.sh new file mode 100755 index 0000000..6bd5998 --- /dev/null +++ b/launcher/test.sh @@ -0,0 +1,229 @@ +#!/bin/bash +# +# This script tests numerous tools +# from a downloaded 5 minute section of the HomeBank VanDam daylong audio sample +# ("ACLEW Starter" data) + +# this doesn't work because .bashrc exits immediately if not running interactively +#source /home/vagrant/.bashrc -i +# instead: +export PATH=/home/vagrant/anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin +LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH" + +conda_dir=/home/vagrant/anaconda/bin + +# Absolute path to this script. /home/vagrant/launcher +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/vagrant/ - works out to being user home folder +BASEDIR=`dirname $SCRIPT` +LAUNCHERS=/home/vagrant/launcher +REPOS=/home/vagrant/repos +UTILS=/home/vagrant/utils + +# Paths to Tools +LDC_SAD_DIR=$REPOS/ldc_sad_hmm +OPENSATDIR=$REPOS/OpenSAT # noisemes +OPENSMILEDIR=$REPOS/openSMILE-2.1.0/ +TOCOMBOSAD=$REPOS/To-Combo-SAD +DIARTKDIR=$REPOS/ib_diarization_toolkit +#TALNETDIR=$REPOS/TALNet +DSCOREDIR=$REPOS/dscore +YUNITATORDIR=$REPOS/Yunitator + +FAILURES=false + +echo "Starting tests" +echo "Downloading test audio..." + +cd /vagrant/data +# get transcript +wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip +unzip -q -o VanDam-Daylong.zip + +# This is the working directory for the tests; right beside the input +cd VanDam-Daylong/BN32/ +WORKDIR=`pwd` + +# Get daylong recording from the web +wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 + +DATADIR=data/VanDam-Daylong/BN32 # relative to /vagrant, used by launcher scripts +BASE=BN32_010007 # base filename for test input file, minus .wav or .rttm suffix +BASETEST=${BASE}_test +START=2513 # 41:53 in seconds +STOP=2813 # 46:53 in seconds + +# get 5 minute subset of audio +sox $BASE.mp3 $BASETEST.wav trim $START 5:00 >& /dev/null 2>1 + +# convert CHA to reliable STM +$UTILS/chat2stm.sh $BASE.cha > $BASE.stm 2>/dev/null +# convert STM to RTTM as e.g. BN32_010007.rttm +# shift audio offsets to be 0-relative +cat $BASE.stm | awk -v start=$START -v stop=$STOP -v file=$BASE -e '{if (($4 > start) && ($4 < stop)) print "SPEAKER",file,"1",($4 - start),($5 - $4),"","","","","" }' > $BASETEST.rttm +TEST_RTTM=$WORKDIR/$BASETEST.rttm +TEST_WAV=$WORKDIR/$BASETEST.wav + + +# Check for HTK +echo "Checking for HTK..." +if [ -s /usr/local/bin/HCopy ]; then + echo "HTK is installed." +else + echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" + echo " and rename it to HTK.tar.gz ?" +fi + +# First test in ldc_sad_hmm +echo "Testing LDC SAD..." +if [ -s $LDC_SAD_DIR/perform_sad.py ]; then + cd $LDC_SAD_DIR + TESTDIR=$WORKDIR/ldc_sad-test + rm -rf $TESTDIR; mkdir -p $TESTDIR + $conda_dir/python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} + # convert output to rttm, for diartk. + grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm + if [ -s $TESTDIR/$BASETEST.rttm ]; then + echo "LDC SAD passed the test." + else + FAILURES=true + echo " LDC SAD failed - no output RTTM" + fi +else + echo " LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" +fi + + +# now test Noisemes +echo "Testing noisemes..." +cd $OPENSATDIR +TESTDIR=$WORKDIR/noisemes-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +./runDiarNoisemes.sh $TESTDIR > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/hyp_sum/$BASETEST.rttm ]; then + echo "Noisemes passed the test." +else + FAILURES=true + echo " Noisemes failed - no RTTM output" +fi +# clean up +rm -rf $OPENSATDIR/SSSF/data/feature $OPENSATDIR/SSSF/data/hyp + + +# now test OPENSMILEDIR +echo "Testing OpenSmile SAD..." +cd $OPENSMILEDIR +TESTDIR=$WORKDIR/opensmile-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +$LAUNCHERS/opensmileSad.sh data/VanDam-Daylong/BN32/opensmile-test >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then + echo "OpenSmile SAD passed the test." +else + FAILURES=true + echo " OpenSmile SAD failed - no RTTM output" +fi + +# now test TOCOMBOSAD +echo "Testing ToCombo SAD..." +cd $TOCOMBOSAD +TESTDIR=$WORKDIR/tocombo_sad-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +$LAUNCHERS/tocomboSad.sh data/VanDam-Daylong/BN32/tocombo_sad-test > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then + echo "TOCOMBO SAD passed the test." +else + FAILURES=true + echo " TOCOMBO SAD failed - no output RTTM" +fi + + +# finally test DIARTK +echo "Testing DIARTK..." +cd $DIARTKDIR +TESTDIR=$WORKDIR/diartk-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +# run like the wind +./run-rttm.sh $TEST_WAV $TEST_RTTM $TESTDIR > $TESTDIR/diartk-test.log 2>&1 +if grep -q "command not found" $TESTDIR/diartk-test.log; then + echo " Diartk failed - dependencies (probably HTK)" + FAILURES=true +else + if [ -s $TESTDIR/$BASETEST.rttm ]; then + echo "DiarTK passed the test." + else + FAILURES=true + echo " Diartk failed - no output RTTM" + fi +fi + +# finally test Yunitator +echo "Testing Yunitator..." +cd $YUNITATORDIR +TESTDIR=$WORKDIR/yunitator-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +# let 'er rip +./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/Yunitemp/$BASETEST.rttm ]; then + echo "Yunitator passed the test." +else + FAILURES=true + echo " Yunitator failed - no output RTTM" +fi + + +# Test DSCORE +echo "Testing Dscore..." +cd $DSCOREDIR +TESTDIR=$WORKDIR/dscore-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +cp -r test_ref test_sys $TESTDIR +rm -f test.df +python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/test.df ]; then + echo "DScore passed the test." +else + echo " DScore failed the test - output does not match expected" + FAILURES=true +fi + + +# testing LDC evalSAD (on opensmile) +echo "Testing LDC evalSAD" +if [ -d $LDC_SAD_DIR ]; then + cd $LDC_SAD_DIR + TESTDIR=$WORKDIR/opensmile-test + cp $WORKDIR/$BASETEST.rttm $TESTDIR + $LAUNCHERS/eval.sh $DATADIR/opensmile-test opensmileSad > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} + if [ -s $TESTDIR/opensmileSad_eval.df ]; then + echo "LDC evalSAD passed the test" + else + echo " LDC evalSAD failed - no output .df" + FAILURES=true + fi +else + echo " LDC evalSAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" + FAILURES=true +fi + + +# test finished +if $FAILURES; then + echo "Some tools did not pass the test, but you can still use others" +else + echo "Congratulations, everything is OK!" +fi + +# results +echo "RESULTS:" +for f in /vagrant/$DATADIR/*-test/*.rttm; do $UTILS/sum-rttm.sh $f; done +echo "DSCORE:" +cat /vagrant/data/VanDam-Daylong/BN32/dscore-test/test.df +echo "EVAL_SAD:" +cat $TESTDIR/opensmileSad_eval.df diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh new file mode 100755 index 0000000..bd167a0 --- /dev/null +++ b/launcher/tocomboSad.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Launcher onset routine +source ~/.bashrc +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $(dirname $SCRIPT )` +conda_dir=$BASEDIR/anaconda/bin +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine + + +### Read in variables from user +audio_dir=/vagrant/$1 +trs_format=$2 + + +### Other variables specific to this script +# create temp dir +workdir=$audio_dir/temp/tocomboSad +mkdir -p $workdir +TOCOMBOSADDIR=$REPOS/To-Combo-SAD +MCR=/usr/local/MATLAB/MATLAB_Runtime/v93 + +### SCRIPT STARTS + +if [ $# -ne 1 ]; then + echo "Usage: tocombo_sad.sh " + echo "where dirname is a folder on the host" + echo "containing the wav files (/vagrant/dirname/ in the VM)" + exit 1 +fi + +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# Check audio_dir to see if empty or if contains empty wav +bash /home/vagrant/utils/check_folder.sh $audio_dir + +# let's get our bearings: set CWD to path of ToComboSAD +cd $TOCOMBOSADDIR + +mkdir -p $workdir/feat +rm -f $workdir/filelist.txt +touch $workdir/filelist.txt + +# create temp dir to store audio files with 1 channels, if needed (i.e. if audio to treat has 2 or more channels.) +# Indeed, To Combo Sad Fails when there are more than 1 channels. +for f in $audio_dir/*.wav; do + # Check if audio has 1 channel or more. If it has more, use sox to create a temp audio file w/ 1 channel. + n_chan=$(soxi $f | grep Channels | cut -d ':' -f 2) + if [[ $n_chan -gt 1 ]]; then + base=$(basename $f) + sox -c $n_chan $f -c 1 $workdir/$base + f=$workdir/$base + fi + + echo $f >> $workdir/filelist.txt + +done +echo "finished" + +export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64: + +./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt + +# Retrieve the outputs from the temp folder +mv $workdir/*ToCombo.txt $audio_dir + +#convert to rttms +for f in $audio_dir/*.ToCombo.txt; do + bn=`basename $f .wav.ToCombo.txt` + python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > $audio_dir/tocomboSad_$bn.rttm +done + +# Delete temporary folder +rm -rf $workdir diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh new file mode 100755 index 0000000..01d58f2 --- /dev/null +++ b/launcher/yunitate.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run OpenSAT with hard coded models & configs found here and in /vagrant +# assumes Python environment in /home/${user}/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to Yunitator (go one folder up and to Yunitator) +YUNITATDIR=$(dirname $BASEDIR)/Yunitator + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of Yunitator +cd $YUNITATDIR + +# Iterate over files +echo "Starting" +for f in `ls $audio_dir/*.wav`; do + ./runYunitator.sh $f +done + +echo "$0 finished running" + +# take all the .rttm in $audio_dir/Yunitemp/ and move them to /vagrant/data +for sad in `ls $audio_dir/Yunitemp/*.rttm`; do + _rttm=$(basename $sad) + rttm=$audio_dir/yunitator_${_rttm} + # Remove not needed SIL lines + # sed -i '/ SIL /d' $sad + mv $sad $rttm +done + +# simply remove hyp and feature +rm -rf $audio_dir/Yunitemp diff --git a/test.wav b/test.wav old mode 100644 new mode 100755 diff --git a/test2.mp3 b/test2.mp3 old mode 100644 new mode 100755 diff --git a/test2.rttm b/test2.rttm old mode 100644 new mode 100755 diff --git a/utils b/utils deleted file mode 160000 index 0ed7abd..0000000 --- a/utils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0ed7abd67daac8a46bff31e66e8f83475fce3bea diff --git a/utils/.gitignore b/utils/.gitignore new file mode 100755 index 0000000..fcff087 --- /dev/null +++ b/utils/.gitignore @@ -0,0 +1,33 @@ +# History files +.Rhistory +.Rapp.history + +# Session Data files +.RData + +# Example code in package build process +*-Ex.R + +# Output files from R CMD build +/*.tar.gz + +# Output files from R CMD check +/*.Rcheck/ + +# RStudio files +.Rproj.user/ + +# produced vignettes +vignettes/*.html +vignettes/*.pdf + +# OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 +.httr-oauth + +# knitr and R markdown default cache directories +/*_cache/ +/cache/ + +# Temporary files created by R markdown +*.utf8.md +*.knit.md diff --git a/utils/README.md b/utils/README.md new file mode 100755 index 0000000..af578e2 --- /dev/null +++ b/utils/README.md @@ -0,0 +1,4 @@ +# Utils +This repository contains utilities that are potentially useful to more than one tool in the ACLEW Diarization VM. It also contains some launchers that are in quarantine at present: +noisemes_full.sh +yuniSeg.sh diff --git a/utils/adjust_timestamps.py b/utils/adjust_timestamps.py new file mode 100755 index 0000000..c598301 --- /dev/null +++ b/utils/adjust_timestamps.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python +# +# +import pympi as pmp +import shutil +import os +import argparse +import subprocess +from collections import defaultdict +from operator import itemgetter + + +def eaf2rttm(path_to_eaf): + """ + function to write a new .rttm file which is a transcription of the .eaf + given as input + + """ + + # in EAF, timestamps are in milliseconds, convert them to seconds + # TODO read scale from header of EAF + sampling_freq = 1000.0 + + print('\n') + # read eaf file + EAF = pmp.Elan.Eaf(path_to_eaf) + + participants = [] + + # gather all the talker's names + for k in EAF.tiers.keys(): + + if 'PARTICIPANT' in EAF.tiers[k][2].keys(): + + if EAF.tiers[k][2]['PARTICIPANT'] not in participants: + + participants.append(EAF.tiers[k][2]['PARTICIPANT']) + + print('participants: {}'.format(participants)) + + base = os.path.basename(path_to_eaf) + name = os.path.splitext(base)[0] + + print('parsing file: {}'.format(name)) + + # get the begining, ending and transcription for each annotation of + # each tier + rttm = [] + for participant in participants: + if participant not in EAF.tiers: + continue + for _, val in EAF.tiers[participant][0].items(): + # Get timestamps + start = val[0] + end = val[1] + + t0 = EAF.timeslots[start] / sampling_freq + length = EAF.timeslots[end] / sampling_freq - t0 + + # get transcription + transcript = val[2] + + rttm.append((name, t0, length, transcript, participant)) + + return rttm + +def eaf2rttm_CAS(path_to_eaf): + """ + function to write a new .rttm file which is a transcription of the .eaf + given as input + + """ + + sampling_freq = 1000.0 + + print('\n') + EAF = pmp.Elan.Eaf(path_to_eaf) + + participants = [] + + for k in EAF.tiers.keys(): + + if 'PARTICIPANT' in EAF.tiers[k][2].keys(): + + if EAF.tiers[k][2]['PARTICIPANT'] not in participants: + + participants.append(EAF.tiers[k][2]['PARTICIPANT']) + + print('participants: {}'.format(participants)) + + base = os.path.basename(path_to_eaf) + name = os.path.splitext(base)[0] + + print('parsing file: {}'.format(name)) + + # get the begining, ending and transcription for each annotation of + # each tier + rttm = [] + for participant in participants: + + for _, val in EAF.tiers[participant][0].items(): + # Get timestamps + start = val[0] + end = val[1] + + t0 = EAF.timeslots[start] / sampling_freq + length = EAF.timeslots[end] / sampling_freq - t0 + + # get transcription + transcript = val[2] + + rttm.append((name, t0, length, transcript, participant)) + return rttm + +def write_rttm(output, rttm_path, annotations): + """ write annotations to rttm_path""" + + with open(os.path.join(output, rttm_path), 'w') as fout: + rttm_name = rttm_path.split('.')[0] + print len(annotations) + for name, t0, length, transcript, participant in annotations: + fout.write(u"SPEAKER\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n".format + (rttm_name, 1, "%.3f" %t0, "%.3f" %length, transcript, + "", participant, 1 )) + +def get_all_on_offs(eaf): + """ + Return all the annotated intervals from the current file + """ + EAF = pmp.Elan.Eaf(eaf) + + all_intervals = EAF.tiers['on_off'][0] + + # get the segments delimited for "on_off" tier, + # as those give the timestamps between which are the annotations + on_offs = [] + for key in all_intervals: + interv = all_intervals[key] + beg_end = interv[2] + beg, end = [float(time) for time in beg_end.split('_')] + # store in seconds, not milliseconds + on_offs.append((beg/1000.0, end/1000.0)) + + return on_offs + +def get_all_on_offs_CAS(eaf): + """ + Return all the annotated intervals from the current file + """ + EAF = pmp.Elan.Eaf(eaf) + + all_intervals = EAF.tiers['code'][0] + + on_offs = [] + for key in all_intervals: + interv = all_intervals[key] + beg_end = interv[2] + _beg = interv[0] + _end = interv[1] + beg = EAF.timeslots[_beg] + end = EAF.timeslots[_end] + + # store in seconds, not milliseconds + on_offs.append((beg/1000.0, end/1000.0)) + + return on_offs + +def cut_audio(on_offs, input_audio, dest): + """ + Extract from the daylong recordings the small parts that have + been annotated + """ + + # for each annotated segment, call sox to extract the part from the + # wav file + # Also, write each onset/offset with 6 digits + for on, off in on_offs: + audio_base = os.path.splitext(input_audio)[0] + wav_name = os.path.basename(audio_base) + dir_name = os.path.split(os.path.dirname(audio_base))[-1] + + # add the necessary number of 0's to the onsets/offsets + # to have 6 digits + str_on = str(int(on)) + str_off = str(int(off)) + + str_on = (6 - len(str_on)) * '0' + str_on + str_off = (6 - len(str_off)) * '0' + str_off + output_audio = '_'.join([dir_name, wav_name, + str_on, str_off]) + '.wav' + cmd = ['sox', input_audio, os.path.join(dest, output_audio), + 'trim', str(on), str(off - on)] + print " ".join(cmd) + subprocess.call(cmd) + +def extract_from_rttm(on_offs, rttm): + """ + For each minute of annotation, extract the annotation of that minute + from the transcription and write a distinct .rttm file with all the + timestamps with reference to the begining of that segment. + """ + sorted_rttm = sorted(rttm, key=itemgetter(1)) + + # create dict { (annotated segments) -> [annotation] } + extract_rttm = defaultdict(list) + for on, off in on_offs: + for name, t0, length, transcript, participant in sorted_rttm: + end = t0 + length + if (on <= t0 < off) or (on <= end < off): + # if the current annotation is (at least partially) + # contained in the current segment, append it. + # Adjust the segment to strictly fit in on-off + t0 = max(t0, on) + end = min(end, off) + length = end - t0 + extract_rttm[(on, off)].append((name, t0 - on, + length, + transcript, participant)) + elif (on > t0) and (end >= off): + # if the current annotation completely contains the annotated + # segment, add it also. This shouldn't happen, so print a + # warning also. + print('Warning: speaker speaks longer than annotated segment.\n' + 'Please check annotation from speaker {},' + 'between {} {}, segment {} {}.\n'.format(name, t0, + end, on, off)) + extract_rttm[(on, off)].append((name, 0, off - on, + transcript, participant)) + elif (end < on): + # wait until reach segment + continue + elif (t0 >= off): + # no point in continuing further since the rttm is sorted. + break + + return extract_rttm + +def main(): + """ + Take as input one eaf and wav file, and extract the segments from the + wav that have been annotated. + """ + parser = argparse.ArgumentParser(description="extract annotated segments") + parser.add_argument('eaf', type=str, + help='''Path to the transcription of the wave file, ''' + ''' in eaf format.''') + parser.add_argument('wav', type=str, + help='''Path to the wave file to treat''') + parser.add_argument('output', type=str) + parser.add_argument('-c', '--CAS', action='store_true', + help='''By default the script detects the segments''' + ''' using the "on_off" tier. For the CAS corpus,''' + ''' we should use the "code" tier.\n''' + ''' Enable this option when treating the CAS corpus''') + args = parser.parse_args() + + output = args.output + print output + #if not os.path.isdir( os.path.join(output, 'treated')): + # os.makedirs(os.path.join(output, 'treated')) + #if not os.path.isdir( os.path.join(output, 'treated', 'talker_role')): + # os.makedirs(os.path.join(output, 'treated', 'talker_role')) + + if args.CAS: + # read transcriptions + complete_rttm = eaf2rttm_CAS(args.eaf) + + # extract annotated segments + on_offs = get_all_on_offs_CAS(args.eaf) + else: + # read transcriptions + complete_rttm = eaf2rttm(args.eaf) + + # extract annotated segments + on_offs = get_all_on_offs(args.eaf) + + # cut audio files according to on_off/code tier in eaf annotations + cut_audio(on_offs, args.wav, output) + + # store in dict the annotations to write in rttm format + extract_rttm = extract_from_rttm(on_offs, complete_rttm) + + # write one rttm file per on_off/tier segment + for key in extract_rttm: + base = os.path.basename(args.eaf) + + # get the name of the corpus by taking the name of the folder and removing "raw" + dir_name = os.path.split( os.path.dirname(args.eaf) )[-1].split('_')[-1] + + name = os.path.splitext(base)[0] + # check is initials of annotator are in eaf name + if '-' in name: + name = name.split('-')[0] + + # add 0's to have exactly 6 digits (i.e. 1 second is 000001 s) + str_on = str(int(key[0])) + str_off = str(int(key[1])) + + str_on = (6 - len(str_on)) * '0' + str_on + str_off = (6 - len(str_off)) * '0' + str_off + + rttm_path = '_'.join([dir_name, name, + str_on, str_off]) + '.rttm' + write_rttm(output, rttm_path, extract_rttm[key]) + + +if __name__ == '__main__': + main() diff --git a/utils/catspa-syllabify-corpus.pl b/utils/catspa-syllabify-corpus.pl new file mode 100755 index 0000000..36a8c4a --- /dev/null +++ b/utils/catspa-syllabify-corpus.pl @@ -0,0 +1,93 @@ +#!/usr/bin/perl + +# Alex Cristia alecristia@gmail.com 2015-07-13 adapted VERY MINIMALLY this code from scripts +# distributed by Lawrence Phillips & Lisa Pearl, 12/23/13 (UCI-Brent-Syllabic Corpus) - credit is owed mainly to those authors + +# Uses the maximum onset principle to fully syllabify a corpus +use File::Basename; + +$language=$ARGV[0]; +$filecorpus=$ARGV[1]; +$output=$ARGV[2]; +$dirname=dirname($filecorpus); + +#print "\n the language is $language\n"; +# /input/ OR /scripts/ ? +# Save valid onsets from ValidOnsets.txt +%onsets = {}; +open(ONSETS, "<$dirname/$language-ValidOnsets.txt") or die("Couldn't open $dirname/$language-ValidOnsets.txt\n"); +while(defined($fileline = )){ + chomp($fileline); + #print "$fileline\n"; + $onsets{$fileline} = 1; #This is an odd way of stating things + #print "added"; +} +#print "out of the while"; +close(ONSETS); + +# Save valid vowels from Vowels.txt +%vowels = {}; +open(VOWELS, "<$dirname/$language-Vowels.txt") or die("Couldn't open $dirname/$language-Vowels.txt\n"); +my $vowels = ; +close(VOWELS); +#print "$vowels\n"; + +# Go through CORPUS.txt, +# for nonsyllabified words: for each syllable, find its vowel, and its maximum onset, given acceptable onsets and beginning of word. +# print syllabified version to syllabified-CORPUS.txt. +open(SYLLABIFIED, ">$output") or die("Couldn't open $output for writing\n"); +open(CORPUS, "<$filecorpus") or die("Couldn't open $filecorpus for reading"); + + + +while(defined($fileline = )){ + #print "entered first while\n"; + chomp($fileline); + $currline = $fileline; + @wordarray = split(" ", $currline); # divide the line into a set of words + $syllline="";#we start with a clean slate for each line + while(@wordarray > 0){ + $currword = pop(@wordarray); # cut out the last word in the word array & put it in currword + #print "now looking at $currword\n"; + @chararray = split(//, $currword); + + $syllword="";#we start with a clean slate for each word + $currsyllable=""; #and for the syllable + + while(@chararray > 0){ + $currchar = pop(@chararray); # cut out the last char in the char array for this word & put it in currchar + $currsyllable = $currchar.$currsyllable; # append currchar to current syllable - that will be necessary regardless of whether it's a vowel or a coda + # if hit a vowel.. + #if($currchar =~ /[ae3EiOo0u]/){ + if($currchar =~ /[$vowels]/){ + # print "$currchar\n"; + #if(@chararray[@chararray-1] !=~ /[ae3EiOo0u]/){ + if(@chararray[@chararray-1] !=~ /[$vowels]/){ + # print "@chararray[@chararray-1]\n"; + #if this char is a vowel and the previous one is not, then we need to make the onset + $onset = ""; #we start with nothing as the onset + #then we want to take one letter at a time and check whether their concatenation makes a good onset + while(@chararray > 0 && exists($onsets{@chararray[@chararray-1] . $onset})){ + #print "$onsets{@chararray[@chararray-1] . $onset}\n"; + $currchar = pop(@chararray); + $onset = $currchar . $onset; + } + #we get here either because we've concatenated the onset+rest or because there was no onset and the preceding element is a vowel, so this is the end of the syllable + $currsyllable = $onset . $currsyllable; + # add syllable to word entry + } + $syllword = "\/" . $currsyllable . $syllword; + $currsyllable = ""; + }#we end the if we are looking at a vowel + }#when we end this while there are no more characters in this word, so we can add it + $syllline=$syllword. " " . $syllline; + #print "$syllword\n"; + + } #while we work our way through the words in the line -- so when we exit this, we are ready to print out a syllabified line + if($syllline){ + print SYLLABIFIED "$syllline\n"; + } +}#while there are lines in this file + +close(SYLLABIFIED); +close(CORPUS); \ No newline at end of file diff --git a/utils/change_tsi_lena_names.py b/utils/change_tsi_lena_names.py new file mode 100755 index 0000000..88134ce --- /dev/null +++ b/utils/change_tsi_lena_names.py @@ -0,0 +1,43 @@ +import glob +import os +import re +import argparse + +parser = argparse.ArgumentParser(description="Convert the old naming convention of tsi/lena files into the new one.") +parser.add_argument('-f', '--folder', type=str, required=True, + help="path to the input folder tsi/lena (containing C25_NA_M14_20170719_56040.{wav|rttm} files).") +args = parser.parse_args() + +path_tsi_lena=os.path.join("/vagrant", args.folder) +rttm_files = glob.iglob(os.path.join(path_tsi_lena, '*.rttm')) + +for rttm in rttm_files: + dirname = os.path.dirname(rttm) + basename = os.path.splitext(os.path.basename(rttm))[0] + basename_splitted = basename.split('_') + + old_name = os.path.splitext(basename)[0] + if basename[0] == 'C' and len(basename_splitted) == 5: + new_name = '_'.join([basename_splitted[0], + basename_splitted[3], + basename_splitted[4]]) + + # Modify rttm name + new_path_rttm = os.path.join(dirname, new_name+'.rttm') + os.rename(rttm ,new_path_rttm) + + # Modify wav name + old_path_wav = os.path.join(dirname, old_name+'.wav') + new_path_wav = os.path.join(dirname, new_name+'.wav') + os.rename(old_path_wav, new_path_wav) + + # Do the change within the rttm (column 2 containing the filename) + new_name = os.path.splitext(new_name)[0] + f = open(new_path_rttm, 'r+b') + f_content = f.read() + f_content = re.sub(old_name, new_name, f_content) + f.seek(0) + f.truncate() + f.write(f_content) + f.close() + diff --git a/utils/chat2stm.sh b/utils/chat2stm.sh new file mode 100755 index 0000000..d1420dd --- /dev/null +++ b/utils/chat2stm.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# +# Shell script to convert .CHA format to .STM format +# +# ./cha2stm.sh .cha produces .stm +# +# To have this use replacement words instead of marking OOV words as "" +# swap (uncomment) the last line to change the arguments to parse_cha_xml.sh + +BASEDIR=$(dirname $0) + +if [ $# -ne 1 ]; then + echo "Usage: cha2stm.sh .cha" + echo + exit 1; +fi + +filename=$(basename "$1") +dirname=$(dirname "$1") +extension="${filename##*.}" +basename="${filename%.*}" + +# Install Java 8 and CHATTER +# First get chatter +mkdir -p ~/bin/lib +( +cd ~/bin/lib +if [ ! -f chatter.jar ]; then + wget http://talkbank.org/software/chatter.jar || exit 1 +fi + +# now get java 8 +if [ -d zulu8.17.0.3-jdk8.0.102-linux_x64 ]; then + : + #echo "Not installing Java 8 since it is already there." 1>&2 +else + echo "Downloading and installing Java 8" 1>&2 + wget http://cdn.azul.com/zulu/bin/zulu8.17.0.3-jdk8.0.102-linux_x64.tar.gz 1>&2 || exit 1 + tar -zxvf zulu8.17.0.3-jdk8.0.102-linux_x64.tar.gz 1>&2 + rm zulu8.17.0.3-jdk8.0.102-linux_x64.tar.gz 1>&2 + echo "Done installing Java 8" 1>&2 +fi +) + +if [ -f $dirname/$basename.cha ]; then + # + # First convert CHA to CHATTER xml + ~/bin/lib/zulu8.17.0.3-jdk8.0.102-linux_x64/bin/java -cp ~/bin/lib/chatter.jar org.talkbank.chatter.App -inputFormat cha -outputFormat xml -output $dirname/$basename.xml $dirname/$basename.cha + + # Convert CHATTER xml to STM + #python scripts/parse_cha_xml.py $dirname/$basename.xml --stm --replacement + python $BASEDIR/parse_cha_xml.py $dirname/$basename.xml --stm --oov +fi diff --git a/utils/check_folder.sh b/utils/check_folder.sh new file mode 100755 index 0000000..d7be677 --- /dev/null +++ b/utils/check_folder.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +check_folder=$(readlink -f $1) + +# First check that the folder is not empty +if [[ -z "$(ls -A $check_folder)" ]]; then + echo "data folder is empty!" + exit +else + echo "wavs and transcriptions found !" +fi + +# Then, check the consistency of all the files -> check if +# the wav have no amplitude +# (credit to http://decided.ly/2013/02/06/find-silent-audio-files/) +## A quick hack like script to list all the files that have +## a low amplitude. + +Max=0.0 # Any amplitude greater than this will NOT be listed +#OutList=~/output.list # The name of the file that contains a +# list of file names only of all the +# low-amplitude files. + +# rm $OutList +for each in `ls $check_folder/*.wav` +do + amplitude=$(sox "$each" -n stat 2>&1 | grep "Maximum amplitude" | cut -d ":" -f 2 | sed 's/ //g') + if [[ $(echo "if (${amplitude} > ${Max}) 1 else 0" | bc) -eq 0 ]] + then + echo "$each --> $amplitude" >&2 + echo "$each seems empty !" + fi +done + +echo "Tests finished" diff --git a/utils/chunk.sh b/utils/chunk.sh new file mode 100755 index 0000000..572e163 --- /dev/null +++ b/utils/chunk.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# chunk.sh - break files into 5 minute segments in a special folder +# then run a processing script on the folder of chunks +# then merge the resulting RTTMs back together into the +# folder where the input file resides +# +# assumes $1 is full path to a large WAV file +# assumes $2 is path to script to run (such as are found in tools/ +# that takes a folder name in /vagrant, and processes all WAVs in it) +# +# produces a single .rttm in the same folder $1 was found in +# +# uses /vagrant/chunk/ for temporary results + +if [[ $# < 2 ]]; then + echo "Usage: " $0 " " + echo " e.g. tools/chunk.sh /vagrant/ami.wav tools/yunitate.sh" + exit +fi + +WORKFOLDER="/vagrant/chunk" + +# remember basename for later ;) +filename=$(basename "$1") +basename="${filename%.*}" # name without extension +dirname=`dirname $1` # input folder + +if [[ -f $WORKFOLDER ]]; then + # clean out the folder first + rm -rf $WORKFOLDER/* +else + # create the folder + mkdir -p $WORKFOLDER +fi + +# Create 5 minute (except for last piece) named chunk-001.wav chunk-002.wav etc. +sox $1 $WORKFOLDER/chunk-.wav trim 0 300 : newfile : restart + +# run whichever tool you were going to run over the $WORKFOLDER folder +# assume tools are like in ~/tools and assume path is /vagrant/ +# but are only given +$2 chunk + +# assume output is in $WORKFOLDER/chunk-00x.rttm - rename/ rejoin + +OUTFILE=$dirname/$basename.rttm +rm -f $OUTFILE # don't want to append to existing one! +touch $OUTFILE + +COUNT=0 +for f in `ls $WORKFOLDER/*chunk-*.rttm`; do + + # add $COUNT seconds to start time (column 4) of RTTM, and concatenate to $OUTFILE + cat $f | awk -v ADDME=$COUNT '{print $1,$2,$3,($4+ADDME),$5,$6,$7,$8,$9}' >> $OUTFILE + + # increment COUNT in 5 minutes' worth of secons (300) + COUNT=$(($COUNT + 300)) + +done + diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh new file mode 100755 index 0000000..61e2195 --- /dev/null +++ b/utils/create_ref_sys.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +audio_dir=$1 +model_prefix=$2 +create_lab=$3 + +base_directory=$(echo "$audio_dir" | awk -F "/" '{print $2}') + +if [ "$base_directory" != "vagrant" ]; then + audio_dir=/vagrant/$1 +fi + +display_usage() { + echo "Given a folder, and a model prefix, creates a folder that contains the reference transcriptions" + echo "and another folder containing the predicted transcriptions." + echo "usage: $0 [audio_dir] [model_prefix] [create_lab]" + echo " audio_dir The directory that contains the audio files and the transcription." + echo " model_prefix The model prefix (beginning of the files generated by the model)." + echo " create_lab (Optional, true or false) Indicates whether to create .lab files in the reference folder." + exit 1 + } + +if ! [[ $# =~ ^(2|3)$ ]]; then + display_usage +fi + +if [ -z "$3" ]; then + create_lab=false +fi + + +if ! [[ $model_prefix =~ ^(ldc_sad|noisemesSad|tocomboSad|opensmileSad|lenaSad|lena|yunitator|\ +diartk_ldcSad|diartk_noisemesSad|diartk_tocomboSad|diartk_opensmileSad|diartk_goldSad|\ +yuniseg_ldcSad|yuniseg_noisemesSad|yuniseg_tocomboSad|yuniseg_opensmileSad|yuniseg_goldSad)$ ]]; then + echo "You're trying to create folders containing the reference transcriptions, and the predicted ones." + echo "However, you specified a wrong tool name." + echo "Please, check the name of the SAD/diarization tool." + exit 1; +fi + + +# Create temp_ref folder +mkdir -p $audio_dir/temp_ref +for wav in `ls $audio_dir/*.wav`; do + base=$(basename $wav .wav) + cp $audio_dir/${base}.rttm $audio_dir/temp_ref/${base}.rttm + # Sort rttm by onset + sort --key 4 --numeric-sort $audio_dir/${base}.rttm -o $audio_dir/temp_ref/${base}.rttm + # Change tabulations to white-spaces + sed -i 's/\t/ /g' $audio_dir/temp_ref/${base}.rttm + # Replace two or more occurrences of whitespace by just one + sed -i 's/ \+/ /g' $audio_dir/temp_ref/${base}.rttm + if [ $create_lab == true ]; then + awk '{print $4" "($4+$5)" speech"}' $audio_dir/temp_ref/${base}.rttm > $audio_dir/temp_ref/${base}.lab + fi +done + +# Create temp_sys folder and copy all of the sys rttm inside of it +# Remove the model_prefix of it +mkdir -p $audio_dir/temp_sys +for rttm in `ls $audio_dir/${model_prefix}_*.rttm`; do + base=$(basename $rttm .rttm) + out=`echo $base | sed "s/${model_prefix}\_//g"` + cp $rttm $audio_dir/temp_sys/${out}.rttm + if [ $create_lab == true ]; then + echo "creating: " $audio_dir/temp_sys/${out}.lab + awk '{print $4" "($4+$5)" speech"}' $rttm > $audio_dir/temp_sys/${out}.lab + fi +done + +# check that temp_sys is not empty, otherwise exit and remove it. +if [ -z "$(ls -A $audio_dir/temp_sys)" ]; then + echo "Didn't find any transcription from the model prefix you specified. Please get the ${model_prefix}_my_file.rttm before" + rm -rf $audio_dir/temp_sys $audio_dir/temp_ref + exit +fi diff --git a/utils/diarization.sh b/utils/diarization.sh new file mode 100755 index 0000000..3c02186 --- /dev/null +++ b/utils/diarization.sh @@ -0,0 +1,184 @@ +#!/bin/bash + +set -o errexit + +if [ $# -ne 2 ]; then + echo "Usage: ./diarization.sh " + exit +fi + +#define the directory where the results will be saved +datadir=$2 + +# make output folder +mkdir -p $2 +echo "$1 1 0 1000000000 U U U 1" > $datadir/show.uem.seg + +if [ -z $LOCALCLASSPATH ]; then +#LOCALCLASSPATH=lib/LIUM_SpkDiarization-4.2.jar +LOCALCLASSPATH=lium_spkdiarization-8.4.1.jar +fi + +#turn off tracing +trace="--trace" +#trace="" +#turn off help text +#help="--help" +help="" + +#the MFCC file +features="$1 1 0 1000000000 U U U 1" + +#the MFCC corresponds to sphinx 12 MFCC + Energy +# sphinx=the mfcc was computed by the sphinx tools +# 1: static coefficients are present in the file +# 1: energy coefficient is present in the file +# 0: delta coefficients are not present in the file +# 0: delta energy coefficient is not present in the file +# 0: delta delta coefficients are not present in the file +# 0: delta delta energy coefficient is not present in the file +# 13: total size of a feature vector in the mfcc file +# 0:0:0: no feature normalization +fInputDesc="sphinx,1:1:0:0:0:0,13,0:0:0" +fInputDesc="audio2sphinx,1:1:0:0:0:0,13,0:0:0" + +#this variable is use in CLR/NCLR clustering and gender detection +#the MFCC corresponds to sphinx 12 MFCC + E +# sphinx=the mfcc is computed by sphinx tools +# 1: static coefficients are present in the file +# 3: energy coefficient is present in the file but will not be used +# 2: delta coefficients are not present in the file and will be computed on the fly +# 0: delta energy coefficient is not present in the file +# 0: delta delta coefficients are not present in the file +# 0: delta delta energy coefficient is not present in the file +# 13: size of a feature vector in the mfcc file +# 1:1:300:4: the MFCC are wrapped (feature warping using a sliding windows of 300 features), +# next the features are centered and reduced: mean and variance are computed by segment +fInputDescCLR="sphinx,1:3:2:0:0:0,13,1:1:300:4" +fInputDescCLR="audio2sphinx,1:3:2:0:0:0,13,1:1:300:4" + + +show="show" + +#get the initial segmentation file +#uem="$2" +uem=$datadir/show.uem.seg + +#set the java virtual machine program +java="java" +#if [ -n $JAVA_BIN ]; then +# java=$JAVA_BIN +#fi + + +#define where the UBM GMM is +ubm=models/ubm.gmm + + +#define where the speech / non-speech set of GMMs is +#pmsgmm=./model/sms.gmms +pmsgmm=models/sms.gmms + +#define where the silence set of GMMs is +sgmm=models/s.gmms + +#define where the gender and bandwidth set of GMMs (4 models) is +#(female studio, male studio, female telephone, male telephone) +ggmm=models/gender.gmms + + +echo "#####################################################" +echo "# $show" +echo "#####################################################" + + + +iseg=./$datadir/$show.i.seg +pmsseg=./$datadir/$show.pms.seg + + +adjseg=./$datadir/$show.adj.h.seg + +# Check the validity of the MFCC +$java -Xmx1024m -classpath $LOCALCLASSPATH fr.lium.spkDiarization.programs.MSegInit $trace $help \ + --fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=$uem --sOutputMask=./$datadir/show.i.seg $show + +# Speech / non-speech segmentation using a set of GMMs +$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MDecode $trace $help \ + --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,0:0:0 --fInputMask=$features --sInputMask=$iseg \ +--sOutputMask=$pmsseg --dPenality=500,500,10 --tInputMask=$pmsgmm $show + +# GLR-based segmentation, make small segments +$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MSeg $trace $help \ + --kind=FULL --sMethod=GLR --fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.i.seg \ +--sOutputMask=./$datadir/show.s.seg $show + +# Linear clustering, fuse consecutive segments of the same speaker from the start to the end +$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MClust $trace $help \ +--fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.s.seg \ +--sOutputMask=./$datadir/show.l.seg --cMethod=l --cThr=2.5 $show + +# Hierarchical bottom-up BIC clustering + $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MClust $trace $help \ +--fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.l.seg \ +--sOutputMask=./$datadir/show.h.seg --cMethod=h --cThr=6 $show + +# Initialize one speaker GMM with 8 diagonal Gaussian components for each cluster + $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MTrainInit $help $trace \ +--nbComp=8 --kind=DIAG --fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.h.seg \ +--tOutputMask=./$datadir/show.init.gmms $show + +# EM computation for each GMM + $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MTrainEM $help $trace \ +--nbComp=8 --kind=DIAG --fInputMask=$features --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.h.seg \ +--tOutputMask=./$datadir/show.gmms --tInputMask=./$datadir/show.init.gmms $show + + # Viterbi decoding using the set of GMMs trained by EM + $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MDecode $trace $help \ +--fInputMask=${features} --fInputDesc=$fInputDesc --sInputMask=./$datadir/show.h.seg \ +--sOutputMask=./$datadir/show.d.seg --dPenality=250 --tInputMask=$datadir/show.gmms $show + + # Adjust segment boundaries near silence sections + $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.tools.SAdjSeg $help $trace \ + --fInputMask=$features --fInputDesc=audio2sphinx,1:1:0:0:0:0,13,0:0:0 --sInputMask=./$datadir/show.d.seg \ +--sOutputMask=$adjseg $show + + # Filter speaker segmentation according to speech / non-speech segmentation +flt1seg=./$datadir/$show.flt1.seg +$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.tools.SFilter $help $trace \ + --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,0:0:0 --fInputMask=$features --fltSegMinLenSpeech=150 --fltSegMinLenSil=25 \ +--sFilterClusterName=music --fltSegPadding=25 --sFilterMask=$pmsseg --sInputMask=$adjseg --sOutputMask=$flt1seg $show + +flt2seg=./$datadir/$show.flt2.seg +$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.tools.SFilter $help $trace \ + --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,0:0:0 --fInputMask=$features --fltSegMinLenSpeech=150 --fltSegMinLenSil=25 \ +--sFilterClusterName=jingle --fltSegPadding=25 --sFilterMask=$pmsseg --sInputMask=$flt1seg --sOutputMask=$flt2seg $show + + + # Split segments longer than 20s (useful for transcription) + splseg=./$datadir/$show.spl.seg + $java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.tools.SSplitSeg $help \ + --sFilterMask=$pmsseg --sFilterClusterName=iS,iT,j --sInputMask=$flt2seg --sSegMaxLen=2000 --sSegMaxLenModel=2000 \ +--sOutputMask=$splseg --fInputMask=$features --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,0:0:0 --tInputMask=$sgmm $show + + + + +#------------------------------------------------------------------------------- +# Set gender and bandwidth +gseg=./$datadir/$show.g.seg +$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MScore $help \ + --sGender --sByCluster --fInputDesc=audio2sphinx,1:3:2:0:0:0,13,1:1:0 --fInputMask=$features --sInputMask=$splseg \ +--sOutputMask=$gseg --tInputMask=$ggmm $show + + + +# NCLR clustering +# Features contain static and delta and are centered and reduced (--fInputDesc) +c=1.7 +spkseg=./$datadir/$show.c.seg +$java -Xmx1024m -classpath "$LOCALCLASSPATH" fr.lium.spkDiarization.programs.MClust $help $trace \ + --fInputMask=$features --fInputDesc=$fInputDescCLR --sInputMask=$gseg \ +--sOutputMask=./$datadir/show.seg --cMethod=ce --cThr=$c --tInputMask=$ubm \ +--emCtrl=1,5,0.01 --sTop=5,$ubm --tOutputMask=./$datadir/$show.c.gmm $show + diff --git a/utils/eaf2enriched_txt.sh b/utils/eaf2enriched_txt.sh new file mode 100755 index 0000000..5234516 --- /dev/null +++ b/utils/eaf2enriched_txt.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +INPUT_FOLDER=$1 +LANG=$2 +SCRIPT_DIR=$(dirname "$0") + +display_usage() { + echo "Given a folder containing eaf file, creates an enriched txt version of them." + echo "For each files, this script produces a txt version containing :" + echo -e "\t onset" + echo -e "\t off" + echo -e "\t speaker" + echo -e "\t cleaned up transcription" + echo -e "\t number of words" + echo -e "\t phonemized (or syllabified) version of the transcription" + echo -e "\t number of syllables" + + echo "usage: $0 [input] [language]" + echo " input The folder where to find the eaf files (REQUIRED)." + echo " output The language of the transcription : english, spanish or tzeltal (REQUIRED)." + exit 1 + } + +if [ -z "$1" ] || [ -z "$2" ] || ! [[ $LANG =~ ^(english|spanish|tzeltal)$ ]]; then + display_usage +fi + +for eaf_path in /vagrant/$1/*.eaf; do + eaf_path=${eaf_path#/vagrant/} + without_extension="${eaf_path%.*}" + echo "Converting $eaf_path files to ${without_extension}.txt ..." + python $SCRIPT_DIR/eaf2txt.py -i $eaf_path + + echo "Enriching ${without_extension}.txt" + $SCRIPT_DIR/selcha2clean.sh ${without_extension}.txt ${without_extension}_enriched.txt $LANG + + rm /vagrant/${without_extension}.txt +done \ No newline at end of file diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py new file mode 100755 index 0000000..c54a1b4 --- /dev/null +++ b/utils/eaf2txt.py @@ -0,0 +1,89 @@ +""" +This script converts an eaf file into a txt file containing the following information : + +onset offset transcription receiver speaker_tier + +It can be run either on a single eaf file, or on a whole folder containing eaf files. + +Example of use : + python tools/eaf2txt.py -i data/0396.eaf # One one file + python tools/eaf2txt.py -i data/ # On a whole folder + +About the naming convention of the output : + For each file called input_file.eaf, the result will be stored in input_file.txt +""" + +import pympi as pmp +import argparse +import os +import glob + + +def eaf2txt(path_to_eaf, output_folder, cleanup=False): + """ + Convert an eaf file to the txt format by extracting the onset, offset, ortho, + and the speaker tier. Note that the ortho field has been made by a human and needs + to be clean up. + + Parameters + ---------- + path_to_eaf : path to the eaf file. + + Write a txt whose name is the same than the eaf's one in output_folder + """ + basename = os.path.splitext(os.path.basename(path_to_eaf))[0] + output_path = os.path.join(output_folder, basename + '.txt') + output_file = open(output_path, 'w') + EAF = pmp.Elan.Eaf(path_to_eaf) + tiers = EAF.tiers + for tier in tiers: + try: + annotations = EAF.get_annotation_data_for_tier(tier) + except KeyError: + print("Tier %s ignored..." %tier) + for annotation in annotations: + parameters = EAF.get_parameters_for_tier(tier) + if 'PARTICIPANT' in parameters: + if len(annotation) == 4: + onset, offset, receiver, transcript = annotation[0], annotation[1], annotation[2], annotation[3] + elif len(annotation) == 3: + onset, offset, receiver, transcript = annotation[0], annotation[1], '', annotation[2] + else: + raise ValueError("Format unknown : %s\n" % annotation) + speaker = parameters['PARTICIPANT'] + + if cleanup: + transcript = clean_up_annotation(transcript) + output_file.write("%d\t%d\t%s\t%s\t%s\n" % (onset, offset, receiver, transcript, speaker)) + output_file.close() + +def main(): + parser = argparse.ArgumentParser(description="convert .eaf into .rttm") + parser.add_argument('-i', '--input', type=str, required=True, + help="path to the input .eaf file or the folder containing eaf files.") + args = parser.parse_args() + + # Initialize the output folder as the same folder than the input + # if not provided by the user. + if args.input[-4:] == '.eaf': + output = os.path.dirname(args.input) + else: + output = args.input + + data_dir = '/vagrant' + args.input = os.path.join(data_dir, args.input) + output = os.path.join(data_dir, output) + + if not os.path.isdir(output): + os.mkdir(output) + + if args.input[-4:] == '.eaf': # A single file has been provided by the user + eaf2txt(args.input, output) + else: # A whole folder has been provided + eaf_files = glob.iglob(os.path.join(args.input, '*.eaf')) + for eaf_path in eaf_files: + print("Processing %s" % eaf_path) + eaf2txt(eaf_path, output) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/utils/elan2rttm.py b/utils/elan2rttm.py new file mode 100755 index 0000000..0b917be --- /dev/null +++ b/utils/elan2rttm.py @@ -0,0 +1,75 @@ +""" +written in python3.5 + +script for translating .eaf annotation files into .rttm format + +WARNING: this version results in a loss of information since .rttm +only keeps speaker ID regardless of the nature of the speech (whereas +.eaf contains additional information such as speech nature e.g. MWU, VCM ...) + +This information might be recovered in an advanced version of this script + +""" + + +import pympi as pmp +import argparse +import os + + +def eaf2rttm(path_to_eaf, path_to_write_rttm): + """ + function to write a new .rttm file which is a transcription of the .eaf + given as input + + """ + + sampling_freq = 1000 + + print('\n') + EAF = pmp.Elan.Eaf(path_to_eaf) + + participants = [] + + for k in EAF.tiers.keys(): + + if 'PARTICIPANT' in EAF.tiers[k][2].keys(): + + if EAF.tiers[k][2]['PARTICIPANT'] not in participants: + + participants.append(EAF.tiers[k][2]['PARTICIPANT']) + + print('participants: {}'.format(participants)) + + base = os.path.basename(path_to_eaf) + name = os.path.splitext(base)[0] + + print('parsing file: {}'.format(name)) + + with open(os.path.join(path_to_write_rttm, name + ".rttm"), "w") as rttm: + + for participant in participants: + + for _, val in EAF.tiers[participant][0].items(): + + start = val[0] + end = val[1] + + t0 = float(EAF.timeslots[start]) / sampling_freq + length = float(EAF.timeslots[end]) / sampling_freq - t0 + + rttm.write(u"SPEAKER {} {} {} {} {} {} {} {}\n".format + (name, 1, "%.2f" % t0, "%.2f" % length, "", "", participant, 1 )) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="convert .eaf into .rttm") + parser.add_argument('-i', '--input', type=str, required=True, + help="path to the input .eaf file.") + parser.add_argument('-o', '--output', type=str, required=True, + help="path to the folder in which to write the output." + "The output .rttm file will have the same name as the " + "input file - except for the extension") + args = parser.parse_args() + +eaf2rttm(args.input, args.output) diff --git a/utils/empty_transcription.sh b/utils/empty_transcription.sh new file mode 100755 index 0000000..a5084ae --- /dev/null +++ b/utils/empty_transcription.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# +# author: the ACLEW team +# +# after all the transcriptions are extracted, +# look for wav file for which no transcription +# exist, and create empty file + +for wav in `ls $1/*.wav`; do + id=$(basename $wav .wav) + eaf=$1/$id.rttm + if [ ! -f $eaf ]; then + touch $eaf + fi +done diff --git a/utils/extract_stats_chi.py b/utils/extract_stats_chi.py new file mode 100755 index 0000000..6ab3bb3 --- /dev/null +++ b/utils/extract_stats_chi.py @@ -0,0 +1,124 @@ +import sys +import argparse +import glob +import os +import re +from collections import OrderedDict + + +def detect_ad_chi_tt(previous_activity, curr_activity, last_silence_dur, chi, mal, fem): + if last_silence_dur <= 2.0: + if (previous_activity in mal and curr_activity in chi) or \ + (previous_activity in fem and curr_activity in chi) or \ + (previous_activity in chi and curr_activity in mal) or \ + (previous_activity in chi and curr_activity in fem): + return 1 + return 0 + + +def compute_statistics(rttm_path, chi, mal, fem): + chi_dur=0.0 + chi_utt=0 + ad_dur=0.0 + ad_utt=0 + ad_chi_tt=0 + + silence_dur = 0 + prev_activity = None + onset_prev = 0 + dur_prev = 0 + + with open(rttm_path,'r') as rttm: + for line in rttm: + line = line.replace('\t', ' ') + line = re.sub('\s+', ' ', line).strip() + anno_fields = line.split(' ') + curr_activity = anno_fields[7] + if curr_activity != 'SIL' and curr_activity != 'S': # We're managing things as if 'SIL' lines weren't exist + onset = float(anno_fields[3]) + dur = float(anno_fields[4]) + + if curr_activity in chi: + chi_dur += dur + chi_utt += 1 + elif curr_activity in mal or curr_activity in fem: + ad_dur += dur + ad_utt +=1 + else: + print("Activity %s not recognized" % (curr_activity)) + sys.exit(1) + + if onset_prev + dur_prev == onset: + silence_dur = 0.0 + else: + silence_dur = onset - onset_prev - dur_prev + + ad_chi_tt += detect_ad_chi_tt(prev_activity, curr_activity, silence_dur, chi, mal, fem) + + # We're managing things as if SIL lines weren't exist + + prev_activity=curr_activity + onset_prev=onset + dur_prev=dur + + filename = os.path.basename(rttm_path).split('.')[0] + res = [filename, chi_dur, chi_utt, ad_dur, ad_utt, ad_chi_tt] + return res + +def write_stats(list_stats, folder): + filename=os.path.join(folder,"stats.txt") + + with open(filename,'w') as fn: + fn.write("filename\tchi_dur\tchi_utt\tad_dur\tad_utt\tad_chi_tt\n") + for stats in list_stats: + fn.write('\t'.join(map(str,stats))+'\n') + +def main(): + parser = argparse.ArgumentParser(description="convert .txt into .rttm") + parser.add_argument('-f', '--folder', type=str, required=True, + help="path to the folder where to find the rttm to analyze." + "Note that all of the rttm are scanned.") + parser.add_argument('--chi', nargs='+', type=str, required=True, + help="labels that need to be considered as being child vocalization.") + parser.add_argument('--mal', nargs='+', type=str, required=True, + help="labels that need to be considered as being male adult speech.") + parser.add_argument('--fem', nargs='+', type=str, required=True, + help="labels that need to be considered as being female adult speech.") + args = parser.parse_args() + + # Below the values that need to be consider when evaluating tsi/lena folder + # prob C22_20170717_5640 + ## Gold files + # chi=['CHI*','C1', 'C2'] + # mal=['MA1','MA2'] + # fem=['MOT*','FA1','FA2'] + + ## Yunitator + # chi = ['CHI'] + # mal = ['MAL'] + # fem = ['FEM'] + + ## Lena N tag + # chi = ['CXN', 'CHN'] + # mal = ['MAN'] + # fem = ['FAN'] + + ## Lena MFC + # chi = ['C'] + # mal = ['M'] + # fem = ['F'] + + ## Lena N and F separated (should be the equivalent of MFC + # chi = ['CHN', 'CXN', 'CHF', 'CXF'] + # mal = ['MAN', 'MAF'] + # fem = ['FAN', 'FAF'] + args.folder=os.path.join('/vagrant', args.folder) + rttm_files = [fn for fn in glob.iglob(os.path.join(args.folder, '*.rttm')) + if 'cutted' not in fn] + list_stats=[] + for rttm_path in rttm_files: + list_stats.append(compute_statistics(rttm_path, args.chi, args.mal, args.fem)) + + write_stats(list_stats, args.folder) +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/utils/frame_cutter.py b/utils/frame_cutter.py new file mode 100755 index 0000000..b181e90 --- /dev/null +++ b/utils/frame_cutter.py @@ -0,0 +1,220 @@ +import sys +import os +import argparse +import re +import glob +import numpy as np +from scipy.io import wavfile + +def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): + """ + Given a rttm file, create a new file whose represents the same rttm cutted in frames. + If one frame has been classified as several classes in the original rttm, it concatenates classes. + Note that all of the frames that have not been classified in the original rttm are considered as being SIL. + Note that it will read the associated wav file to get the total duration of the recording. + + Parameters + ---------- + path_to_rttm : path to the rttm file. + frame_length : frame length. + output_file : path to the output file. + prefix : the prefix that needs to be remove (from rttm) to map the rttm to the wav file. + labels_map : to map the labels from original rttm (values) to the output rttm (keys). + + Write a rttm whose name is the same than the rttm's one suffixed by _cutted.rttm + """ + basename = os.path.splitext(os.path.basename(path_to_rttm))[0] + if prefix != "": + basename = basename.split(prefix)[1] + dirname = os.path.dirname(path_to_rttm) + wav_path = os.path.join(dirname,basename+'.wav') + if os.path.isfile(wav_path): + fs, data = wavfile.read(wav_path) + tot_dur_s = len(data)*1.0/fs + else: + print("Something went wrong while reading the wav file %s. Can not get total duration..." % wav_path) + sys.exit(1) + + frame_length_s = float(frame_length)/1000.0 + frames = np.arange(0.0, tot_dur_s, frame_length_s) + # We don't want to loose any data + if frames[-1] < tot_dur_s: + frames = np.append(frames, frames[-1]+frame_length_s) + + with open(path_to_rttm, 'r') as rttm: + with open(output_file, 'w') as output: + onset_prev_s = 0.0 + dur_prev_s = 0.0 + act_prev = None + append_prev = False + onset_s = None + + for line in rttm: + line = line.replace('\t', ' ') + line = re.sub('\s+', ' ', line).strip() + anno_fields = line.split(' ') + onset_s = float(anno_fields[3]) + dur_s = float(anno_fields[4]) + curr_activity = anno_fields[7] + + if onset_s > onset_prev_s + dur_prev_s : #There's been silence just before ! + sil_dur_s = onset_s - onset_prev_s - dur_prev_s + onset_sil_s = onset_prev_s + dur_prev_s + single_activity_cutter(basename, output, frame_length_s, + sil_dur_s, onset_sil_s, 'SIL', tot_dur_s, labels_map) + act_prev = 'SIL' + dur_prev_s = sil_dur_s + onset_prev_s = onset_sil_s + + single_activity_cutter(basename, output, frame_length_s, + dur_s, onset_s, curr_activity, tot_dur_s, labels_map) + + # Update previous fields + act_prev = curr_activity + dur_prev_s = dur_s + onset_prev_s = onset_s + + # Fill the last one by SILENCE + ## Handle empty rttm + if onset_s is None: + onset_s = 0.0 + dur_s = 0.0 + + if onset_s + dur_s < tot_dur_s: + sil_dur_s = tot_dur_s - onset_s-dur_s + onset_sil_s = onset_s + dur_s + single_activity_cutter(basename, output, frame_length_s, + sil_dur_s, onset_sil_s, 'SIL', tot_dur_s, labels_map) + + +def single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, curr_activity, tot_dur_s, labels_map): + """ + Given an activity, its onset and its duration, cut it into frames of length frame_length_s. + + Parameters + ---------- + basename The basename of the input rttm. + output The path of the output file. + frame_length_s The frame length (in s). + dur_s The duration of the current activity (in s). + onset_s The onset of the current activity (in s). + curr_activity The current activity. + labels_map : To map the labels from original rttm (values) to the output rttm (keys). + + """ + # We don't want to consider any fake labels generated after the duration of the wav file + if onset_s + dur_s > tot_dur_s: + dur_s = max(tot_dur_s - onset_s, 0) + if onset_s > tot_dur_s: + onset_s = 0.0 + + diff_s = onset_s - int(onset_s / frame_length_s) * frame_length_s + onset_s = int(onset_s / frame_length_s) * frame_length_s + n_frames = int((dur_s+diff_s) / frame_length_s) + # Get the output label (we want a full match or nothing) + activity = [k for k,v in labels_map.items() if re.match("("+v+")\Z", curr_activity) is not None] + if len(activity) != 1: + print("Can not map the input label to the output one : %s" % curr_activity) + sys.exit(1) + else: + activity = activity[0] + + for i in range(0, n_frames): + output.write("SPEAKER %s 1 %s %s %s \n" % \ + (basename, onset_s + frame_length_s * i, + str(frame_length_s), activity)) + + if not np.isclose(onset_s + frame_length_s * n_frames, onset_s+dur_s+diff_s, rtol=1e-05, atol=1e-08, equal_nan=False): + output.write("SPEAKER %s 1 %s %s %s \n" % \ + (basename, onset_s + frame_length_s * n_frames, + str(frame_length_s), activity)) + + +def aggregate_overlap(path_to_rttm, output_file): + """ + Given a cutted rttm file, aggregate the activities that happen in the same time. + The class of the generated frame will take the form of spkr1/spkr2 ... + + Parameters + ---------- + path_to_rttm Path to the input rttm file that have been previously cutted. + output_file Path to the output file. + """ + basename = os.path.splitext(os.path.basename(path_to_rttm))[0] + with open(path_to_rttm, 'r') as rttm: + with open(output_file, 'w') as output: + lines = rttm.readlines() + lines = sorted(lines, key=lambda line: float(line.split()[3])) + k = 0 + while k < len(lines): # Loop through the whole file + line_k = lines[k].split() + onset_k, dur_k, act_k = line_k[3], line_k[4], line_k[7] + frame_activity = [act_k] + j = k + 1 + while j < len(lines): # Loop through the activities that have the same onset + line_j = lines[j].split() + onset_j, dur_j, act_j = line_j[3], line_j[4], line_j[7] + if onset_k != onset_j: + output.write("SPEAKER %s 1 %s %s %s \n" % \ + (basename, onset_k, dur_k, '/'.join(frame_activity))) + break + else: # onset_k == onset_j: + if act_j not in frame_activity: + frame_activity.append(act_j) + frame_activity.sort() # Consider alphabetical order + k += 1 + j += 1 + k += 1 + + output.write("SPEAKER %s 1 %s %s %s \n" % \ + (basename, onset_k, dur_k, '/'.join(frame_activity))) + + + + +def main(): + parser = argparse.ArgumentParser(description="convert a rttm file into another rttm cutted in frames.") + parser.add_argument('-i', '--input', type=str, required=True, + help="path to the input .rttm file or the folder containing rttm files.") + parser.add_argument('-l', '--length', type=float, required=False, default=100.0, + help="the frame length in ms (Default to 100 ms).") + parser.add_argument('-p', '--prefix', type=str, default="", + help="the prefix that needs to be removed to map the rttm to the wav.") + args = parser.parse_args() + + labels_map = {"CHI": "CHI.?|CXN|CHN|C.?", + "FEM": "FAN|FAF|FEM|F|MOT.?|FA.?", + "MAL": "MAL|M|MAN|MA.?", + "SIL": "SIL|S"} + + # Initialize the output folder as the same folder than the input + # if not provided by the user. + if args.input[-5:] == '.rttm': + output = os.path.dirname(args.input) + else: + output = args.input + + data_dir = '/vagrant' + args.input = os.path.join(data_dir, args.input) + output = os.path.join(data_dir, output) + + if not os.path.isdir(output): + os.mkdir(output) + + if args.input[-5:] == '.rttm': # A single file has been provided by the user + output = os.path.splitext(args.input)[0]+'_cutted.rttm' + print(output) + cutter(args.input, args.length, output+'.tmp', args.prefix, labels_map) + aggregate_overlap(output+'.tmp', output) + os.remove(output+'.tmp') + else: # A whole folder has been provided + rttm_files = glob.iglob(os.path.join(args.input, '*.rttm')) + for rttm_path in rttm_files: + print("Processing %s" % rttm_path) + output = os.path.splitext(rttm_path)[0] + '_cutted.rttm' + cutter(rttm_path, args.length, output + '.tmp', args.prefix, labels_map) + aggregate_overlap(output + '.tmp', output) + os.remove(output + '.tmp') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/utils/generate_html.py b/utils/generate_html.py new file mode 100755 index 0000000..a5ab577 --- /dev/null +++ b/utils/generate_html.py @@ -0,0 +1,44 @@ +# generate_html.py +""" +Given a list of folders that have been fed to the different models, +generate a html file presenting the following results : + +wip + +Use case : + python tools/generate_html.py -f data/ -o data/html +It will scan folder data/ and generates the html interface at data/html. +""" + +import argparse +import os +import glob +from html_python.files_page import FilesPage +from html_python.models_page import ModelsPage +from html_python.style_css import StyleCSS +from html_python.page import Page + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-f', '--folder', type=str, + help=' Folder that needs to be analyzed', required=True) + parser.add_argument('-o', '--output', type = str, + help=' The folder where the html files will be generated.', required=True) + + args = parser.parse_args() + + # define data dir + data_dir = "/vagrant" + args.folder = os.path.join(data_dir, args.folder) + args.output = os.path.join(data_dir, args.output) + + style_css = StyleCSS(args.output) + files_html = FilesPage(args.output, args.folder) + files_html.write_statistics() + + models_html = ModelsPage(args.output, args.folder) + models_html.write_statistics() + models_html.close() + +if __name__ == '__main__': + main() diff --git a/utils/get_aclewStarter.sh b/utils/get_aclewStarter.sh new file mode 100755 index 0000000..a1909bf --- /dev/null +++ b/utils/get_aclewStarter.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# +# author = the ACLEW Team +# +# Use this script to download the aclew Starter from databrary and start using +# it with the DiViMe. +# This script should be launched from the DiViMe folder, which also contains +# the VagrantFile. + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` + +# url to dataset in zip format +aclewStarter_url=https://nyu.databrary.org/volume/390/zip/true +aclewStarter_folder=databrary390-Bergelson-Warlaumont-Cristia-Casillas-Rosemberg-Soderstrom-Rowland-Durrant-Bunce-Starter-ACLEW + +# create data directory to store dataset and download zip file +if [[ ! -d "aclewStarter" ]]; then + mkdir $BASEDIR/aclewStarter +fi + +cd $BASEDIR/aclewStarter + +echo "downloading the ACLEW Starter Dataset..." +wget $aclewStarter_url + +# unzip archive and keep data when there is both the audio file and +# the transcription. Delete the archive file +unzip true +rm true + +# regroup wavs and transcriptions and remove those that don't have a match +cd $aclewStarter_folder +mkdir transcript +mkdir wav + +mv sessions/*/*.wav wav/ +mv materials*/*.eaf transcript/ + +echo "processing all the ACLEW Starter files..." +for eaf in $(ls transcript/); do + base=$(echo $eaf | cut -d '-' -f 1) + if [[ -f wav/${base}.wav ]]; then + mv transcript/$eaf transcript/${base}.eaf + vagrant ssh -c "python varia/elan2rttm.py -i /vagrant/aclewStarter/$aclewStarter_folder/transcript/${base}.eaf -o /vagrant/aclewStarter/" + mv wav/${base}.wav ../ + else + rm transcript/$eaf + fi +done + +# When all the files are seen, delete the extracted raw folder +cd ../ +rm -rf $aclewStarter_folder + +echo "You can now use the ACLEW Starter dataset!" diff --git a/utils/high_volubility.py b/utils/high_volubility.py new file mode 100755 index 0000000..609ba5b --- /dev/null +++ b/utils/high_volubility.py @@ -0,0 +1,526 @@ +#!/usr/bin/env python +# +# author = The ACLEW Team +# +""" +This script extract short snippets of sound (approx. 10s long), +and runs them through a SAD or diarization tool to detect chunks of audio with : + +1) a lot of speech. +--> python tools/high_volubility.py file_path.wav --sad noisemes_sad + +2) a lot of child speech +--> python tools/high_volubility.py file_path.wav --diar yunitate --mode CHI + +3) a lot of parent-child conversations +--> python tools/high_volubility.py file_path.wav --diar yunitate --mode PCCONV + +4) a lot of adults conversations with a child minimally aware +--> python tools/high_volubility.py file_path.wav --diar yunitate --mode ACCA +""" + +import os +import sys +import re +import wave +import math +import numpy +import argparse +import subprocess + +from operator import itemgetter + + +def get_audio_length(wav): + """ Return duration of Wave file. + + Input: + wav: path to the wav file. + + Output: + dur: float, duration, in seconds, of wav file. + """ + + audio = wave.open(wav, 'r') + frames = audio.getnframes() + rate = audio.getframerate() + duration = frames / float(rate) + audio.close() + + return duration + + +def select_onsets(duration, step): + """ Return list of onsets on which this script will extract the chunks of + 10s + + Input: + duration: float, duration of the daylong recording + + Ouput: + onsets: list[floats], list the onsets on which this script will extract + the chunks of 10s to be run through the SAD tools + """ + return numpy.arange(0.0, duration, step) + + +def extract_chunks(wav, onset_list, chunk_size, temp): + """ Given a list of onset and a length in seconds, extract a snippet of + audio at each onset of this length. The extraction will be done using + SoX, called by subprocess. + + Input: + wav: path to the wav file. + onset_list: list[float], list of the onsets in the 'wav' file at which + we'll extract the segments + chunk_size: float, length in seconds of the chunks of audio this script + will extract. + + Output: + 'temp': the output of this function is the set of small wav file of + 'chunk_size' seconds in the temp folder. + The name of the wav files will be: + id_onset_length.wav + where id is the name of the original wav file, onset is the + onset at which the chunk occurs in the original wav file, and + length is the length of the chunk. + """ + + # for each onset, call SoX using subprocess to extract a chunk. + for on in onset_list: + + # get "id" basename of wav file + basename = os.path.splitext(os.path.basename(wav))[0] + + # create name of output + off = on + chunk_size + str_on = (6 - len(str(on))) * '0' + str(on) + str_off = (6 - len(str(off))) * '0' + str(off) + + chunk_name = '_'.join([basename, str_on, str_off]) + + # call subprocess + cmd = ['sox', wav, + os.path.join(temp, '{}.wav'.format(chunk_name)), + 'trim', str(on), str(chunk_size)] + subprocess.call(cmd) + + +def run_Model(temp_rel, temp_abs, sad, diar=None): + """ When all the snippets of sound are extracted, and stored in the temp + file, run them through a sad or diar tool, and keep + the 10%% that have the most speech. + By default, the function is on the SAD mode. That means that it will + run a SAD model (by default noiseme). However, if the diar parameter is + provided, this function will be on the diarization mode. + + Input: + temp_rel: relative path to the temp folder in which the snippets of + sounds are stored. Here we need the relative path, not the + abs path, since the SAD tool will add the "/vagrant/" part of + the path. + temp_abs: absolute path to the temp folder in which the snippets of + sounds are stored. + sad: name of the sad tool to be used to analyze the snippets of + sound + diar: name of the diar tool to be used to analyze the snippets of + sound. Note that it will use that sad parameter as a choice + of SAD provider. + + Output: + _: In temp, the SAD analyses will be written in RTTM format. + """ + if diar is not None: # Diarization mode + if diar == 'yunitate': + cmd = ['tools/{}.sh'.format(diar), '{}'.format(temp_rel)] + elif diar == 'diartk': + cmd = ['tools/{}.sh'.format(diar), '{}'.format(temp_rel), '{}'.format(sad)] + else: + cmd = ['exit 1'] + else: # SAD mode + cmd = ['tools/{}.sh'.format(sad), '{}'.format(temp_rel)] + + subprocess.call(cmd) + + # After the model has finished running, remove the wav files + for fin in os.listdir(temp_abs): + if fin.endswith('.wav'): + os.remove(os.path.join(temp_abs, fin)) + + +def extract_base_name(filename, diar): + """ + Giving a filename generated by a model and composed of : + model_name + wav_filename + tbeg + tdur + Extracts the base name composed of the three last elements. + + Input: + filename: a filename generated by a model + diar: a diarization model (if provided) + + Output: + base : wavfilename_tbeg_tdur + """ + if diar == 'yunitate': + base = filename.split('_')[1:] + else: + base = filename.split('_')[2:] + + base = os.path.splitext('_'.join(base))[0] + return base + + +def detect_parent_child_conv(previous_activity, curr_activity, last_silence_dur): + """ + Attempts to try if a turn-taking happened between a child and his/her parents + + Input: + previous_activity: the last activity amongst ['CHI', 'MAL', 'FEM'] + curr_activity: the current activity amongst ['CHI', 'MAL', 'FEM'] + last_silence_dur: the duration of the last silence + + Output: + A boolean indicating if a turn-taking happened between a child and his/her parents + True : a turn-taking happened + False : nothing happened + """ + if last_silence_dur <= 2.0: + if (previous_activity == 'MAL' and curr_activity == 'CHI') or \ + (previous_activity == 'FEM' and curr_activity == 'CHI') or \ + (previous_activity == 'CHI' and curr_activity == 'MAL') or \ + (previous_activity == 'CHI' and curr_activity == 'FEM'): + + return True + return False + +def detect_adults_conv(previous_activity, curr_activity, last_silence_dur): + """ + Attempts to try if a turn-taking happened between two adults + + Input: + previous_activity: the last activity amongst ['CHI', 'MAL', 'FEM'] + curr_activity: the current activity amongst ['CHI', 'MAL', 'FEM'] + last_silence_dur: the duration of the last silence + + Output: + A boolean indicating if a turn-taking happened between a child and his/her parents + True : a turn-taking happened + False : nothing happened + """ + if last_silence_dur <= 2.0: + if (previous_activity == 'MAL' and curr_activity == 'FEM') or \ + (previous_activity == 'FEM' and curr_activity == 'MAL') or \ + (previous_activity == 'FEM' and curr_activity == 'FEM') or \ + (previous_activity == 'MAL' and curr_activity == 'MAL'): + + return True + return False + +def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False): + """ When the model has finished producing its outputs, read all the + transcriptions and sort the files by the quantity of their speech + content or the quantity of their speech belonging to the noiseme_class. + + Input: + temp: path to the temp folder in which the snippets of sound are + stored. Here we need the relative path, not the absolute + path, since the SAD tool will add the "/vagrant/" part of + the path. + sad: name of the sad tool to be used to analyze the snippets of + sound. + perc: the percentage of speech to keep. + diar: the diarization model (if provided). + mode: the type of speech that needs to be kept (has to be amongst ['CHI']). + child_aware : (only used if mode == ACCA) Indicates, if we should filter the snippets + that don't present any child activity. + + Output: + sorted_files: list(str), list of the files, sorted by the quantity + of the speech content (as returned by the SAD tool) + or the quantity of the speech content classified as + belonging to the noiseme class (as returned by the + diarization tool). + only 10 %% of all files, that contain the most speech + """ + + # get list of model outputs + all_files = os.listdir(temp_abs) + diar_mode = diar is not None + if diar_mode: + model = diar + else: + model = sad + + # we consider only the annotations that have been generated by the model + annotations = [file for file in all_files if file.startswith(model[:-1])] + + # read all annotations and store duple in list (filename, speech_dur) + files_n_dur = [] + for file in annotations: + + # we extract the base name composed of wav_file_name + t_deg + t_dur + base = extract_base_name(file, diar) + + with open(os.path.join(temp_abs, file), 'r') as fin: + speech_activity = fin.readlines() + + # total duration of the speech of interest + tot_dur = 0.0 + # duration of the last silence + silence_dur = 0.0 + # type of the last activity + previous_activity = None + onset_prev = 0.0 + dur_prev = 0.0 + # variable to detect if the child is aware in ACCA mode. + chi_points = 0.0 + + for line in speech_activity: + anno_fields = line.split(' ') + dur = float(anno_fields[4]) + onset = float(anno_fields[3]) + curr_activity = anno_fields[7] + + + if onset_prev+dur_prev == onset: + silence_dur = 0.0 + else: + silence_dur = onset-onset_prev-dur_prev + + + if not diar_mode: # SAD mode + tot_dur += dur + elif diar_mode and mode == 'CHI' and curr_activity == 'CHI': # Child detection mode + tot_dur += 1 + elif diar_mode and mode == 'PCCONV': # Parent-child detection mode + if detect_parent_child_conv(previous_activity, curr_activity, silence_dur): + # Here we consider more an objective function (number of turn-taking) that + # we want to maximize. That comes from the fact that adults speak during a + # longer time while children speak only for few seconds. And we don't want + # to put too much weight on the adults speech. + tot_dur += 1 + elif diar_mode and mode == 'ACCA': # Adults conversation child aware detection + if detect_adults_conv(previous_activity, curr_activity, silence_dur): + tot_dur += 1 + elif curr_activity == 'CHI': + chi_points += 1 + + previous_activity = curr_activity + onset_prev = onset + dur_prev = dur + + files_n_dur.append((base, tot_dur, chi_points)) + + # remove annotation when finished reading + os.remove(os.path.join(temp_abs, file)) + + if child_aware and diar_mode == 'ACCA': + files_n_dur = [file for file in files_n_dur if file[2] > 3] + + if len(files_n_dur) == 0: + raise ValueError("No moments for the {} mode has been found.\n Try to decrease the step parameter or " + \ + "to increase the size of the chunks.") + + files_n_dur = sorted(files_n_dur, key=itemgetter(1), reverse=True) + + # return top 10%% of snippets + percent = max(1, int(math.ceil(perc * len(files_n_dur)))) + + sorted_files = files_n_dur[:percent] + + return sorted_files + +def new_onsets_two_minutes(sorted_files): + """ + Given a selection of file with lots of speech, + extract new 2minutes long chunks of audio in the original wav, + centered around the short 10s snippets that were analysed. + + Input: + sorted_files: list of the snippets that were selected + because they had lot of speech + temp_abs: absolute path to the temp folder that contains the + snippets + wav: path to the daylong recording + Ouput: + _: in the temp folder, new two minutes long chunks of + audio will be stored. + """ + + # loop over selected files and retrieve their onsets from their name + new_onset_list = [] + for snippet, speech_dur, chi_points in sorted_files: + onset = os.path.splitext(snippet)[0].split('_')[-2] + offset = os.path.splitext(snippet)[0].split('_')[-1] + + length = float(offset) - float(onset) + + # new segment is centered around snippet, so get middle of snippet + new_onset = length / 2 + float(onset) + + new_onset_list.append(new_onset) + + return new_onset_list + +def new_onsets_five_minutes(sorted_files): + """ + Given a selection of file with lots of speech, + extract new 5minutes long chunks of audio in the original wav, + by adding 2 minutes before and 1 minute after the 2minute chunks. + + Input: + sorted_files: list of the snippets that were selected + because they had lot of speech + temp_abs: absolute path to the temp folder that contains the + snippets + wav: path to the daylong recording + Ouput: + _: in the temp folder, new two minutes long chunks of + audio will be stored. + """ + # loop over selected files and retrieve their onsets from their name + new_onset_list = [] + for snippet, speech_dur, chi_points in sorted_files: + onset = os.path.splitext(snippet)[0].split('_')[-2] + offset = os.path.splitext(snippet)[0].split('_')[-1] + + # new segment starts 2 minute before the 2 minute chunk + new_onset = float(onset) - 120.0 + + new_onset_list.append(new_onset) + + return new_onset_list + + +def main(): + """ + Get duration of wav file + Given duration of wav file, extract list of onsets + Given list of onsets in wav file, extract chunks of wav + + Input: + daylong: path to the daylong recording + --step: (optional) step in seconds between each chunk. + By default 600 seconds. + --chunk_size: (optional) size of the chunks to extract. + --temp: (optional) path to a temporary folder to store the + extracted chunks. + --sad: (optional) name of the SAD tool to call to analyse + the chunks. By default noiseme + --diar: (optional) name of the diarization tool to call to analyse + the chunks. No default option + + """ + parser = argparse.ArgumentParser() + + parser.add_argument('daylong', metavar='AUDIO_FILE', + help='''Give RELATIVE path to the daylong recording''' + '''in wav format.''') + parser.add_argument('--step', default=600.0, type=float, + help='''(Optional) Step, in seconds, between each chunk of ''' + '''audio that will be extracted to be analysed by the SAD ''' + '''tool. By default, step=600 seconds (10 minutes)''') + parser.add_argument('--chunk_sizes', nargs=3, + default=[10.0, 120.0, 300.0], type=float, + help='''(Optional) Size of the chunks to extract and analyze. ''' + '''By default it's 10.0 120.0 300.0: \n''' + '''10s chunks are extracted, analyzed by the ''' + '''SAD tool, the 10%% chunks that contain the most speech ''' + '''are kept, than 120s chunks centered on the 10s chunks, ''' + '''these are again analysed by the SAD tool, the 10%% that ''' + ''' contain the most speech are kept, and 300.0s chunks ''' + ''' are finally extracted around these kept chunks.''') + parser.add_argument('--percentage', default=10, type=float, + help='''(Optional) Percentage of snippets to keep at each stage. ''' + '''By default, we keep 10%% of snippets each time.\n''' + '''For a 15h long recording, we have 90x10s snippets, ''' + '''we keep the 10%% with the most speech content, that ''' + '''lead to 9x120s snippets, we again keep the 10%% with the ''' + '''most speech content, so in the end we have 1x300 seconds ''' + '''segment.''') + parser.add_argument('--temp', default='tmp', + help='''(Optional) Path to a temp folder in which the small wav ''' + '''segments will be stored. If it doesn't exist, it will be ''' + '''created.''') + parser.add_argument('--sad', default='noisemes_sad', + help='''(Optional) name of the sad tool that will be used to ''' + '''analyze the snippets of sound''') + parser.add_argument('--diar', + help='''(Optional) name of the diar tool that will be used to ''' + '''analyze the snippets of sound. If this argument is provided by + the user, this script will be on the diarization mode. Otherwise, it will + be on the SAD mode.''') + parser.add_argument('--mode', default='CHI', choices=['CHI', 'PCCONV', 'ACCA'], + help='''(Optional) the noiseme class(es) of interest. ''' + '''Used only when the diar argument is provided.''') + + args = parser.parse_args() + + if args.diar == 'yunitate' and (args.mode == 'PCCONV' or args.mode == 'ACCA' or args.mode == 'CHI'): + if args.chunk_sizes[0] == 10.0: + print("Resetting chunk size at 20.0 seconds (more suitable for CHI/PCCONV/ACCA mode).") + args.chunk_sizes[0] = 20.0 + if args.step == 600.0: + print("Resetting step at 300.0 seconds (more suitable for CHI/PCCONV/ACCA mode).") + args.step = 300.0 + + # Define Data dir + data_dir = "/vagrant" + + # check if temp dir exist and create it if not + temp_abs = os.path.join(data_dir, args.temp) + temp_rel = args.temp # to launch SAD tool we need the relative path to temp + + if not os.path.isdir(temp_abs): + os.makedirs(temp_abs) + + # Define absolute path to wav file + wav_abs = os.path.join(data_dir, args.daylong) + + # get percentage + perc = args.percentage / 100.0 + + # get path to current (tools/) dir - useful to call the SAD tool + dir_path = os.path.dirname(os.path.realpath(__file__)) + + # get duration + duration = get_audio_length(wav_abs) + + # get list of onsets + onset_list = select_onsets(duration, args.step) + + # call subprocess to extract the chunks + extract_chunks(wav_abs, onset_list, args.chunk_sizes[0], temp_abs) + + # analyze using SAD tool + run_Model(temp_rel, temp_abs, args.sad, args.diar) + + # sort by speech duration + sorted_files = read_analyses(temp_abs, args.sad, perc, args.diar, args.mode) + + # get new onsets for two minutes chunks + new_onset_list = new_onsets_two_minutes(sorted_files) + + # extract two minutes chunks + extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[1], temp_abs) + + # analyze using SAD tool + run_Model(temp_rel, temp_abs, args.sad, args.diar) + + # sort by speech duration again + child_aware = False + if args.mode == 'ACCA': + child_aware = True + + sorted_files = read_analyses(temp_abs, args.sad, perc, args.diar, args.mode, child_aware) + + # get new onsets for five minutes chunks + new_onset_list = new_onsets_five_minutes(sorted_files) + + # extract final five minutes long chunks + output_dir = os.path.dirname(wav_abs) + extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[2], output_dir) + + +if __name__ == '__main__': + main() diff --git a/utils/html_python/__init__.py b/utils/html_python/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/utils/html_python/files_page.py b/utils/html_python/files_page.py new file mode 100755 index 0000000..bc56fdd --- /dev/null +++ b/utils/html_python/files_page.py @@ -0,0 +1,179 @@ +import html_python.page as page +import html_python.utils as utils +import html_python.style_css as style_css +import numpy as np +import os +import glob +import random +import numbers +from collections import OrderedDict + + +class FilesPage(page.Page): + + def __init__(self, output_folder, results_folder): + # Initialize self.output_folder & self.results_folder + page.Page.__init__(self, output_folder, results_folder) + + self.N_files = 20 # Fix the number of files to print in the table + + # List of gold files + self.gold_files = [fn for fn in glob.iglob(os.path.join(self.results_folder, '*.rttm')) + if not os.path.basename(fn).startswith(('ldc_sad', 'diartk', 'noisemes_sad', + 'opensmile', 'tocombo_sad', 'lena', 'yunitator'))] + # Name of the html that will be generated + self.name = 'files.html' + + # File descriptor + self.html = open(os.path.join(self.output_folder, self.name), 'w') + + tabs = '\n' + \ + '' + self.html.write(tabs)#write tabs + + # Compute statistics + self._compute_statistics() + + if len(self.audio_stats) > self.N_files: + self.random_indices = np.sort(random.sample(range(0, len(self.audio_stats)), self.N_files)) + else: + self.random_indices = range(0, len(self.audio_stats)) + + def _compute_statistics(self): + + self.audio_stats = [] + self.gold_stats = [] + + # Empty OrderedDict that will contains the unique keys of the gold file + # We use only the keys, it's to fake an OrderedSet that doesn't exist natively in python. + # The difficulty here is that gold2.rttm could have some participants that gold1.rttm doesn't have. + # We still want to consider them in all of the rttm to present the results in a table. + self.gold_keys = OrderedDict({}) + for gold in self.gold_files: #for each reference rttm file + + wav_path = os.path.splitext(gold)[0]+'.wav' + + # Get .wav information + audio_stats_file = utils.analyze_wav(wav_path) + self.audio_stats.append(audio_stats_file) + + # Analyze gold + dur_wav = audio_stats_file['duration (s)'] + gold_stats_file = utils.analyze_rttm(gold, dur_wav) + self.gold_keys = OrderedDict.fromkeys(self.gold_keys.keys() + gold_stats_file.keys()) + self.gold_stats.append(gold_stats_file) + + self._compute_averages() + self.audio_stats = np.array(self.audio_stats) + self.gold_stats = np.array(self.gold_stats) + + def _compute_averages(self): + + # Get audio stats averages + self.averages_audio = OrderedDict(zip(self.audio_stats[0].keys()[2:], [0.0] * (len(self.audio_stats[0]) - 2))) + for line in self.audio_stats: + for key in line.keys(): + if isinstance(line[key], numbers.Number) and line[key] is not None: # None and non numbers are considered as being 0.0 + self.averages_audio[key] += line[key] + + for k, v in self.averages_audio.items(): + self.averages_audio[k] = v/len(self.audio_stats) + + # Get gold stats averages + self.averages_gold = OrderedDict(zip(self.gold_keys.keys()[1:], [0.0] * (len(self.gold_keys) - 1))) + for line in self.gold_stats: + for key in line.keys(): + if isinstance(line[key], numbers.Number) and line[key] is not None: # None and non numbers are considered as being 0.0 + self.averages_gold[key] += line[key] + + for k, v in self.averages_gold.items(): + self.averages_gold[k] = v/len(self.gold_stats) + + + def _write_value(self, value, number_of_digits = 4): + if isinstance(value, str): + self.html.write(' %s \n' % value) + elif isinstance(value, float) or isinstance(value, np.float64) or isinstance(value, np.float32): + self.html.write(' %.*f\n' % (number_of_digits,value)) + elif isinstance(value, int): + self.html.write(' %d \n' % value) + + def write_audio_stats(self): + keys = self.audio_stats[0].keys() + + # Open table + self.html.write('

Audio level statistics

\n\n') + + # Write first line of the table + self.html.write('\n') + for k in keys: + self.html.write('\n' % k) + self.html.write('\n') + + # Write audio statistics + for d in self.audio_stats[self.random_indices]: + self.html.write('\n') + for key, value in d.items(): + self._write_value(value, 4) + + self.html.write('\n') + + # Write averages + self.averages_audio["filename"] = "averages" + for k in keys: + if k in self.averages_audio: + self._write_value(self.averages_audio[k], 4) + else: + self._write_value("") + + # Close table + self.html.write('
%s
') + + + def write_gold_stats(self): + + keys = self.gold_stats[0].keys() + + # Open table + self.html.write('

Annotation level statistics

\n\n') + + # Write first line of the table + self.html.write('\n') + for k in self.gold_keys: + self.html.write('\n' % k) + self.html.write('\n') + + # Write gold statistics + for d in self.gold_stats[self.random_indices]: + self.html.write('\n') + for key in self.gold_keys: + if key in d: + self._write_value(d[key], 2) + else: + self._write_value("") + self.html.write('\n') + + # Write averages + self.averages_gold["filename"] = "averages" + for k in self.gold_keys: + if k in self.averages_gold: + self._write_value(self.averages_gold[k], 2) + else: + self._write_value("") + + # Close table + self.html.write('
%s
') + + def write_statistics(self): + self.write_audio_stats() + self.write_gold_stats() + if len(self.audio_stats) > self.N_files: + self.html.write("

Note : a random sample of %d files has been made to lighten the presentation." % self.N_files) + + def close(self): + self.html.close() \ No newline at end of file diff --git a/utils/html_python/models_page.py b/utils/html_python/models_page.py new file mode 100755 index 0000000..249872c --- /dev/null +++ b/utils/html_python/models_page.py @@ -0,0 +1,103 @@ +import html_python.page as page +import html_python.utils as utils +import numpy as np +import os +import glob +import html_python.style_css as style_css +from collections import OrderedDict + + +class ModelsPage(page.Page): + + def __init__(self, output_folder, results_folder): + # Initialize self.output_folder & self.results_folder + page.Page.__init__(self, output_folder, results_folder) + + # Name of the html that will be generated + self.name = 'models.html' + + # File descriptor + self.html = open(os.path.join(self.output_folder, self.name), 'w') + + tabs = '\n' + \ + '' + self.html.write(tabs) #write tabs + + # List of df files present in the results_folder + self.df_files = [fn for fn in glob.iglob(os.path.join(self.results_folder, '*.df'))] + + def _get_statistics(self): + self.sad_stats = [] + self.diar_stats = [] + for df_path in self.df_files: + basename = os.path.splitext(os.path.basename(df_path))[0] + if basename.startswith(('diartk','lena','yunitator')): + self.diar_stats.append(utils.get_averages(df_path)) + else: + self.sad_stats.append(utils.get_averages(df_path)) + + def _write_SAD_statistics(self): + # Write SAD table + if len(self.sad_stats) == 0: + self.html.write("No SAD model evaluations have been found.") + else: + # Open table + self.html.write('

SAD statistics

\n\n') + # Write first line of the table + self.html.write('\n') + keys = self.sad_stats[0].keys() + for k in keys: + self.html.write('\n' % k) + self.html.write('\n') + + # Write statistics + for d in self.sad_stats: + self.html.write('\n') + for key, value in d.items(): + utils.write_value(self.html, value, 4) + self.html.write('\n') + # Close table + self.html.write('
%s
') + + def _write_diar_statistics(self): + # Write SAD table + if len(self.diar_stats) == 0: + self.html.write("No diarization model evaluations have been found.") + else: + # Open table + self.html.write('

Diarization statistics

\n\n') + # Write first line of the table + self.html.write('\n') + keys = self.diar_stats[0].keys() + for k in keys: + self.html.write('\n' % k) + self.html.write('\n') + + # Write statistics + for d in self.diar_stats: + self.html.write('\n') + for key, value in d.items(): + utils.write_value(self.html, value, 2) + self.html.write('\n') + + # Close table + self.html.write('
%s
') + + def write_statistics(self): + if len(self.df_files) == 0: + self.html.write("No df files have been found... Please run the evaluation of choose another folder.") + else: + self._get_statistics() + self._write_SAD_statistics() + self._write_diar_statistics() + + + + + def close(self): + self.html.close() \ No newline at end of file diff --git a/utils/html_python/page.py b/utils/html_python/page.py new file mode 100755 index 0000000..0c59ba0 --- /dev/null +++ b/utils/html_python/page.py @@ -0,0 +1,30 @@ +from abc import ABCMeta, abstractmethod +import os + +# Used to read the rttm generated by all the different models. +# The first element '' is to handle gold rttm +sad_prefixes = ['ldc_sad_', 'noisemes_sad_', 'tocombo_sad_', 'opensmile_sad_'] +diar_prefixes = ['diartk_goldSad_', 'diartk_ldcSad_', 'diartk_tocomboSad_', + 'diartk_noisemesSad_', 'diartk_opensmileSad_'] + +class Page: + __metaclass__ = ABCMeta + + @abstractmethod + def __init__(self, output_folder, results_folder): + # The output folder where to store the html/css files. + self.output_folder = output_folder + + # The folders that we need to analyze/aggregate + self.results_folder = results_folder + + if not os.path.exists(self.output_folder): + os.makedirs(self.output_folder) + + @abstractmethod + def write_statistics(self): + raise NotImplementedError('subclasses must override write_statistics()!') + + @abstractmethod + def close(self): + raise NotImplementedError('subclasses must override close()!') diff --git a/utils/html_python/style_css.py b/utils/html_python/style_css.py new file mode 100755 index 0000000..db1bc75 --- /dev/null +++ b/utils/html_python/style_css.py @@ -0,0 +1,33 @@ +import os + +css_name = "style.css" # global variable + + +class StyleCSS: + + def __init__(self, output_folder): + # The output folder where to store the html/css files. + self.output_folder = output_folder + + if not os.path.exists(self.output_folder): + os.makedirs(self.output_folder) + + self.css = open(os.path.join(self.output_folder, 'style.css'), 'w') + + # tabs style + tabs_style = "ul {background: #333;list-style: none;overflow: hidden;text-align: center;}\n" + \ + "ul li {display: inline-block;}\n" + \ + "ul li a {padding: 5px 10px;background: #333;color: #fff;line-height: 3em;display: block; }\n" + \ + "ul li a:hover {background: #e4e4e4;color: #333;}\n" + \ + "li.active>a {background: #e4e4e4;color: #333;}\n" + \ + "a {display : block;color : #666;text-decoration : none;padding : 4px;}\n" + + # table style + table_style = "table {margin: 0 auto;}\n" +\ + "td, th {border: 1px solid #ddd;padding: 8px;text-align: center;}\n" +\ + "tr:nth-child(even){background-color: #f2f2f2;}\n" +\ + "tr:hover {background-color: #ddd;}\n" +\ + "th {padding-top: 12px;padding-bottom: 12px;text-align: center;background-color: #333;color: white;}\n" + self.css.write(tabs_style) + self.css.write(table_style) + self.css.close() \ No newline at end of file diff --git a/utils/html_python/utils.py b/utils/html_python/utils.py new file mode 100755 index 0000000..82a1678 --- /dev/null +++ b/utils/html_python/utils.py @@ -0,0 +1,164 @@ +from scipy.io import wavfile +import collections +import numpy as np +import os + + +# Utility functions +def write_value(fn, value, number_of_digits=4): + if isinstance(value, str): + fn.write(' %s \n' % value) + elif isinstance(value, float) or isinstance(value, np.float64) or isinstance(value, np.float32): + fn.write(' %.*f\n' % (number_of_digits, value)) + elif isinstance(value, int): + fn.write(' %d \n' % value) + + +def signaltonoise(a, axis=0, ddof=0): + """ + The signal-to-noise ratio of the input data. + Returns the signal-to-noise ratio of `a`, here defined as the mean + divided by the standard deviation. + Parameters + ---------- + a : array_like + An array_like object containing the sample data. + axis : int or None, optional + If axis is equal to None, the array is first ravel'd. If axis is an + integer, this is the axis over which to operate. Default is 0. + ddof : int, optional + Degrees of freedom correction for standard deviation. Default is 0. + Returns + ------- + s2n : ndarray + The mean to standard deviation ratio(s) along `axis`, or 0 where the + standard deviation is 0. + """ + a = np.asanyarray(a) + m = a.mean(axis) + sd = a.std(axis=axis, ddof=ddof) + return np.where(sd == 0, 0, m / sd) + +def analyze_wav(filepath): + """ + Analyzes a wav file and returns some audio statistics. + Parameters + ---------- + filepath + + Returns + ------- + statistics : + """ + basename = os.path.splitext(os.path.basename(filepath))[0] + + if os.path.splitext(filepath)[1] == '.wav' and os.path.isfile(filepath): + fs, data = wavfile.read(filepath) + data_type = type(data[0]) + if data_type == np.int16: + wav_format = '16-bit PCM' + MAX_WAV_AMP = 32767.0 + elif data_type == np.int32: + wav_format = '32-bit PCM' + MAX_WAV_AMP = 2147483647.0 + elif data_type == np.uint8: + wav_format = '8-bit PCM' + MAX_WAV_AMP = 255.0 + elif data_type == np.float32: + wav_format = '32-bit floating-point' + MAX_WAV_AMP = 1.0 + + # Normalization between -1 and 1 + data = data/MAX_WAV_AMP + + # Compute metrics + duration = len(data)*1.0/fs + mean_amplitude = np.mean(data) + max_amplitude = np.max(data) + snr = float(signaltonoise(data)) + statistics = collections.OrderedDict([("filename", basename), + ("wav format", wav_format), + ("duration (s)", duration), + ("mean amplitude", mean_amplitude), + ("max amplitude", max_amplitude), + ("signal to noise ratio", snr)]) + return statistics + + +def _detect_overlap(t_beg, dur, t_beg_prev, dur_prev): + + if t_beg_prev + dur_prev > t_beg: + if t_beg_prev+dur_prev > t_beg+dur: + return dur + else: + return t_beg_prev + dur_prev - t_beg + return 0.0 + + +def analyze_rttm(filepath, dur_wav): + basename = os.path.splitext(os.path.basename(filepath))[0] + dict = collections.OrderedDict([("filename", basename), + ("% total speech", 0.0), + ("% overlap", 0.0), + ("number of participants", 0)]) + + if os.path.splitext(filepath)[1] == '.rttm' and os.path.isfile(filepath): + fn = open(filepath) + t_beg_prev, dur_prev, participant_prev = 0.0, 0.0, None + for line in fn: + fields = line.split() + type, t_beg, dur, participant = fields[0], float(fields[3]), float(fields[4]), fields[7] + + # Add information about the participant + prop_key = "% of "+participant + if prop_key in dict: + dict[prop_key] += dur + else: + dict[prop_key] = dur + + # Add information about the overall speech + if type == 'SPEAKER': + dict["% total speech"] += dur + + # Compute overlap + dict["% overlap"] += _detect_overlap(t_beg, dur, t_beg_prev,dur_prev) + + # Update previous + t_beg_prev, dur_prev, participant_prev = t_beg, dur, participant + + # Normalization step + # Normalize participants speech duration by total speech + if dict["% total speech"]: + for k, v in dict.items(): + if k.startswith("% of "): + dict["number of participants"] += 1 + dict[k] /= dict["% total speech"] + # Normalize % overlap by total speech + dict["% overlap"] /= dict["% total speech"] + + # Normalize total speech by wav duration + dict["% total speech"] /= dur_wav + + fn.close() + return dict + +def get_averages(df_path): + column_sums = None + basename = os.path.splitext(os.path.basename(df_path))[0] + with open(df_path) as file: + header=file.readline() + header=header.replace('\n','').split('\t') + if header[0] == 'filename': + header=header[1:] + + lines = file.readlines() + rows_of_numbers = [map(float, line.replace('%','').replace('\n','').replace('NA','0.0').split('\t')[1:]) for line in lines] + sums = map(sum, zip(*rows_of_numbers)) + averages = [sum_item / len(lines) for sum_item in sums] + + # Add model name + header.insert(0, 'filename') + averages.insert(0, basename) + averages = collections.OrderedDict(zip(header, averages)) + return averages + diff --git a/utils/its2rttm.py b/utils/its2rttm.py new file mode 100755 index 0000000..f3e190a --- /dev/null +++ b/utils/its2rttm.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# +# author: The ACLEW Team +# +# This script takes as input its file +# and convert it to rttm file. + +import os +import re +import argparse + + +def its_line_2_rttm_line(its_line, rttm_name): + """ + < Segment spkr = "TVF" average_dB = "-49.61" peak_dB = "-38.96" startTime = "PT31819.24S" endTime = "PT31820.61S" / > + to + SPEAKER rttm_name 1 t_beg dur class + """ + its_line = its_line[its_line.find("<"):] + + rttm_line = "" + if its_line[:8] == " " +\ + " " +\ + spkr + " " +\ + " " +\ + "\n" + + return rttm_line + + +def its_2_rttm(input_path, output_path): + """Read a RTTM file indicating gold diarization""" + rttm_name = os.path.splitext(os.path.basename(output_path))[0] + + with open(input_path, 'r') as its: + with open(output_path, 'w') as rttm: + for its_line in its: + rttm_line = its_line_2_rttm_line(its_line, rttm_name) + rttm.write(rttm_line) + +def main(): + """Take transcription file in its format as input, and write """ + """it into rttm format.""" + parser = argparse.ArgumentParser( + description='Take transcription file in its format as input, and write ' + 'it into rttm format.', + add_help=True, + usage='%(prog)s [its] [rttm]') + parser.add_argument( + 'its', type=str, metavar='PATH', + help='Path to the its input') + parser.add_argument( + 'rttm', type=str, metavar='PATH', + help='Path to the rttm output') + + args = parser.parse_args() + + its_2_rttm(args.its, args.rttm) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/utils/its2rttm.sh b/utils/its2rttm.sh new file mode 100755 index 0000000..7f54580 --- /dev/null +++ b/utils/its2rttm.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Given a folder, convert all of the its files to rttm + +SCRIPT_PATH=$(dirname "$(readlink -f "$0")") + +folder=$1 + +if [ -z "$folder" ]; then + echo "You must specify a folder containing its files." + exit +fi + +if [ ! -n "$(ls -A $folder/*.its 2>/dev/null)" ] +then + echo "The folder you specified does not contain any its files." + +fi + +for its_file in $folder/*.its +do + rttm_name=${its_file%.its}.rttm + python $SCRIPT_PATH/its2rttm.py $its_file $rttm_name +done diff --git a/utils/lab2rttm.sh b/utils/lab2rttm.sh new file mode 100755 index 0000000..57f8103 --- /dev/null +++ b/utils/lab2rttm.sh @@ -0,0 +1,30 @@ +#sample rttm file +#SPEAKER NDAR_TC217KM7 1 0.01 0.12 spk7 +# structure is blah filename blah onset dur blah blah speakerid blah +#times are in seconds + +#sample min file +#0 6031 S0 +#structure is onset offset speakerid +#numbers are in seconds + +#takes as input a folder that contains txts +#and will receive the rttm files +#eg ./min2rttm.sh /pylon2/ci560op/acrsta/data/starterACLEW/ + +folder=$1 + +for j in $folder/*.lab +do +#echo $j +#echo "$folder/${subf}_ref.rttm" + subf=`basename ${j} | sed "s/.lab//"` + type=${subf: -5} + + if [ $type != "_lena" ] + then + type="" + fi + subf=`echo $subf | sed "s/_lena//"` + grep ' speech' $j | awk '{print "SPEAKER" " " "'$subf'" " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $folder/${subf}${type}.rttm +done diff --git a/utils/make_big_corpus.sh b/utils/make_big_corpus.sh new file mode 100755 index 0000000..12d08a2 --- /dev/null +++ b/utils/make_big_corpus.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# this script takes as input, for $corpus, the folder containing the daylong recordings +# and the transcriptions in eaf format in a folder raw_$corpus. It reads the transcriptions +# in the eaf files and cuts the wav to only keep the transcribed part, and convert the transcribed +# part into rttm with the same names as the cut wavs. + +# take the name of the corpus as input and define the hard coded paths - they shall not change! +corpus=$1 # should be chosen between BER, WAR, SOD and CAS +working_dir=/DATA2T/aclew_data_update +daylong_dir=/DATA2T/aclew_daylong_data +temp_dir=$working_dir/temp # create temp dir to store wav. will be removed at end of script + +# Define function to check if all small wavs have an rttm. If not, create an empty one. +create_empty_rttm() { + # check the wav files and the talker_roles to see if the rttm exists + # if it doesn't, create an empty rttm file. + wav=$1 + rttms=$2 + for fin in `ls $wav/*.wav`; do + basename=$(basename $fin .wav) + if [[ ! -f $rttms/${basename}.rttm ]]; then + touch $rttms/${basename}.rttm + fi + done +} + +## Treat BER WAR the "simple way", add parameters to take into account the format of CAS and SOD/SOD2 +#if [[ $corpus == 'BER' ]] || [[ $corpus == 'WAR' ]] || [[ $corpus == 'CAS' ]]; then +if [[ $corpus != 'SOD2' ]] ; then + mkdir -p $temp_dir/$corpus/SAD + for wav in `ls $daylong_dir/$corpus/*.wav`; do + base=$(basename $wav .wav) + eaf=raw_$corpus/${base}.eaf + if [[ $corpus == 'CAS' ]]; then + python $working_dir/adjust_timestamps.py $working_dir/github_data/$eaf $wav $temp_dir --CAS + else + python $working_dir/adjust_timestamps.py $working_dir/github_data/$eaf $wav $temp_dir 2>&1 + fi + # now remove old wav and transcriptions: + + done + rm $working_dir/ACLEW_data/databrary_ACLEW/wavs/${corpus}_*wav $working_dir/ACLEW_data/databrary_ACLEW/talker_role/${corpus}_*rttm + mv $temp_dir/*.rttm $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ + mv $temp_dir/*.wav $working_dir/ACLEW_data/databrary_ACLEW/wavs/ + + # create empty rttms when the wav has no transcription (nobody's talking)' + #create_empty_rttm $corpus/treated $corpus/treated/talker_role + + # Now create the SAD + rm $working_dir/ACLEW_data/databrary_ACLEW/SAD/${corpus}_*rttm + python remove_overlap_rttm.py $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ $working_dir/ACLEW_data/databrary_ACLEW/SAD +fi + +# SOD : the eaf have the same name as the wav, but they added '-$name' where $name is the initials of the annotator +if [[ $corpus == 'SOD2' ]]; then + echo "treating SOD" 2>&1 + corpus=SOD + mkdir -p $temp_dir/$corpus/SAD + for wav in `ls $daylong_dir/$corpus/*.wav`; do + base=$(basename $wav .wav) + eaf=raw_$corpus/${base}-TS.eaf + if [ ! -f $working_dir/github_data/$eaf ]; then + eaf=raw_$corpus/${base}-JK.eaf + fi + python $working_dir/adjust_timestamps.py $working_dir/github_data/$eaf $wav $temp_dir 2>&1 + + done + mv $temp_dir/*.rttm $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ + mv $temp_dir/*.wav $working_dir/ACLEW_data/databrary_ACLEW/wavs/ + + # Now create the SAD + python remove_overlap_rttm.py $working_dir/ACLEW_data/databrary_ACLEW/talker_role/ $working_dir/ACLEW_data/databrary_ACLEW/SAD + +fi +# create empty rttms when the wav has no transcription (nobody's talking)' + +#create_empty_rttm $corpus/treated $corpus/treated/talker_role + +# Now create the SAD +#python remove_overlap_rttm.py $corpus/treated/talker_role $corpus/treated/SAD + + +## CAS : the eaf don't have the 'on_off' tier to encode the segments, instead it's called "code" - this is taken +## into account in adjust_timestamps.py with the --CAS parameter +#if [[ $corpus == 'CAS' ]]; then +# #convert2wav $corpus +# mkdir -p $corpus/treated/SAD +# for wav in `ls $corpus/*.wav`; do +# base=$(basename $wav .wav) +# eaf=$corpus/raw_$corpus/${base}.eaf +# python $working_dir/adjust_timestamps.py $eaf $wav --CAS +# done +#fi +## create empty rttms when the wav has no transcription (nobody's talking)' +# +#create_empty_rttm $corpus/treated $corpus/treated/talker_role +# +## Now create the SAD +#python remove_overlap_rttm.py $corpus/treated/talker_role $corpus/treated/SAD +##done +# diff --git a/utils/noisemes_full.sh b/utils/noisemes_full.sh new file mode 100755 index 0000000..b93fcf5 --- /dev/null +++ b/utils/noisemes_full.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run OpenSAT with hard coded models & configs found here and in /vagrant +# assumes Python environment in /home/${user}/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to OpenSAT (go on folder up and to opensat) +OPENSATDIR=$(dirname $BASEDIR)/OpenSAT + +if [ $# -ne 1 ]; then + echo "Usage: noisemes_full.sh " + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of OpenSAT +cd $OPENSATDIR + +# first features +echo "extracting features for noisemes_full" +for file in `ls $audio_dir/*.wav`; do + SSSF/code/feature/extract-htk-vm2.sh $file +done + + + + +# then confidences +#/home/vagrant/anaconda/bin/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename +echo "predicting classes" +#$conda_dir/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename +$conda_dir/python SSSF/code/predict/1-confidence-vm4.py $audio_dir +echo "noisemes_full finished running" + +# take all the .rttm in /vagrant/data/hyp_sum and move them to /vagrant/data - move features and hyp_sum to another folder also. +for sad in `ls $audio_dir/hyp_sum/*.rttm`; do + _rttm=$(basename $sad) + rttm=$audio_dir/noiseme_full_${_rttm} + mv $sad $rttm +done + +# simply remove hyp and feature +rm -rf $audio_dir/feature $audio_dir/hyp_sum + +#if [ ! -d "$audio_dir/noiseme_full_temp" ]; then +# mkdir -p $audio_dir/noiseme_full_temp +#fi +# +#if [! -d "$audio_dir/noiseme_full_temp" ]; then +# mv $audio_dir/hyp_sum $audio_dir/noiseme_full_temp +#else +# echo "can't move hyp_sum/ folder to noiseme_full_temp/ because temp is already full" +#fi +# +#if [! -d "$audio_dir/noiseme_full_temp" ]; then +# mv $audio_dir/feature $audio_dir/noiseme_full_temp +#else +# echo "can't move features/ folder to noiseme_full_temp/ because temp is already full" +#fi +# diff --git a/utils/parse_cha_xml.py b/utils/parse_cha_xml.py new file mode 100755 index 0000000..f9a561f --- /dev/null +++ b/utils/parse_cha_xml.py @@ -0,0 +1,191 @@ +# parse_cha_xml.py +# +# Given CHATTER format xml (http://talkbank.org/software/chatter.html) +# supplied as an argument, or via a pipe, print out STM format text +# +# To toggle whether UNIBET words are printed out, or instead appear as "" +# set the switch --oov. To instead print their replacements, set the switch --replacment +# +# usage ./parse_cha_xml.py P1_6W_SE_C6.xml +# +# Change Log: +# 17 Jan 2018 - print plaintext utterances even if no timecode present +# - added handling of "happening" and formType elements +# to support things like "singing", yell, shout etc. +# - added metadata for speaker e.g. as +# found in 'participant' tags + +from xml.dom.minidom import parse +import sys,argparse,os + +reload(sys) +sys.setdefaultencoding("utf-8") + +parser=argparse.ArgumentParser(description="""Description""") +parser.add_argument('--oov', action='store_true', help='print symbols for nonwords') +parser.add_argument('--replacement', action='store_true', help='print replacement words') +parser.add_argument('--stm', action='store_true', help='produce STM format') +parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), help='CHATTER (xml) format input file', + default=sys.stdin) +args=parser.parse_args() + +# a table of speaker IDs and related metadata + +infile = args.infile.name +if infile == '': + dom = parse(sys.stdin) +else: + dom = parse(infile) +utts = dom.getElementsByTagName('u') # utterances +participants = dom.getElementsByTagName('participant') + +oov = args.oov +stm = args.stm +replace = args.replacement +#recording = infile[infile.rfind("/")+1:] +# get only base name (chop off .xml extension) +recording = os.path.splitext(os.path.basename(infile))[0] + +#utterance = "" + +parts = {} +for part in participants: + label = "<"; ident = "" + name = ""; role = ""; sex = "u" + for key in part.attributes.keys(): + if key == "id": + ident = part.attributes[key].nodeValue.encode('utf8') + if key == "name": + name = part.attributes[key].nodeValue.encode('utf8') + name = name.replace(" ","") + if key == "role": + role = part.attributes[key].nodeValue.encode('utf8') + role = role.replace(" ","") + if key == "sex": + sex = part.attributes[key].nodeValue.encode('utf8') + if sex == "male": sex = "m" + if sex == "female": sex = "f" + parts[ident]=("<"+name+","+sex+","+role+">").lower() +# print parts[ident] + +# add the word found inside node passed in as argument +def addWord( node ): + global utterance + for wordlet in node.childNodes: + if wordlet.nodeType == wordlet.TEXT_NODE: + unibet = False + s = wordlet.nodeValue + try: s.decode('ascii') + except UnicodeDecodeError: unibet = True + utterance += " " + if oov and unibet: + utterance += "" + else: + utterance += wordlet.nodeValue.encode('utf8') + + +def addReplacement ( group ): + added = False + for subword in group.childNodes: + if subword.nodeType == subword.ELEMENT_NODE and subword.tagName == 'replacement': + for replacement in subword.childNodes: + if replacement.nodeType == replacement.ELEMENT_NODE and replacement.tagName == 'w': + addWord( replacement ) + added = True + # didn't find a - just output the word + if not added: addWord( group ) + +def addUnibetOrReplacement( node ): + global utterance + for key in node.attributes.keys(): + if key == "untranscribed": + if oov: + utterance += " " + "" + else: + addWord( node ) + if key == "type" and (node.attributes[key].nodeValue == "fragment"): + utterance += " " + node.firstChild.nodeValue + if key == "formType": + if node.attributes[key].nodeValue == "UNIBET": + if replace: + addReplacement( node ) + else: + addWord( node ) + else: # for all other form types + # e.g. singing, babbling, kana, onomotapoeia, family-specific, letter, child-invented + # output word + addWord( node ) + +for utt in utts: + utterance = "" + start = 0 + has_timecode = False + # speaker + for key in utt.attributes.keys(): + if key == "who": + speaker=utt.attributes[key].nodeValue + spk_reco_clause = recording+" "+speaker+" "+recording+"_"+speaker + + for word in utt.childNodes: + # time code + if word.nodeType == word.ELEMENT_NODE and word.tagName == 'media': + has_timecode = True + for key in word.attributes.keys(): + if key == "start": + start = word.attributes[key].nodeValue + if key == "end": + end = word.attributes[key].nodeValue + if stm: + # Don't output if start == end; confuses downstream systems + if start != end: + print spk_reco_clause+" "+start+" "+end+" "+parts[speaker]+\ + utterance.lower().replace("_"," ").replace("-","") + sys.stdout.flush() + else: + print utterance.lower().replace("_"," ").replace("-","") + sys.stdout.flush() + utterance = "" + + # tb:wordType ("" tag) + if word.nodeType == word.ELEMENT_NODE and word.tagName == 'w': + if len(word.attributes.keys())==0: + if word.childNodes.length == 1: + addWord( word ) + else: + if replace: + addReplacement( word ) + else: + addWord( word ) + else: + addUnibetOrReplacement( word ) + # tb:element type ("" tag): + if word.nodeType == word.ELEMENT_NODE and word.tagName == 'e': + for wordlet in word.childNodes: + if wordlet.nodeType == wordlet.ELEMENT_NODE and wordlet.tagName == 'happening': + for txt in wordlet.childNodes: + thetxt = txt.nodeValue + utterance += " <" + thetxt.encode('utf8') + ">" + # tb:groupType or phoneticGroupType ("" or "" tag): + if word.nodeType == word.ELEMENT_NODE and (word.tagName == 'g' or word.tagName == 'pg'): + for group in word.childNodes: + if group.nodeType == group.ELEMENT_NODE and group.tagName == 'w': + if len(group.attributes.keys())==0: + if group.childNodes.length == 1: + addWord( group ) + else: + if replace: + addReplacement( group ) + else: + addWord( group ) + else: + # print oov (or unibet encoded word) + if oov: + utterance += " " + "" + else: + addUnibetOrReplacement( group ) + # done with utterance. if it had no timecode, was not printed(!) so + # print now + if not has_timecode: + print utterance.lower().replace("_"," ").replace("-","") + sys.stdout.flush() + utterance = "" diff --git a/utils/rttm2labels.py b/utils/rttm2labels.py new file mode 100755 index 0000000..0cca5f4 --- /dev/null +++ b/utils/rttm2labels.py @@ -0,0 +1,41 @@ +#! /usr/bin/python +''' +Created on Oct 4, 2014 +@author: fmetze,er1k +convert RTTM (segmented) to Audacity labels format +''' + +import sys +import datetime +import re + +def printbuf (begin, end, text): + datetime1 = datetime.datetime.utcfromtimestamp(begin) + datetime2 = datetime.datetime.utcfromtimestamp(end) + allseconds1 = 60 * datetime1.minute + 3600 * datetime1.hour + datetime1.second + allseconds2 = 60 * datetime2.minute + 3600 * datetime2.hour + datetime2.second + print "%s.%s\t%s.%s\t%s" % (allseconds1, datetime1.strftime('%f'), allseconds2, datetime2.strftime('%f'), text) + + +for l in sys.stdin: + + m = re.match("^(.*) (.*) (.*) (\S+) (\S+) (.*) (.*) (.*) (.*)$", l) + if m: + type, file = m.group(1, 2) + channel = int(m.group(3)) + starttime = float(m.group(4)) + duration = float(m.group(5)) + ortho = m.group(6) + stype = m.group(7) + name = m.group(8) + conf = m.group(9) + + printbuf (starttime, starttime+duration, name) + begin = starttime + + elif re.match(";.*", l) or re.match("#.*", l): + pass + + else: + raise Exception("cannot process line: " + l) + diff --git a/utils/rttm2scp.py b/utils/rttm2scp.py new file mode 100755 index 0000000..f7b0008 --- /dev/null +++ b/utils/rttm2scp.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# +# author: The ACLEW Team +# +# This script takes as input gold rttm file +# that transcribes a diarization, and converts it +# to a gold scp file indicating Speech Activity. +# It is necessary, to avoid overlaps between speech intervals +# and to sort the intervals by onsets. + +import os +import sys +import argparse +from intervaltree import IntervalTree, Interval +from operator import itemgetter + +def read_rttm(input_path): + """Read a RTTM file indicating gold diarization""" + with open(input_path, 'r') as fin: + # RTTM format is + # SPEAKER fname 1 onset duration spkr + rttm = fin.readlines() + #sad = IntervalTree() + all_intervals = [] + fname = "" + for line in rttm: + row = line.strip('\n').split() + fname, onset, dur = row[1], row[3], row[4] + if float(dur) == 0: + # Remove empty intervals + continue + elif float(dur) < 0: + print("{} shows an interval with negative duration." + " Please inspect file, this shouldn't happen".format( + line)) + continue + + # add interval to list + all_intervals.append((float(onset), float(onset) + float(dur))) + + # sort intervals by their onset + all_intervals.sort() + + # look at each interval, add them in growing order of onset, + # trim the beginning if it overlaps with previous interval, + # and completely delete if it is contained by the previous interval. + sad = [] + prev_on = 0 + prev_off = 0 + for onset, offset in all_intervals: + if len(sad) == 0: + # don't check anything for first interval + sad.append((onset, offset)) + prev_on = onset + prev_off = offset + continue + + if onset < prev_off: + if offset <= prev_off: + # interval is completely contained in the previous one + continue + onset = prev_off + + sad.append((onset, offset)) + prev_on = onset + prev_off = offset + + return sad, fname + +def write_scp(out_intervals, fname, output): + """Write output in SCP format""" + + with open(output, 'w') as fout: + fout.write(u'') # write empty string in case out_intervals is empty + for onset, offset in out_intervals: + fout.write(u'{fname}_{on}_{off}={fname}.fea[{on},{off}]\n'.format( + fname=fname, + on=int(onset*100), + off=int(offset*100))) + +def main(): + """Take diarization in RTTM format as input, and write """ + """SAD in scp format, with ordered intervals, as output.""" + parser = argparse.ArgumentParser( + description='Take diarization in RTTM format as input, and write ' + 'SAD in scp format, with ordered intervals, as output.', + add_help=True, + usage='%(prog)s [RTTM] [SCP]') + parser.add_argument( + 'rttm', type=str, metavar='PATH', + help='Path to the RTTM input') + parser.add_argument( + 'scp', type=str, metavar='PATH', + help='Path to the SCP output') + + args = parser.parse_args() + + sad_tree, fname = read_rttm(args.rttm) + write_scp(sad_tree, fname, args.scp) + +if __name__ == "__main__": + main() diff --git a/utils/rttm2scp.sh b/utils/rttm2scp.sh new file mode 100755 index 0000000..6dc3176 --- /dev/null +++ b/utils/rttm2scp.sh @@ -0,0 +1,17 @@ +#sample rttm file +#SPEAKER NDAR_TC217KM7 1 0.01 0.12 spk7 +# structure is blah filename blah onset dur blah blah speakerid blah +# +#sample scp file: +#BER_0713_07_02_21041_-1_60=BER_0713_07_02_21041.scp[-1,60] +#structure of scp file is: +#filename_begining_end=features[begining,end] + +rttm_in=$1 +basename=$2 +featfile=$3 +scp_out=$4 + + +grep SPEAKER $rttm_in | awk -v base="$basename" -v feats="$featfile" '{begg=$4*100;endd=($4+$5)*100; print base "_" begg "_" endd "="feats "[" begg "," endd "]"}' > $scp_out + diff --git a/utils/runTALNet.sh b/utils/runTALNet.sh new file mode 100755 index 0000000..6da0d8d --- /dev/null +++ b/utils/runTALNet.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run 537 class classifier with hard coded models & configs found here +# assumes Python environment in /home/${user}/anaconda/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to classify tool (go one folder up and to 537cls) +CLASSIFY=$(dirname $BASEDIR)/TALNet + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "in /vagrant containing wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of TALNet +cd $CLASSIFY + +# Iterate over files +echo "Starting" +for f in `ls ${audio_dir}/*.wav`; do + ./runTALNet.sh $f + base=$(basename $f .wav) + mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat +done + +echo "$0 finished running" diff --git a/utils/selcha2clean.sh b/utils/selcha2clean.sh new file mode 100755 index 0000000..379a017 --- /dev/null +++ b/utils/selcha2clean.sh @@ -0,0 +1,169 @@ +#!/usr/bin/env bash +# Given a txt file containing the following fields : onset offset transcription receiver speaker_tier (Note that eaf2txt.py generates such kind of files) +# Returns an enriched version of it by cleaning the transcription field, syllabifying (or phonemizing it), counting the number of words, and the number of syllables + +LC_CTYPE=C +#########VARIABLES +#Variables that have been passed by the user +SELFILE=$1 +ORTHO=$2 +LANG=$3 +######### + + +display_usage() { + echo "Given a txt files containing the following fields : onset offset transcription receiver speaker_tier" + echo "and a language, returns an enriched version of this file by :" + echo -e "\t 1) Cleaning the transcription field (removing human-made errors)" + echo -e "\t 2) Counting the number of words" + echo -e "\t 3) Phonemizing (if english)/Syllabifying (if spanish or tzeltal) the transcription" + echo -e "\t 4) Counting the number of syllables" + echo "usage: $0 [input] [output] [language]" + echo " input The file path where to find the input txt file (REQUIRED)." + echo " output The output path (REQUIRED)." + echo " language The language of the transcription : english, spanish or tzeltal (REQUIRED)." + exit 1 + } + +if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || ! [[ $LANG =~ ^(english|spanish|tzeltal)$ ]]; then + display_usage +fi + +# Get relative and absolute paths that we need. +DATA_DIR=/vagrant +SELFILE_ABS="$DATA_DIR/$SELFILE" +ORTHO_ABS="$DATA_DIR/$ORTHO" +DIRNAME_ABS=$(dirname "${ORTHO_ABS}") +CLEAN_TRANSCRIPT_ABS=$DIRNAME_ABS"/clean_transcript.txt" +PHONEMIZED_ABS=$DIRNAME_ABS"/phonemized.txt" +DIRNAME_REL=$(dirname "${ORTHO}") +CLEAN_TRANSCRIPT_REL=$DIRNAME_REL"/clean_transcript.txt" +PHONEMIZED_REL=$DIRNAME_REL"/phonemized.txt" + +echo "Cleaning $SELFILE" + + +### HANDLING REPETITIONS ### +###  word [x2] ### +### or [x2]   ### +cut -f 4 -d$'\t' $SELFILE_ABS | +sed "s/\[ \+/\[/g" | +sed "s/ \+\[/\[/g" | +sed -r "s/\[X([0-9]+)/\[x\1/g" | +sed "s/> \+/>/g" > ${CLEAN_TRANSCRIPT_ABS}.tmp + +python -c " +import re +for line in open(\"${CLEAN_TRANSCRIPT_ABS}.tmp\"): + + if '<' in line and '>' in line: + newline = re.sub('<(.*)>\[x([0-9]+)\]', r'\1 \2', line) + if newline != line: + n = int(newline[-2:-1]) + newline = newline[:-2]*n + else: + newline = line + else: + reg = re.sub('(.*)\[x([0-9]+)\]', r'\1\2', line) + newline=[] + for word in reg.split(): + if word[-1].isdigit(): + newline += [word[:-1]]*int(word[-1]) + else: + newline += [word] + newline = ' '.join(newline) + newline = newline.rstrip() # Remove all \newline and let the print function puts only one of them + print(newline) +" > ${CLEAN_TRANSCRIPT_ABS}2.tmp + + +### CLEAN human-made inconsistencies + +cat ${CLEAN_TRANSCRIPT_ABS}2.tmp | +sed "s/\_/ /g" | +sed '/^0(.*) .$/d' | +sed 's/\..*$//g' | #this code deletes bulletpoints (Û+numbers +sed 's/\?.*$//g' | +sed 's/\!.*$//g' | +tr -d '\"' | +tr -d '\^' | #used to be identical to previous line +tr -d '\/' | +sed 's/\+/ /g' | +tr -d '\.' | +tr -d '\?' | +tr -d '!' | +tr -d ';' | +tr -d '\<' | +tr -d '\>' | +tr -d ',' | +tr -d ':' | +tr -d '~' | +sed 's/&=[^ ]*//g' | +sed 's/&[^ ]*//g' | #delete words beginning with & ##IMPORTANT CHOICE COULD HAVE CHOSEN TO NOT DELETE SUCH NEOLOGISMS/NONWORDS +sed 's/\[[^[]*\]//g' | #delete comments +#sed 's/([^(]*)//g' | #IMPORTANT CHOICE -- UNCOMMENT THIS LINE AND COMMENT OUT THE NEXT TO DELETE MATERIAL NOTED AS NOT PRONOUNCED +sed 's/(//g' | sed 's/)//g' | #IMPORTANT CHOICE -- UNCOMMENT THIS LINE AND COMMENT OUT THE PRECEDING TO REMOVE PARENTHESES TAGGING UNPRONOUNCED MATERIAL +sed 's/xxx//g' | +sed 's/www//g' | +sed 's/XXX//g' | +sed 's/yyy//g' | +sed 's/0*//g' | +sed 's/[^ ]*@s:[^ ]*//g' | #delete words tagged as being a switch into another language +#sed 's/[^ ]*@o//g' | #delete words tagged as onomatopeic +sed 's/@[^ ]*//g' | #delete tags beginning with @ IMPORTANT CHOICE, COULD HAVE CHOSEN TO DELETE FAMILIAR/ONOMAT WORDS +sed "s/\'/ /g" | +tr -s ' ' | +sed 's/ $//g' | +sed 's/^ //g' | +sed 's/^[ ]*//g' | +sed 's/ $//g' | +#sed '/^$/d' | # We don't want to remove end lines here +sed '/^ $/d' | +sed 's/\^//g' | +sed 's/\-//g' | +sed 's/\[\=//g' | # We observed [= occurrences that we're not interested in. Has to be careful about that one +sed 's/[0-9]//g' | # We remove all of the remaining numbers +#tr -d '\t' | +awk '{gsub("\"",""); print}' > ${CLEAN_TRANSCRIPT_ABS}3.tmp + +SCRIPT_DIR=$(dirname "$0") +$SCRIPT_DIR/syllabify.sh ${CLEAN_TRANSCRIPT_REL}3.tmp ${PHONEMIZED_REL} $LANG + +## Append number of words to the clean transcription +cat ${CLEAN_TRANSCRIPT_ABS}3.tmp | awk -F'[ ]' '{print $0"\t"NF}' > ${CLEAN_TRANSCRIPT_ABS} + +## Concatenate those 2 files +python -c " +import re +transcript_f = open(\"${CLEAN_TRANSCRIPT_ABS}\") +phonemized_f = open(\"${PHONEMIZED_ABS}\") + +for transcript_l in transcript_f.readlines(): + nb_words = transcript_l.split('\t')[1] + if int(nb_words) == 0: + x=2 + print(\"\t0\t\t0\") + else: + phoneme_l = phonemized_f.readline() + transcript_l = transcript_l.rstrip() + phoneme_l = phoneme_l.rstrip() + print(transcript_l+'\t'+phoneme_l) +" > $ORTHO_ABS.tmp + +## Now we concatenate the original csv files and the clean ortho (by column) +### Extract everything except transcript column from the original file +cut -f1,2,3,5 -d$'\t' $SELFILE_ABS > ${ORTHO_ABS}2.tmp + +### Concatenate the latter columns to the clean one contained in _tmp3.txt +paste -d$'\t' ${ORTHO_ABS}2.tmp ${ORTHO_ABS}.tmp > $ORTHO_ABS + +##This is to process all the "junk" that were generated when making the +##changes from included to ortho. For e.g., the cleaning process +##generated double spaces between 2 words (while not present in +##included) +sed -i -e 's/ $//g' $ORTHO_ABS + +# Remove temporary files +rm ${DIRNAME_ABS}/*.tmp +rm ${CLEAN_TRANSCRIPT_ABS} +rm ${PHONEMIZED_ABS} \ No newline at end of file diff --git a/utils/sum-rttm.sh b/utils/sum-rttm.sh new file mode 100755 index 0000000..056d831 --- /dev/null +++ b/utils/sum-rttm.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# sum-rttm.sh +# +# Compute and print the number of lines in an RTTM, and the sum of durations +# for use in comparing system outputs +# +# Takes 1 argument: path to an RTTM file + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "where RTTMfile is an RTTM filename" + exit 1 +fi + +LINES=`cat $1 | wc -l` +SUM=`awk '{SUM+=$5} END {print SUM}' $1` + +echo -e 'LINES: '$LINES'\tDURATION SUM: '$SUM'\tFILE: '$1 diff --git a/utils/syllabify.sh b/utils/syllabify.sh new file mode 100755 index 0000000..0c3444f --- /dev/null +++ b/utils/syllabify.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Given an input file (containing raw text), an output one, and a language (english, spanish or tzeltal) +# Write in the output file the phonemization (if english) or the syllabification (if spanish or tzeltal) of it, +# and count the number of syllables +### Script parameters +INPUT=$1 +OUTPUT=$2 +LANG=$3 +VOWELS=$4 +### +DATA_DIR="/vagrant" +INPUT=$DATA_DIR"/"$INPUT +OUTPUT=$DATA_DIR"/"$OUTPUT +DIRNAME=${INPUT%/*} +EXTENSION=${INPUT##*.} + +display_usage() { + echo "Given the path to a file (.tmp or .txt) containing sentences, a language (english, spanish or tzeltal)," + echo "and a list of vowels, create a .syll file containing the original sentence, the phonemized/syllabified" + echo "version of it, and the number of syllables present in the original sentence." + echo "usage: $0 [input] [output] [language] [vowels]" + echo " input The file path where to find the transcription. Has to be txt or tmp extension. (REQUIRED)" + echo " output The output path. (REQUIRED)" + echo " language The language of the transcription (OPTIONAL, default = english)" + echo " vowels The list of vowels of the language if language set on spanish or tzeltal (OPTIONAL, default = aeiou)" + exit 1 + } + +if [ -z "$1" ] || [ -z "$2" ] || ! [[ $EXTENSION =~ ^(txt|tmp)$ ]]; then + display_usage +fi + +if [ -z "$3" ]; then + echo "No languages has been provided. Setting this parameter to english." + LANG="english" +fi + +if [ "$3" == "spanish" ] || [ "$3" == "tzeltal" ]; then + if [ -z "$4" ]; then + VOWELS="aeiouáéíóúü" + echo "Language set on spanish or tzeltal. But no vowels have been provided." + echo "Setting this parameter to $VOWELS" + echo $VOWELS > $DIRNAME"/"$LANG"-Vowels.txt" + fi +fi + +if [ "$3" == "english" ]; then + echo "Pĥonemizing $INPUT ..." + # Phonemize the clean version + phonemize ${INPUT} -o ${OUTPUT}.tmp -s - + + ## Append number of syllables to the phonemized transcription + cat ${OUTPUT}.tmp | awk -F- '{print $0"\t"NF-1}' > ${OUTPUT} +elif [ "$3" == "spanish" ] || [ "$3" == "tzeltal" ]; then + # Changing upper case to lower case + cat $INPUT | tr '[:upper:]' '[:lower:]' | tr 'A-ZÂÁÀÄÊÉÈËÏÍÎÖÓÔÖÚÙÛÑÇ' 'a-zâáàäêéèëïíîöóôöúùûñç' > $INPUT.tmp + # Get all the different words in the corpus + # and get the different onsets by removing what follows the first vowel + cat $INPUT.tmp | tr ' ' '\n' | sort | uniq | + sed 's/[aeiou].*//g' | grep .| uniq > $DIRNAME"/"$LANG"-ValidOnsets.txt" + SCRIPT_DIR=$(dirname "$0") + perl $SCRIPT_DIR/catspa-syllabify-corpus.pl $LANG $INPUT.tmp $OUTPUT.tmp + + ## Append number of syllables + cat $OUTPUT.tmp | awk -F'/' '{print $0"\t"NF-1}' > $OUTPUT + + rm $INPUT.tmp $DIRNAME"/"$LANG"-ValidOnsets.txt" $DIRNAME"/"$LANG"-Vowels.txt" +else + echo "Language unknown." + exit 1 +fi + +echo "Done." + +rm $OUTPUT.tmp + + diff --git a/utils/textgrid2rttm.py b/utils/textgrid2rttm.py new file mode 100755 index 0000000..ea7e35f --- /dev/null +++ b/utils/textgrid2rttm.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# +# author = julien karadayi +# +# This script converts transcription in Text Grid / Praat format +# to RTTM format. This is useful for evaluating performances of +# Speech detection algorithms with the *dscore* package, +# in the DiarizationVM virtual machine. +# The 1 and 0 labels are sent to " speech ", and no label / "x" label +# are not written in output (which means it is described as "non speech") + +import os +import argparse +# from praatio import tgio +import tgt # tgt is better thant praatio for our application + # because it allows to manipulate the timestamps, + # which is something we cannot do with praatio. + + + +def textgrid2rttm(textgrid): + ''' + Take in input the path to a text grid, + and output a dictionary of lists *{spkr: [ (onset, duration) ]}* + that can easily be written in rttm format. + ''' + # init output + rttm_out = dict() + + # open textgrid + #tg = tgio.openTextgrid(textgrid) + tg = tgt.read_textgrid(textgrid) + + # loop over all speakers in this text grid + #for spkr in tg.tierNameList: + for spkr in tg.get_tier_names(): + + spkr_timestamps = [] + # loop over all annotations for this speaker + #for interval in tg.tierDict[spkr].entryList: + for _interval in tg.get_tiers_by_name(spkr): + for interval in _interval: + + bg, ed, label = interval.start_time,\ + interval.end_time,\ + interval.text + + #if label == "x": + # continue + #elif label == "1" or label == "2": + # spkr_timestamps.append((bg, ed-bg)) + spkr_timestamps.append((bg, ed-bg)) + + # add list of onsets, durations for each speakers + rttm_out[spkr] = spkr_timestamps + return rttm_out + + +def write_rttm(rttm_out, basename_whole): + ''' + take a dictionary {spkr:[ (onset, duration) ]} as input + and write on rttm output by speaker + ''' + # write one rttm file for the whole wav, indicating + # only regions of speech, and not the speaker + with open(basename_whole + '.rttm', 'w') as fout: + for spkr in rttm_out: + for bg, dur in rttm_out[spkr]: + fout.write(u'SPEAKER {} 1 {} {} ' + ' {} \n'.format( + basename_whole.split('/')[-1], bg, dur, spkr)) + + +if __name__ == '__main__': + command_example = "python textgrid2rttm.py /folder/" + parser = argparse.ArgumentParser(epilog=command_example) + parser.add_argument('input_file', + help=''' Input File ''') + parser.add_argument('output_file', + help='''Name of the output file in which to write''') + + args = parser.parse_args() + + rttm_out = textgrid2rttm(args.input_file) + write_rttm(rttm_out, args.output_file) + #if not os.path.isdir(args.output_folder_whole): + # os.makedirs(args.output_folder_whole) + + #for fold in os.listdir(args.input_folder): + # for fin in os.listdir(os.path.join(args.input_folder, fold)): + # if not fin.endswith('m1.TextGrid'): + # # read only text grids with full anotation + # # in this folder + # continue + + # tg_in = os.path.join(args.input_folder, fold, fin) + # basename_whole = os.path.join(args.output_folder_whole, + # '_'.join(fin.split('_')[0:3])) + + # # extract begining/durations of speech intervals + # rttm_out = textgrid2rttm(tg_in) + # # write 1 rttm per spkr transcribed in this text grid + # write_rttm(rttm_out, basename_whole) diff --git a/utils/tocombo2rttm.py b/utils/tocombo2rttm.py new file mode 100755 index 0000000..1479bdc --- /dev/null +++ b/utils/tocombo2rttm.py @@ -0,0 +1,52 @@ +#!/usr/bin/bash +# + +import os +import sys +import ipdb + +tocombo = sys.argv[1] +output = sys.argv[2] + +# read VAD input +with open(tocombo, 'r') as fin: + + trs = fin.readlines() + shortened_trs = [] + + # there's one line per 0.1 second, so aggregate to get the whole segment + # with constant state of speech/nonspeech + for i, line in enumerate(trs): + on, off, state = line.strip('\n').split(' ') + if i == 0: + first_on = on + prev_off = off + prev_state = state + elif i > 0 and i < len(trs) - 1: + if not state == prev_state: + shortened_trs.append((first_on, prev_off, prev_state)) + first_on = on + prev_off = off + prev_state = state + elif state == prev_state: + prev_off = off + prev_state = state + elif i == len(trs) - 1: + if not state == prev_state: + shortened_trs.append((first_on, prev_off, prev_state)) + shortened_trs.append((on, off, state)) + elif state == prev_state: + shortened_trs.append((first_on, off, state)) + +shortened_trs = [(float(on), float(off), int(state)) for on, off, state in shortened_trs] + +# write rttm output +fname = os.path.basename(tocombo).split('.')[0] +with open(output, 'w') as fout: + for on, off, state in shortened_trs: + if state == 1: + vad = "speech" + else: + continue + fout.write(u"SPEAKER {} {} {} {} {} {} {} {}\n".format + (fname, 1, on, off - on, "", "", vad, 1 )) diff --git a/utils/train_test_split.py b/utils/train_test_split.py new file mode 100755 index 0000000..64ad008 --- /dev/null +++ b/utils/train_test_split.py @@ -0,0 +1,146 @@ +import os +import glob +import shutil +import numpy as np +import argparse +from math import floor, ceil + +### GLOBAL VARIABLE +default_test_prop = 0.5 + +def _create_empty_train_test(input_folder): + """ + Given an input folder, create a train and test folder. + If these folders already exist, move their content to the input folder before creating new train and test folders. + + Parameters + ---------- + input_folder path to the input folder + + Returns + ------- + path of the train folder and path of the test folder + """ + train_folder, test_folder = os.path.join(input_folder, 'train'), os.path.join(input_folder, 'test') + + # Bring back files to the parent directory + files = glob.glob(os.path.join(train_folder, '*'))+glob.glob(os.path.join(test_folder, '*')) + for path_f in files: + basename = os.path.basename(path_f) + shutil.move(path_f, os.path.join(input_folder, basename)) + + # Delete train and test folder + if os.path.isdir(train_folder): + shutil.rmtree(train_folder) + + if os.path.isdir(test_folder): + shutil.rmtree(test_folder) + + # Create new ones + os.makedirs(train_folder) + os.makedirs(test_folder) + + return train_folder, test_folder + + +def split(input_folder, test_prop, train_prop): + """ + Given an input folder, a proportion for the test set, a proportion for the training set, split the pairs + (.wav/.rttm) into a training folder and a test folder. + + Parameters + ---------- + input_folder the path to the input folder (containing wav and rttm files) + test_prop the proportion of the data that will be included in the test set + train_prop the proportion of the data that will be included in the training set + """ + # Create empty train and test directories. + # Move their content to the parent directory if they already exist + train_folder, test_folder = _create_empty_train_test(input_folder) + + # Check for all the wav into the the input_folder + wav = np.array(glob.glob(os.path.join(input_folder, "*.wav"))) + np.random.shuffle(wav) + + n_samples = len(wav) + n_train, n_test = np.int(floor(train_prop*n_samples)), np.int(ceil(test_prop*n_samples)) + + training_idx = np.arange(n_train) + test_idx = np.arange(n_train, n_train + n_test) + + train, test = wav[training_idx], wav[test_idx] + + # Move wav files ONLY if an associated rttm is found + for train_f in train: + basename = os.path.splitext(os.path.basename(train_f))[0] + old_path = os.path.join(input_folder, basename) + new_path = os.path.join(train_folder, basename) + if os.path.exists(old_path+'.rttm'): + os.rename(old_path+'.rttm', new_path+'.rttm') + os.rename(old_path+'.wav', new_path+'.wav') + else: + print("Ignoring file %s whose rttm has not been found." % (basename+'.wav')) + + for test_f in test: + basename = os.path.splitext(os.path.basename(test_f))[0] + old_path = os.path.join(input_folder, basename) + new_path = os.path.join(test_folder, basename) + if os.path.exists(old_path+'.rttm'): + os.rename(old_path+'.rttm', new_path+'.rttm') + os.rename(old_path+'.wav', new_path+'.wav') + else: + print("Ignoring file %s whose rttm has not been found." % (basename+'.wav')) + + n_real_train = len([f for f in glob.glob(os.path.join(train_folder, '*')) if os.path.isfile(f)]) / 2 + n_real_test = len([f for f in glob.glob(os.path.join(test_folder, '*')) if os.path.isfile(f)]) / 2 + + if n_real_train == 0: + print("Warning : The training set that you generated is empty !") + if n_real_test == 0: + print("Warning : The test set that you generated is empty !") + + + + + +def main(): + parser = argparse.ArgumentParser(description="Split a folder into a train set and a test set.") + parser.add_argument('-f', '--folder', type=str, required=True, + help='path to the folder that needs to be splitted.') + parser.add_argument('--test_prop', type=float, default=None, + help='''a float between 0.0 and 1.0 representing the proportion of the + dataset to include in the test set. If not specfied, the + value is automatically set to the complement of the + --train_prop. If --train_prop is not specified, --test_prop is set to + {}'''.format(default_test_prop)) + parser.add_argument('--train_prop', default=None, type=float, + help='''a float between 0.0 and 1.0 representing the proportion of the + dataset to include in the train set. If not specified, the + value is automatically set to the complement of --test_prop''') + parser.add_argument('-r', '--random_seed', default=None, type=int, + help='Seed the generator (for reproducible results)') + args = parser.parse_args() + + if args.train_prop is None: + test_prop = default_test_prop if args.test_prop is None else args.test_prop + else: + test_prop = 1.0-args.train_prop if args.test_prop is None else args.test_prop + train_prop = args.train_prop + + if test_prop < 0.0 or test_prop > 1.0 or train_prop < 0.0 or train_prop > 1.0: + raise ValueError("The test proportion and the train proportion must be between 0 and 1") + + data_dir = "/vagrant" + input_folder = os.path.join(data_dir, args.folder) + if not os.path.isdir(input_folder): + raise ValueError("The folder that you want to split is not found. Please check the path that you provided.") + + # Set the random seed + if args.random_seed is not None: + np.random.seed(args.random_seed) + + split(input_folder, test_prop, train_prop) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/utils/txt2rttm.py b/utils/txt2rttm.py new file mode 100755 index 0000000..cba1ae4 --- /dev/null +++ b/utils/txt2rttm.py @@ -0,0 +1,140 @@ +""" +This script converts an txt file into a rttm one. +The txt file must contain : class onset offset. +It can be run either on a single txt file, or on a whole folder containing txt files. + +Example of use : + python tools/txt2rttm.py -i data/my_file.txt # One one file + python tools/txt2rttm.py -i data/ # On a whole folder + python tools/txt2rttm.py -i data/ -l True # On a whole folder + lena mode activated + +If the lena mode is activated, it will look for a file called tsi_key_info.xlsx in the input folder +that contains a column file_lena (storing lena names, ex : e20170722_093015_009456_2040_2100_lena) +and a column key (containg the associated ACLEW name) +About the naming convention of the output : + For each file called input_file.txt, the result will be stored in input_file.rttm +""" + +import pympi as pmp +import argparse +import os +import sys +import glob +from openpyxl import load_workbook + +def lena_to_aclew_name(tsi_key_info, basename): + """ + Convert lena names to ACLEW names. + + Parameters + ---------- + tsi_key_info : the path to the tsi_key_infos.xlsx file + basename : the basename of the txt file that needs to be converted. This name follows the LENA naming convention. + + Returns + ------- + The name respecting the ACLEW naming convention + """ + onset = basename.split('_')[3] + basename_beg = '_'.join(basename.split('_')[0:3]) # Get the first 3 elements + wb = load_workbook(tsi_key_info,data_only=True) + wb = wb.worksheets[0] + first_row = wb.rows[0] + file_lena_num_col = None + key_num_col = None + + # Get num of the column + for idx in range(0, len(first_row)): + cell = first_row[idx] + if cell.value == "file_lena": + file_lena_num_col = idx + if cell.value == "key": + key_num_col = idx + + # Loop through the cells to look for the basename + if file_lena_num_col is not None and key_num_col is not None: + for row in wb.rows[1:]: + file_lena = row[file_lena_num_col].value + key_num = row[key_num_col].value + if file_lena == basename_beg: + child, good_date = key_num.split('_') + return '_'.join(['lena',child,good_date,onset]) + + +def txt2rttm(path_to_txt, output_folder, labels_to_keep, lena_mode=False, only_first_letter=False): + """ + Convert an txt file to the rttm format by extracting the + Parameters + ---------- + path_to_txt : path to the txt file. + output_folder : where to store the output files + + Write a rttm whose name is the same than the txt's one in output_folder + """ + basename = os.path.splitext(os.path.basename(path_to_txt))[0] + if lena_mode: + dirname = os.path.dirname(path_to_txt) + output_basename = lena_to_aclew_name(os.path.join(dirname, 'tsi_key_info.xlsx'), basename) + output_path = os.path.join(dirname, output_basename + '.rttm') + # Change the output_basename because we don't want to write the model prefix lena_ + # in the rttm fil + output_basename = '_'.join(output_basename.split('_')[1:]) + else: + output_path = os.path.join(output_folder, basename + '.rttm') + output_basename = os.path.splitext(os.path.basename(output_path))[0] + + with open(path_to_txt, 'r') as txt: + with open(output_path, 'w') as rttm: + for line in txt: + activity, onset, offset = line.rstrip().split('\t') + dur = float(offset)-float(onset) + + if lena_mode and activity in labels_to_keep: + if only_first_letter: + activity = activity[0] + rttm.write("SPEAKER %s 1 %s %s %s \n" % (output_basename, onset, str(dur), activity)) + elif not lena_mode: + rttm.write("SPEAKER %s 1 %s %s %s \n" % (output_basename, onset, str(dur), activity)) + + +def main(): + parser = argparse.ArgumentParser(description="convert .txt into .rttm") + parser.add_argument('-i', '--input', type=str, required=True, + help="path to the input .txt file or the folder containing txt files.") + parser.add_argument('-l', '--lena_mode', type=bool, required=False, default=False, + help="indicates whether to use this script in the lena mode or not. If the lena mode" + "is activated, it will read the table tsi_key_info.xlsx in the input folder and" + "will change the naming convention of the output in consequences") + parser.add_argument('-t', '--to_keep', nargs='+', type=str, required=True, + help='List of labels that needs to be kept.') + parser.add_argument('-fl', '--only_first_letter', type=bool, default=False, + help='Indicates if the output labels will be produced by keeping only the first letter' + 'of the original labels.') + args = parser.parse_args() + + + # Initialize the output folder as the same folder than the input + # if not provided by the user. + if args.input[-4:] == '.txt': + output = os.path.dirname(args.input) + else: + output = args.input + + data_dir = '/vagrant' + args.input = os.path.join(data_dir, args.input) + output = os.path.join(data_dir, output) + + if not os.path.isdir(output): + os.mkdir(output) + + if args.input[-4:] == '.txt': # A single file has been provided by the user + txt2rttm(args.input, output, args.to_keep, args.lena_mode, args.only_first_letter) + else: # A whole folder has been provided + txt_files = glob.iglob(os.path.join(args.input, '*.txt')) + for txt_path in txt_files: + print("Processing %s" % txt_path) + txt2rttm(txt_path, output, args.to_keep, args.lena_mode, args.only_first_letter) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/utils/vad_segmenter_aclew.conf.txt b/utils/vad_segmenter_aclew.conf.txt new file mode 100755 index 0000000..35f1636 --- /dev/null +++ b/utils/vad_segmenter_aclew.conf.txt @@ -0,0 +1,62 @@ +/////////////////////////////////////////////////////////////////////////////////////// +///////// > openSMILE LSTM-RNN voice activity detector< ////////////////// +///////// ////////////////// +///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// +///////// All rights reserverd. ////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + + +[componentInstances:cComponentManager] +instance[dataMemory].type = cDataMemory +instance[waveSource].type = cWaveSource + +[waveSource:cWaveSource] +writer.dmLevel = wave +filename = \cm[inputfile(I){input.wav}:name of input file] +monoMixdown = 1 +start = 0 +end = -1 +endrel = 0 +noHeader = 0 +buffersize_sec = 10 + + + ; inculdes a VAD module +\{vad_opensource.conf.inc} + ; and a turn detector module +\{turnDetector.conf.inc} +;\{\cm[turnDetector(T){turnDetector.conf}:filename of turn detector config file]} + + +[componentInstances:cComponentManager] + ; the wave file segmenter +instance[waveSinkCut].type = cWaveSinkCut + ; optional: CSV output +instance[csvSink].type = cCsvSink +printLevelStats = 0 + +[waveSinkCut:cWaveSinkCut] +reader.dmLevel = frames +fileBase = \cm[waveoutput(W){?}:prefix of WAV output files] +fileExtension = .wav +fileNameFormatString = %s%04d%s +startIndex = 1 +preSil = 0.1 +postSil = 0.1 +multiOut = 1 +sampleFormat = 16bit +; sample rate should be read from the input level +; automatically. In some cases this does not work due to +; round-off errors, so you can force it manually here: +;forceSampleRate = 44100 +;forceSampleRate = 16000 +saveSegmentTimes = \cm[saveSegmentTimes{times.dat}:file to save segment times to] +showSegmentTimes = 1 + +[csvSink:cCsvSink] +reader.dmLevel=vad_VAD_voice +filename= \cm[csvoutput{?}:name of VAD output file] +printHeader = 0 +timestamp = 1 +number = 0 + diff --git a/utils/yuniSeg.sh b/utils/yuniSeg.sh new file mode 100755 index 0000000..976b135 --- /dev/null +++ b/utils/yuniSeg.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run YuniSeg with hard coded models & configs found here and in /vagrant +# assumes Python environment in /home/${user}/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to YuniSeg (go one folder up and to Yunitator) +YUNITATDIR=$(dirname $BASEDIR)/Yunitator +# let's get our bearings: set CWD to the path of Yunitator +cd $YUNITATDIR + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "containing the wav and rttm files" + echo "and SADtoolname is the SAD to use." + echo "Choices are:" + echo " ldc_sad" + echo " noisemes" + echo " tocombosad" + echo " opensmile" + echo " textgrid" + echo " eaf" + echo " rttm" + exit 1 +fi + +audio_dir=/vagrant/$1 +trs_format=$2 + +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc, but may not be if run from outside VM +export PATH=/home/${user}/anaconda/bin:$PATH + + +# Iterate over files +echo "Starting" +for f in `ls $audio_dir/*.wav`; do + filename=$(basename "$f") + basename="${filename%.*}" + echo "treating $basename" + + # output filename produced by runYuniSegs + outfile=$audio_dir/$basename.yuniSeg.rttm + + case $trs_format in + "ldc_sad") + sys="ldcSad" + model_prefix="ldc_sad_" + ;; + "") + # add default case + echo "Warning: no SAD source specified, using Noisemes by default, at your own risk." + echo "Next time, please specify SAD." + sys="noisemesSad" + model_prefix="noisemes_sad_" + ;; + "noisemes") + sys="noisemesSad" + model_prefix="noisemes_sad_" + ;; + "tocombosad") + sys="tocomboSad" + model_prefix="tocombo_sad_" + ;; + "opensmile") + sys="opensmileSad" + model_prefix="opensmile_sad_" + ;; + "textgrid") + sys="goldSad" + model_prefix=${trs_format}_ + $conda_dir/python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid ${trs_format}_${basename}.rttm + ;; + "eaf") + sys="goldSad" + model_prefix=${trs_format}_ + $conda_dir/python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf ${trs_format}_${basename}.rttm + ;; + "rttm") + sys="goldSad" + model_prefix="" + ;; + *) + echo "ERROR: please choose SAD system between:" + echo " ldc_sad" + echo " noisemes" + echo " tocombosad" + echo " opensmile" + echo " textgrid" + echo " eaf" + echo " rttm" + echo "Now exiting..." + exit 1 + ;; + esac + + ./runYuniSegs.sh $f $audio_dir/${model_prefix}${basename}.rttm + cp $outfile $audio_dir/yuniseg_${sys}_${basename}.rttm + + if [ ! -s $audio_dir/yuniseg_${sys}_${basename}.rttm ]; then + # if diarization failed, still write an empty file... + touch $audio_dir/yuniseg_${sys}_${basename}.rttm + fi +done + +echo "$0 finished running" + +# simply remove hyp and feature +rm $outfile +rm -rf $audio_dir/Yunitemp From 4799fff609b66f1c4782c55cdc8ec05927cf6e63 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 19 Nov 2018 20:13:56 +0000 Subject: [PATCH 051/299] restore lost fixes --- Vagrantfile | 10 +++++----- launcher/eval.sh | 1 - launcher/evalDiar.sh | 3 ++- launcher/evalSAD.sh | 13 ++++++------- launcher/opensmileSad.sh | 9 +++++---- launcher/test.sh | 2 +- utils/create_ref_sys.sh | 5 +++-- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index f2d07cf..040e7e8 100755 --- a/Vagrantfile +++ b/Vagrantfile @@ -209,11 +209,11 @@ Vagrant.configure("2") do |config| sudo python setup.py install #install launcher and utils - cd /home/${user}/ - git clone https://github.com/aclew/launcher.git - chmod +x launcher/* - git clone https://github.com/aclew/utils.git - chmod +x utils/* +# cd /home/${user}/ +# git clone https://github.com/aclew/launcher.git +# chmod +x launcher/* +# git clone https://github.com/aclew/utils.git +# chmod +x utils/* # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) diff --git a/launcher/eval.sh b/launcher/eval.sh index a218022..320ed2b 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -40,7 +40,6 @@ if [ $# -lt 2 ] ; then display_usage fi -echo "audio_dir in eval.sh is: " $audio_dir ### SCRIPT STARTS case $system in diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 65caef7..173fe9a 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -98,7 +98,8 @@ elif [ "$2" == "lena" ]; then sys_name="lena" fi -$BASEDIR/create_ref_sys.sh $audio_dir $sys_name +echo $BASEDIR/create_ref_sys.sh $1 $sys_name +$BASEDIR/create_ref_sys.sh $1 $sys_name echo "evaluating" diff --git a/launcher/evalSAD.sh b/launcher/evalSAD.sh index 1ae74e7..e5160b0 100755 --- a/launcher/evalSAD.sh +++ b/launcher/evalSAD.sh @@ -2,10 +2,10 @@ # Launcher onset routine source ~/.bashrc SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` -conda_dir=$BASEDIR/anaconda/bin -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils +BASEDIR=`dirname $SCRIPT` # folder where this script resides. Useless. +conda_dir=/home/vagrant/anaconda/bin +REPOS=/home/vagrant/repos +UTILS=/home/vagrant/utils # end of launcher onset routine @@ -51,9 +51,8 @@ fi # Set CWD to path of scoring tool cd $ldcSad_DIR -#mkdir - -$UTILS/create_ref_sys.sh $audio_dir $sys_name true +echo $UTILS/create_ref_sys.sh $1 $sys_name true +$UTILS/create_ref_sys.sh $1 $sys_name true echo "evaluating" #$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 9d48927..32299b9 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -2,10 +2,11 @@ # Launcher onset routine source ~/.bashrc SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` -conda_dir=$BASEDIR/anaconda/bin -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils +BASEDIR=`dirname $SCRIPT` # this is the home folder of this script + # not the home folder of the 'vagrant' user in the VM +conda_dir=/home/vagrant/anaconda/bin +REPOS=/home/vagrant/repos +UTILS=/home/vagrant/utils # end of launcher onset routine ### Read in variables from user diff --git a/launcher/test.sh b/launcher/test.sh index 6bd5998..dfc158c 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -54,7 +54,7 @@ START=2513 # 41:53 in seconds STOP=2813 # 46:53 in seconds # get 5 minute subset of audio -sox $BASE.mp3 $BASETEST.wav trim $START 5:00 >& /dev/null 2>1 +sox $BASE.mp3 $BASETEST.wav trim $START 5:00 >& /dev/null 2>&1 # silence output # convert CHA to reliable STM $UTILS/chat2stm.sh $BASE.cha > $BASE.stm 2>/dev/null diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh index 61e2195..4c3c0db 100755 --- a/utils/create_ref_sys.sh +++ b/utils/create_ref_sys.sh @@ -1,13 +1,13 @@ #!/usr/bin/env bash -audio_dir=$1 +audio_dir=/vagrant/$1 model_prefix=$2 create_lab=$3 base_directory=$(echo "$audio_dir" | awk -F "/" '{print $2}') if [ "$base_directory" != "vagrant" ]; then - audio_dir=/vagrant/$1 + audio_dir=$1 fi display_usage() { @@ -38,6 +38,7 @@ yuniseg_ldcSad|yuniseg_noisemesSad|yuniseg_tocomboSad|yuniseg_opensmileSad|yunis exit 1; fi +echo "audio_dir is: " $audio_dir # Create temp_ref folder mkdir -p $audio_dir/temp_ref From 9a37eb6c1175b420a8bbc3b41272b07302352840 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 19 Nov 2018 21:05:58 +0000 Subject: [PATCH 052/299] fix test, usage, chunk --- launcher/tocomboSad.sh | 8 ++++---- launcher/yunitate.sh | 12 ++++++------ utils/chunk.sh | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index bd167a0..537576f 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -2,10 +2,10 @@ # Launcher onset routine source ~/.bashrc SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` -conda_dir=$BASEDIR/anaconda/bin -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils +BASEDIR=`dirname $SCRIPT` +conda_dir=/home/vagrant/anaconda/bin +REPOS=/home/vagrant/repos +UTILS=/home/vagrant/utils # end of launcher onset routine diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 01d58f2..eb52f59 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -4,15 +4,15 @@ source ~/.bashrc conda_dir=/home/vagrant/anaconda/bin -# run OpenSAT with hard coded models & configs found here and in /vagrant -# assumes Python environment in /home/${user}/ +# run Yunitator with hard coded models & configs +# assumes Python environment in /home/vagrant/anaconda/bin -# Absolute path to this script. /home/user/bin/foo.sh +# Absolute path to this script. /home/vagrant/launcher/yunitate.sh SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin +# Absolute path this script is in. /home/vagrant/launcher BASEDIR=`dirname $SCRIPT` # Path to Yunitator (go one folder up and to Yunitator) -YUNITATDIR=$(dirname $BASEDIR)/Yunitator +YUNITATDIR=/home/vagrant/repos/Yunitator if [ $# -ne 1 ]; then echo "Usage: $0 " @@ -27,7 +27,7 @@ dirname=$(dirname "$audio_dir") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash /home/vagrant/utils/check_folder.sh $audio_dir # this is set in user's login .bashrc diff --git a/utils/chunk.sh b/utils/chunk.sh index 572e163..dcfb416 100755 --- a/utils/chunk.sh +++ b/utils/chunk.sh @@ -6,7 +6,7 @@ # folder where the input file resides # # assumes $1 is full path to a large WAV file -# assumes $2 is path to script to run (such as are found in tools/ +# assumes $2 is path to script to run (such as are found in utils/ # that takes a folder name in /vagrant, and processes all WAVs in it) # # produces a single .rttm in the same folder $1 was found in @@ -15,7 +15,7 @@ if [[ $# < 2 ]]; then echo "Usage: " $0 " " - echo " e.g. tools/chunk.sh /vagrant/ami.wav tools/yunitate.sh" + echo " e.g. utils/chunk.sh /vagrant/ami.wav launcher/yunitate.sh" exit fi @@ -38,9 +38,9 @@ fi sox $1 $WORKFOLDER/chunk-.wav trim 0 300 : newfile : restart # run whichever tool you were going to run over the $WORKFOLDER folder -# assume tools are like in ~/tools and assume path is /vagrant/ +# assume programs are like in ~/launcher and assume path is /vagrant/ # but are only given -$2 chunk +$2 `basename $WORKFOLDER` # assume output is in $WORKFOLDER/chunk-00x.rttm - rename/ rejoin @@ -54,7 +54,7 @@ for f in `ls $WORKFOLDER/*chunk-*.rttm`; do # add $COUNT seconds to start time (column 4) of RTTM, and concatenate to $OUTFILE cat $f | awk -v ADDME=$COUNT '{print $1,$2,$3,($4+ADDME),$5,$6,$7,$8,$9}' >> $OUTFILE - # increment COUNT in 5 minutes' worth of secons (300) + # increment COUNT in 5 minutes' worth of seconds (300) COUNT=$(($COUNT + 300)) done From 7a7e88f1a00994d2fd6e1977d050c4690340d5f4 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 20 Nov 2018 16:03:13 +0000 Subject: [PATCH 053/299] rename, reorganize --- launcher/talnet.sh | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100755 launcher/talnet.sh diff --git a/launcher/talnet.sh b/launcher/talnet.sh new file mode 100755 index 0000000..6ccc956 --- /dev/null +++ b/launcher/talnet.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run 537 class classifier with hard coded models & configs found here +# assumes Python environment in /home/${user}/anaconda/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to classify tool (go one folder up and to 537cls) +CLASSIFY=/home/vagrant/repos/TALNet + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "in /vagrant containing wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of TALNet +cd $CLASSIFY + +# Iterate over files +echo "Starting" +for f in `ls ${audio_dir}/*.wav`; do + ./runTALNet.sh $f + base=$(basename $f .wav) + mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat +done + +echo "$0 finished running" From 9e0d4b8ba1ab28355d0b4c964c492f571ad3f514 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 20 Nov 2018 16:49:03 +0000 Subject: [PATCH 054/299] deletion, fix yunitate.sh, chunk.sh --- launcher/537classify.sh | 48 ----------------------------------------- launcher/yunitate.sh | 26 ++++++++++++++-------- utils/chunk.sh | 2 +- 3 files changed, 18 insertions(+), 58 deletions(-) delete mode 100755 launcher/537classify.sh diff --git a/launcher/537classify.sh b/launcher/537classify.sh deleted file mode 100755 index a88185e..0000000 --- a/launcher/537classify.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin - -# run 537 class classifier with hard coded models & configs found here -# assumes Python environment in /home/${user}/anaconda/ - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to classify tool (go one folder up and to 537cls) -CLASSIFY=$(dirname $BASEDIR)/537cls - -if [ $# -ne 1 ]; then - echo "Usage: $0 " - echo "where dirname is the name of the folder" - echo "containing the wav files" - exit 1 -fi - -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" -# Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir - - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - -# let's get our bearings: set CWD to the path of Yunitator -cd $CLASSIFY - -# Iterate over files -echo "Starting" -for f in `ls ${audio_dir}/*.wav`; do - ./run537classify.sh $f - base=$(basename $f .wav) - mv $audio_dir/${base}.rttm ${audio_dir}/537cls_${base}.rttm - mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/537cls_${base}.frame_prob.mat -done - -echo "$0 finished running" diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index eb52f59..613a29b 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -1,8 +1,8 @@ #!/bin/bash # Since the script is built to be launched outside of the vm, source # the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin +#source ~/.bashrc +#conda_dir=/home/vagrant/anaconda/bin # run Yunitator with hard coded models & configs # assumes Python environment in /home/vagrant/anaconda/bin @@ -22,6 +22,7 @@ if [ $# -ne 1 ]; then fi audio_dir=/vagrant/$1 +YUNITEMP=$audio_dir/Yunitemp filename=$(basename "$audio_dir") dirname=$(dirname "$audio_dir") extension="${filename##*.}" @@ -30,22 +31,29 @@ basename="${filename%.*}" bash /home/vagrant/utils/check_folder.sh $audio_dir -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - # let's get our bearings: set CWD to the path of Yunitator cd $YUNITATDIR +# make output folder for features, below input folder +mkdir -p $YUNITEMP + # Iterate over files -echo "Starting" +echo "Starting $0" for f in `ls $audio_dir/*.wav`; do - ./runYunitator.sh $f + + basename=`basename $f .wav` + # first features + ./extract-htk-vm2.sh $f + + # then confidences + python diarize.py $YUNITEMP/$basename.htk $YUNITEMP/$basename.rttm.sorted + sort -V -k3 $YUNITEMP/$basename.rttm.sorted > $YUNITEMP/$basename.rttm done echo "$0 finished running" # take all the .rttm in $audio_dir/Yunitemp/ and move them to /vagrant/data -for sad in `ls $audio_dir/Yunitemp/*.rttm`; do +for sad in `ls $YUNITEMP/*.rttm`; do _rttm=$(basename $sad) rttm=$audio_dir/yunitator_${_rttm} # Remove not needed SIL lines @@ -54,4 +62,4 @@ for sad in `ls $audio_dir/Yunitemp/*.rttm`; do done # simply remove hyp and feature -rm -rf $audio_dir/Yunitemp +rm -rf $YUNITEMP diff --git a/utils/chunk.sh b/utils/chunk.sh index dcfb416..5219a97 100755 --- a/utils/chunk.sh +++ b/utils/chunk.sh @@ -19,7 +19,7 @@ if [[ $# < 2 ]]; then exit fi -WORKFOLDER="/vagrant/chunk" +WORKFOLDER="/vagrant/data/temp/chunk" # remember basename for later ;) filename=$(basename "$1") From 42d611f393f3820bf93e8ae8e4013665619bc599 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 20 Nov 2018 19:02:01 +0000 Subject: [PATCH 055/299] implement --keep-temp --- launcher/diartk.sh | 27 ++++++++++++++++++++++++--- launcher/eval.sh | 12 ++++++++---- launcher/evalDiar.sh | 31 ++++++++++++++++++------------- launcher/evalSAD.sh | 9 ++++++++- launcher/ldcSad.sh | 11 ++++++++++- launcher/noisemesSad.sh | 28 +++++++++------------------- launcher/opensmileSad.sh | 9 ++++++++- launcher/tocomboSad.sh | 11 +++++++++-- launcher/yunitate.sh | 11 +++++++++-- 9 files changed, 103 insertions(+), 46 deletions(-) diff --git a/launcher/diartk.sh b/launcher/diartk.sh index e053de3..2e3b1cf 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -2,18 +2,37 @@ # Launcher onset routine source ~/.bashrc SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $(dirname $SCRIPT )` +BASEDIR=/home/vagrant conda_dir=$BASEDIR/anaconda/bin REPOS=$BASEDIR/repos UTILS=$BASEDIR/utils # end of launcher onset routine +if [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 " + echo "where audio-dir is the name of the folder" + echo "containing the wav files" + echo "and is one of:" + echo " ldcSad" + echo " noisemesSad" + echo " tocomboSad" + echo " opensmileSad" + echo " textgrid" + echo " eaf" + echo " rttm" + + exit 1 +fi + +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi ### Read in variables from user audio_dir=/vagrant/$1 trs_format=$2 - ### Other variables specific to this script # create temp dir workdir=$audio_dir/temp/diartk @@ -114,4 +133,6 @@ for fin in `ls $audio_dir/*.wav`; do done # Delete temporary folder -rm -rf $workdir +if ! $KEEPTEMP; then + rm -rf $workdir +fi diff --git a/launcher/eval.sh b/launcher/eval.sh index 320ed2b..49d95c8 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -36,22 +36,26 @@ display_usage() { exit 1 } -if [ $# -lt 2 ] ; then +if [ $# -eq 0 ] ; then display_usage fi +KEEPTEMP="" +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP="--keep-temp" +fi ### SCRIPT STARTS case $system in "tocomboSad"|"opensmileSad"|"ldcSad"|"noisemesSad|lenaSad") - sh $LAUNCHER/evalSAD.sh $audio_dir $system + sh $LAUNCHER/evalSAD.sh $audio_dir $system $KEEPTEMP ;; "yunitate"|"lenaDiar") - sh $LAUNCHER/evalDiar.sh $audio_dir $system + sh $LAUNCHER/evalDiar.sh $audio_dir $system $KEEPTEMP ;; "diartk") sad=$3 - sh $LAUNCHER/evalDiar.sh $audio_dir $system $sad + sh $LAUNCHER/evalDiar.sh $audio_dir $system $sad $KEEPTEMP ;; *) display_usage diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 173fe9a..3a478af 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -2,7 +2,6 @@ # Since the script is built to be launched outside of the vm, source # the .bashrc which is not necessarily sourced! source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # Absolute path to this script. /home/user/bin/foo.sh SCRIPT=$(readlink -f $0) @@ -22,21 +21,25 @@ display_usage() { echo " - diartk" echo " - yunitate" echo "Transcription (mandatory for model == diartk) choices are:" - echo " -ldc_sad" - echo " -noisemes" - echo " -opensmile" - echo " -tocombosad" - echo " -textgrid" - echo " -eaf" - echo " -rttm" + echo " ldc_sad" + echo " noisemes" + echo " opensmile" + echo " tocombosad" + echo " textgrid" + echo " eaf" + echo " rttm" exit 1; } -if ! [[ $2 =~ ^(diartk|yunitate|lena)$ ]] || [ "$2" == "diartk" ] && [ $# -ne 3 ]; then +if ! [[ $2 =~ ^(diartk|yunitate|lena)$ ]] || [ "$2" == "diartk" ] && [ $# -lt 3 ]; then display_usage fi +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi # data directory audio_dir=/vagrant/$1 @@ -68,14 +71,14 @@ if [[ $model =~ ^(diartk|yuniseg) ]]; then sys_name=$model"_goldSad" for wav in `ls $audio_dir/*.wav`; do base=$(basename $wav .wav) - $conda_dir/python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid $audio_dir/${basename}.rttm + python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid $audio_dir/${basename}.rttm done ;; "eaf") sys_name=$model"_goldSad" for wav in `ls $audio_dir/*.wav`; do base=$(basename $wav .wav) - $conda_dir/python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf $audio_dir/${basename}.rttm + python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf $audio_dir/${basename}.rttm done ;; "rttm") @@ -103,7 +106,7 @@ $BASEDIR/create_ref_sys.sh $1 $sys_name echo "evaluating" -$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $audio_dir/temp_ref $audio_dir/temp_sys +python score_batch.py $audio_dir/${sys_name}_eval.df $audio_dir/temp_ref $audio_dir/temp_sys # Check if some gold files are empty. If so, add a line in the eval dataframe for fin in `ls $audio_dir/temp_ref/*.rttm`; do @@ -121,4 +124,6 @@ done echo "done evaluating, check $1/${sys_name}_eval.df for the results" # remove temps -rm -rf $audio_dir/temp_ref $audio_dir/temp_sys +if ! $KEEPTEMP; then + rm -rf $audio_dir/temp_ref $audio_dir/temp_sys +fi diff --git a/launcher/evalSAD.sh b/launcher/evalSAD.sh index e5160b0..97203f7 100755 --- a/launcher/evalSAD.sh +++ b/launcher/evalSAD.sh @@ -20,6 +20,11 @@ basename="${filename%.*}" # check system to evaluate system=$2 +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + ### Other variables specific to this script # Path to scoring tool NOTE: NOT dscore! @@ -78,5 +83,7 @@ sed -i "s/,//g" $audio_dir/${sys_name}_eval.df echo "done evaluating, check $1/${sys_name}_eval.df for the results" # remove temps -rm -rf $workdir/temp_ref $workdir/temp_sys +if ! $KEEPTEMP; then + rm -rf $workdir/temp_ref $workdir/temp_sys +fi diff --git a/launcher/ldcSad.sh b/launcher/ldcSad.sh index 590ff8d..bba281b 100755 --- a/launcher/ldcSad.sh +++ b/launcher/ldcSad.sh @@ -17,13 +17,18 @@ workdir=$audio_dir/temp/diartk mkdir -p $workdir ### SCRIPT STARTS -if [ $# -ne 1 ]; then +if [ $# -lt 1 ]; then echo "Usage: ldcSad.sh " echo "where dirname is the name of the folder" echo "containing the wav files" exit 1 fi +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + # Check audio_dir to see if empty or if contains empty wav bash $UTILS/check_folder.sh $audio_dir @@ -45,3 +50,7 @@ for wav in `ls $audio_dir/*.wav`; do touch $rttm_out fi done + +if ! $KEEPTEMP; then + rm -rf $workdir +fi diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 2fd5bc2..bdeffcf 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -14,13 +14,18 @@ BASEDIR=`dirname $SCRIPT` # Path to OpenSAT (go on folder up and to opensat) OPENSATDIR=$(dirname $BASEDIR)/OpenSAT -if [ $# -ne 1 ]; then +if [ $# -lt 2 ]; then echo "Usage: noisemes_sad.sh " echo "where dirname is a folder on the host" echo "containing the wav files (/vagrant/dirname/ in the VM)" exit 1 fi +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + audio_dir=/vagrant/$1 filename=$(basename "$audio_dir") dirname=$(dirname "$audio_dir") @@ -60,21 +65,6 @@ for sad in `ls $audio_dir/hyp_sum/*.lab`; do done # simple remove hyp and feature -rm -rf $audio_dir/hyp_sum $audio_dir/feature -# mv hyp and features folders to a temp that the user can delete. -#if [ ! -d "$audio_dir/noiseme_sad_temp" ]; then -# mkdir -p $audio_dir/noiseme_sad_temp -#fi -# -#if [! -d "$audio_dir/noiseme_sad_temp" ]; then -# mv $audio_dir/hyp_sum $audio_dir/noiseme_sad_temp -#else -# echo "can't move hyp_sum/ folder to noiseme_sad_temp/ because temp is already full" -#fi -# -#if [! -d "$audio_dir/noiseme_sad_temp" ]; then -# mv $audio_dir/feature $audio_dir/noiseme_sad_temp -#else -# echo "can't move features/ folder to noiseme_sad_temp/ because temp is already full" -#fi -# +if ! $KEEPTEMP; then + rm -rf $audio_dir/hyp_sum $audio_dir/feature +fi diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 32299b9..cd976ea 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -26,6 +26,11 @@ if [ $# -lt 1 ]; then exit 1 fi +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + filename=$(basename "$1") dirname=$(dirname "$1") extension="${filename##*.}" @@ -58,4 +63,6 @@ for output in $(ls $workdir/*.txt); do done # Delete temporary folder -rm -rf $workdir +if ! $KEEPTEMP; then + rm -rf $workdir +fi diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index 537576f..303d66f 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -23,13 +23,18 @@ MCR=/usr/local/MATLAB/MATLAB_Runtime/v93 ### SCRIPT STARTS -if [ $# -ne 1 ]; then +if [ $# -lt 1 ]; then echo "Usage: tocombo_sad.sh " echo "where dirname is a folder on the host" echo "containing the wav files (/vagrant/dirname/ in the VM)" exit 1 fi +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + filename=$(basename "$audio_dir") dirname=$(dirname "$audio_dir") extension="${filename##*.}" @@ -75,4 +80,6 @@ for f in $audio_dir/*.ToCombo.txt; do done # Delete temporary folder -rm -rf $workdir +if ! $KEEPTEMP; then + rm -rf $workdir +fi diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 613a29b..5ccfedd 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -14,13 +14,18 @@ BASEDIR=`dirname $SCRIPT` # Path to Yunitator (go one folder up and to Yunitator) YUNITATDIR=/home/vagrant/repos/Yunitator -if [ $# -ne 1 ]; then +if [ $# -lt 1 ] || [ $# -gt 2 ]; then echo "Usage: $0 " echo "where dirname is the name of the folder" echo "containing the wav files" exit 1 fi +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + audio_dir=/vagrant/$1 YUNITEMP=$audio_dir/Yunitemp filename=$(basename "$audio_dir") @@ -62,4 +67,6 @@ for sad in `ls $YUNITEMP/*.rttm`; do done # simply remove hyp and feature -rm -rf $YUNITEMP +if ! $KEEPTEMP; then + rm -rf $YUNITEMP +fi From bb9a530af3f00e4f71d4f3390c70e775e200da0c Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 20 Nov 2018 21:47:27 +0000 Subject: [PATCH 056/299] test more tools in the DiViMe way --- launcher/opensmileSad.sh | 2 +- launcher/test.sh | 25 ++++++++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index cd976ea..54b01b6 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -45,7 +45,7 @@ for sad in `ls $audio_dir/*.wav`; do file=$sad id=`basename $file` id=${id%.wav} - > $audio_dir/${id}.txt #Make it empty if already present +# > $audio_dir/${id}.txt #Make it empty if already present echo "Processing $id ..." LD_LIBRARY_PATH=/usr/local/lib \ $OPENSMILE \ diff --git a/launcher/test.sh b/launcher/test.sh index dfc158c..2c617ec 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -10,6 +10,13 @@ export PATH=/home/vagrant/anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH" +KEEPTEMP="" +if [ $# -eq 1 ]; then + if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP="--keep-temp" + fi +fi + conda_dir=/home/vagrant/anaconda/bin # Absolute path to this script. /home/vagrant/launcher @@ -118,7 +125,7 @@ cd $OPENSMILEDIR TESTDIR=$WORKDIR/opensmile-test rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR -$LAUNCHERS/opensmileSad.sh data/VanDam-Daylong/BN32/opensmile-test >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} +$LAUNCHERS/opensmileSad.sh $DATADIR/opensmile-test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then echo "OpenSmile SAD passed the test." @@ -133,7 +140,7 @@ cd $TOCOMBOSAD TESTDIR=$WORKDIR/tocombo_sad-test rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR -$LAUNCHERS/tocomboSad.sh data/VanDam-Daylong/BN32/tocombo_sad-test > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} +$LAUNCHERS/tocomboSad.sh $DATADIR/tocombo_sad-test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then echo "TOCOMBO SAD passed the test." @@ -148,19 +155,22 @@ echo "Testing DIARTK..." cd $DIARTKDIR TESTDIR=$WORKDIR/diartk-test rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +cp $TEST_RTTM $TESTDIR # run like the wind -./run-rttm.sh $TEST_WAV $TEST_RTTM $TESTDIR > $TESTDIR/diartk-test.log 2>&1 +$LAUNCHERS/diartk.sh $DATADIR/diartk-test rttm > $TESTDIR/diartk-test.log 2>&1 if grep -q "command not found" $TESTDIR/diartk-test.log; then echo " Diartk failed - dependencies (probably HTK)" FAILURES=true else - if [ -s $TESTDIR/$BASETEST.rttm ]; then + if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then echo "DiarTK passed the test." else FAILURES=true echo " Diartk failed - no output RTTM" fi fi +rm $TESTDIR/$BASETEST.rttm # finally test Yunitator echo "Testing Yunitator..." @@ -169,8 +179,9 @@ TESTDIR=$WORKDIR/yunitator-test rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR # let 'er rip -./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/Yunitemp/$BASETEST.rttm ]; then +#./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +$LAUNCHERS/yunitate.sh $DATADIR/yunitator-test > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then echo "Yunitator passed the test." else FAILURES=true @@ -200,7 +211,7 @@ if [ -d $LDC_SAD_DIR ]; then cd $LDC_SAD_DIR TESTDIR=$WORKDIR/opensmile-test cp $WORKDIR/$BASETEST.rttm $TESTDIR - $LAUNCHERS/eval.sh $DATADIR/opensmile-test opensmileSad > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} + $LAUNCHERS/eval.sh $DATADIR/opensmile-test opensmileSad $KEEPTEMP > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/opensmileSad_eval.df ]; then echo "LDC evalSAD passed the test" else From 956cc18cff9ffe888bf99e22f4e01b179e0e37b1 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 20 Nov 2018 22:25:21 +0000 Subject: [PATCH 057/299] test all tools' launch scripts --- launcher/noisemesSad.sh | 2 +- launcher/test.sh | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index bdeffcf..475f459 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -14,7 +14,7 @@ BASEDIR=`dirname $SCRIPT` # Path to OpenSAT (go on folder up and to opensat) OPENSATDIR=$(dirname $BASEDIR)/OpenSAT -if [ $# -lt 2 ]; then +if [ $# -lt 1 ]; then echo "Usage: noisemes_sad.sh " echo "where dirname is a folder on the host" echo "containing the wav files (/vagrant/dirname/ in the VM)" diff --git a/launcher/test.sh b/launcher/test.sh index 2c617ec..0aac9c2 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -107,16 +107,17 @@ cd $OPENSATDIR TESTDIR=$WORKDIR/noisemes-test rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR -./runDiarNoisemes.sh $TESTDIR > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} +#./runDiarNoisemes.sh $TESTDIR > $TESTDIR/noisemes-test.log 2>&1 +$LAUNCHERS/noisemesSad.sh $DATADIR/noisemes-test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/hyp_sum/$BASETEST.rttm ]; then +if [ -s $TESTDIR/noisemes_sad_$BASETEST.rttm ]; then echo "Noisemes passed the test." else FAILURES=true echo " Noisemes failed - no RTTM output" fi # clean up -rm -rf $OPENSATDIR/SSSF/data/feature $OPENSATDIR/SSSF/data/hyp +#rm -rf $OPENSATDIR/SSSF/data/feature $OPENSATDIR/SSSF/data/hyp # now test OPENSMILEDIR @@ -158,7 +159,7 @@ rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR cp $TEST_RTTM $TESTDIR # run like the wind -$LAUNCHERS/diartk.sh $DATADIR/diartk-test rttm > $TESTDIR/diartk-test.log 2>&1 +$LAUNCHERS/diartk.sh $DATADIR/diartk-test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 if grep -q "command not found" $TESTDIR/diartk-test.log; then echo " Diartk failed - dependencies (probably HTK)" FAILURES=true @@ -180,7 +181,7 @@ rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR # let 'er rip #./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -$LAUNCHERS/yunitate.sh $DATADIR/yunitator-test > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +$LAUNCHERS/yunitate.sh $DATADIR/yunitator-test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then echo "Yunitator passed the test." else From 8c745a1969051d3b6ea7cdfcba2a169dda76af9f Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 21 Nov 2018 14:20:15 -0500 Subject: [PATCH 058/299] remove sudo, put launcher/ on PATH --- Vagrantfile | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) mode change 100755 => 100644 Vagrantfile diff --git a/Vagrantfile b/Vagrantfile old mode 100755 new mode 100644 index 040e7e8..d5e0acd --- a/Vagrantfile +++ b/Vagrantfile @@ -97,8 +97,8 @@ Vagrant.configure("2") do |config| end config.vm.provision "shell", inline: <<-SHELL - sudo apt-get update -y - sudo apt-get upgrade -y + apt-get update -y + apt-get upgrade -y if grep --quiet vagrant /etc/passwd then @@ -107,15 +107,15 @@ Vagrant.configure("2") do |config| user="ubuntu" fi - sudo apt-get install -y git make automake libtool autoconf patch subversion fuse \ + apt-get install -y git make automake libtool autoconf patch subversion fuse \ libatlas-base-dev libatlas-dev liblapack-dev sox libav-tools g++ \ zlib1g-dev libsox-fmt-all sshfs gcc-multilib libncurses5-dev unzip - sudo apt-get install -y openjdk-6-jre || sudo apt-get install -y icedtea-netx-common icedtea-netx -# sudo apt-get install -y libtool-bin apache2 + apt-get install -y openjdk-6-jre || apt-get install -y icedtea-netx-common icedtea-netx +# apt-get install -y libtool-bin apache2 # Kaldi and others want bash - otherwise the build process fails - [ $(readlink /bin/sh) == "dash" ] && sudo ln -s -f bash /bin/sh + [ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh # Install Anaconda and Theano echo "Downloading Anaconda-2.3.0..." @@ -125,7 +125,7 @@ Vagrant.configure("2") do |config| echo "Installing Anaconda-2.3.0..." sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" if ! grep -q -i anaconda .bashrc; then - echo "export PATH=/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc + echo "export PATH=/home/vagrant/launcher:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc fi # assume 'conda' is installed now (get path) su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" @@ -191,7 +191,7 @@ Vagrant.configure("2") do |config| #Install to-combo sad and dependencies (matlab runtime environnement) git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 - sudo apt-get install -y libxt-dev libx11-xcb1 + apt-get install -y libxt-dev libx11-xcb1 # Install DiarTK git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 @@ -201,12 +201,12 @@ Vagrant.configure("2") do |config| git clone http://github.com/srvk/dscore #--branch v1.0 # Phonemizer installation - sudo apt-get install -y festival espeak + apt-get install -y festival espeak git clone https://github.com/bootphon/phonemizer cd phonemizer python setup.py build - sudo apt-get install -y python-setuptools - sudo python setup.py install + apt-get install -y python-setuptools + python setup.py install #install launcher and utils # cd /home/${user}/ @@ -226,7 +226,7 @@ Vagrant.configure("2") do |config| ln -s /vagrant/utils /home/${user}/ # Some cleanup - sudo apt-get autoremove -y + apt-get autoremove -y # Silence error message from missing file touch /home/${user}/.Xauthority From 862bc12568505bf911b6dbef7bf61c55deb3ceda Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 22 Nov 2018 11:15:59 +0100 Subject: [PATCH 059/299] minor --- docs/source/index.rst | 1 + launcher | 1 - utils | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) delete mode 160000 launcher delete mode 160000 utils diff --git a/docs/source/index.rst b/docs/source/index.rst index 95d1d50..98f3fe8 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,6 +13,7 @@ Welcome to DiViMe's documentation! initial_questions install usage + formats tool_doc troubleshoot instructions_for_contributors diff --git a/launcher b/launcher deleted file mode 160000 index f2a820c..0000000 --- a/launcher +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f2a820c01966bf11df501077b0de89d5bd3b0dd1 diff --git a/utils b/utils deleted file mode 160000 index 0ed7abd..0000000 --- a/utils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0ed7abd67daac8a46bff31e66e8f83475fce3bea From eb741bd8bd67f4a144cce5707e4ee07ac3d598a7 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 22 Nov 2018 11:16:09 +0100 Subject: [PATCH 060/299] minor --- docs/source/formats.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 docs/source/formats.md diff --git a/docs/source/formats.md b/docs/source/formats.md new file mode 100644 index 0000000..081b3ba --- /dev/null +++ b/docs/source/formats.md @@ -0,0 +1,42 @@ +=========== END ===== + +TO ADD SOMEWHERE ELSE +Specific examples for the different tool types +- If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named toolnameSad_filename.rttm, which will look like this: + +``` +SPEAKER file17 1 0.00 0.77 speech +SPEAKER file17 1 1.38 2.14 speech + +``` + +- If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the previous bulletpoint. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then provide them with a clear error, such as “TOOLNAME failed because you did not provide a sad/vad annotation file. Please refer to the docs for the list of available sad/vad tools.”. Your diarization-type tool should return one rttm per audio file, named toolnameDiar_filename.rttm, which must look like this: + +``` +SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 +SPEAKER family 1 4.6 1.2 background 0.327808111906 +SPEAKER family 1 5.8 1.1 speech 0.430758684874 +SPEAKER family 1 6.9 1.2 background 0.401730179787 +SPEAKER family 1 8.1 0.7 speech 0.407463937998 +SPEAKER family 1 8.8 1.1 background 0.37258502841 +SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +``` + +- If your tool is not a VAD/SAD but it is a classifier that assumes only raw acoustic input, then declare it as a sad/vad, and follow the instructions for vad/sad above, except that you'll adapt the rttm output to the classes you typically have. For example, one tool classifies audio into noiseme categories. It returns rttm's like this one: + + +``` +SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 +SPEAKER family 1 4.6 1.2 background 0.327808111906 +SPEAKER family 1 5.8 1.1 speech 0.430758684874 +SPEAKER family 1 6.9 1.2 background 0.401730179787 +SPEAKER family 1 8.1 0.7 speech 0.407463937998 +SPEAKER family 1 8.8 1.1 background 0.37258502841 +SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +``` +** todo: expand diar tool section** + +- If your tool is a classifier or annotator that works only on a subtype of speaker (e.g., only on children's speech, or only on adults’ speech), then assume that each wav is accompanied by an rttm that has this information noted in column XX. + +** todo: expand add tool section** + From 06450f26fef90926812196c4f96996b4981c67e7 Mon Sep 17 00:00:00 2001 From: Junghan Date: Mon, 26 Nov 2018 06:47:04 +0000 Subject: [PATCH 061/299] Add python3 env - separate bootstrapping from Vagrant file - make conda env instead of downloading new miniconda --- Vagrantfile | 147 +++----------------------------------------- bootstrap.sh | 146 +++++++++++++++++++++++++++++++++++++++++++ environment.yml | 25 ++++++++ launcher/python3.sh | 13 ++++ update.sh | 20 ++++++ 5 files changed, 212 insertions(+), 139 deletions(-) create mode 100644 bootstrap.sh create mode 100644 environment.yml create mode 100644 launcher/python3.sh create mode 100644 update.sh diff --git a/Vagrantfile b/Vagrantfile index d5e0acd..707e168 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -96,143 +96,12 @@ Vagrant.configure("2") do |config| #override.vm.box = "https://github.com/azure/vagrant-azure/raw/v2.0/dummy.box" end - config.vm.provision "shell", inline: <<-SHELL - apt-get update -y - apt-get upgrade -y - - if grep --quiet vagrant /etc/passwd - then - user="vagrant" - else - user="ubuntu" - fi - - apt-get install -y git make automake libtool autoconf patch subversion fuse \ - libatlas-base-dev libatlas-dev liblapack-dev sox libav-tools g++ \ - zlib1g-dev libsox-fmt-all sshfs gcc-multilib libncurses5-dev unzip - apt-get install -y openjdk-6-jre || apt-get install -y icedtea-netx-common icedtea-netx -# apt-get install -y libtool-bin apache2 - - - # Kaldi and others want bash - otherwise the build process fails - [ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh - - # Install Anaconda and Theano - echo "Downloading Anaconda-2.3.0..." - cd /home/${user} - wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh - #bash Anaconda-2.3.0-Linux-x86_64.sh -b # batch install into /home/vagrant/anaconda - echo "Installing Anaconda-2.3.0..." - sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" - if ! grep -q -i anaconda .bashrc; then - echo "export PATH=/home/vagrant/launcher:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc - fi - # assume 'conda' is installed now (get path) - su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" - - # install Matlab runtime environment - cd /tmp - wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip - unzip -q MCR_R2017b_glnxa64_installer.zip - ./install -mode silent -agreeToLicense yes - # add Matlab stuff to path - echo 'LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH"' >> /home/${user}/.bashrc - rm /tmp/MCR_R2017b_glnxa64_installer.zip - - # Install OpenSMILE - echo "Installing OpenSMILE" - su ${user} -c "mkdir -p /home/${user}/repos/" - cd /home/${user}/repos/ - wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz - tar zxvf OpenSMILE-2.1.tar.gz - # install SMILExtract system-wide - cp openSMILE-2.1.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin - chmod +x /usr/local/bin/SMILExtract - rm OpenSMILE-2.1.tar.gz - - # optionally Install HTK (without it, some other tools will not work) - # the idea is to make users independently download HTK installer since - # we cannot redistribute - if [ -f /vagrant/HTK.tar.gz ] - then - cd /home/${user}/repos/ - su ${user} -c "tar zxf /vagrant/HTK.tar.gz" - cd htk - ./configure --without-x --disable-hslab - sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile - make all - make install - fi - - - - # POPOULATE THE REPOSITORY SECTION - cd /home/${user}/repos/ - - # Get OpenSAT=noisemes and dependencies - git clone http://github.com/srvk/OpenSAT # --branch v1.0 # need Dev - su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" - - cp /vagrant/conf/.theanorc /home/${user}/ - export PATH=/home/${user}/anaconda/bin:$PATH - su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" - - - # Install ldc-sad - # run this version 'by hand' in the VM in repos/ using your github username and password - #git clone http://github.com/aclew/ldc_sad_hmm - - - # Install Yunitator and dependencies - git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev - su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" - su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" - - - #Install to-combo sad and dependencies (matlab runtime environnement) - git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 - apt-get install -y libxt-dev libx11-xcb1 - - # Install DiarTK - git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 - - - # Install eval - git clone http://github.com/srvk/dscore #--branch v1.0 - - # Phonemizer installation - apt-get install -y festival espeak - git clone https://github.com/bootphon/phonemizer - cd phonemizer - python setup.py build - apt-get install -y python-setuptools - python setup.py install - - #install launcher and utils -# cd /home/${user}/ -# git clone https://github.com/aclew/launcher.git -# chmod +x launcher/* -# git clone https://github.com/aclew/utils.git -# chmod +x utils/* - - - # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) - # and intervaltree (needed for rttm2scp.py) - # and recommonmark (needed to make html in docs/) - su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" - - # Link /vagrant/launcher and /vagrant/utils to home folder where scripts expect them - ln -s /vagrant/launcher /home/${user}/ - ln -s /vagrant/utils /home/${user}/ - - # Some cleanup - apt-get autoremove -y - - # Silence error message from missing file - touch /home/${user}/.Xauthority - - # Provisioning runs as root; we want files to belong to '${user}' - chown -R ${user}:${user} /home/${user} - - SHELL + config.vm.provision "bootstrap", type: "shell", run: "once" do |s| + s.path = "bootstrap.sh" + end + + config.vm.provision "update", type: "shell", run: "always" do |s| + s.path = "update.sh" + end + end diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100644 index 0000000..65f8bde --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,146 @@ +echo "Start bootstraping DiViMe" +apt-get update -y +apt-get upgrade -y + +if grep --quiet vagrant /etc/passwd +then + user="vagrant" +else + user="ubuntu" +fi + +sudo apt-get install -y git make automake libtool autoconf patch subversion fuse \ + libatlas-base-dev libatlas-dev liblapack-dev sox libav-tools g++ \ + zlib1g-dev libsox-fmt-all sshfs gcc-multilib libncurses5-dev unzip bc \ + openjdk-6-jre icedtea-netx-common icedtea-netx libxt-dev libx11-xcb1 \ + libc6-dev-i386 festival espeak python-setuptools gawk \ + libboost-all-dev + + +# Kaldi and others want bash - otherwise the build process fails +[ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh + +# Install Anaconda and Theano +echo "Downloading Anaconda-2.3.0..." +cd /home/${user} +wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh +#bash Anaconda-2.3.0-Linux-x86_64.sh -b # batch install into /home/vagrant/anaconda +echo "Installing Anaconda-2.3.0..." +sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" +if ! grep -q -i anaconda .bashrc; then + echo "export PATH=/home/vagrant/launcher:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc +fi +# assume 'conda' is installed now (get path) +su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" + +# python3 env +# Install Miniconda and python libraries +# miniconda=Miniconda3-4.5.11-Linux-x86_64.sh +echo "Checking python3" +cd /home/$user +cp /vagrant/environment.yml /home/${user}/ +su ${user} -c "/home/${user}/anaconda/bin/conda env create -f environment.yml" + + +# install Matlab runtime environment +cd /tmp +wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip +unzip -q MCR_R2017b_glnxa64_installer.zip +./install -mode silent -agreeToLicense yes +# add Matlab stuff to path +echo 'LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH"' >> /home/${user}/.bashrc +rm /tmp/MCR_R2017b_glnxa64_installer.zip + +# Install OpenSMILE +echo "Installing OpenSMILE" + su ${user} -c "mkdir -p /home/${user}/repos/" +cd /home/${user}/repos/ +wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz +tar zxvf OpenSMILE-2.1.tar.gz +# install SMILExtract system-wide +cp openSMILE-2.1.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin +chmod +x /usr/local/bin/SMILExtract +rm OpenSMILE-2.1.tar.gz + +# optionally Install HTK (without it, some other tools will not work) +# the idea is to make users independently download HTK installer since +# we cannot redistribute +cd /home/${user} +if [ -f /vagrant/HTK.tar.gz ]; then + if [[ ! -d htk ]]; then + cd /home/${user}/repos/ + su ${user} -c "tar zxf /vagrant/HTK.tar.gz" + cd htk + ./configure --without-x --disable-hslab + sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + make all + make install + fi +fi + + + +# POPOULATE THE REPOSITORY SECTION +cd /home/${user}/repos/ + + # Get OpenSAT=noisemes and dependencies +git clone http://github.com/srvk/OpenSAT # --branch v1.0 # need Dev +su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" + +cp /vagrant/conf/.theanorc /home/${user}/ +export PATH=/home/${user}/anaconda/bin:$PATH +su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" + + +# Install ldc-sad +# run this version 'by hand' in the VM in repos/ using your github username and password +#git clone http://github.com/aclew/ldc_sad_hmm + + +# Install Yunitator and dependencies +git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev +su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" +su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" + + +#Install to-combo sad and dependencies (matlab runtime environnement) +git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 + +# Install DiarTK +git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 + + +# Install eval +git clone http://github.com/srvk/dscore #--branch v1.0 + +# Phonemizer installation +git clone https://github.com/bootphon/phonemizer +cd phonemizer +python setup.py build +python setup.py install + +#install launcher and utils +# cd /home/${user}/ +# git clone https://github.com/aclew/launcher.git +# chmod +x launcher/* +# git clone https://github.com/aclew/utils.git +# chmod +x utils/* + + +# install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) +# and intervaltree (needed for rttm2scp.py) +# and recommonmark (needed to make html in docs/) +su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" + +# Link /vagrant/launcher and /vagrant/utils to home folder where scripts expect them +ln -s /vagrant/launcher /home/${user}/ +ln -s /vagrant/utils /home/${user}/ + +# Some cleanup +apt-get autoremove -y + +# Silence error message from missing file +touch /home/${user}/.Xauthority + +# Provisioning runs as root; we want files to belong to '${user}' +chown -R ${user}:${user} /home/${user} \ No newline at end of file diff --git a/environment.yml b/environment.yml new file mode 100644 index 0000000..cb0e4a2 --- /dev/null +++ b/environment.yml @@ -0,0 +1,25 @@ +name: divime +channels: + - defaults + - conda-forge + - pytorch +dependencies: + - python=3.6.5 # python2 dependency + - cython + - numpy + - scipy + - mkl + - mkl-service + - dill + - tabulate + - joblib + - cudatoolkit + - pytorch-cpu + - scikit-learn + - pip: + - theano # install theano + - intervaltree + - pympi-ling # eaf -> rttm conversion + - tgt # textgrid -> rttm conversion + - ipdb # divime specific + diff --git a/launcher/python3.sh b/launcher/python3.sh new file mode 100644 index 0000000..c7fce76 --- /dev/null +++ b/launcher/python3.sh @@ -0,0 +1,13 @@ +# activate divime environment to use python 3.6.5 +source activate divime + +# list of libararies installed can be found with +# conda list +# to install new packages, edit environment.yml file + + +# sample usage +# python [some_file] ... + +# to switch back to python 2 +source deactivate \ No newline at end of file diff --git a/update.sh b/update.sh new file mode 100644 index 0000000..a9c4e95 --- /dev/null +++ b/update.sh @@ -0,0 +1,20 @@ +if grep --quiet vagrant /etc/passwd +then + user="vagrant" +else + user="ubuntu" +fi + +echo "Check git updates" +############################################# +# Get OpenSAT and all the tools +# Install DiarTK, LDC SAD, LDC scoring, Rajat's LENA stuff +cd /home/${user}/repos +release=v1.0 +(cd "OpenSAT"; git pull) +(cd "ib_diarization_toolkit" ; git pull; git checkout $release) +#(cd "ldc_sad_hmm" ; git pull) +(cd "dscore" ; git pull) +(cd "Yunitator" ; git pull) +(cd "To-Combo-SAD" ; git pull; git checkout $release) +############################################# \ No newline at end of file From 18cbaecf5d9dd96c6eb468b9d0df56962e31b3b2 Mon Sep 17 00:00:00 2001 From: Junghan Date: Mon, 26 Nov 2018 09:27:01 +0000 Subject: [PATCH 062/299] Python3 launcher scripts - usage : vagrant ssh -c "launcher/python3/test.sh" - outputs identical test result as python2 version - yunifier not yet working --- launcher/python3/noisemesSad.sh | 71 ++++++ launcher/python3/opensmileSad.sh | 66 ++++++ launcher/{python3.sh => python3/readme.txt} | 0 launcher/python3/test.sh | 247 ++++++++++++++++++++ launcher/python3/tocomboSad.sh | 83 +++++++ launcher/python3/yunitate.sh | 74 ++++++ 6 files changed, 541 insertions(+) create mode 100755 launcher/python3/noisemesSad.sh create mode 100755 launcher/python3/opensmileSad.sh rename launcher/{python3.sh => python3/readme.txt} (100%) create mode 100644 launcher/python3/test.sh create mode 100755 launcher/python3/tocomboSad.sh create mode 100755 launcher/python3/yunitate.sh diff --git a/launcher/python3/noisemesSad.sh b/launcher/python3/noisemesSad.sh new file mode 100755 index 0000000..7a10d93 --- /dev/null +++ b/launcher/python3/noisemesSad.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# noisemes_sad.sh +source activate divime + +# run OpenSAT with hard coded models & configs found here and in /vagrant + + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +# Path to OpenSAT (go on folder up and to opensat) + + + +if [ $# -lt 1 ]; then + echo "Usage: noisemes_sad.sh " + echo "where dirname is a folder on the host" + echo "containing the wav files (/vagrant/dirname/ in the VM)" + exit 1 +fi + +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# Check audio_dir to see if empty or if contains empty wav +bash $UTILS/check_folder.sh $audio_dir + +# let's get our bearings: set CWD to path of OpenSAT +cd $OPENSATDIR +git checkout develop/python3 + +# make output folder for features, below input folder +mkdir -p $audio_dir/feature + +# first features +echo "extracting features for speech activity detection" +for file in `ls $audio_dir/*.wav`; do + SSSF/code/feature/extract-htk-vm2.sh $file +done + +# then confidences +#python SSSF/code/predict/1-confidence-vm3.py $1 +echo "detecting speech and non speech segments" +python SSSF/code/predict/1-confidence-vm5.py $audio_dir +echo "finished detecting speech and non speech segments" + +# take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. +for sad in `ls $audio_dir/hyp_sum/*.lab`; do + base=$(basename $sad .lab) + rttm_out=noisemes_sad_${base}.rttm + if [ -s $sad ]; then + grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out + else + touch $audio_dir/$rttm_out + fi +done + +# simple remove hyp and feature +if ! $KEEPTEMP; then + rm -rf $audio_dir/hyp_sum $audio_dir/feature +fi +git checkout master \ No newline at end of file diff --git a/launcher/python3/opensmileSad.sh b/launcher/python3/opensmileSad.sh new file mode 100755 index 0000000..4547a41 --- /dev/null +++ b/launcher/python3/opensmileSad.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Launcher onset routine +source activate divime + +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $SCRIPT` # this is the home folder of this script + # not the home folder of the 'vagrant' user in the VM +# end of launcher onset routine + +### Read in variables from user +audio_dir=/vagrant/$1 + +### Other variables specific to this script +OSHOME=$REPOS/openSMILE-2.1.0/ +CONFIG_FILE=$UTILS/vad_segmenter_aclew.conf.txt +OPENSMILE=$OSHOME/bin/linux_x64_standalone_static/SMILExtract +workdir=$audio_dir/temp/opensmileSad +mkdir -p $workdir + +### SCRIPT STARTS + +if [ $# -lt 1 ]; then + echo "USAGE: $0 " + exit 1 +fi + +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + +filename=$(basename "$1") +dirname=$(dirname "$1") +extension="${filename##*.}" +basename="${filename%.*}" + + +cd $OSHOME/scripts/vad + +# Use OpenSMILE 2.1.0 +for sad in `ls $audio_dir/*.wav`; do + + file=$sad + id=`basename $file` + id=${id%.wav} +# > $audio_dir/${id}.txt #Make it empty if already present + echo "Processing $id ..." + LD_LIBRARY_PATH=/usr/local/lib \ + $OPENSMILE \ + -C $CONFIG_FILE \ + -I $file \ + -turndebug 1 \ + -noconsoleoutput 1 \ + -saveSegmentTimes $workdir/${id}.txt \ + -logfile $workdir/opensmile-vad.log > /dev/null +done + +for output in $(ls $workdir/*.txt); do + id=$(basename $output .txt) + awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > $audio_dir/opensmileSad_$id.rttm +done + +# Delete temporary folder +if ! $KEEPTEMP; then + rm -rf $workdir +fi diff --git a/launcher/python3.sh b/launcher/python3/readme.txt similarity index 100% rename from launcher/python3.sh rename to launcher/python3/readme.txt diff --git a/launcher/python3/test.sh b/launcher/python3/test.sh new file mode 100644 index 0000000..77148b1 --- /dev/null +++ b/launcher/python3/test.sh @@ -0,0 +1,247 @@ +#!/bin/bash +# +# This script tests numerous tools +# from a downloaded 5 minute section of the HomeBank VanDam daylong audio sample +# ("ACLEW Starter" data) + +# this doesn't work because .bashrc exits immediately if not running interactively +#source /home/vagrant/.bashrc -i +# instead: +export PATH=/home/vagrant/anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin +LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH" + +KEEPTEMP="" +if [ $# -eq 1 ]; then + if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP="--keep-temp" + fi +fi + + +# Absolute path to this script. /home/vagrant/launcher +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/vagrant/ - works out to being user home folder +BASEDIR=`dirname $SCRIPT` +export LAUNCHERS=/home/vagrant/launcher/python3 +export REPOS=/home/vagrant/repos +export UTILS=/home/vagrant/utils + +# Paths to Tools +LDC_SAD_DIR=$REPOS/ldc_sad_hmm +export OPENSATDIR=$REPOS/OpenSAT # noisemes +OPENSMILEDIR=$REPOS/openSMILE-2.1.0/ +TOCOMBOSAD=$REPOS/To-Combo-SAD +DIARTKDIR=$REPOS/ib_diarization_toolkit +#TALNETDIR=$REPOS/TALNet +DSCOREDIR=$REPOS/dscore +YUNITATORDIR=$REPOS/Yunitator + +FAILURES=false + +echo "Starting tests" +echo "Downloading test audio..." + +cd /vagrant/data +# get transcript +wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip +# cp /vagrant/VanDam-Daylong.zip . +unzip -q -o VanDam-Daylong.zip + +# This is the working directory for the tests; right beside the input +cd VanDam-Daylong/BN32/ +WORKDIR=`pwd` + +# Get daylong recording from the web +wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 +# cp /vagrant/BN32_010007.mp3 . + +DATADIR=data/VanDam-Daylong/BN32 # relative to /vagrant, used by launcher scripts +BASE=BN32_010007 # base filename for test input file, minus .wav or .rttm suffix +BASETEST=${BASE}_test +START=2513 # 41:53 in seconds +STOP=2813 # 46:53 in seconds + +# get 5 minute subset of audio +sox $BASE.mp3 $BASETEST.wav trim $START 5:00 >& /dev/null 2>&1 # silence output + +# convert CHA to reliable STM +$UTILS/chat2stm.sh $BASE.cha > $BASE.stm 2>/dev/null +# convert STM to RTTM as e.g. BN32_010007.rttm +# shift audio offsets to be 0-relative +cat $BASE.stm | awk -v start=$START -v stop=$STOP -v file=$BASE -e '{if (($4 > start) && ($4 < stop)) print "SPEAKER",file,"1",($4 - start),($5 - $4),"","","","","" }' > $BASETEST.rttm +TEST_RTTM=$WORKDIR/$BASETEST.rttm +TEST_WAV=$WORKDIR/$BASETEST.wav + + +# Check for HTK +echo "Checking for HTK..." +if [ -s /usr/local/bin/HCopy ]; then + echo "HTK is installed." +else + echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" + echo " and rename it to HTK.tar.gz ?" +fi + +# First test in ldc_sad_hmm +echo "Testing LDC SAD..." +if [ -s $LDC_SAD_DIR/perform_sad.py ]; then + cd $LDC_SAD_DIR + TESTDIR=$WORKDIR/ldc_sad-test + rm -rf $TESTDIR; mkdir -p $TESTDIR + python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} + # convert output to rttm, for diartk. + grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm + if [ -s $TESTDIR/$BASETEST.rttm ]; then + echo "LDC SAD passed the test." + else + FAILURES=true + echo " LDC SAD failed - no output RTTM" + fi +else + echo " LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" +fi + + +# now test Noisemes +echo "Testing noisemes..." +cd $OPENSATDIR +TESTDIR=$WORKDIR/noisemes-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +#./runDiarNoisemes.sh $TESTDIR > $TESTDIR/noisemes-test.log 2>&1 +$LAUNCHERS/noisemesSad.sh $DATADIR/noisemes-test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/noisemes_sad_$BASETEST.rttm ]; then + echo "Noisemes passed the test." +else + FAILURES=true + echo " Noisemes failed - no RTTM output" +fi +# clean up +#rm -rf $OPENSATDIR/SSSF/data/feature $OPENSATDIR/SSSF/data/hyp + + +# now test OPENSMILEDIR +echo "Testing OpenSmile SAD..." +cd $OPENSMILEDIR +TESTDIR=$WORKDIR/opensmile-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +$LAUNCHERS/opensmileSad.sh $DATADIR/opensmile-test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then + echo "OpenSmile SAD passed the test." +else + FAILURES=true + echo " OpenSmile SAD failed - no RTTM output" +fi + +# now test TOCOMBOSAD +echo "Testing ToCombo SAD..." +cd $TOCOMBOSAD +TESTDIR=$WORKDIR/tocombo_sad-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +$LAUNCHERS/tocomboSad.sh $DATADIR/tocombo_sad-test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then + echo "TOCOMBO SAD passed the test." +else + FAILURES=true + echo " TOCOMBO SAD failed - no output RTTM" +fi +exit 0; + + +# # finally test DIARTK +echo "Testing DIARTK..." +cd $DIARTKDIR +TESTDIR=$WORKDIR/diartk-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +cp $TEST_RTTM $TESTDIR +# run like the wind +$LAUNCHERS/diartk.sh $DATADIR/diartk-test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 +if grep -q "command not found" $TESTDIR/diartk-test.log; then + echo " Diartk failed - dependencies (probably HTK)" + FAILURES=true +else + if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then + echo "DiarTK passed the test." + else + FAILURES=true + echo " Diartk failed - no output RTTM" + fi +fi +rm $TESTDIR/$BASETEST.rttm + +# finally test Yunitator +echo "Testing Yunitator..." +cd $YUNITATORDIR +TESTDIR=$WORKDIR/yunitator-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +# let 'er rip +#./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +$LAUNCHERS/yunitate.sh $DATADIR/yunitator-test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then + echo "Yunitator passed the test." +else + FAILURES=true + echo " Yunitator failed - no output RTTM" +fi + + +# Test DSCORE +echo "Testing Dscore..." +cd $DSCOREDIR +git checkout develop/python3 +TESTDIR=$WORKDIR/dscore-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +cp -r test_ref test_sys $TESTDIR +rm -f test.df +source activate divime +python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} +source deactivate +if [ -s $TESTDIR/test.df ]; then + echo "DScore passed the test." +else + echo " DScore failed the test - output does not match expected" + FAILURES=true +fi +git checkout master + + +# testing LDC evalSAD (on opensmile) +echo "Testing LDC evalSAD" +if [ -d $LDC_SAD_DIR ]; then + cd $LDC_SAD_DIR + TESTDIR=$WORKDIR/opensmile-test + cp $WORKDIR/$BASETEST.rttm $TESTDIR + $LAUNCHERS/eval.sh $DATADIR/opensmile-test opensmileSad $KEEPTEMP > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} + if [ -s $TESTDIR/opensmileSad_eval.df ]; then + echo "LDC evalSAD passed the test" + else + echo " LDC evalSAD failed - no output .df" + FAILURES=true + fi +else + echo " LDC evalSAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" + FAILURES=true +fi + + +# test finished +if $FAILURES; then + echo "Some tools did not pass the test, but you can still use others" +else + echo "Congratulations, everything is OK!" +fi + +# results +echo "RESULTS:" +for f in /vagrant/$DATADIR/*-test/*.rttm; do $UTILS/sum-rttm.sh $f; done +echo "DSCORE:" +cat /vagrant/data/VanDam-Daylong/BN32/dscore-test/test.df +echo "EVAL_SAD:" +cat $TESTDIR/opensmileSad_eval.df diff --git a/launcher/python3/tocomboSad.sh b/launcher/python3/tocomboSad.sh new file mode 100755 index 0000000..c896644 --- /dev/null +++ b/launcher/python3/tocomboSad.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# Launcher onset routine +SCRIPT=$(readlink -f $0) +BASEDIR=`dirname $SCRIPT` +# end of launcher onset routine + + +### Read in variables from user +audio_dir=/vagrant/$1 +trs_format=$2 + + +### Other variables specific to this script +# create temp dir +workdir=$audio_dir/temp/tocomboSad +mkdir -p $workdir +TOCOMBOSADDIR=$REPOS/To-Combo-SAD +MCR=/usr/local/MATLAB/MATLAB_Runtime/v93 + +### SCRIPT STARTS + +if [ $# -lt 1 ]; then + echo "Usage: tocombo_sad.sh " + echo "where dirname is a folder on the host" + echo "containing the wav files (/vagrant/dirname/ in the VM)" + exit 1 +fi + +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" + +# Check audio_dir to see if empty or if contains empty wav +bash /home/vagrant/utils/check_folder.sh $audio_dir + +# let's get our bearings: set CWD to path of ToComboSAD +cd $TOCOMBOSADDIR +git checkout develop/python3 + +mkdir -p $workdir/feat +rm -f $workdir/filelist.txt +touch $workdir/filelist.txt + +# create temp dir to store audio files with 1 channels, if needed (i.e. if audio to treat has 2 or more channels.) +# Indeed, To Combo Sad Fails when there are more than 1 channels. +for f in $audio_dir/*.wav; do + # Check if audio has 1 channel or more. If it has more, use sox to create a temp audio file w/ 1 channel. + n_chan=$(soxi $f | grep Channels | cut -d ':' -f 2) + if [[ $n_chan -gt 1 ]]; then + base=$(basename $f) + sox -c $n_chan $f -c 1 $workdir/$base + f=$workdir/$base + fi + + echo $f >> $workdir/filelist.txt + +done +echo "finished" + +export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64: + +./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt + +# Retrieve the outputs from the temp folder +mv $workdir/*ToCombo.txt $audio_dir + +#convert to rttms +for f in $audio_dir/*.ToCombo.txt; do + bn=`basename $f .wav.ToCombo.txt` + python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > $audio_dir/tocomboSad_$bn.rttm +done + +# Delete temporary folder +if ! $KEEPTEMP; then + rm -rf $workdir +fi +git checkout master diff --git a/launcher/python3/yunitate.sh b/launcher/python3/yunitate.sh new file mode 100755 index 0000000..b9dadfd --- /dev/null +++ b/launcher/python3/yunitate.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source activate divime + +# run Yunitator with hard coded models & configs +# assumes Python environment in /home/vagrant/anaconda/bin + +# Absolute path to this script. /home/vagrant/launcher/yunitate.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/vagrant/launcher +BASEDIR=`dirname $SCRIPT` +# Path to Yunitator (go one folder up and to Yunitator) +YUNITATDIR=/home/vagrant/repos/Yunitator + +if [ $# -lt 1 ] || [ $# -gt 2 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + +audio_dir=/vagrant/$1 +YUNITEMP=$audio_dir/Yunitemp +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $UTILS/check_folder.sh $audio_dir + + +# let's get our bearings: set CWD to the path of Yunitator +cd $YUNITATDIR +git checkout develop/python3 + + +# make output folder for features, below input folder +mkdir -p $YUNITEMP + +# Iterate over files +echo "Starting $0" +for f in `ls $audio_dir/*.wav`; do + + basename=`basename $f .wav` + # first features + ./extract-htk-vm2.sh $f + + # then confidences + python diarize.py $YUNITEMP/$basename.htk $YUNITEMP/$basename.rttm.sorted + sort -V -k3 $YUNITEMP/$basename.rttm.sorted > $YUNITEMP/$basename.rttm +done + +echo "$0 finished running" + +# take all the .rttm in $audio_dir/Yunitemp/ and move them to /vagrant/data +for sad in `ls $YUNITEMP/*.rttm`; do + _rttm=$(basename $sad) + rttm=$audio_dir/yunitator_${_rttm} + # Remove not needed SIL lines + # sed -i '/ SIL /d' $sad + mv $sad $rttm +done + +# simply remove hyp and feature +if ! $KEEPTEMP; then + rm -rf $YUNITEMP +fi +git checkout master \ No newline at end of file From dce338d8f9c55d25dd97ce31e5156da2e278958a Mon Sep 17 00:00:00 2001 From: Alex Cristia Date: Mon, 26 Nov 2018 12:35:54 -0500 Subject: [PATCH 063/299] Update install.md --- docs/source/install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index eada5a1..7d8a0e2 100644 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -14,7 +14,7 @@ Try the following first: - In it, navigate to the directory in which you want the VM to be hosted - type in: -`$ git clone https://github.com/aclew/DiViMe` +`$ git clone https://github.com/srvk/DiViMe` 3. Change into it by @@ -38,7 +38,7 @@ The first time you do this, it will take at least 20 minutes to install all the Once the virtual machine will be installed, it will stay stuck at "installation finished" for few minutes. However, the tools are not yet installed at this step. You will need to wait for the tools to be installed, and to take back the control of the terminal to run the tools. -The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/aclew/DiViMe/issues), describing your situation. +The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/srvk/DiViMe/issues), describing your situation. Advanced topic: [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker) From 457d4f471bcc0837cbadb16489354ccb3a8758a8 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 26 Nov 2018 13:21:38 -0500 Subject: [PATCH 064/299] minor --- docs/source/install.md | 2 +- docs/source/yunitator.md | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index a704903..64f02cb 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -38,7 +38,7 @@ The first time you do this, it will take at least 20 minutes to install all the Once the virtual machine will be installed, it will stay stuck at "installation finished" for few minutes. However, the tools are not yet installed at this step. You will need to wait for the tools to be installed, and to take back the control of the terminal to run the tools. -The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/aclew/DiViMe/issues), describing your situation. +The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/srvk/DiViMe/issues), describing your situation. Advanced topic: [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker) diff --git a/docs/source/yunitator.md b/docs/source/yunitator.md index 764ee9b..479f06e 100755 --- a/docs/source/yunitator.md +++ b/docs/source/yunitator.md @@ -7,9 +7,7 @@ Given that there is no reference for this tool, we provide a more extensive intr The data used for training were: -- ACLEW Starter+ dataset (see Le Franc et al. 2018 Interspeech for explanations and reference) -- Tsimane dataset (idem) -- Data collected from Namibian and Vanuatu children (total of about 24h; recorded, sampled, and annotated like the Tsimane dataset) +- ACLEW Starter dataset - VanDam public 5-min dataset (about 13h; https://homebank.talkbank.org/access/Public/VanDam-5minute.html); noiseme-sad used to detect and remove intraturn silences Talker identity annotations collapsed into the following 4 types: @@ -19,19 +17,19 @@ Talker identity annotations collapsed into the following 4 types: - male adults (class prior .03) - non-vocalizations (class prior .75) -The features were MED (multimedia event detection) feature, extracted with OpenSMILE. They were extracted in 2s windows moving 100ms each step. There were 6,669 dims at first, PCA?ed down to 50 dims +The features were MED (multimedia event detection) feature, extracted with OpenSMILE. They were extracted in 2s windows moving 100ms each step. There were 6,669 dims at first, PCA-ed down to 50 dims -The model was a RNN, with 1 bidirectional GRU layer and 200 units in each direction. There was a softmax output layer, which therefore doesn?t predict overlaps.. +The model was a RNN, with 1 bidirectional GRU layer and 200 units in each direction. There was a softmax output layer, which therefore doesn't predict overlaps.. The training regime used 5-fold cross-validation, with 5 models trained on 4/5 of the data and tested on the remainder. The outputs are poooled together to measure performance. The final model was trained on all the data. -The loss function was cross entropy with classes weighted by 1/prior. The batch size was 5 sequences of 625 frames (in order to accommodate the fact that many of the clips were 1 minute long). The optimizer was Adam, the inital LR was .001 and the LR schedule was *=.999 every epoch. +The loss function was cross entropy with classes weighted by 1/prior. The batch size was 5 sequences of 500 frames. The optimizer was SGD with Nesterov momentum=.9, the inital LR was .01 and the LR schedule was *=0.8 if frame accuracy doesn’t reach new best in 4 epochs The resulting F1 for the key classes were: -- Child .55 (Precision .5, recall .61) -- Female adult .44 (P .41, R .48) -- Male adult .24 (P .22, R .28) +- Child .55 (Precision .55, recall .55) +- Male adult .43 (P .31, R .61) +- Female adult .55 (P .5, R .62) ## Main references: From c99151560b919a5199ed590d95a6c9bd964bc4b2 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 26 Nov 2018 15:34:08 -0500 Subject: [PATCH 065/299] further cleanup: DiViMe root, vagrant home --- .theanorc | 13 ------------- bootstrap.sh | 6 ++++-- environment.yml => conf/environment.yml | 0 test.wav | Bin 574008 -> 0 bytes test2.mp3 | Bin 230400 -> 0 bytes test2.rttm | 4 ---- 6 files changed, 4 insertions(+), 19 deletions(-) delete mode 100755 .theanorc rename environment.yml => conf/environment.yml (100%) delete mode 100755 test.wav delete mode 100755 test2.mp3 delete mode 100755 test2.rttm diff --git a/.theanorc b/.theanorc deleted file mode 100755 index af1aa2a..0000000 --- a/.theanorc +++ /dev/null @@ -1,13 +0,0 @@ -[global] -floatX = float32 -device = cpu - -[nvcc] -#fastmath = True - -[lib] -cnmem = 0.9 - -[cuda] -root = /opt/cuda-8.0 -#root = /usr/local/cuda-7.0 diff --git a/bootstrap.sh b/bootstrap.sh index 65f8bde..9741a56 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -32,13 +32,15 @@ if ! grep -q -i anaconda .bashrc; then fi # assume 'conda' is installed now (get path) su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" +# clean up big installer in home folder +rm -f Anaconda-2.3.0-Linux-x86_64.sh # python3 env # Install Miniconda and python libraries # miniconda=Miniconda3-4.5.11-Linux-x86_64.sh echo "Checking python3" cd /home/$user -cp /vagrant/environment.yml /home/${user}/ +cp /vagrant/conf/environment.yml /home/${user}/ su ${user} -c "/home/${user}/anaconda/bin/conda env create -f environment.yml" @@ -143,4 +145,4 @@ apt-get autoremove -y touch /home/${user}/.Xauthority # Provisioning runs as root; we want files to belong to '${user}' -chown -R ${user}:${user} /home/${user} \ No newline at end of file +chown -R ${user}:${user} /home/${user} diff --git a/environment.yml b/conf/environment.yml similarity index 100% rename from environment.yml rename to conf/environment.yml diff --git a/test.wav b/test.wav deleted file mode 100755 index 3b424b77e0b04384b288ea5d3f0e1a36934f28d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 574008 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 M`Vt3At2eqcF%l*?8hRH24L& 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ⅅ9zQ_`p9A49m=A_(w~=p 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

WP!Is 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 diff --git a/test2.rttm b/test2.rttm deleted file mode 100755 index b8d7d53..0000000 --- a/test2.rttm +++ /dev/null @@ -1,4 +0,0 @@ -SPEAKER test2 1 0.00 2.03 speech -SPEAKER test2 1 2.49 3.29 speech -SPEAKER test2 1 6.45 3.5 speech -SPEAKER test2 1 10.71 2.92 speech From d0ff8fa9c522508d413bca4b9eceef6a1263d284 Mon Sep 17 00:00:00 2001 From: Emmanuel Dupoux Date: Mon, 26 Nov 2018 16:20:54 -0500 Subject: [PATCH 066/299] modifs de la doc --- docs/source/initial_questions.md | 21 ++++++++++---------- docs/source/install.md | 10 +++++----- docs/source/instructions_for_contributors.md | 18 ++++++++++++++++- docs/source/references.md | 2 +- docs/source/tool_doc.md | 2 +- docs/source/usage.md | 6 +++--- 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/docs/source/initial_questions.md b/docs/source/initial_questions.md index 2d3029f..a996352 100755 --- a/docs/source/initial_questions.md +++ b/docs/source/initial_questions.md @@ -1,36 +1,35 @@ -# Initial questions +# Before starting ## What is the ACLEW DiViMe? -It is a collection of diarization tools, i.e., it allows users to add annotations onto a raw audio recording. At present, we have tools to do the following types of annotation: +It is a collection of speech processing tools allowing users to automatically add annotations onto a raw audio recording. At present, we have tools to do the following types of annotation: -1) Speech activity detection (answers the question: when is someone talking?) +1) Speech activity detection (_when is someone talking?_) -2) Talker diarization (answers the question: who is talking?) +2) Talker diarization (_who is talking?_) -3) Role diarization (answers the question: what kind of person is talking?) +3) Role diarization (_what kind of person is talking?_) We are hoping to add more tools in the future, including register detection, syllable quantification, and vocal maturity estimation. ## Who is the ACLEW DiViMe for? -Our target users have "difficult" recordings, E.G. recorded in natural environment, from sensitive populations, etc. Therefore, we are assuming users who are unable to share their audio recordings. Our primary test case involves language acquisition in children 0-3 years of age. +ACLEW DiViMe is for researchers dealing with speech recorded in naturalistic environments (speech in the wild), typically in daylong recording settings. The population recorded may be sensitive, therefore researchers may not be able to share their audio recordings. Our primary test case involves language acquisition in children 0-3 years of age. -We are hoping to make the use of these tools as easy as possible, but some command line programming will be unavoidable. If you are worried when reading this, we can recommend the Software Carpentry programming courses for researchers, and particularly their [unix bash](http://swcarpentry.github.io/shell-novice) and [version control](http://swcarpentry.github.io/git-novice/) bootcamps. +We are trying to make the use of these tools as easy as possible, but some command line programming/scripting is unavoidable. If you are worried when reading this, we can recommend the Software Carpentry programming courses for researchers, and particularly their [unix bash](http://swcarpentry.github.io/shell-novice) and [version control](http://swcarpentry.github.io/git-novice/) bootcamps. ## What exactly is inside the ACLEW DiViMe? -A virtual machine is actually a mini-computer that gets set up inside your computer. This creates a virtual environment within which we can be sure that our tools run, and run in the same way across all computers (Windows, Mac, Linux). +A virtual machine (VM) is actually a mini-computer that gets set up inside your computer. This creates a virtual environment within which we can be sure that our tools run, and run in the same way across all computers (Windows, Mac, Linux). Inside this mini-computer, we have tried to put several tools for each one of our three questions. Please note that some of the tools are developed by fellow researchers and programmers, and since we do not control them, we cannot be absolutely certain they will work. Therefore, we provide a general introduction to the contents in the usage section, and a specific list of tools in dedicated Detailed instructions sections. - ## How should I cite ACLEW DiViMe? The main citation is this paper, which explains the structure and idea, and provides some evaluation: Adrien Le Franc, Eric Riebling, Julien Karadayi, Yun Wang, Camila Scaff, Florian Metze, and Alejandrina Cristia. -The ACLEW DiViMe: An easy-to-use diarization tool. In Proc. INTERSPEECH, Hyderabad; India, September 2018. +[The ACLEW DiViMe: An easy-to-use diarization tool](https://www.isca-speech.org/archive/Interspeech_2018/pdfs/2324.pdf). In Proc. INTERSPEECH, Hyderabad; India, September 2018. The idea of using virtual machines to package speech tools comes from this work: -Florian Metze, Eric Fosler-Lussier, and Rebecca Bates. The speech recognition virtual kitchen. In Proc. INTERSPEECH, Lyon; France, August 2013. https://github.org/srvk. \ No newline at end of file +Florian Metze, Eric Fosler-Lussier, and Rebecca Bates. The speech recognition virtual kitchen. In Proc. INTERSPEECH, Lyon; France, August 2013. [https://github.org/srvk](https://github.org/srvk). \ No newline at end of file diff --git a/docs/source/install.md b/docs/source/install.md index 64f02cb..2d46840 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -1,4 +1,4 @@ -# Installation instructions +# Installing DiViMe ## First installation @@ -18,13 +18,13 @@ Try the following first: 3. Change into it by -`$ cd divime` +`$ cd DiViMe` 4. Install HTK HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. -- Go to the HTK download page http://htk.eng.cam.ac.uk/download.shtml +- Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) - Register by following the instructions on the left (under "Getting HTK": Register) - Check that you have received your password via email; you will need it for the next step. - Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). The download is probably called HTK-3.4.1.tar.gz, although the numbers may change if they update their code. @@ -84,7 +84,7 @@ This is the simple test with a few short files. If you would like to run a test If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. -## Update instructions +## Updating DiViMe If there is a new version of DiViMe, you'll need to perform the following 3 steps from within the DiViME folder on your terminal: @@ -95,7 +95,7 @@ $ git pull $ vagrant up ``` -## Uninstallation instructions +## Uninstallation If you want to get rid of the files completely, you should perform the following 3 steps from within the DiViME folder on your terminal: diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index 3642a1c..71c229c 100755 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -1,4 +1,4 @@ -# Instructions for contributors +# Contributing / Developing ## Before you start @@ -89,3 +89,19 @@ add your wrapper add a section to the test specific to your tool pull request + +## Updating the documentation + +The documentation is written in markdown and compiled into a website using sphynx. +The source of the documentation is in the shared directory ```docs/source```; once rebuilt +locally, the html is in ```docs/build/html/index.html``` + +Developers can modify the doc and recompile locally it using: + +``` +vagrant ssh -c "cd /vagrant/docs; make html" +``` + +once they are happy with the result, they can commit their changes as described above. + + diff --git a/docs/source/references.md b/docs/source/references.md index 74f4f46..afe8654 100755 --- a/docs/source/references.md +++ b/docs/source/references.md @@ -1,4 +1,4 @@ -# Further information on the formats +# File Formats ### RTTM diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index 1290bfc..ebaf836 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -1,3 +1,3 @@ -# Documentation of individual tools +# Detailed Tools Doc This section of the documentation gets populated with information from the different working tools. diff --git a/docs/source/usage.md b/docs/source/usage.md index 191d058..ab609fc 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -1,10 +1,10 @@ -# Use instructions +# Using DiViMe ## Overview This is an overview of the full tool presentation found in the next stage, recapping the main steps: -1. Put your data in /data/ +1. Put your data in the ```data``` shared directory. 2. Do `$ vagrant up` to "wake the machine up" 3. Choose between: running a speech activity detection system followed by a diarization system (steps 3 and 4 below), or a tool that directly segments recordings into 3 main roles, namely child, male adult, female adult (step 5 below) 4. If you have some annotations, you can evaluate how the tools did (step 6 below) @@ -14,7 +14,7 @@ Next we provide instructions for all tools. More detailed information about each ## Short instructions for all tools -1. Put sound files (and annotations, if you have any) inside the "data" folder inside the DiViMe folder. If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. +1. Put sound files (and annotations, if you have any) inside the shared ```data``` folder. If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. It is probably safer to make a copy (rather than moving them), in case you later decide to delete the whole vagrant folder. From a4fcb94ae7e874eb7f7d184a53928407c4756e98 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 26 Nov 2018 16:31:50 -0500 Subject: [PATCH 067/299] added routine to install htk after provisioning --- launcher/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 0aac9c2..c20598b 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -78,7 +78,7 @@ if [ -s /usr/local/bin/HCopy ]; then echo "HTK is installed." else echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" - echo " and rename it to HTK.tar.gz ?" + echo " and rename it to HTK.tar.gz? If not, do so now, then run: ssh -c \"install_htk.sh\" " fi # First test in ldc_sad_hmm @@ -161,7 +161,7 @@ cp $TEST_RTTM $TESTDIR # run like the wind $LAUNCHERS/diartk.sh $DATADIR/diartk-test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 if grep -q "command not found" $TESTDIR/diartk-test.log; then - echo " Diartk failed - dependencies (probably HTK)" + echo " Diartk failed - dependencies (probably HTK is missing)" FAILURES=true else if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then From 9fe300276efb19514420a19af1108f01b52d1c53 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 26 Nov 2018 16:34:56 -0500 Subject: [PATCH 068/299] added routine to install htk after provisioning --- utils/install_htk.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 utils/install_htk.sh diff --git a/utils/install_htk.sh b/utils/install_htk.sh new file mode 100755 index 0000000..4fd25f2 --- /dev/null +++ b/utils/install_htk.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# install HTK after the fact + +# optionally Install HTK (without it, some other tools will not work) +# the idea is to make users independently download HTK installer since +# we cannot redistribute +cd /home/${user} +if [ -f /vagrant/HTK.tar.gz ]; then + if [[ ! -d htk ]]; then + cd /home/${user}/repos/ + su ${user} -c "tar zxf /vagrant/HTK.tar.gz" + cd htk + ./configure --without-x --disable-hslab + sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + make all + make install + fi +fi + + From f3d3bf37fde750f9dddfa496eb7bfb20aaa7221f Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 26 Nov 2018 21:35:24 +0000 Subject: [PATCH 069/299] fix pathname bug --- launcher/noisemesSad.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 475f459..5e9a4ee 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -7,12 +7,12 @@ conda_dir=/home/vagrant/anaconda/bin # run OpenSAT with hard coded models & configs found here and in /vagrant -# Absolute path to this script. /home/user/bin/foo.sh +# Absolute path to this script. /home/vagrant/launcher/noisemesSad.sh SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` +# home folder +BASEDIR=/home/vagrant # Path to OpenSAT (go on folder up and to opensat) -OPENSATDIR=$(dirname $BASEDIR)/OpenSAT +OPENSATDIR=/home/vagrant/repos/OpenSAT if [ $# -lt 1 ]; then echo "Usage: noisemes_sad.sh " @@ -33,7 +33,7 @@ extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/utils/check_folder.sh $audio_dir # let's get our bearings: set CWD to path of OpenSAT cd $OPENSATDIR From cc8fb7b080f6fa2a8f6368626eac45f3b06c1d8b Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 26 Nov 2018 16:35:42 -0500 Subject: [PATCH 070/299] added routine to install htk after provisioning --- utils/install_htk.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/install_htk.sh b/utils/install_htk.sh index 4fd25f2..71ad3d1 100755 --- a/utils/install_htk.sh +++ b/utils/install_htk.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env/bash # install HTK after the fact # optionally Install HTK (without it, some other tools will not work) From f0f249b9d788f75ba47dcfe9f2bb0a13c08be0aa Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 26 Nov 2018 16:37:06 -0500 Subject: [PATCH 071/299] added routine to install htk after provisioning --- utils/install_htk.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/install_htk.sh b/utils/install_htk.sh index 71ad3d1..41aafa1 100755 --- a/utils/install_htk.sh +++ b/utils/install_htk.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env/bash +#!/bin/bash # install HTK after the fact # optionally Install HTK (without it, some other tools will not work) From 6056dc1dcdade79bbb28dd30d7a8a8d8fe570606 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 26 Nov 2018 16:42:25 -0500 Subject: [PATCH 072/299] minor --- utils/create_ref_sys.sh | 2 +- utils/eaf2enriched_txt.sh | 2 +- utils/install_htk.sh | 9 ++++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh index 4c3c0db..250e882 100755 --- a/utils/create_ref_sys.sh +++ b/utils/create_ref_sys.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/bash audio_dir=/vagrant/$1 model_prefix=$2 diff --git a/utils/eaf2enriched_txt.sh b/utils/eaf2enriched_txt.sh index 5234516..26c3ff0 100755 --- a/utils/eaf2enriched_txt.sh +++ b/utils/eaf2enriched_txt.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/bash INPUT_FOLDER=$1 LANG=$2 SCRIPT_DIR=$(dirname "$0") diff --git a/utils/install_htk.sh b/utils/install_htk.sh index 41aafa1..ed43a19 100755 --- a/utils/install_htk.sh +++ b/utils/install_htk.sh @@ -1,6 +1,13 @@ #!/bin/bash # install HTK after the fact +if grep --quiet vagrant /etc/passwd +then + user="vagrant" +else + user="ubuntu" +fi + # optionally Install HTK (without it, some other tools will not work) # the idea is to make users independently download HTK installer since # we cannot redistribute @@ -13,7 +20,7 @@ if [ -f /vagrant/HTK.tar.gz ]; then ./configure --without-x --disable-hslab sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile make all - make install + sudo make install fi fi From 13b22d0cd82231448a6e836587bbf1c74b0002cf Mon Sep 17 00:00:00 2001 From: Emmanuel Dupoux Date: Mon, 26 Nov 2018 16:50:54 -0500 Subject: [PATCH 073/299] corrected the install_htk.sh with sudo --- utils/install_htk.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/install_htk.sh b/utils/install_htk.sh index ed43a19..d82ca12 100755 --- a/utils/install_htk.sh +++ b/utils/install_htk.sh @@ -15,11 +15,11 @@ cd /home/${user} if [ -f /vagrant/HTK.tar.gz ]; then if [[ ! -d htk ]]; then cd /home/${user}/repos/ - su ${user} -c "tar zxf /vagrant/HTK.tar.gz" + sudo tar zxf /vagrant/HTK.tar.gz cd htk - ./configure --without-x --disable-hslab - sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile - make all + sudo ./configure --without-x --disable-hslab + sudo sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + sudo make all sudo make install fi fi From b751c3aaab178051acb0bcfab0b0f18068a5dda5 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 26 Nov 2018 21:55:16 +0000 Subject: [PATCH 074/299] add utils to path --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 bootstrap.sh diff --git a/bootstrap.sh b/bootstrap.sh old mode 100644 new mode 100755 index 9741a56..4501787 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -28,7 +28,7 @@ wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.ra echo "Installing Anaconda-2.3.0..." sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" if ! grep -q -i anaconda .bashrc; then - echo "export PATH=/home/vagrant/launcher:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc + echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc fi # assume 'conda' is installed now (get path) su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" From 0852e892d8462749d4c791f3268cf6d92c4f3230 Mon Sep 17 00:00:00 2001 From: Emmanuel Dupoux Date: Mon, 26 Nov 2018 16:55:46 -0500 Subject: [PATCH 075/299] minor --- launcher/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index c20598b..6433851 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -40,7 +40,7 @@ YUNITATORDIR=$REPOS/Yunitator FAILURES=false echo "Starting tests" -echo "Downloading test audio..." +echo "Downloading data..." cd /vagrant/data # get transcript @@ -78,7 +78,7 @@ if [ -s /usr/local/bin/HCopy ]; then echo "HTK is installed." else echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" - echo " and rename it to HTK.tar.gz? If not, do so now, then run: ssh -c \"install_htk.sh\" " + echo " and rename it to HTK.tar.gz? If not, do so now, then run: ssh -c \"utils/install_htk.sh\" " fi # First test in ldc_sad_hmm From e2a5ca73d6cb93e4eebeea8b31335e984c99cdfc Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 26 Nov 2018 17:28:43 -0500 Subject: [PATCH 076/299] don't re download test data --- launcher/test.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 6433851..9b6146a 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -40,19 +40,24 @@ YUNITATORDIR=$REPOS/Yunitator FAILURES=false echo "Starting tests" -echo "Downloading data..." cd /vagrant/data # get transcript -wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip -unzip -q -o VanDam-Daylong.zip +if [ ! -s VanDam-Daylong.zip ]; then + echo "Downloading test transcript..." + wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip + unzip -q -o VanDam-Daylong.zip +fi # This is the working directory for the tests; right beside the input cd VanDam-Daylong/BN32/ WORKDIR=`pwd` # Get daylong recording from the web -wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 +if [ ! -s BN32_010007.mp3 ]; then + echo "Downloading test audio..." + wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 +fi DATADIR=data/VanDam-Daylong/BN32 # relative to /vagrant, used by launcher scripts BASE=BN32_010007 # base filename for test input file, minus .wav or .rttm suffix From de7869737c5893f51f74d03902c8d37d91ff72f1 Mon Sep 17 00:00:00 2001 From: jing Date: Mon, 26 Nov 2018 18:11:44 -0500 Subject: [PATCH 077/299] merge vcm commands --- bootstrap.sh | 10 ++++++++++ launcher/test.sh | 21 +++++++++++++++++++-- update.sh | 3 ++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 9741a56..4aa1ac6 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -64,6 +64,14 @@ cp openSMILE-2.1.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin chmod +x /usr/local/bin/SMILExtract rm OpenSMILE-2.1.tar.gz +# Install openSMILE2.3.0 +su ${user} -c "mkdir -p /home/${user}/repos/" +cd /home/${user}/repos/ +wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz +tar zxvf OpenSMILE-2.3.tar.gz +chmod +x openSMILE-2.3.0/bin/linux_x64_standalone_static/SMILExtract +rm OpenSMILE-2.3.tar.gz + # optionally Install HTK (without it, some other tools will not work) # the idea is to make users independently download HTK installer since # we cannot redistribute @@ -104,6 +112,8 @@ git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" +# Install VCM +git clone https://github.com/MilesICL/vcm #Install to-combo sad and dependencies (matlab runtime environnement) git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 diff --git a/launcher/test.sh b/launcher/test.sh index c20598b..57ac891 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -36,6 +36,7 @@ DIARTKDIR=$REPOS/ib_diarization_toolkit #TALNETDIR=$REPOS/TALNet DSCOREDIR=$REPOS/dscore YUNITATORDIR=$REPOS/Yunitator +VCMDIR=$REPOS/vcm FAILURES=false @@ -78,7 +79,7 @@ if [ -s /usr/local/bin/HCopy ]; then echo "HTK is installed." else echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" - echo " and rename it to HTK.tar.gz? If not, do so now, then run: ssh -c \"install_htk.sh\" " + echo " and rename it to HTK.tar.gz ?" fi # First test in ldc_sad_hmm @@ -161,7 +162,7 @@ cp $TEST_RTTM $TESTDIR # run like the wind $LAUNCHERS/diartk.sh $DATADIR/diartk-test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 if grep -q "command not found" $TESTDIR/diartk-test.log; then - echo " Diartk failed - dependencies (probably HTK is missing)" + echo " Diartk failed - dependencies (probably HTK)" FAILURES=true else if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then @@ -225,6 +226,22 @@ else fi +# Testing VCM +echo "Testing VCM..." +cd $VCMDIR +TESTDIR=$WORKDIR/vcm-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +# let 'er rip +#./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +$LAUNCHERS/vcm.sh $DATADIR/vcm-test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then + echo "VCM passed the test." +else + FAILURES=true + echo " VCM failed - no output RTTM" +fi + # test finished if $FAILURES; then echo "Some tools did not pass the test, but you can still use others" diff --git a/update.sh b/update.sh index a9c4e95..df73da1 100644 --- a/update.sh +++ b/update.sh @@ -16,5 +16,6 @@ release=v1.0 #(cd "ldc_sad_hmm" ; git pull) (cd "dscore" ; git pull) (cd "Yunitator" ; git pull) +(cd "VCM"; git pull) (cd "To-Combo-SAD" ; git pull; git checkout $release) -############################################# \ No newline at end of file +############################################# From 4eb25e301bb976885a59612839689b88ac60835a Mon Sep 17 00:00:00 2001 From: jing Date: Mon, 26 Nov 2018 18:13:43 -0500 Subject: [PATCH 078/299] add vcm doc and vcm.sh --- docs/source/vcm.md | 19 ++++++++++++++ launcher/vcm.sh | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100755 docs/source/vcm.md create mode 100755 launcher/vcm.sh diff --git a/docs/source/vcm.md b/docs/source/vcm.md new file mode 100755 index 0000000..fa02fcd --- /dev/null +++ b/docs/source/vcm.md @@ -0,0 +1,19 @@ +# VCM + +## General intro +Two independent models: one (modelLing) to predicts lingustic vs. non-linguistic infant vocalisations; the other one (modelSyll) predicts canonical vs. non-canonical syllables if given a lingustic infant vocalication. + +Specifically, the modelLing was trained on Alex's infant lingustic dataset (refer to this paper: https://static1.squarespace.com/static/591f756559cc68d09fc2e308/t/5b3a94cb758d4645603085db/1530565836736/ZhangEtAl_2018.pdf), and modelSyll was trained on Anne's infant syllable vocalisation dataset (refer to this paper: https://pdfs.semanticscholar.org/2b25/bc84d2c4668e6d17f4f9343106f726198cd0.pdf). + +Feature set: 88 eGeMAPS extracted by openSMILE-2.3.0 on the segment level. + +Model: two hidden layers feed-forward neural networks with 1024 hidden nodes per each hidden layer. A log_softmax layer is stacked as an output layer. The optimiser was set to SGD with a learning rate 0.01, and the batch size is 64. + +Setups: Both the infant linguistic and syllable vocalisation datasets were split into train, development, and test partitions following a speaker independent strategy. + +Results: The results are 67.5% UAR and 76.6% WAR on the test set for the lingustic voc classification; and are 70.4% UAR and 69.2% WAR for the syllable voc classification. + + +## Main references: + +There is no official reference for this tool. diff --git a/launcher/vcm.sh b/launcher/vcm.sh new file mode 100755 index 0000000..8ec9b46 --- /dev/null +++ b/launcher/vcm.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc +conda_dir=/home/vagrant/anaconda/bin + +# run OpenSAT with hard coded models & configs found here and in /vagrant +# assumes Python environment in /home/${user}/ + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=`dirname $SCRIPT` +#| Path to VCM (go one folder up and to VCM) +VCMDIR=/home/vagrant/repos/vcm + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "where dirname is the name of the folder" + echo "containing the wav files" + exit 1 +fi + +audio_dir=/vagrant/$1 +filename=$(basename "$audio_dir") +dirname=$(dirname "$audio_dir") +extension="${filename##*.}" +basename="${filename%.*}" +# Check audio_dir to see if empty or if contains empty wav +bash $BASEDIR/check_folder.sh $audio_dir + +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + + + +# this is set in user's login .bashrc +#export PATH=/home/${user}/anaconda/bin:$PATH + +# let's get our bearings: set CWD to the path of VCM +cd $VCMDIR + +# Iterate over files +echo "Starting" +for f in `ls $audio_dir/*.wav`; do + echo $f + ./runVCM.sh $f +done + +echo "$0 finished running" + +# take all the .rttm in $audio_dir/VCMtemp/ and move them to /vagrant/data +for vcm in `ls $audio_dir/VCMtemp/*.rttm`; do + _rttm=$(basename $vcm) + rttm=$audio_dir/${_rttm} + mv $vcm $rttm +done + +# simply remove hyp and feature +if ! $KEEPTEMP; then + rm -rf $audio_dir/VCMtemp +fi From 9ecc0d0e748cad103073f6dc40c77c776fec3be2 Mon Sep 17 00:00:00 2001 From: jing Date: Mon, 26 Nov 2018 18:21:33 -0500 Subject: [PATCH 079/299] update test.sh --- launcher/test.sh | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 9b6146a..aaff247 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -36,28 +36,24 @@ DIARTKDIR=$REPOS/ib_diarization_toolkit #TALNETDIR=$REPOS/TALNet DSCOREDIR=$REPOS/dscore YUNITATORDIR=$REPOS/Yunitator +VCMDIR=$REPOS/vcm FAILURES=false echo "Starting tests" +echo "Downloading test audio..." cd /vagrant/data # get transcript -if [ ! -s VanDam-Daylong.zip ]; then - echo "Downloading test transcript..." - wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip - unzip -q -o VanDam-Daylong.zip -fi +wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip +unzip -q -o VanDam-Daylong.zip # This is the working directory for the tests; right beside the input cd VanDam-Daylong/BN32/ WORKDIR=`pwd` # Get daylong recording from the web -if [ ! -s BN32_010007.mp3 ]; then - echo "Downloading test audio..." - wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 -fi +wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 DATADIR=data/VanDam-Daylong/BN32 # relative to /vagrant, used by launcher scripts BASE=BN32_010007 # base filename for test input file, minus .wav or .rttm suffix @@ -83,7 +79,7 @@ if [ -s /usr/local/bin/HCopy ]; then echo "HTK is installed." else echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" - echo " and rename it to HTK.tar.gz? If not, do so now, then run: ssh -c \"utils/install_htk.sh\" " + echo " and rename it to HTK.tar.gz ?" fi # First test in ldc_sad_hmm @@ -166,7 +162,7 @@ cp $TEST_RTTM $TESTDIR # run like the wind $LAUNCHERS/diartk.sh $DATADIR/diartk-test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 if grep -q "command not found" $TESTDIR/diartk-test.log; then - echo " Diartk failed - dependencies (probably HTK is missing)" + echo " Diartk failed - dependencies (probably HTK)" FAILURES=true else if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then @@ -230,6 +226,22 @@ else fi +# Testing VCM +echo "Testing VCM..." +cd $VCMDIR +TESTDIR=$WORKDIR/vcm-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +# let 'er rip +#./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +$LAUNCHERS/vcm.sh $DATADIR/vcm-test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then + echo "VCM passed the test." +else + FAILURES=true + echo " VCM failed - no output RTTM" +fi + # test finished if $FAILURES; then echo "Some tools did not pass the test, but you can still use others" @@ -244,3 +256,4 @@ echo "DSCORE:" cat /vagrant/data/VanDam-Daylong/BN32/dscore-test/test.df echo "EVAL_SAD:" cat $TESTDIR/opensmileSad_eval.df + From 5a54b32faf36dc6a2132c4f57471266df8bf4cc0 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 26 Nov 2018 18:47:51 -0500 Subject: [PATCH 080/299] minor --- launcher/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/test.sh b/launcher/test.sh index aaff247..e5d40b6 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -79,7 +79,7 @@ if [ -s /usr/local/bin/HCopy ]; then echo "HTK is installed." else echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" - echo " and rename it to HTK.tar.gz ?" + echo " and rename it to HTK.tar.gz? If so, then you may need to re-install it. Run: vagrant ssh -c \"utils/install_htk.sh\" " fi # First test in ldc_sad_hmm From df2f73e447f51729dec35649b945c19de8609cf9 Mon Sep 17 00:00:00 2001 From: MarvinLavechin Date: Tue, 27 Nov 2018 02:20:17 +0100 Subject: [PATCH 081/299] Bug fix on eaf2txt.py, consider only tiers whose name starts by xds@ or vcm@ --- utils/eaf2txt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py index c54a1b4..354df99 100755 --- a/utils/eaf2txt.py +++ b/utils/eaf2txt.py @@ -36,6 +36,7 @@ def eaf2txt(path_to_eaf, output_folder, cleanup=False): output_file = open(output_path, 'w') EAF = pmp.Elan.Eaf(path_to_eaf) tiers = EAF.tiers + tiers = {key: value for key, value in tiers.items() if key.startswith(('xds@', 'vcm@'))} for tier in tiers: try: annotations = EAF.get_annotation_data_for_tier(tier) @@ -86,4 +87,4 @@ def main(): eaf2txt(eaf_path, output) if __name__ == '__main__': - main() \ No newline at end of file + main() From 97a74806ceade1e54f29da278577defb9d0dbfba Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 27 Nov 2018 11:21:27 -0500 Subject: [PATCH 082/299] Commit again the overwritten changes to not re-download test audio & transcript if already present --- launcher/test.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index e5d40b6..5873f9d 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -41,12 +41,14 @@ VCMDIR=$REPOS/vcm FAILURES=false echo "Starting tests" -echo "Downloading test audio..." cd /vagrant/data -# get transcript -wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip -unzip -q -o VanDam-Daylong.zip + +if [ ! -s VanDam-Daylong.zip ]; then + echo "Downloading test transcript..." + wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip + unzip -q -o VanDam-Daylong.zip +fi # This is the working directory for the tests; right beside the input cd VanDam-Daylong/BN32/ @@ -54,6 +56,10 @@ WORKDIR=`pwd` # Get daylong recording from the web wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 +if [ ! -s BN32_010007.mp3 ]; then + echo "Downloading test audio..." + wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 +fi DATADIR=data/VanDam-Daylong/BN32 # relative to /vagrant, used by launcher scripts BASE=BN32_010007 # base filename for test input file, minus .wav or .rttm suffix From b041840858bbc2da238891a8c3047e7d830aa24f Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 27 Nov 2018 12:08:49 -0500 Subject: [PATCH 083/299] Refresh EVAL_SAD --- launcher/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/test.sh b/launcher/test.sh index 5873f9d..e67248f 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -261,5 +261,5 @@ for f in /vagrant/$DATADIR/*-test/*.rttm; do $UTILS/sum-rttm.sh $f; done echo "DSCORE:" cat /vagrant/data/VanDam-Daylong/BN32/dscore-test/test.df echo "EVAL_SAD:" -cat $TESTDIR/opensmileSad_eval.df +cat $WORKDIR/opensmile-test/opensmileSad_eval.df From 805c42b5d2db164adcc21c07ecf5c22c0981eca9 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 27 Nov 2018 12:45:56 -0500 Subject: [PATCH 084/299] fix path VCM->vcm --- update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.sh b/update.sh index df73da1..7f08222 100644 --- a/update.sh +++ b/update.sh @@ -16,6 +16,6 @@ release=v1.0 #(cd "ldc_sad_hmm" ; git pull) (cd "dscore" ; git pull) (cd "Yunitator" ; git pull) -(cd "VCM"; git pull) +(cd "vcm"; git pull) (cd "To-Combo-SAD" ; git pull; git checkout $release) ############################################# From 36a7c5ff6ae250c97a5e53b228c043eb5025221b Mon Sep 17 00:00:00 2001 From: jaden-w Date: Tue, 27 Nov 2018 13:48:21 -0500 Subject: [PATCH 085/299] Fixed line endings --- launcher/noisemesSad.sh | 13 ++++++++++--- launcher/yunitate.sh | 16 ++++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 5e9a4ee..b7e519f 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -3,7 +3,8 @@ # Since the script is built to be launched outside of the vm, source # the .bashrc which is not necessarily sourced! source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin +# conda_dir=/home/vagrant/anaconda/bin +source activate divime # run OpenSAT with hard coded models & configs found here and in /vagrant @@ -13,6 +14,7 @@ SCRIPT=$(readlink -f $0) BASEDIR=/home/vagrant # Path to OpenSAT (go on folder up and to opensat) OPENSATDIR=/home/vagrant/repos/OpenSAT +YUNITATORDIR=/home/vagrant/repos/Yunitator if [ $# -lt 1 ]; then echo "Usage: noisemes_sad.sh " @@ -47,10 +49,13 @@ for file in `ls $audio_dir/*.wav`; do SSSF/code/feature/extract-htk-vm2.sh $file done +cd $YUNITATORDIR + # then confidences #python SSSF/code/predict/1-confidence-vm3.py $1 echo "detecting speech and non speech segments" -$conda_dir/python SSSF/code/predict/1-confidence-vm5.py $audio_dir +# $conda_dir/python SSSF/code/predict/1-confidence-vm5.py $audio_dir +python ~/repos/Yunitator/yunified.py noisemes $audio_dir 4000 echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. @@ -58,7 +63,7 @@ for sad in `ls $audio_dir/hyp_sum/*.lab`; do base=$(basename $sad .lab) rttm_out=noisemes_sad_${base}.rttm if [ -s $sad ]; then - grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out + grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out else touch $audio_dir/$rttm_out fi @@ -68,3 +73,5 @@ done if ! $KEEPTEMP; then rm -rf $audio_dir/hyp_sum $audio_dir/feature fi + +source deactivate diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 5ccfedd..8d53e08 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -3,6 +3,7 @@ # the .bashrc which is not necessarily sourced! #source ~/.bashrc #conda_dir=/home/vagrant/anaconda/bin +source activate divime # run Yunitator with hard coded models & configs # assumes Python environment in /home/vagrant/anaconda/bin @@ -49,12 +50,17 @@ for f in `ls $audio_dir/*.wav`; do basename=`basename $f .wav` # first features ./extract-htk-vm2.sh $f - - # then confidences - python diarize.py $YUNITEMP/$basename.htk $YUNITEMP/$basename.rttm.sorted - sort -V -k3 $YUNITEMP/$basename.rttm.sorted > $YUNITEMP/$basename.rttm done +python yunified.py yunitator $audio_dir 4000 + +for f in `ls $YUNITEMP/*.rttm.sorted`; do + filename=$(basename "$f") + basename="${filename%.*}" + + sort -V -k3 $f > $YUNITEMP/$basename +done + echo "$0 finished running" # take all the .rttm in $audio_dir/Yunitemp/ and move them to /vagrant/data @@ -70,3 +76,5 @@ done if ! $KEEPTEMP; then rm -rf $YUNITEMP fi + +source deactivate From 16c3fb66890f849b8e13ed8eae84b91c45a4a6a8 Mon Sep 17 00:00:00 2001 From: jaden-w Date: Tue, 27 Nov 2018 13:57:36 -0500 Subject: [PATCH 086/299] Make bootstrap pull yunified versions of repos --- bootstrap.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 47bde07..9e19029 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -94,7 +94,7 @@ fi cd /home/${user}/repos/ # Get OpenSAT=noisemes and dependencies -git clone http://github.com/srvk/OpenSAT # --branch v1.0 # need Dev +git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" cp /vagrant/conf/.theanorc /home/${user}/ @@ -108,7 +108,7 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install Yunitator and dependencies -git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev +git clone https://github.com/srvk/Yunitator --branch yunified # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" From 1f1a7ff4b4a0df994265d482701434757975a129 Mon Sep 17 00:00:00 2001 From: Junghan Date: Tue, 27 Nov 2018 14:45:56 -0500 Subject: [PATCH 087/299] move config files to conf/ --- Vagrantfile | 6 +++--- Dockerfile => conf/Dockerfile | 0 bootstrap.sh => conf/bootstrap.sh | 16 ++++++++-------- update.sh => conf/update.sh | 7 +++---- 4 files changed, 14 insertions(+), 15 deletions(-) rename Dockerfile => conf/Dockerfile (100%) rename bootstrap.sh => conf/bootstrap.sh (92%) rename update.sh => conf/update.sh (73%) diff --git a/Vagrantfile b/Vagrantfile index 707e168..827fa7a 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -97,11 +97,11 @@ Vagrant.configure("2") do |config| end config.vm.provision "bootstrap", type: "shell", run: "once" do |s| - s.path = "bootstrap.sh" + s.path = "conf/bootstrap.sh" end - config.vm.provision "update", type: "shell", run: "always" do |s| - s.path = "update.sh" + config.vm.provision "update", type: "shell", run: "never" do |s| + s.path = "conf/update.sh" end end diff --git a/Dockerfile b/conf/Dockerfile similarity index 100% rename from Dockerfile rename to conf/Dockerfile diff --git a/bootstrap.sh b/conf/bootstrap.sh similarity index 92% rename from bootstrap.sh rename to conf/bootstrap.sh index 47bde07..c132e13 100755 --- a/bootstrap.sh +++ b/conf/bootstrap.sh @@ -38,7 +38,7 @@ rm -f Anaconda-2.3.0-Linux-x86_64.sh # python3 env # Install Miniconda and python libraries # miniconda=Miniconda3-4.5.11-Linux-x86_64.sh -echo "Checking python3" +echo "Create python3 env" cd /home/$user cp /vagrant/conf/environment.yml /home/${user}/ su ${user} -c "/home/${user}/anaconda/bin/conda env create -f environment.yml" @@ -55,7 +55,7 @@ rm /tmp/MCR_R2017b_glnxa64_installer.zip # Install OpenSMILE echo "Installing OpenSMILE" - su ${user} -c "mkdir -p /home/${user}/repos/" +su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz tar zxvf OpenSMILE-2.1.tar.gz @@ -93,8 +93,8 @@ fi # POPOULATE THE REPOSITORY SECTION cd /home/${user}/repos/ - # Get OpenSAT=noisemes and dependencies -git clone http://github.com/srvk/OpenSAT # --branch v1.0 # need Dev +# Get OpenSAT=noisemes and dependencies +git clone http://github.com/srvk/OpenSAT su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" cp /vagrant/conf/.theanorc /home/${user}/ @@ -108,7 +108,7 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install Yunitator and dependencies -git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev +git clone https://github.com/srvk/Yunitator su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" @@ -116,14 +116,14 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" git clone https://github.com/MilesICL/vcm #Install to-combo sad and dependencies (matlab runtime environnement) -git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 +git clone https://github.com/srvk/To-Combo-SAD # Install DiarTK -git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 +git clone http://github.com/srvk/ib_diarization_toolkit # Install eval -git clone http://github.com/srvk/dscore #--branch v1.0 +git clone http://github.com/srvk/dscore # Phonemizer installation git clone https://github.com/bootphon/phonemizer diff --git a/update.sh b/conf/update.sh similarity index 73% rename from update.sh rename to conf/update.sh index df73da1..84a7b28 100644 --- a/update.sh +++ b/conf/update.sh @@ -10,12 +10,11 @@ echo "Check git updates" # Get OpenSAT and all the tools # Install DiarTK, LDC SAD, LDC scoring, Rajat's LENA stuff cd /home/${user}/repos -release=v1.0 (cd "OpenSAT"; git pull) -(cd "ib_diarization_toolkit" ; git pull; git checkout $release) +(cd "ib_diarization_toolkit" ; git pull) #(cd "ldc_sad_hmm" ; git pull) (cd "dscore" ; git pull) (cd "Yunitator" ; git pull) -(cd "VCM"; git pull) -(cd "To-Combo-SAD" ; git pull; git checkout $release) +(cd "vcm"; git pull) +(cd "To-Combo-SAD" ; git pull) ############################################# From a5534aec02da47b4c29655d154e68e464d499622 Mon Sep 17 00:00:00 2001 From: Junghan Date: Tue, 27 Nov 2018 17:09:35 -0500 Subject: [PATCH 088/299] bug fix --- conf/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index c132e13..56036dc 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -69,7 +69,7 @@ su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz tar zxvf OpenSMILE-2.3.tar.gz -chmod +x openSMILE-2.3.0/bin/linux_x64_standalone_static/SMILExtract +chmod +x opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract rm OpenSMILE-2.3.tar.gz # optionally Install HTK (without it, some other tools will not work) From a96a9f9a354202cd8abb3bb1732da8ae971e8471 Mon Sep 17 00:00:00 2001 From: jaden-w Date: Tue, 27 Nov 2018 17:21:30 -0500 Subject: [PATCH 089/299] Modify yunified scripts for new Yunitator --- bootstrap.sh | 4 ++-- launcher/noisemesSad.sh | 18 +++++++++--------- launcher/yunitate.sh | 5 +++-- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 9e19029..e01fe3b 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -94,7 +94,7 @@ fi cd /home/${user}/repos/ # Get OpenSAT=noisemes and dependencies -git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev +# git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" cp /vagrant/conf/.theanorc /home/${user}/ @@ -108,7 +108,7 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install Yunitator and dependencies -git clone https://github.com/srvk/Yunitator --branch yunified # --branch v1.0 # need Dev +git clone https://github.com/srvk/Yunitator --branch develop/yunified # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index b7e519f..ccc88a5 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -13,11 +13,11 @@ SCRIPT=$(readlink -f $0) # home folder BASEDIR=/home/vagrant # Path to OpenSAT (go on folder up and to opensat) -OPENSATDIR=/home/vagrant/repos/OpenSAT +# OPENSATDIR=/home/vagrant/repos/OpenSAT YUNITATORDIR=/home/vagrant/repos/Yunitator if [ $# -lt 1 ]; then - echo "Usage: noisemes_sad.sh " + echo "Usage: noisemesSad.sh " echo "where dirname is a folder on the host" echo "containing the wav files (/vagrant/dirname/ in the VM)" exit 1 @@ -29,6 +29,7 @@ if [ $BASH_ARGV == "--keep-temp" ]; then fi audio_dir=/vagrant/$1 +TEMPNAME=feature filename=$(basename "$audio_dir") dirname=$(dirname "$audio_dir") extension="${filename##*.}" @@ -38,24 +39,23 @@ basename="${filename%.*}" bash $BASEDIR/utils/check_folder.sh $audio_dir # let's get our bearings: set CWD to path of OpenSAT -cd $OPENSATDIR +# cd $OPENSATDIR +cd $YUNITATORDIR # make output folder for features, below input folder -mkdir -p $audio_dir/feature +mkdir -p $audio_dir/$TEMPNAME # first features echo "extracting features for speech activity detection" for file in `ls $audio_dir/*.wav`; do - SSSF/code/feature/extract-htk-vm2.sh $file + ./extract-htk-vm2.sh $file $TEMPNAME done -cd $YUNITATORDIR - # then confidences #python SSSF/code/predict/1-confidence-vm3.py $1 echo "detecting speech and non speech segments" # $conda_dir/python SSSF/code/predict/1-confidence-vm5.py $audio_dir -python ~/repos/Yunitator/yunified.py noisemes $audio_dir 4000 +python yunified.py noisemes $audio_dir 4000 echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. @@ -71,7 +71,7 @@ done # simple remove hyp and feature if ! $KEEPTEMP; then - rm -rf $audio_dir/hyp_sum $audio_dir/feature + rm -rf $audio_dir/hyp_sum $audio_dir/$TEMPNAME fi source deactivate diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 8d53e08..2f71de7 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -28,7 +28,8 @@ if [ $BASH_ARGV == "--keep-temp" ]; then fi audio_dir=/vagrant/$1 -YUNITEMP=$audio_dir/Yunitemp +TEMPNAME=Yunitemp +YUNITEMP=$audio_dir/$TEMPNAME filename=$(basename "$audio_dir") dirname=$(dirname "$audio_dir") extension="${filename##*.}" @@ -49,7 +50,7 @@ for f in `ls $audio_dir/*.wav`; do basename=`basename $f .wav` # first features - ./extract-htk-vm2.sh $f + ./extract-htk-vm2.sh $f $TEMPNAME done python yunified.py yunitator $audio_dir 4000 From 4507112a1f65a92dde8760c2875e02e6e03cb83b Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 27 Nov 2018 22:36:49 +0000 Subject: [PATCH 090/299] update for OpenSMILE 2.3.0 --- conf/turnDetector.conf.inc | 37 +++++++++++++++++++++ conf/vad_segmenter_aclew.conf | 60 +++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100755 conf/turnDetector.conf.inc create mode 100755 conf/vad_segmenter_aclew.conf diff --git a/conf/turnDetector.conf.inc b/conf/turnDetector.conf.inc new file mode 100755 index 0000000..62c7139 --- /dev/null +++ b/conf/turnDetector.conf.inc @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////////////// +///////// > openSMILE LSTM-RNN voice activity detector< ////////////////// +///////// ////////////////// +///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// +///////// All rights reserverd. ////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + + + + +;; turn detector configuration module + +[componentInstances:cComponentManager] +instance[turn].type=cTurnDetector + +[turn:cTurnDetector] +reader.dmLevel=vad_VAD_voice +writer.dmLevel=isTurn +readVad=1 +threshold = -0.1 +threshold2 = -0.1 +writer.levelconf.noHang=1 +msgInterval = 0 +messageRecp = waveSinkCut +eventRecp = waveSinkCut +statusRecp = waveSinkCut +debug=\cm[turndebug{4}:set this to 1 to see turn/speaking debug messages] +;; examples for constraining the turn length +;; minTurnLengthTurnFrameTimeMessage=0.9 +;; maxTurnLength=10.0 +; default (0) is infinite maximum length +maxTurnLength=0 +maxTurnLengthGrace=1 +nPre = 8 +nPost = 35 + + diff --git a/conf/vad_segmenter_aclew.conf b/conf/vad_segmenter_aclew.conf new file mode 100755 index 0000000..2b07ec4 --- /dev/null +++ b/conf/vad_segmenter_aclew.conf @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////////// +///////// > openSMILE LSTM-RNN voice activity detector< ////////////////// +///////// ////////////////// +///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// +///////// All rights reserverd. ////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + + +[componentInstances:cComponentManager] +instance[dataMemory].type = cDataMemory +instance[waveSource].type = cWaveSource + +[waveSource:cWaveSource] +writer.dmLevel = wave +filename = \cm[inputfile(I){input.wav}:name of input file] +monoMixdown = 1 +start = 0 +end = -1 +endrel = 0 +noHeader = 0 +buffersize_sec = 10 + + + ; inculdes a VAD module +\{vad_opensource.conf.inc} + ; and a turn detector module +\{\cm[turnDetector(T){turnDetector.conf.inc}:filename of turn detector config file]} + + +[componentInstances:cComponentManager] + ; the wave file segmenter +instance[waveSinkCut].type = cWaveSinkCut + ; optional: CSV output +instance[csvSink].type = cCsvSink +printLevelStats = 0 + +[waveSinkCut:cWaveSinkCut] +reader.dmLevel = framesVAD +fileBase = \cm[waveoutput(W){output_segment_}:prefix of WAV output files] +fileExtension = .wav +fileNameFormatString = %s%04d%s +startIndex = 1 +preSil = 0.1 +postSil = 0.1 +multiOut = 1 +sampleFormat = 16bit +; sample rate should be read from the input level +; automatically. In some cases this does not work due to +; round-off errors, so you can force it manually here: +;forceSampleRate = 44100 +;forceSampleRate = 16000 +saveSegmentTimes = \cm[saveSegmentTimes{?}:file to save segment times to] + +[csvSink:cCsvSink] +reader.dmLevel=vad_VAD_voice +filename= \cm[csvoutput{?}:name of VAD output file] +printHeader = 0 +timestamp = 1 +number = 0 + From 42265dc839f0fd732dcefee62a18c9fa32d541cb Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 27 Nov 2018 22:57:24 +0000 Subject: [PATCH 091/299] test 2.3.0 opensmileSad --- launcher/test.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index e67248f..3b03257 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -30,7 +30,7 @@ UTILS=/home/vagrant/utils # Paths to Tools LDC_SAD_DIR=$REPOS/ldc_sad_hmm OPENSATDIR=$REPOS/OpenSAT # noisemes -OPENSMILEDIR=$REPOS/openSMILE-2.1.0/ +OPENSMILEDIR=$REPOS/opensmile-2.3.0/ TOCOMBOSAD=$REPOS/To-Combo-SAD DIARTKDIR=$REPOS/ib_diarization_toolkit #TALNETDIR=$REPOS/TALNet @@ -114,7 +114,6 @@ cd $OPENSATDIR TESTDIR=$WORKDIR/noisemes-test rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR -#./runDiarNoisemes.sh $TESTDIR > $TESTDIR/noisemes-test.log 2>&1 $LAUNCHERS/noisemesSad.sh $DATADIR/noisemes-test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/noisemes_sad_$BASETEST.rttm ]; then @@ -123,8 +122,6 @@ else FAILURES=true echo " Noisemes failed - no RTTM output" fi -# clean up -#rm -rf $OPENSATDIR/SSSF/data/feature $OPENSATDIR/SSSF/data/hyp # now test OPENSMILEDIR From 21bbab70c7a5348df86a10d836ff3a0fd714f526 Mon Sep 17 00:00:00 2001 From: Junghan Date: Tue, 27 Nov 2018 18:28:27 -0500 Subject: [PATCH 092/299] Vagrant bootstrapping improvement - remove older version of openSMILE (2.1.0 -> 2.3.0) - add useful warnings/breakpoints inside provisioning --- conf/bootstrap.sh | 62 +++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 56036dc..aa0791d 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -16,7 +16,6 @@ sudo apt-get install -y git make automake libtool autoconf patch subversion fuse libc6-dev-i386 festival espeak python-setuptools gawk \ libboost-all-dev - # Kaldi and others want bash - otherwise the build process fails [ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh @@ -24,13 +23,20 @@ sudo apt-get install -y git make automake libtool autoconf patch subversion fuse echo "Downloading Anaconda-2.3.0..." cd /home/${user} wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh -#bash Anaconda-2.3.0-Linux-x86_64.sh -b # batch install into /home/vagrant/anaconda echo "Installing Anaconda-2.3.0..." sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" + +# check if anaconda is installed correctly +if ! [ -x "$(command -v /home/${user}/anaconda/bin/conda)" ]; then + echo "*******************************" + echo " conda installation failed" + echo "*******************************" + exit 1 +fi + if ! grep -q -i anaconda .bashrc; then echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc fi -# assume 'conda' is installed now (get path) su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" # clean up big installer in home folder rm -f Anaconda-2.3.0-Linux-x86_64.sh @@ -42,13 +48,24 @@ echo "Create python3 env" cd /home/$user cp /vagrant/conf/environment.yml /home/${user}/ su ${user} -c "/home/${user}/anaconda/bin/conda env create -f environment.yml" - +if [ $? -ne 0 ]; then PYTHON3_INSTALLED=false; fi # install Matlab runtime environment +echo "Download matlab installer" cd /tmp wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip +echo "Install matlab" unzip -q MCR_R2017b_glnxa64_installer.zip ./install -mode silent -agreeToLicense yes + +# check if matlab is installed correctly +if [ $? -ne 0 ]; then + echo "*******************************" + echo " matlab installation failed" + echo "*******************************" + exit 1 +fi + # add Matlab stuff to path echo 'LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH"' >> /home/${user}/.bashrc rm /tmp/MCR_R2017b_glnxa64_installer.zip @@ -57,19 +74,11 @@ rm /tmp/MCR_R2017b_glnxa64_installer.zip echo "Installing OpenSMILE" su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ -wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz -tar zxvf OpenSMILE-2.1.tar.gz -# install SMILExtract system-wide -cp openSMILE-2.1.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin -chmod +x /usr/local/bin/SMILExtract -rm OpenSMILE-2.1.tar.gz - -# Install openSMILE2.3.0 -su ${user} -c "mkdir -p /home/${user}/repos/" -cd /home/${user}/repos/ wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz tar zxvf OpenSMILE-2.3.tar.gz chmod +x opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract +cp opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin +if [ $? -ne 0 ]; then OPENSMILE_INSTALLED=false; fi rm OpenSMILE-2.3.tar.gz # optionally Install HTK (without it, some other tools will not work) @@ -85,11 +94,10 @@ if [ -f /vagrant/HTK.tar.gz ]; then sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile make all make install + if [ $? -eq 0 ]; then HTK_INSTALLED=true; fi fi fi - - # POPOULATE THE REPOSITORY SECTION cd /home/${user}/repos/ @@ -98,15 +106,12 @@ git clone http://github.com/srvk/OpenSAT su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" cp /vagrant/conf/.theanorc /home/${user}/ -export PATH=/home/${user}/anaconda/bin:$PATH su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" - # Install ldc-sad # run this version 'by hand' in the VM in repos/ using your github username and password #git clone http://github.com/aclew/ldc_sad_hmm - # Install Yunitator and dependencies git clone https://github.com/srvk/Yunitator su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" @@ -121,7 +126,6 @@ git clone https://github.com/srvk/To-Combo-SAD # Install DiarTK git clone http://github.com/srvk/ib_diarization_toolkit - # Install eval git clone http://github.com/srvk/dscore @@ -138,7 +142,6 @@ python setup.py install # git clone https://github.com/aclew/utils.git # chmod +x utils/* - # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) # and intervaltree (needed for rttm2scp.py) # and recommonmark (needed to make html in docs/) @@ -156,3 +159,20 @@ touch /home/${user}/.Xauthority # Provisioning runs as root; we want files to belong to '${user}' chown -R ${user}:${user} /home/${user} + +# Installation status +if ! $PYTHON3_INSTALLED; then + echo "*********************************************" + echo "Warning: python3 environment is not installed" + echo "*********************************************" +fi +if ! $OPENSMILE_INSTALLED; then + echo "***********************************" + echo "Warning: OpenSMILE is not installed" + echo "***********************************" +fi +if ! $HTK_INSTALLED; then + echo "*****************************" + echo "Warning: HTK is not installed" + echo "*****************************" +fi From 0281e419144d48d56982abf9865c14d45556f7c7 Mon Sep 17 00:00:00 2001 From: Junghan Date: Tue, 27 Nov 2018 18:39:56 -0500 Subject: [PATCH 093/299] opensmilesad 2.3.0 path fix --- launcher/opensmileSad.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 54b01b6..35b15d5 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -13,7 +13,7 @@ UTILS=/home/vagrant/utils audio_dir=/vagrant/$1 ### Other variables specific to this script -OSHOME=$REPOS/openSMILE-2.1.0/ +OSHOME=$REPOS/opensmile-2.3.0/ CONFIG_FILE=$UTILS/vad_segmenter_aclew.conf.txt OPENSMILE=$OSHOME/bin/linux_x64_standalone_static/SMILExtract workdir=$audio_dir/temp/opensmileSad From b620c3a1c72a99c710bfda8ef91d2e14232834ed Mon Sep 17 00:00:00 2001 From: MarvinLavechin Date: Wed, 28 Nov 2018 01:11:36 +0100 Subject: [PATCH 094/299] Force the user to install HTK 3.4.1, update doc and install_htk.sh in consequences --- docs/source/install.md | 4 ++-- utils/install_htk.sh | 24 +++++++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 2d46840..2b63eca 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -27,8 +27,8 @@ HTK is used by some of these tools (until we find and implement an open-source r - Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) - Register by following the instructions on the left (under "Getting HTK": Register) - Check that you have received your password via email; you will need it for the next step. -- Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). The download is probably called HTK-3.4.1.tar.gz, although the numbers may change if they update their code. -- Move the HTK-*.tar.gz file into the root folder of this repository (alongside Vagrantfile), and rename it HTK.tar.gz +- Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. +- Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). 5. Type diff --git a/utils/install_htk.sh b/utils/install_htk.sh index d82ca12..91e4993 100755 --- a/utils/install_htk.sh +++ b/utils/install_htk.sh @@ -12,16 +12,22 @@ fi # the idea is to make users independently download HTK installer since # we cannot redistribute cd /home/${user} -if [ -f /vagrant/HTK.tar.gz ]; then - if [[ ! -d htk ]]; then - cd /home/${user}/repos/ - sudo tar zxf /vagrant/HTK.tar.gz - cd htk - sudo ./configure --without-x --disable-hslab - sudo sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile - sudo make all - sudo make install +if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then + if [[ ! -d repos/htk ]]; then + cd /home/${user}/repos/ + sudo tar zxf /vagrant/HTK-3.4.1.tar.gz + cd htk + sudo ./configure --without-x --disable-hslab + sudo sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + sudo make all + sudo make install + else + echo "Visibly htk has been already installed..." + echo "You should try to remove the folder repos/htk within the VM" + echo "and rerun this script." fi +else + echo "Can't find HTK-3.4.1.tar.gz. Check that you installed the right version." fi From 690cddac7dd5a86bfdf6241f1da85a3e297dc616 Mon Sep 17 00:00:00 2001 From: MarvinLavechin Date: Wed, 28 Nov 2018 02:05:14 +0100 Subject: [PATCH 095/299] Add a speech extractors which extracts segments annotated as speech by a SAD --- utils/speech_extractor.py | 78 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 utils/speech_extractor.py diff --git a/utils/speech_extractor.py b/utils/speech_extractor.py new file mode 100644 index 0000000..5e76b80 --- /dev/null +++ b/utils/speech_extractor.py @@ -0,0 +1,78 @@ +import argparse +import os +import sys +import subprocess + + +def extracts_speech(wav, sad, out): + """ + Read a .rttm file and extracts segments of the wav files that + have been annotated as being speech. + + :param wav: Path to the audio file (.wav). + :param sad: Path to the rttm file (.rttm). + :param out: Folder where the segments need to be stored. + """ + if not os.path.isfile(wav): + print("The audio file %s has not been found." % wav) + sys.exit(1) + + if not os.path.isfile(sad): + print("The SAD file %s has not been found." % sad) + sys.exit(1) + + with open(sad, 'r') as rttm: + for line in rttm: + # Replace tabulations by spaces + fields = line.replace('\t', ' ') + # Remove several successive spaces + fields = ' '.join(fields.split()) + fields = fields.split(' ') + onset, duration, activity = float(fields[3]), float(fields[4]), fields[7] + offset = onset+duration + if activity == 'speech': + basename = os.path.basename(wav).split('.wav')[0] + output = os.path.join(out, '_'.join([basename, str(onset), str(offset)])+'.wav') + cmd = ['sox', wav, output, + 'trim', str(onset), str(duration)] + print("Cutting %s from %s to %s " % (os.path.basename(wav), str(onset), str(offset))) + subprocess.call(cmd) + +def main(): + parser = argparse.ArgumentParser(description="Extracts segments that have" + "been annotated as speech by" + "a SAD tool.") + parser.add_argument('-i', '--input', type=str, required=True, + help="Path to the .wav files (or to the folder containing wav files).") + parser.add_argument('-s', '--sad', type=str, required=False, default="gold", + choices=["ldc_sad", "noisemes", "opensmile", "tocombosad", "gold"], + help="Indicates which SAD needs to be used to extract the audio file.") + parser.add_argument('-o', '--output', type=str, required=False, + help="Path to the folder where the extracted segments need to be stored. " + "(Relative to the input folder)") + args = parser.parse_args() + + wav = os.path.join("/vagrant", args.input) + if args.output is not None: + out = os.path.join(os.path.dirname(wav), args.output) + else: + out = os.path.dirname(wav) + + if not os.path.exists(out): + os.makedirs(out) + + name_map = { + 'ldc_sad': 'ldcSad_', + 'noisemes': 'noisemes_sad_', + 'opensmile': 'opensmileSad_', + 'tocombosad': 'tocomboSad_', + 'gold': '', + } + + sad = os.path.join(os.path.dirname(wav), name_map[args.sad] + os.path.basename(wav).replace(".wav", ".rttm")) + print(sad) + extracts_speech(wav, sad, out) + + +if __name__ == '__main__': + main() \ No newline at end of file From f4302da8107871b71a2fd35d75fef5ad97f3b1f1 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 28 Nov 2018 14:20:42 +0000 Subject: [PATCH 096/299] use OS 2.3.0 --- launcher/opensmileSad.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 35b15d5..4f5aefb 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -7,15 +7,16 @@ BASEDIR=`dirname $SCRIPT` # this is the home folder of this script conda_dir=/home/vagrant/anaconda/bin REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils +CONF=/vagrant/conf # end of launcher onset routine ### Read in variables from user audio_dir=/vagrant/$1 ### Other variables specific to this script -OSHOME=$REPOS/opensmile-2.3.0/ -CONFIG_FILE=$UTILS/vad_segmenter_aclew.conf.txt -OPENSMILE=$OSHOME/bin/linux_x64_standalone_static/SMILExtract +OSHOME=$REPOS/opensmile-2.3.0 +CONFIG_FILE=$CONF/vad_segmenter_aclew.conf +OPENSMILE=SMILExtract workdir=$audio_dir/temp/opensmileSad mkdir -p $workdir @@ -39,13 +40,13 @@ basename="${filename%.*}" cd $OSHOME/scripts/vad -# Use OpenSMILE 2.1.0 +# Use OpenSMILE 2.3.0 for sad in `ls $audio_dir/*.wav`; do file=$sad id=`basename $file` id=${id%.wav} -# > $audio_dir/${id}.txt #Make it empty if already present + > $audio_dir/${id}.txt #Make it empty if already present echo "Processing $id ..." LD_LIBRARY_PATH=/usr/local/lib \ $OPENSMILE \ @@ -54,7 +55,7 @@ for sad in `ls $audio_dir/*.wav`; do -turndebug 1 \ -noconsoleoutput 1 \ -saveSegmentTimes $workdir/${id}.txt \ - -logfile $workdir/opensmile-vad.log > /dev/null + -logfile $workdir/opensmile-vad.log done for output in $(ls $workdir/*.txt); do From 81ff156d5c3cecd7dcc1d80014c08361a8e53322 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 28 Nov 2018 15:18:21 +0000 Subject: [PATCH 097/299] clean temp WAV files --- launcher/opensmileSad.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 4f5aefb..7b2894b 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -58,6 +58,9 @@ for sad in `ls $audio_dir/*.wav`; do -logfile $workdir/opensmile-vad.log done +# clean up generated WAV files in working directory (tool_home/scripts/vad) +rm -f output_segment_*.wav + for output in $(ls $workdir/*.txt); do id=$(basename $output .txt) awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > $audio_dir/opensmileSad_$id.rttm From 35a7027f264bfaf1cd4bf63d538ecf08b2d7988e Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 28 Nov 2018 12:03:33 -0500 Subject: [PATCH 098/299] Remove python path env variables - Default python2 anaconda path is in /home/vagrant/.bashrc - for python2 version, just use python - for python3 version, run `source activate divime` and then use python. Be sure to `source deactivate` if switching back to python2 --- launcher/diartk.sh | 20 +++++++++----------- launcher/eval.sh | 2 -- launcher/evalDiar.sh | 3 --- launcher/evalSAD.sh | 6 ++---- launcher/ldcSad.sh | 4 +--- launcher/noisemesSad.sh | 6 +----- launcher/opensmileSad.sh | 2 -- launcher/python3/test.sh | 6 ------ launcher/python3/yunitate.sh | 1 - launcher/talnet.sh | 7 ------- launcher/test.sh | 9 +-------- launcher/tocomboSad.sh | 2 -- launcher/vcm.sh | 9 --------- launcher/yunitate.sh | 5 ----- utils/noisemes_full.sh | 14 +++----------- utils/runTALNet.sh | 9 --------- utils/yuniSeg.sh | 13 ++----------- 17 files changed, 19 insertions(+), 99 deletions(-) diff --git a/launcher/diartk.sh b/launcher/diartk.sh index 2e3b1cf..cdcb65b 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=/home/vagrant -conda_dir=$BASEDIR/anaconda/bin REPOS=$BASEDIR/repos UTILS=$BASEDIR/utils # end of launcher onset routine @@ -63,30 +61,30 @@ for fin in `ls $audio_dir/*.wav`; do case $trs_format in "ldcSad") sys="ldcSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/ldcSad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/ldcSad_${basename}.rttm $scpfile ;; "noisemesSad") sys="noisemesSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile ;; "tocomboSad") sys="tocomboSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/tocombo_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/tocombo_sad_${basename}.rttm $scpfile ;; "opensmileSad") sys="opensmileSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/opensmile_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/opensmile_sad_${basename}.rttm $scpfile ;; "textgrid") sys="goldSad" - $conda_dir/python /home$UTILS/textgrid2rttm.py $audio_dir/${basename}.TextGrid $workdir/${basename}.rttm - $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + python /home$UTILS/textgrid2rttm.py $audio_dir/${basename}.TextGrid $workdir/${basename}.rttm + python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile rm $workdir/$basename.rttm ;; "eaf") sys="goldSad" - $conda_dir/python /home$UTILS/elan2rttm.py $audio_dir/${basename}.eaf $workdir/${basename}.rttm - $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + python /home$UTILS/elan2rttm.py $audio_dir/${basename}.eaf $workdir/${basename}.rttm + python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile rm $workdir/$basename.rttm ;; "rttm") @@ -95,7 +93,7 @@ for fin in `ls $audio_dir/*.wav`; do # tab them before using them. cp $audio_dir/${basename}.rttm $workdir/${basename}.rttm sed -i 's/ \+/\t/g' $workdir//${basename}.rttm - $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile ;; *) echo "ERROR: please choose SAD system between:" diff --git a/launcher/eval.sh b/launcher/eval.sh index 49d95c8..8e3e23c 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=/home/vagrant -conda_dir=$BASEDIR/anaconda/bin REPOS=$BASEDIR/repos UTILS=$BASEDIR/utils LAUNCHER=$BASEDIR/launcher diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 3a478af..e2f2eef 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -1,7 +1,4 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc # Absolute path to this script. /home/user/bin/foo.sh SCRIPT=$(readlink -f $0) diff --git a/launcher/evalSAD.sh b/launcher/evalSAD.sh index 97203f7..010e684 100755 --- a/launcher/evalSAD.sh +++ b/launcher/evalSAD.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=`dirname $SCRIPT` # folder where this script resides. Useless. -conda_dir=/home/vagrant/anaconda/bin REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils # end of launcher onset routine @@ -60,7 +58,7 @@ echo $UTILS/create_ref_sys.sh $1 $sys_name true $UTILS/create_ref_sys.sh $1 $sys_name true echo "evaluating" -#$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys +# python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys # create /vagrant/results if it doesn't exist echo "filename DCF FA MISS" > $audio_dir/${sys_name}_eval.df for lab in `ls $workdir/temp_sys/*.lab`; do @@ -74,7 +72,7 @@ for lab in `ls $workdir/temp_sys/*.lab`; do elif [ ! -s $workdir/temp_sys/$base.lab ] && [ -s $workdir/temp_ref/$base.lab ]; then echo $base" 75.00% 0.00% 100.00%" >> $audio_dir/${sys_name}_eval.df else - $conda_dir/python score.py $workdir/temp_ref $lab | awk -v var="$base" -F" " '{if ($1=="DCF:") {print var"\t"$2"\t"$4"\t"$6}}' >> $audio_dir/${sys_name}_eval.df + python score.py $workdir/temp_ref $lab | awk -v var="$base" -F" " '{if ($1=="DCF:") {print var"\t"$2"\t"$4"\t"$6}}' >> $audio_dir/${sys_name}_eval.df fi done diff --git a/launcher/ldcSad.sh b/launcher/ldcSad.sh index bba281b..3f5d2c9 100755 --- a/launcher/ldcSad.sh +++ b/launcher/ldcSad.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=/home/vagrant -conda_dir=$BASEDIR/anaconda/bin REPOS=$BASEDIR/repos UTILS=$BASEDIR/utils # end of launcher onset routine @@ -36,7 +34,7 @@ bash $UTILS/check_folder.sh $audio_dir cd $LDC_SAD_DIR # launch ldc -$conda_dir/python perform_sad.py -L $workdir $audio_dir/*.wav +python perform_sad.py -L $workdir $audio_dir/*.wav echo "finished using ldcSad_hmm. Please look inside $1 to see the output in *.rttm format" # move all files to name them correctly diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 5e9a4ee..ca4e6c1 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -1,9 +1,5 @@ #!/bin/bash # noisemes_sad.sh -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run OpenSAT with hard coded models & configs found here and in /vagrant @@ -50,7 +46,7 @@ done # then confidences #python SSSF/code/predict/1-confidence-vm3.py $1 echo "detecting speech and non speech segments" -$conda_dir/python SSSF/code/predict/1-confidence-vm5.py $audio_dir +python SSSF/code/predict/1-confidence-vm5.py $audio_dir echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 4f5aefb..18b1faf 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -1,10 +1,8 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=`dirname $SCRIPT` # this is the home folder of this script # not the home folder of the 'vagrant' user in the VM -conda_dir=/home/vagrant/anaconda/bin REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils CONF=/vagrant/conf diff --git a/launcher/python3/test.sh b/launcher/python3/test.sh index 77148b1..61d67ed 100644 --- a/launcher/python3/test.sh +++ b/launcher/python3/test.sh @@ -4,12 +4,6 @@ # from a downloaded 5 minute section of the HomeBank VanDam daylong audio sample # ("ACLEW Starter" data) -# this doesn't work because .bashrc exits immediately if not running interactively -#source /home/vagrant/.bashrc -i -# instead: -export PATH=/home/vagrant/anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin -LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH" - KEEPTEMP="" if [ $# -eq 1 ]; then if [ $BASH_ARGV == "--keep-temp" ]; then diff --git a/launcher/python3/yunitate.sh b/launcher/python3/yunitate.sh index b9dadfd..32ea71e 100755 --- a/launcher/python3/yunitate.sh +++ b/launcher/python3/yunitate.sh @@ -4,7 +4,6 @@ source activate divime # run Yunitator with hard coded models & configs -# assumes Python environment in /home/vagrant/anaconda/bin # Absolute path to this script. /home/vagrant/launcher/yunitate.sh SCRIPT=$(readlink -f $0) diff --git a/launcher/talnet.sh b/launcher/talnet.sh index 6ccc956..4f18cf1 100755 --- a/launcher/talnet.sh +++ b/launcher/talnet.sh @@ -1,11 +1,6 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run 537 class classifier with hard coded models & configs found here -# assumes Python environment in /home/${user}/anaconda/ # Absolute path to this script. /home/user/bin/foo.sh SCRIPT=$(readlink -f $0) @@ -30,8 +25,6 @@ basename="${filename%.*}" bash $BASEDIR/check_folder.sh $audio_dir -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH # let's get our bearings: set CWD to the path of TALNet cd $CLASSIFY diff --git a/launcher/test.sh b/launcher/test.sh index 3b03257..0d4490c 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -4,12 +4,6 @@ # from a downloaded 5 minute section of the HomeBank VanDam daylong audio sample # ("ACLEW Starter" data) -# this doesn't work because .bashrc exits immediately if not running interactively -#source /home/vagrant/.bashrc -i -# instead: -export PATH=/home/vagrant/anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin -LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH" - KEEPTEMP="" if [ $# -eq 1 ]; then if [ $BASH_ARGV == "--keep-temp" ]; then @@ -17,7 +11,6 @@ if [ $# -eq 1 ]; then fi fi -conda_dir=/home/vagrant/anaconda/bin # Absolute path to this script. /home/vagrant/launcher SCRIPT=$(readlink -f $0) @@ -94,7 +87,7 @@ if [ -s $LDC_SAD_DIR/perform_sad.py ]; then cd $LDC_SAD_DIR TESTDIR=$WORKDIR/ldc_sad-test rm -rf $TESTDIR; mkdir -p $TESTDIR - $conda_dir/python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} + python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} # convert output to rttm, for diartk. grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm if [ -s $TESTDIR/$BASETEST.rttm ]; then diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index 303d66f..f59747d 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=`dirname $SCRIPT` -conda_dir=/home/vagrant/anaconda/bin REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils # end of launcher onset routine diff --git a/launcher/vcm.sh b/launcher/vcm.sh index 8ec9b46..dce74b6 100755 --- a/launcher/vcm.sh +++ b/launcher/vcm.sh @@ -1,8 +1,4 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run OpenSAT with hard coded models & configs found here and in /vagrant # assumes Python environment in /home/${user}/ @@ -34,11 +30,6 @@ if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi - - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - # let's get our bearings: set CWD to the path of VCM cd $VCMDIR diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 5ccfedd..d5db808 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -1,11 +1,6 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -#source ~/.bashrc -#conda_dir=/home/vagrant/anaconda/bin # run Yunitator with hard coded models & configs -# assumes Python environment in /home/vagrant/anaconda/bin # Absolute path to this script. /home/vagrant/launcher/yunitate.sh SCRIPT=$(readlink -f $0) diff --git a/utils/noisemes_full.sh b/utils/noisemes_full.sh index b93fcf5..9af469b 100755 --- a/utils/noisemes_full.sh +++ b/utils/noisemes_full.sh @@ -1,8 +1,4 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run OpenSAT with hard coded models & configs found here and in /vagrant # assumes Python environment in /home/${user}/ @@ -29,10 +25,6 @@ basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav bash $BASEDIR/check_folder.sh $audio_dir - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - # let's get our bearings: set CWD to the path of OpenSAT cd $OPENSATDIR @@ -46,10 +38,10 @@ done # then confidences -#/home/vagrant/anaconda/bin/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename +# python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename echo "predicting classes" -#$conda_dir/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename -$conda_dir/python SSSF/code/predict/1-confidence-vm4.py $audio_dir +# python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename +python SSSF/code/predict/1-confidence-vm4.py $audio_dir echo "noisemes_full finished running" # take all the .rttm in /vagrant/data/hyp_sum and move them to /vagrant/data - move features and hyp_sum to another folder also. diff --git a/utils/runTALNet.sh b/utils/runTALNet.sh index 6da0d8d..df3dd0b 100755 --- a/utils/runTALNet.sh +++ b/utils/runTALNet.sh @@ -1,11 +1,6 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run 537 class classifier with hard coded models & configs found here -# assumes Python environment in /home/${user}/anaconda/ # Absolute path to this script. /home/user/bin/foo.sh SCRIPT=$(readlink -f $0) @@ -29,10 +24,6 @@ basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav bash $BASEDIR/check_folder.sh $audio_dir - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - # let's get our bearings: set CWD to the path of TALNet cd $CLASSIFY diff --git a/utils/yuniSeg.sh b/utils/yuniSeg.sh index 976b135..7f4ccdb 100755 --- a/utils/yuniSeg.sh +++ b/utils/yuniSeg.sh @@ -1,8 +1,4 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run YuniSeg with hard coded models & configs found here and in /vagrant # assumes Python environment in /home/${user}/ @@ -38,11 +34,6 @@ trs_format=$2 # Check audio_dir to see if empty or if contains empty wav bash $BASEDIR/check_folder.sh $audio_dir - -# this is set in user's login .bashrc, but may not be if run from outside VM -export PATH=/home/${user}/anaconda/bin:$PATH - - # Iterate over files echo "Starting" for f in `ls $audio_dir/*.wav`; do @@ -80,12 +71,12 @@ for f in `ls $audio_dir/*.wav`; do "textgrid") sys="goldSad" model_prefix=${trs_format}_ - $conda_dir/python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid ${trs_format}_${basename}.rttm + python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid ${trs_format}_${basename}.rttm ;; "eaf") sys="goldSad" model_prefix=${trs_format}_ - $conda_dir/python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf ${trs_format}_${basename}.rttm + python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf ${trs_format}_${basename}.rttm ;; "rttm") sys="goldSad" From 9f7b1c0b1c4824fc38be20cded86b8b2f48dd7f8 Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 28 Nov 2018 12:05:58 -0500 Subject: [PATCH 099/299] add opensmile installation error --- conf/bootstrap.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index aa0791d..4fa5414 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -78,9 +78,17 @@ wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz tar zxvf OpenSMILE-2.3.tar.gz chmod +x opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract cp opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin -if [ $? -ne 0 ]; then OPENSMILE_INSTALLED=false; fi rm OpenSMILE-2.3.tar.gz +# check if opensmile if installed +if ! [ -x "$(command -v SMILExtract)" ]; then + echo "*******************************" + echo " OPENSMILE installation failed" + echo "*******************************" + OPENSMILE_INSTALLED=false; +fi + + # optionally Install HTK (without it, some other tools will not work) # the idea is to make users independently download HTK installer since # we cannot redistribute From ad621af55d5d781ebe5bcfb1bfeb85d16a284a09 Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 28 Nov 2018 12:16:56 -0500 Subject: [PATCH 100/299] python3 readme --- launcher/README.md | 17 +++++++++++++++++ launcher/python3/README.md | 18 ++++++++++++++++++ launcher/python3/readme.txt | 13 ------------- 3 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 launcher/python3/README.md delete mode 100644 launcher/python3/readme.txt diff --git a/launcher/README.md b/launcher/README.md index a81e2ae..f4f9ad6 100755 --- a/launcher/README.md +++ b/launcher/README.md @@ -34,4 +34,21 @@ evalSAD.sh test.sh ``` +### python3 +``` +# activate divime environment to use python 3.6.5 +# put below in run script +source activate divime + +# list of libararies installed can be found with +# conda list +# to install new packages, edit conf/environment.yml file +# to switch back to python 2, run +source deactivate + +# And to use python3, make sure you use correct syntax +# in python files and/or checkout python3 branch from +# each tool +# see python3/ for examples +``` diff --git a/launcher/python3/README.md b/launcher/python3/README.md new file mode 100644 index 0000000..410aca0 --- /dev/null +++ b/launcher/python3/README.md @@ -0,0 +1,18 @@ +### python3 +``` +# activate divime environment to use python 3.6.5 +# put below in run script +source activate divime + +# list of libararies installed can be found with +# conda list +# to install new packages, edit conf/environment.yml file + +# to switch back to python 2, run +source deactivate + +# And to use python3, make sure you use correct syntax +# in python files and/or checkout python3 branch from +# each tool +# see python3/ for examples +``` \ No newline at end of file diff --git a/launcher/python3/readme.txt b/launcher/python3/readme.txt deleted file mode 100644 index c7fce76..0000000 --- a/launcher/python3/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -# activate divime environment to use python 3.6.5 -source activate divime - -# list of libararies installed can be found with -# conda list -# to install new packages, edit environment.yml file - - -# sample usage -# python [some_file] ... - -# to switch back to python 2 -source deactivate \ No newline at end of file From ee8f90ba1cd090ebd750b420458df27d70dafae9 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 28 Nov 2018 15:06:45 -0500 Subject: [PATCH 101/299] move all test folders to test/ --- launcher/test.sh | 64 ++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 0d4490c..09d95a1 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -81,12 +81,16 @@ else echo " and rename it to HTK.tar.gz? If so, then you may need to re-install it. Run: vagrant ssh -c \"utils/install_htk.sh\" " fi +TESTDIR=$WORKDIR/test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +cp $WORKDIR/$BASETEST.rttm $TESTDIR + # First test in ldc_sad_hmm echo "Testing LDC SAD..." if [ -s $LDC_SAD_DIR/perform_sad.py ]; then cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/ldc_sad-test - rm -rf $TESTDIR; mkdir -p $TESTDIR + python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} # convert output to rttm, for diartk. grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm @@ -104,10 +108,8 @@ fi # now test Noisemes echo "Testing noisemes..." cd $OPENSATDIR -TESTDIR=$WORKDIR/noisemes-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -$LAUNCHERS/noisemesSad.sh $DATADIR/noisemes-test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} + +$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/noisemes_sad_$BASETEST.rttm ]; then echo "Noisemes passed the test." @@ -120,10 +122,8 @@ fi # now test OPENSMILEDIR echo "Testing OpenSmile SAD..." cd $OPENSMILEDIR -TESTDIR=$WORKDIR/opensmile-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -$LAUNCHERS/opensmileSad.sh $DATADIR/opensmile-test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} + +$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then echo "OpenSmile SAD passed the test." @@ -135,10 +135,8 @@ fi # now test TOCOMBOSAD echo "Testing ToCombo SAD..." cd $TOCOMBOSAD -TESTDIR=$WORKDIR/tocombo_sad-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -$LAUNCHERS/tocomboSad.sh $DATADIR/tocombo_sad-test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} + +$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then echo "TOCOMBO SAD passed the test." @@ -151,12 +149,10 @@ fi # finally test DIARTK echo "Testing DIARTK..." cd $DIARTKDIR -TESTDIR=$WORKDIR/diartk-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR + cp $TEST_RTTM $TESTDIR # run like the wind -$LAUNCHERS/diartk.sh $DATADIR/diartk-test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 +$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 if grep -q "command not found" $TESTDIR/diartk-test.log; then echo " Diartk failed - dependencies (probably HTK)" FAILURES=true @@ -168,17 +164,15 @@ else echo " Diartk failed - no output RTTM" fi fi -rm $TESTDIR/$BASETEST.rttm +#rm $TESTDIR/$BASETEST.rttm # finally test Yunitator echo "Testing Yunitator..." cd $YUNITATORDIR -TESTDIR=$WORKDIR/yunitator-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR + # let 'er rip #./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -$LAUNCHERS/yunitate.sh $DATADIR/yunitator-test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then echo "Yunitator passed the test." else @@ -190,8 +184,8 @@ fi # Test DSCORE echo "Testing Dscore..." cd $DSCOREDIR -TESTDIR=$WORKDIR/dscore-test -rm -rf $TESTDIR; mkdir -p $TESTDIR +#TESTDIR=$WORKDIR/dscore-test +#rm -rf $TESTDIR; mkdir -p $TESTDIR cp -r test_ref test_sys $TESTDIR rm -f test.df python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} @@ -207,9 +201,9 @@ fi echo "Testing LDC evalSAD" if [ -d $LDC_SAD_DIR ]; then cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/opensmile-test - cp $WORKDIR/$BASETEST.rttm $TESTDIR - $LAUNCHERS/eval.sh $DATADIR/opensmile-test opensmileSad $KEEPTEMP > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} +# TESTDIR=$WORKDIR/opensmile-test +# cp $WORKDIR/$BASETEST.rttm $TESTDIR + $LAUNCHERS/eval.sh $DATADIR/test opensmileSad $KEEPTEMP > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/opensmileSad_eval.df ]; then echo "LDC evalSAD passed the test" else @@ -225,12 +219,12 @@ fi # Testing VCM echo "Testing VCM..." cd $VCMDIR -TESTDIR=$WORKDIR/vcm-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR +#TESTDIR=$WORKDIR/vcm-test +#rm -rf $TESTDIR; mkdir -p $TESTDIR +#ln -fs $TEST_WAV $TESTDIR # let 'er rip #./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -$LAUNCHERS/vcm.sh $DATADIR/vcm-test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} +$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then echo "VCM passed the test." else @@ -247,9 +241,9 @@ fi # results echo "RESULTS:" -for f in /vagrant/$DATADIR/*-test/*.rttm; do $UTILS/sum-rttm.sh $f; done +for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done echo "DSCORE:" -cat /vagrant/data/VanDam-Daylong/BN32/dscore-test/test.df +cat /vagrant/data/VanDam-Daylong/BN32/test/test.df echo "EVAL_SAD:" -cat $WORKDIR/opensmile-test/opensmileSad_eval.df +cat $WORKDIR/test/opensmileSad_eval.df From c8cb9ed00babe328e37ace7558067e3795b9aa73 Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 28 Nov 2018 15:10:40 -0500 Subject: [PATCH 102/299] Miniconda for future use - tested with test.sh - uses miniconda2-4.5.11, latest as of Nov 18' --- conf/bootstrap.sh | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 4fa5414..5f99ebe 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -41,9 +41,28 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tab # clean up big installer in home folder rm -f Anaconda-2.3.0-Linux-x86_64.sh +# To use miniconda (~40MB) instead of anaconda (~350MB), uncomment below block +# echo "Downloading Miniconda-4.5.11..." +# wget -q https://repo.continuum.io/miniconda/Miniconda2-4.5.11-Linux-x86_64.sh +# echo "Install miniconda (as Anaconda)" +# sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Miniconda2-4.5.11-Linux-x86_64.sh -b -p /home/${user}/anaconda" +# # check if anaconda is installed correctly +# if ! [ -x "$(command -v /home/${user}/anaconda/bin/conda)" ]; then +# echo "*******************************" +# echo " conda installation failed" +# echo "*******************************" +# exit 1 +# fi + +# if ! grep -q -i anaconda .bashrc; then +# echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc +# fi +# su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib cython=0.22.1" + +# # clean up big installer in home folder +# rm -f Miniconda2-4.5.11-Linux-x86_64.sh + # python3 env -# Install Miniconda and python libraries -# miniconda=Miniconda3-4.5.11-Linux-x86_64.sh echo "Create python3 env" cd /home/$user cp /vagrant/conf/environment.yml /home/${user}/ From 7f2d6b5c201ebf7f0edfe3f458c79715306affdd Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 28 Nov 2018 15:31:52 -0500 Subject: [PATCH 103/299] use launcher to run ldc SAD --- launcher/test.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 09d95a1..95478ae 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -91,9 +91,8 @@ echo "Testing LDC SAD..." if [ -s $LDC_SAD_DIR/perform_sad.py ]; then cd $LDC_SAD_DIR - python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} - # convert output to rttm, for diartk. - grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm + $LAUNCHERS/ldcSad.sh $DATADIR/test $KEEPTEMP >& $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} + if [ -s $TESTDIR/$BASETEST.rttm ]; then echo "LDC SAD passed the test." else @@ -203,7 +202,7 @@ if [ -d $LDC_SAD_DIR ]; then cd $LDC_SAD_DIR # TESTDIR=$WORKDIR/opensmile-test # cp $WORKDIR/$BASETEST.rttm $TESTDIR - $LAUNCHERS/eval.sh $DATADIR/test opensmileSad $KEEPTEMP > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} + $LAUNCHERS/eval.sh $DATADIR/test opensmileSad $KEEPTEMP > $WORKDIR/test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/opensmileSad_eval.df ]; then echo "LDC evalSAD passed the test" else From ac851e4bf9b236034ee487e7a94c01f21917686c Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 15:48:04 -0500 Subject: [PATCH 104/299] minor --- conf/bootstrap.sh | 24 +++-- docs/source/ldcSad.md | 14 --- docs/source/tool_doc.md | 201 +++++++++++++++++++++++++++++++++++++++- utils/install_htk.sh | 2 - 4 files changed, 214 insertions(+), 27 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 5f99ebe..27bd7fc 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -112,19 +112,23 @@ fi # the idea is to make users independently download HTK installer since # we cannot redistribute cd /home/${user} -if [ -f /vagrant/HTK.tar.gz ]; then - if [[ ! -d htk ]]; then - cd /home/${user}/repos/ - su ${user} -c "tar zxf /vagrant/HTK.tar.gz" - cd htk - ./configure --without-x --disable-hslab - sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile - make all - make install - if [ $? -eq 0 ]; then HTK_INSTALLED=true; fi +if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then + if [[ ! -d repos/htk ]]; then + cd /home/${user}/repos/ + sudo tar zxf /vagrant/HTK-3.4.1.tar.gz + cd htk + sudo ./configure --without-x --disable-hslab + sudo sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + sudo make all + sudo make install + else + echo "Visibly htk has been already installed..." fi +else + echo "Can't find HTK-3.4.1.tar.gz. Check that you installed the right version." fi + # POPOULATE THE REPOSITORY SECTION cd /home/${user}/repos/ diff --git a/docs/source/ldcSad.md b/docs/source/ldcSad.md index d8d33b5..e69de29 100755 --- a/docs/source/ldcSad.md +++ b/docs/source/ldcSad.md @@ -1,14 +0,0 @@ -# LDC SAD - -## General intro - -LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. - -## Main references: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. - - -## Associated references: -Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. -Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index ebaf836..34d20b2 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -1,3 +1,202 @@ # Detailed Tools Doc -This section of the documentation gets populated with information from the different working tools. +This section contains documentation from the different tools. + + +# LDC SAD + +## General intro + +LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. + +## Main references: + +Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. + + +## Associated references: + +Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. +Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. + +## Questions and bug reports + +Not available + +# NoisemesSad + +## General intro + +Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. + + + + + +## Instructions for direct use (ATTENTION, MAY BE OUTDATED) + +You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. + +``` +$ vagrant ssh -c "OpenSAT/runOpenSAT.sh data/<$MYFILE>" +``` + +You can also analyze a group of files as follows: + +``` +$ vagrant ssh -c "OpenSAT/runDiarNoisemes.sh data/" +``` + +This will analyze all .wav's inside the "data" folder. + +Created annotations will be stored inside the same "data" folder. + +This system will classify slices of the audio recording into one of 17 noiseme classes: + +- background +- speech +- speech non English +- mumble +- singing alone +- music + singing +- music alone +- human sounds +- cheer +- crowd sounds +- animal sounds +- engine +- noise_ongoing +- noise_pulse +- noise_tone +- noise_nature +- white_noise +- radio + +#### Some more technical details + +For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": + +``` +$ vagrant ssh +$ cd OpenSAT +``` + +The main script is runOpenSAT.sh and takes one argument: an audio file in .wav format. +Upon successful completion, output will be in the folder (relative to ~/OpenSAT) +`SSSF/data/hyp//confidence.pkl.gz` + +The system will grind first creating features for all the .wav files it found, then will place those features in a subfolder `feature`. Then it will load a model, and process all the features generated, producing output in a subfolder `hyp/` two files per input: `.confidence.mat` and `.confidence.pkl.gz` - a confidence matrix in Matlab v5 mat-file format, and a Python compressed data 'pickle' file. Now, as well, in the `hyp/` folder, `.rttm` with labels found from a config file [noisemeclasses.txt](https://github.com/riebling/OpenSAT/blob/master/noisemeclasses.txt) + +-More details on output format- + +The 18 classes are as follows: +``` +0 background +1 speech +2 speech_ne +3 mumble +4 singing +5 musicSing +6 music +7 human +8 cheer +9 crowd +10 animal +11 engine +12 noise_ongoing +13 noise_pulse +14 noise_tone +15 noise_nature +16 white_noise +17 radio +``` +The frame length is 0.1s. The system also uses a 2-second window, so the i-th frame starts at (0.1 * i - 2) seconds and finishes at (0.1 * i) seconds. That's why 60 seconds become 620 frames. 'speech_ne' means non-English speech + +-Sample RTTM output snippet- +``` +SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 +SPEAKER family 1 4.6 1.2 background 0.327808111906 +SPEAKER family 1 5.8 1.1 speech 0.430758684874 +SPEAKER family 1 6.9 1.2 background 0.401730179787 +SPEAKER family 1 8.1 0.7 speech 0.407463937998 +SPEAKER family 1 8.8 1.1 background 0.37258502841 +SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +``` + +The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the more detailed results as seen above. + + + +## Main references: + +Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) + + +## Associated references: + +S.Burger,Q.Jin,P.F.Schulam,andF.Metze,“Noisemes:Man- ual annotation of environmental noise in audio streams,” Carnegie Mellon University, Pittsburgh, PA; U.S.A., Tech. Rep. CMU-LTI- 12-07, 2012. +S.Strassel,A.Morris,J.G.Fiscus,C.Caruso,H.Lee,P.D.Over, J. Fiumara, B. L. Shaw, B. Antonishek, and M. Michel, “Creating havic: Heterogeneous audio visual internet collection,” in Proc. +LREC. Istanbul, Turkey: ELRA, May 2012. +F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia fea- ture extractor,” in Proceedings of the 21st ACM international con- ference on Multimedia. ACM, 2013, pp. 835–838. + +## Questions and bug reports + +http://github.com/srvk/OpenSAT/issues + +# OpenSmile SAD + + +## General intro + +openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coefficient RASTA-PLP plus first order delta features. It then uses a long short-term memory recurrent neural network (see details in Eyben et al., 2013b) that has been pre-trained on two corpora of read and spontaneous speech by adults recorded in laboratory conditions, augmented with various noise types. + +## Some more technical details + +These are the parameters that are being used with values that depart from the openSMILE default settings (quoted material comes from either of the openSMILE manuals): + +monoMixdown = 1, means "mix down all recorded channels to 1 mono channel" +noHeader = 0, means read the RIFF header (don't need to specify the parameters ‘sampleRate’, ‘channels’, and possibly ‘sampleSize’) +preSil = 0.1 "Specifies the amount of silence at the turn beginning in seconds, i.e. the lag of the turn +detector. This is the length of the data that will be added to the current segment prior to +the turn start time received in the message from the turn detector component"; we use a tighter criterion than the default (.2) +postSil = 0.1 "Specifies the amount of silence at the turn end in seconds. This is the length of the data +that will be added to the current segment after to the turn end time received in the message +from the turn detector component."; we use a tighter criterion than the default (.3) + +You can change these parameters locally by doing: +``` +$ vagrant ssh +$ nano /vagrant/conf/vad/vadSegmenter_aclew.conf +``` + +openSMILE manuals consulted: + +- Eyben, F., Woellmer, M., & Schuller, B. (2013). openSMILE: The Munich open Speech and Music Interpretation by Large space Extraction toolkit. Institute for Human-Machine Communication, version 2.0. http://download2.nust.na/pub4/sourceforge/o/project/op/opensmile/openSMILE_book_2.0-rc1.pdf +- Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf + + +## Main references for this tool: + +Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. + +Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. + +## Questions and bug reports + +https://www.audeering.com/technology/opensmile/#support + +# TOCombo SAD + +## General intro + +This tool's name stands for "Threshold-Optimized" "combo" SAD; we explain each part in turn. It is a SAD because the goal is to extract speech activity. It is called "combo" because it combines linearly 4 different aspects of voicing (harmonicity , clarity, prediction gain, periodicity) in addition to one perceptual spectral flux feature (see details in Sadjadi & Hansen, 2013). These are extracted in 32-ms frames (with a 10 ms stride). The specific version included here corresponds to the Combo SAD introduced in Ziaei et al. (2014) and used further in Ziaei et al (2016). In this work, a threshold was optimized for daylong recordings, which typically have long silent periods, in order to avoid the usual overly large false alarm rates found in typical SAD systems provided with these data. + +## Main references: + +Ziaei, A., Sangwan, A., & Hansen, J. H. (2014). A speech system for estimating daily word counts. In Fifteenth Annual Conference of the International Speech Communication Association. http://193.6.4.39/~czap/letoltes/IS14/IS2014/PDF/AUTHOR/IS141028.PDF +A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. +S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. + +## Questions and bug reports + +Not available diff --git a/utils/install_htk.sh b/utils/install_htk.sh index 91e4993..1094b67 100755 --- a/utils/install_htk.sh +++ b/utils/install_htk.sh @@ -23,8 +23,6 @@ if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then sudo make install else echo "Visibly htk has been already installed..." - echo "You should try to remove the folder repos/htk within the VM" - echo "and rerun this script." fi else echo "Can't find HTK-3.4.1.tar.gz. Check that you installed the right version." From 35679d211390074eaabb85d9749ef947779e8713 Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 16:07:56 -0500 Subject: [PATCH 105/299] reorganized detailed docs --- docs/source/tool_doc.md | 166 ++++++++++++++++++++++++++++++++++------ 1 file changed, 143 insertions(+), 23 deletions(-) diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index 34d20b2..1ec124f 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -1,31 +1,31 @@ -# Detailed Tools Doc +## Speech or Voice activity detection tools -This section contains documentation from the different tools. +This section contains documentation from the different Speech or Voice activity detection tools. -# LDC SAD +## LDC SAD -## General intro +### General intro LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. -## Main references: +### Main references: Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. -## Associated references: +### Associated references: Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. -## Questions and bug reports +### Questions and bug reports Not available -# NoisemesSad +## NoisemesSad -## General intro +### General intro Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. @@ -33,7 +33,7 @@ Noiseme SAD was actually not specifically built as a SAD but rather as a broade -## Instructions for direct use (ATTENTION, MAY BE OUTDATED) +### Instructions for direct use (ATTENTION, MAY BE OUTDATED) You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. @@ -72,7 +72,7 @@ This system will classify slices of the audio recording into one of 17 noiseme c - white_noise - radio -#### Some more technical details +##### Some more technical details For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": @@ -127,30 +127,30 @@ The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the mor -## Main references: +### Main references: Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) -## Associated references: +### Associated references: S.Burger,Q.Jin,P.F.Schulam,andF.Metze,“Noisemes:Man- ual annotation of environmental noise in audio streams,” Carnegie Mellon University, Pittsburgh, PA; U.S.A., Tech. Rep. CMU-LTI- 12-07, 2012. S.Strassel,A.Morris,J.G.Fiscus,C.Caruso,H.Lee,P.D.Over, J. Fiumara, B. L. Shaw, B. Antonishek, and M. Michel, “Creating havic: Heterogeneous audio visual internet collection,” in Proc. LREC. Istanbul, Turkey: ELRA, May 2012. F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia fea- ture extractor,” in Proceedings of the 21st ACM international con- ference on Multimedia. ACM, 2013, pp. 835–838. -## Questions and bug reports +### Questions and bug reports http://github.com/srvk/OpenSAT/issues -# OpenSmile SAD +## OpenSmile SAD -## General intro +### General intro openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coefficient RASTA-PLP plus first order delta features. It then uses a long short-term memory recurrent neural network (see details in Eyben et al., 2013b) that has been pre-trained on two corpora of read and spontaneous speech by adults recorded in laboratory conditions, augmented with various noise types. -## Some more technical details +### Some more technical details These are the parameters that are being used with values that depart from the openSMILE default settings (quoted material comes from either of the openSMILE manuals): @@ -175,28 +175,148 @@ openSMILE manuals consulted: - Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf -## Main references for this tool: +### Main references for this tool: Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. -## Questions and bug reports +### Questions and bug reports https://www.audeering.com/technology/opensmile/#support -# TOCombo SAD +## TOCombo SAD -## General intro +### General intro This tool's name stands for "Threshold-Optimized" "combo" SAD; we explain each part in turn. It is a SAD because the goal is to extract speech activity. It is called "combo" because it combines linearly 4 different aspects of voicing (harmonicity , clarity, prediction gain, periodicity) in addition to one perceptual spectral flux feature (see details in Sadjadi & Hansen, 2013). These are extracted in 32-ms frames (with a 10 ms stride). The specific version included here corresponds to the Combo SAD introduced in Ziaei et al. (2014) and used further in Ziaei et al (2016). In this work, a threshold was optimized for daylong recordings, which typically have long silent periods, in order to avoid the usual overly large false alarm rates found in typical SAD systems provided with these data. -## Main references: +### Main references: Ziaei, A., Sangwan, A., & Hansen, J. H. (2014). A speech system for estimating daily word counts. In Fifteenth Annual Conference of the International Speech Communication Association. http://193.6.4.39/~czap/letoltes/IS14/IS2014/PDF/AUTHOR/IS141028.PDF A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. -## Questions and bug reports +### Questions and bug reports Not available + +## Talker diarization tools + +This section contains documentation from the different Talker diarization tools (i.e., given a speech segment, decide who speaks). + + +## DiarTK + +### General intro + +This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format, from human annotation, or potentially from one of the SAD or VAD tools included in this VM. + +The DiarTK model imported in the VM is a C++ open source toolkit by Vijayasenan & Valente (2012). The algorithm first extracts MFCC features, then performs non-parametric clustering of the frames using agglomerative information bottleneck clustering. At the end of the process, the resulting clusters correspond to a set of speakers. The most likely Diarization sequence between those speakers is computed by Viterbi realignement. + +We use this tool with the following parameter values: + +- weight MFCC = 1 (default) +- Maximum Segment Duration 250 (default) +- Maximum number of clusters possible: 10 (default) +- Normalized Mutual Information threshold: 0.5 (default) +- Beta value: 10 (passed as parameter) +- Number of threads: 3 (passed as parameter) + + +### Main references: + +D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. https://pdfs.semanticscholar.org/71e3/9d42aadd9ec44a42aa5cd21202fedb5eaec5.pdf + +### Questions and bug reports + +http://htk.eng.cam.ac.uk/bugs/buglist.shtml + + +## Other tools + +This section contains documentation from other tools. + + + +## Yunitator + +### General intro + + +Given that there is no reference for this tool, we provide a more extensive introduction based on a presentation Florian Metze gave on 2018-08-13 in an ACLEW Meeting. + +The data used for training were: + +- ACLEW Starter dataset +- VanDam public 5-min dataset (about 13h; https://homebank.talkbank.org/access/Public/VanDam-5minute.html); noiseme-sad used to detect and remove intraturn silences + +Talker identity annotations collapsed into the following 4 types: + +- children (including both the child wearing the device and other children; class prior: .13) +- female adults (class prior .09) +- male adults (class prior .03) +- non-vocalizations (class prior .75) + +The features were MED (multimedia event detection) feature, extracted with OpenSMILE. They were extracted in 2s windows moving 100ms each step. There were 6,669 dims at first, PCA-ed down to 50 dims + +The model was a RNN, with 1 bidirectional GRU layer and 200 units in each direction. There was a softmax output layer, which therefore doesn't predict overlaps.. + +The training regime used 5-fold cross-validation, with 5 models trained on 4/5 of the data and tested on the remainder. The outputs are poooled together to measure performance. The final model was trained on all the data. + +The loss function was cross entropy with classes weighted by 1/prior. The batch size was 5 sequences of 500 frames. The optimizer was SGD with Nesterov momentum=.9, the inital LR was .01 and the LR schedule was *=0.8 if frame accuracy doesn’t reach new best in 4 epochs + +The resulting F1 for the key classes were: + +- Child .55 (Precision .55, recall .55) +- Male adult .43 (P .31, R .61) +- Female adult .55 (P .5, R .62) + + +### Main references: + +There is no official reference for this tool. + +### Questions and bug reports + +Not available + +## VCM + +### General intro +Two independent models: one (modelLing) to predicts linguistic vs. non-linguistic infant vocalisations; the other one (modelSyll) predicts canonical vs. non-canonical syllables if given a linguistic infant vocalization. + +Specifically, the modelLing was trained on an infant linguistic dataset (refer to this paper: https://static1.squarespace.com/static/591f756559cc68d09fc2e308/t/5b3a94cb758d4645603085db/1530565836736/ZhangEtAl_2018.pdf), and modelSyll was trained on another infant syllable vocalisation dataset (refer to this paper: https://pdfs.semanticscholar.org/2b25/bc84d2c4668e6d17f4f9343106f726198cd0.pdf). + +Feature set: 88 eGeMAPS extracted by openSMILE-2.3.0 on the segment level. + +Model: two hidden layers feed-forward neural networks with 1024 hidden nodes per each hidden layer. A log_softmax layer is stacked as an output layer. The optimiser was set to SGD with a learning rate 0.01, and the batch size is 64. + +Setups: Both the infant linguistic and syllable vocalisation datasets were split into train, development, and test partitions following a speaker independent strategy. + +Results: The results are 67.5% UAR and 76.6% WAR on the test set for the lingustic voc classification; and are 70.4% UAR and 69.2% WAR for the syllable voc classification. + + +### Main references: + +There is no official reference for this tool. + +### Questions and bug reports + +https://github.com/MilesICL/vcm/issues/ + + +## TalNet + +### General intro + +There is no information on this tool. + +### Main references: + +There is no official reference for this tool. + +### Questions and bug reports + +Not available + From 817b9af838283dd6f68c7bdd4ea4c63e1957b8ca Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 16:08:34 -0500 Subject: [PATCH 106/299] reorganized detailed docs --- docs/source/diartk.md | 21 ------- docs/source/ldcSad.md | 0 docs/source/noisemesSad.md | 115 ------------------------------------ docs/source/opensmileSad.md | 37 ------------ docs/source/tocomboSad.md | 13 ---- docs/source/vcm.md | 19 ------ docs/source/yunitator.md | 37 ------------ 7 files changed, 242 deletions(-) delete mode 100755 docs/source/diartk.md delete mode 100755 docs/source/ldcSad.md delete mode 100755 docs/source/noisemesSad.md delete mode 100755 docs/source/opensmileSad.md delete mode 100755 docs/source/tocomboSad.md delete mode 100755 docs/source/vcm.md delete mode 100755 docs/source/yunitator.md diff --git a/docs/source/diartk.md b/docs/source/diartk.md deleted file mode 100755 index 4ac5160..0000000 --- a/docs/source/diartk.md +++ /dev/null @@ -1,21 +0,0 @@ -# DiarTK - -## General intro - -This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format, from human annotation, or potentially from one of the SAD or VAD tools included in this VM. - -The DiarTK model imported in the VM is a C++ open source toolkit by Vijayasenan & Valente (2012). The algorithm first extracts MFCC features, then performs non-parametric clustering of the frames using agglomerative information bottleneck clustering. At the end of the process, the resulting clusters correspond to a set of speakers. The most likely Diarization sequence between those speakers is computed by Viterbi realignement. - -We use this tool with the following parameter values: - -- weight MFCC = 1 (default) -- Maximum Segment Duration 250 (default) -- Maximum number of clusters possible: 10 (default) -- Normalized Mutual Information threshold: 0.5 (default) -- Beta value: 10 (passed as parameter) -- Number of threads: 3 (passed as parameter) - - -## Main references: - -D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. https://pdfs.semanticscholar.org/71e3/9d42aadd9ec44a42aa5cd21202fedb5eaec5.pdf diff --git a/docs/source/ldcSad.md b/docs/source/ldcSad.md deleted file mode 100755 index e69de29..0000000 diff --git a/docs/source/noisemesSad.md b/docs/source/noisemesSad.md deleted file mode 100755 index 21ecbe6..0000000 --- a/docs/source/noisemesSad.md +++ /dev/null @@ -1,115 +0,0 @@ -# NoisemesSad - -## General intro - -Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. - - - - - -## Instructions for direct use (ATTENTION, MAY BE OUTDATED) - -You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. - -``` -$ vagrant ssh -c "OpenSAT/runOpenSAT.sh data/<$MYFILE>" -``` - -You can also analyze a group of files as follows: - -``` -$ vagrant ssh -c "OpenSAT/runDiarNoisemes.sh data/" -``` - -This will analyze all .wav's inside the "data" folder. - -Created annotations will be stored inside the same "data" folder. - -This system will classify slices of the audio recording into one of 17 noiseme classes: - -- background -- speech -- speech non English -- mumble -- singing alone -- music + singing -- music alone -- human sounds -- cheer -- crowd sounds -- animal sounds -- engine -- noise_ongoing -- noise_pulse -- noise_tone -- noise_nature -- white_noise -- radio - -#### Some more technical details - -For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": - -``` -$ vagrant ssh -$ cd OpenSAT -``` - -The main script is runOpenSAT.sh and takes one argument: an audio file in .wav format. -Upon successful completion, output will be in the folder (relative to ~/OpenSAT) -`SSSF/data/hyp//confidence.pkl.gz` - -The system will grind first creating features for all the .wav files it found, then will place those features in a subfolder `feature`. Then it will load a model, and process all the features generated, producing output in a subfolder `hyp/` two files per input: `.confidence.mat` and `.confidence.pkl.gz` - a confidence matrix in Matlab v5 mat-file format, and a Python compressed data 'pickle' file. Now, as well, in the `hyp/` folder, `.rttm` with labels found from a config file [noisemeclasses.txt](https://github.com/riebling/OpenSAT/blob/master/noisemeclasses.txt) - --More details on output format- - -The 18 classes are as follows: -``` -0 background -1 speech -2 speech_ne -3 mumble -4 singing -5 musicSing -6 music -7 human -8 cheer -9 crowd -10 animal -11 engine -12 noise_ongoing -13 noise_pulse -14 noise_tone -15 noise_nature -16 white_noise -17 radio -``` -The frame length is 0.1s. The system also uses a 2-second window, so the i-th frame starts at (0.1 * i - 2) seconds and finishes at (0.1 * i) seconds. That's why 60 seconds become 620 frames. 'speech_ne' means non-English speech - --Sample RTTM output snippet- -``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 -``` - -The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the more detailed results as seen above. - - - -## Main references: - -Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) - - -## Associated references: - -S.Burger,Q.Jin,P.F.Schulam,andF.Metze,“Noisemes:Man- ual annotation of environmental noise in audio streams,” Carnegie Mellon University, Pittsburgh, PA; U.S.A., Tech. Rep. CMU-LTI- 12-07, 2012. -S.Strassel,A.Morris,J.G.Fiscus,C.Caruso,H.Lee,P.D.Over, J. Fiumara, B. L. Shaw, B. Antonishek, and M. Michel, “Creating havic: Heterogeneous audio visual internet collection,” in Proc. -LREC. Istanbul, Turkey: ELRA, May 2012. -F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia fea- ture extractor,” in Proceedings of the 21st ACM international con- ference on Multimedia. ACM, 2013, pp. 835–838. diff --git a/docs/source/opensmileSad.md b/docs/source/opensmileSad.md deleted file mode 100755 index 0994e4c..0000000 --- a/docs/source/opensmileSad.md +++ /dev/null @@ -1,37 +0,0 @@ -# OpenSmile SAD - - -## General intro - -openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coefficient RASTA-PLP plus first order delta features. It then uses a long short-term memory recurrent neural network (see details in Eyben et al., 2013b) that has been pre-trained on two corpora of read and spontaneous speech by adults recorded in laboratory conditions, augmented with various noise types. - -## Some more technical details - -These are the parameters that are being used with values that depart from the openSMILE default settings (quoted material comes from either of the openSMILE manuals): - -monoMixdown = 1, means "mix down all recorded channels to 1 mono channel" -noHeader = 0, means read the RIFF header (don't need to specify the parameters ‘sampleRate’, ‘channels’, and possibly ‘sampleSize’) -preSil = 0.1 "Specifies the amount of silence at the turn beginning in seconds, i.e. the lag of the turn -detector. This is the length of the data that will be added to the current segment prior to -the turn start time received in the message from the turn detector component"; we use a tighter criterion than the default (.2) -postSil = 0.1 "Specifies the amount of silence at the turn end in seconds. This is the length of the data -that will be added to the current segment after to the turn end time received in the message -from the turn detector component."; we use a tighter criterion than the default (.3) - -You can change these parameters locally by doing: -``` -$ vagrant ssh -$ nano /vagrant/conf/vad/vadSegmenter_aclew.conf -``` - -openSMILE manuals consulted: - -- Eyben, F., Woellmer, M., & Schuller, B. (2013). openSMILE: The Munich open Speech and Music Interpretation by Large space Extraction toolkit. Institute for Human-Machine Communication, version 2.0. http://download2.nust.na/pub4/sourceforge/o/project/op/opensmile/openSMILE_book_2.0-rc1.pdf -- Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf - - -## Main references for this tool: - -Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. - -Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. diff --git a/docs/source/tocomboSad.md b/docs/source/tocomboSad.md deleted file mode 100755 index 34fa830..0000000 --- a/docs/source/tocomboSad.md +++ /dev/null @@ -1,13 +0,0 @@ -# TOCombo SAD - -## General intro - -This tool's name stands for "Threshold-Optimized" "combo" SAD; we explain each part in turn. It is a SAD because the goal is to extract speech activity. It is called "combo" because it combines linearly 4 different aspects of voicing (harmonicity , clarity, prediction gain, periodicity) in addition to one perceptual spectral flux feature (see details in Sadjadi & Hansen, 2013). These are extracted in 32-ms frames (with a 10 ms stride). The specific version included here corresponds to the Combo SAD introduced in Ziaei et al. (2014) and used further in Ziaei et al (2016). In this work, a threshold was optimized for daylong recordings, which typically have long silent periods, in order to avoid the usual overly large false alarm rates found in typical SAD systems provided with these data. - -## Main references: - -Ziaei, A., Sangwan, A., & Hansen, J. H. (2014). A speech system for estimating daily word counts. In Fifteenth Annual Conference of the International Speech Communication Association. http://193.6.4.39/~czap/letoltes/IS14/IS2014/PDF/AUTHOR/IS141028.PDF -A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. -S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. - - diff --git a/docs/source/vcm.md b/docs/source/vcm.md deleted file mode 100755 index fa02fcd..0000000 --- a/docs/source/vcm.md +++ /dev/null @@ -1,19 +0,0 @@ -# VCM - -## General intro -Two independent models: one (modelLing) to predicts lingustic vs. non-linguistic infant vocalisations; the other one (modelSyll) predicts canonical vs. non-canonical syllables if given a lingustic infant vocalication. - -Specifically, the modelLing was trained on Alex's infant lingustic dataset (refer to this paper: https://static1.squarespace.com/static/591f756559cc68d09fc2e308/t/5b3a94cb758d4645603085db/1530565836736/ZhangEtAl_2018.pdf), and modelSyll was trained on Anne's infant syllable vocalisation dataset (refer to this paper: https://pdfs.semanticscholar.org/2b25/bc84d2c4668e6d17f4f9343106f726198cd0.pdf). - -Feature set: 88 eGeMAPS extracted by openSMILE-2.3.0 on the segment level. - -Model: two hidden layers feed-forward neural networks with 1024 hidden nodes per each hidden layer. A log_softmax layer is stacked as an output layer. The optimiser was set to SGD with a learning rate 0.01, and the batch size is 64. - -Setups: Both the infant linguistic and syllable vocalisation datasets were split into train, development, and test partitions following a speaker independent strategy. - -Results: The results are 67.5% UAR and 76.6% WAR on the test set for the lingustic voc classification; and are 70.4% UAR and 69.2% WAR for the syllable voc classification. - - -## Main references: - -There is no official reference for this tool. diff --git a/docs/source/yunitator.md b/docs/source/yunitator.md deleted file mode 100755 index 479f06e..0000000 --- a/docs/source/yunitator.md +++ /dev/null @@ -1,37 +0,0 @@ -# Yunitator - -## General intro - - -Given that there is no reference for this tool, we provide a more extensive introduction based on a presentation Florian Metze gave on 2018-08-13 in an ACLEW Meeting. - -The data used for training were: - -- ACLEW Starter dataset -- VanDam public 5-min dataset (about 13h; https://homebank.talkbank.org/access/Public/VanDam-5minute.html); noiseme-sad used to detect and remove intraturn silences - -Talker identity annotations collapsed into the following 4 types: - -- children (including both the child wearing the device and other children; class prior: .13) -- female adults (class prior .09) -- male adults (class prior .03) -- non-vocalizations (class prior .75) - -The features were MED (multimedia event detection) feature, extracted with OpenSMILE. They were extracted in 2s windows moving 100ms each step. There were 6,669 dims at first, PCA-ed down to 50 dims - -The model was a RNN, with 1 bidirectional GRU layer and 200 units in each direction. There was a softmax output layer, which therefore doesn't predict overlaps.. - -The training regime used 5-fold cross-validation, with 5 models trained on 4/5 of the data and tested on the remainder. The outputs are poooled together to measure performance. The final model was trained on all the data. - -The loss function was cross entropy with classes weighted by 1/prior. The batch size was 5 sequences of 500 frames. The optimizer was SGD with Nesterov momentum=.9, the inital LR was .01 and the LR schedule was *=0.8 if frame accuracy doesn’t reach new best in 4 epochs - -The resulting F1 for the key classes were: - -- Child .55 (Precision .55, recall .55) -- Male adult .43 (P .31, R .61) -- Female adult .55 (P .5, R .62) - - -## Main references: - -There is no official reference for this tool. From 5c42f7b503b10934e38bfa26ddef08c97331f731 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 28 Nov 2018 16:11:43 -0500 Subject: [PATCH 107/299] prettify --- launcher/test.sh | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 95478ae..4f960a7 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -145,7 +145,7 @@ else fi -# finally test DIARTK +# test DIARTK echo "Testing DIARTK..." cd $DIARTKDIR @@ -165,12 +165,11 @@ else fi #rm $TESTDIR/$BASETEST.rttm -# finally test Yunitator +# test Yunitator echo "Testing Yunitator..." cd $YUNITATORDIR # let 'er rip -#./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} $LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then echo "Yunitator passed the test." @@ -183,8 +182,7 @@ fi # Test DSCORE echo "Testing Dscore..." cd $DSCOREDIR -#TESTDIR=$WORKDIR/dscore-test -#rm -rf $TESTDIR; mkdir -p $TESTDIR + cp -r test_ref test_sys $TESTDIR rm -f test.df python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} @@ -200,8 +198,7 @@ fi echo "Testing LDC evalSAD" if [ -d $LDC_SAD_DIR ]; then cd $LDC_SAD_DIR -# TESTDIR=$WORKDIR/opensmile-test -# cp $WORKDIR/$BASETEST.rttm $TESTDIR + $LAUNCHERS/eval.sh $DATADIR/test opensmileSad $KEEPTEMP > $WORKDIR/test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/opensmileSad_eval.df ]; then echo "LDC evalSAD passed the test" @@ -218,11 +215,7 @@ fi # Testing VCM echo "Testing VCM..." cd $VCMDIR -#TESTDIR=$WORKDIR/vcm-test -#rm -rf $TESTDIR; mkdir -p $TESTDIR -#ln -fs $TEST_WAV $TESTDIR -# let 'er rip -#./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} + $LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then echo "VCM passed the test." From 21dc561f371a9f1715711ed4c476097466ea1392 Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 16:41:36 -0500 Subject: [PATCH 108/299] reorg --- docs/source/formats.md | 59 ++++++++++++++++++++++----------------- docs/source/index.rst | 1 + docs/source/references.md | 15 ---------- docs/source/usage.md | 2 +- 4 files changed, 36 insertions(+), 41 deletions(-) diff --git a/docs/source/formats.md b/docs/source/formats.md index 081b3ba..41e87e6 100644 --- a/docs/source/formats.md +++ b/docs/source/formats.md @@ -1,8 +1,23 @@ -=========== END ===== +# Formats -TO ADD SOMEWHERE ELSE -Specific examples for the different tool types -- If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named toolnameSad_filename.rttm, which will look like this: +This section explains the input and output formats. Each type of tool returns a different type of output, depending on the key information. + +### Input: TextGrid + +TextGrid is a standard format for speech annotation, used by the Praat software. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. + +### Input: Eaf + +Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. + + +## Speech or Voice activity detection output + +RTTM is an annotation format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) +This format is used by the [DiViMe](https://github.com/srvk/DiViMe). + + +Tools that are of the SAD type (SAD or VAD) return one rttm per audio file, named toolnameSad_filename.rttm, which looks like this: ``` SPEAKER file17 1 0.00 0.77 speech @@ -10,33 +25,27 @@ SPEAKER file17 1 1.38 2.14 speech ``` -- If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the previous bulletpoint. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then provide them with a clear error, such as “TOOLNAME failed because you did not provide a sad/vad annotation file. Please refer to the docs for the list of available sad/vad tools.”. Your diarization-type tool should return one rttm per audio file, named toolnameDiar_filename.rttm, which must look like this: +The fourth column indicates the onset of a speech region; the forth column the duration of that speech region. All other columns may be ignored. Regions of non-speech are all the others (e.g., in this example, between .77 and 1.38). -``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 -``` +## Diarization style (diarization or role assignment) output + +RTTM is an annotation format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) +This format is used by the [DiViMe](https://github.com/srvk/DiViMe). -- If your tool is not a VAD/SAD but it is a classifier that assumes only raw acoustic input, then declare it as a sad/vad, and follow the instructions for vad/sad above, except that you'll adapt the rttm output to the classes you typically have. For example, one tool classifies audio into noiseme categories. It returns rttm's like this one: +Diarization-type tools return one rttm per audio file, named toolnameDiar_filename.rttm, which looks like this: ``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +SPEAKER file17 1 4.2 0.4 talker0 +SPEAKER file17 1 4.6 1.2 talker0 +SPEAKER file17 1 5.8 1.1 talker1 +SPEAKER file17 1 6.9 1.2 talker0 +SPEAKER file17 1 8.1 0.7 talker1 ``` -** todo: expand diar tool section** -- If your tool is a classifier or annotator that works only on a subtype of speaker (e.g., only on children's speech, or only on adults’ speech), then assume that each wav is accompanied by an rttm that has this information noted in column XX. -** todo: expand add tool section** +The fourth column indicates the onset of a region, the identity being indicated in ; the forth column the duration of that speech region. All other columns may be ignored. Regions of non-speech are all the others (e.g., in this example, between .77 and 1.38). + + + diff --git a/docs/source/index.rst b/docs/source/index.rst index 98f3fe8..b9e52c7 100755 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,6 +13,7 @@ Welcome to DiViMe's documentation! initial_questions install usage + furterInfo formats tool_doc troubleshoot diff --git a/docs/source/references.md b/docs/source/references.md index afe8654..7fda6a7 100755 --- a/docs/source/references.md +++ b/docs/source/references.md @@ -1,18 +1,3 @@ -# File Formats - -### RTTM - -RTTM is an annotaion format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) -This format is used by the [DiViMe](https://github.com/srvk/DiViMe). - -### TextGrid - -TextGrid is a standard format for speech annotation, used by the Praat software. - -### Eaf - -Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. - # References diff --git a/docs/source/usage.md b/docs/source/usage.md index ab609fc..2242794 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -61,7 +61,7 @@ Pure diarization tools only perform talker diarization (i.e., *who* speaks) but - opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. - tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran tocombosad, the system will run it for you. - textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. -- eaf: this means you want the system to use your eaf annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your eaf files before you start. Please note that the system will convert your eafs into .rttm in the process. +- eaf: this means you want the system to use your eaf annotations. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. - rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. Finally, if no parameter is provided, the system will give an error. From 09abbf4a4649cfb1e6aaea6f2def9e19df2e9cce Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 18:37:55 -0500 Subject: [PATCH 109/299] gladys recs implemented --- docs/source/furtherInfo.md | 40 ++++++ docs/source/initial_questions.md | 4 +- docs/source/install.md | 41 ++---- docs/source/tool_doc.md | 6 +- docs/source/usage.md | 237 ++++++++++++++++++++++++++----- 5 files changed, 262 insertions(+), 66 deletions(-) create mode 100755 docs/source/furtherInfo.md diff --git a/docs/source/furtherInfo.md b/docs/source/furtherInfo.md new file mode 100755 index 0000000..f6b2ab0 --- /dev/null +++ b/docs/source/furtherInfo.md @@ -0,0 +1,40 @@ +# More information about DiViMe + +DiViMe is a virtual machine, whose characteristics and contents are almost completely determined by provisioning scripts found in the DiViMe folder created when you did `git clone https://github.com/srvk/DiViMe/. This section provides information to help you understand the DiViMe structure in conceptual terms (the "pipeline"). We also explain the process of "bootstrapping" or creation of this virtual machine. Finally, we describe the folder structure. If you just want to use the tools in DiViMe, you can probably skip this whole section, or read just the `Pipeline structure` section. + +## Pipeline Structure + +DiViMe is a platform for tools to analyze naturalistic, unannotated audiorecordings. We consider this process to involve three kinds of processes: + +- speech activity detection and voice activity detection = “detecting vocalizations”, +- diarization = “deciding to whom the vocalizations belong”, and +- “additional annotations” + + +Some tools actually combine two of these stages (e.g. a tool may do both speech activity detection and role attribution in one fell swoop). + +## Building a virtual machine + +The structures and contents of the VM are actually built from reproducible directives which are executed when you do `vagrant up`. In technical terms, this is called VM is _provisioning_. In a nutshell, a file called "Vagrantfile" builds the machine (e.g., creates a virtual machine, allocates memory, installs an operating systems). Another file (conf/bootstrap.sh) installs tools within this virtual machine. For detailed documentation, see https://www.vagrantup.com/docs/vagrantfile/. + + + +## Folder Structure + +By virtue of how DiViMe is provisioned, there is some information that is accessible both from the host machine (i.e., your computer) and the virtual machine (i.e., the minicomputer built inside your computer). These are called `shared folders`. + +*The following folders are shared between the host and the virtual machine, and thus accessible from both:* + +- *utils/* contains ancillary files, typically used across more than one tool +- *launcher/* contains files that target users will use to launch different tools +- *conf/* is for configuration files for two potential reasons: they are shared across more than one tool, or to make them more easily editable from outside the VM +- *data/* folder where users put the data to be analyzed, and recover the automatically annotated files + +From within the virtual machine, these are inside /vagrant: /vagrant/utils, /vagrant/launcher, etc. Some of these are also accessible from the home of the default user, through links, ie, ~/utils and ~/launcher. (the default user is vagrant for virtualbox) + +*The following folders can only be found within the virtual machine*: + +- *repos/* contains any repository that is cloned into the machine, typically tools for the user, but also tools used by other tools to do e.g. feature extraction. + +From within the virtual machine, ~/repos is inside the vagrant user’s home folder, so you can access it as ~/repos/ or /home/vagrant/repos. + diff --git a/docs/source/initial_questions.md b/docs/source/initial_questions.md index a996352..544e226 100755 --- a/docs/source/initial_questions.md +++ b/docs/source/initial_questions.md @@ -10,7 +10,9 @@ It is a collection of speech processing tools allowing users to automatically ad 3) Role diarization (_what kind of person is talking?_) -We are hoping to add more tools in the future, including register detection, syllable quantification, and vocal maturity estimation. +4) Vocal type classification (_what kind of vocalization is this one?_) + +We are hoping to add more tools in the future, including register detection, and syllable quantification. ## Who is the ACLEW DiViMe for? diff --git a/docs/source/install.md b/docs/source/install.md index 2b63eca..48a9924 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -6,33 +6,21 @@ Try the following first: 1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link and follow the prompted instructions -1. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. +2. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. -2. Clone the present repository: +3. Clone the present repository: To do this, you must use a terminal. If you don't know what this means, we recommend that you first follow the [Software Carpentry Shell Tutorial](https://swcarpentry.github.io/shell-novice/) (up to 00:45, namely "Introducing the shell", and "Navigating files and directories"). Next, navigate to the directory in which you want the VM to be hosted and type in: `$ git clone https://github.com/srvk/DiViMe` - - Open a terminal window - - In it, navigate to the directory in which you want the VM to be hosted - - type in: +4. Change into this folder: `$ cd DiViMe` -`$ git clone https://github.com/srvk/DiViMe` +5. Install HTK. HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. -3. Change into it by + - Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) + - Register by following the instructions on the left (under "Getting HTK": Register) + - Check that you have received your password via email; you will need it for the next step. + - Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. + - Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). -`$ cd DiViMe` - -4. Install HTK - -HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. - -- Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) -- Register by following the instructions on the left (under "Getting HTK": Register) -- Check that you have received your password via email; you will need it for the next step. -- Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. -- Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). - -5. Type - -`$ vagrant up` +6. Type `$ vagrant up` The first time you do this, it will take at least 20 minutes to install all the packages that are needed to build the virtual machine. Once the virtual machine will be installed, it will stay stuck at "installation finished" for few minutes. However, the tools are not yet installed at this step. @@ -40,7 +28,7 @@ You will need to wait for the tools to be installed, and to take back the contro The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/srvk/DiViMe/issues), describing your situation. -Advanced topic: [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker) +We are working on [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker), but this option is not yet functional. ## Checking your installation @@ -73,20 +61,19 @@ DiarTK passed the test. Congratulations, everything is OK! -This is the simple test with a few short files. If you would like to run a test for use with daylong recordings, please run $ vagrant ssh -c "launcher/test-daylong.sh". Note that this will download a very large recording. ``` ## Common installation errors and fixes -- For LDC SAD, you may get an error "LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include LDC SAD. This error means that you cannot use LDC SAD, but you can use any other SAD/VAD. (For example, noisemesSad.) -- For LDC SAD, Noisemes, and DiarTK, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. The easiest way to fix it is to install HTK (again). +- For ldcSad, you may get an error "ldcSad failed because the code for ldcSad is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include ldcSad. This error means that you cannot use ldcSad, but you can use any other SAD/VAD. (For example, noisemesSad.) +- For ldcSad, noisemesSad, and diartkDiar, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. ## Updating DiViMe -If there is a new version of DiViMe, you'll need to perform the following 3 steps from within the DiViME folder on your terminal: +If there is a new version of DiViMe, you will need to perform the following 3 steps from within the DiViME folder on your terminal: ``` diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index 1ec124f..d7934d6 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -1,4 +1,4 @@ -## Speech or Voice activity detection tools +# Speech or Voice activity detection tools This section contains documentation from the different Speech or Voice activity detection tools. @@ -201,7 +201,7 @@ S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voici Not available -## Talker diarization tools +# Talker diarization tools This section contains documentation from the different Talker diarization tools (i.e., given a speech segment, decide who speaks). @@ -233,7 +233,7 @@ D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in http://htk.eng.cam.ac.uk/bugs/buglist.shtml -## Other tools +# Other tools This section contains documentation from other tools. diff --git a/docs/source/usage.md b/docs/source/usage.md index 2242794..0403454 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -6,36 +6,103 @@ This is an overview of the full tool presentation found in the next stage, recap 1. Put your data in the ```data``` shared directory. 2. Do `$ vagrant up` to "wake the machine up" -3. Choose between: running a speech activity detection system followed by a diarization system (steps 3 and 4 below), or a tool that directly segments recordings into 3 main roles, namely child, male adult, female adult (step 5 below) -4. If you have some annotations, you can evaluate how the tools did (step 6 below) -5. Finally, remember to put the machine back to sleep with `$ vagrant halt` + Next we provide instructions for all tools. More detailed information about each tool can be found in separate readme's. -## Short instructions for all tools +Assuming the installation of the virtual machine is complete and some of the tests have passed, you can now use at least some of the tools in the virtual machine. We explain more about each step below, but in a nutshell, the steps to use DiViMe are always the same: + +1. Put the data you want to process in the ```data/``` directory (or any subdirectory within ```data/```) +2. Go to the DiViMe folder +3. Do `$ vagrant up` to "wake the machine up" +4. Use tools on data, typically by doing `vagrant ssh -c "script.sh [arguments]"`. You can also run a recipe. +5. Finally, remember to put DiViMe back to sleep with `$ vagrant halt` + + +## Further information on Step 1, putting your data into the ```data/``` directory + +Put the sound files that you want analyzed (and annotations, if you have any) inside the shared ```data``` folder. It is probably safer to make a copy of your files (rather than moving them), in case you later decide to delete the whole folder. + +You can drop a whole folder into ```data```. You will provide the path to the specific folder to be analyzed when running the tools (as per instructions below). All `.wav` files in that folder will be analyzed. + +If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. + +If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. For more information on these formats, see the Format section. + +IMPORTANT: If you already analyzed a file with a given tool, re-running the tool will result in the previous analysis being overwritten. + +## Further information on Step 2, going to the DiViMe folder + +To interact with the virtual machine, you must use a terminal. If you don't know what this means, we recommend that you first follow the [Software Carpentry Shell Tutorial](https://swcarpentry.github.io/shell-novice/) (up to 00:45, namely "Introducing the shell", and "Navigating files and directories"). -1. Put sound files (and annotations, if you have any) inside the shared ```data``` folder. If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. +Next, navigate in the terminal window to the DiViMe directory that was created when you did `git clone https://github.com/srvk/DiViMe` when installing DiViMe. - If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. It is probably safer to make a copy (rather than moving them), in case you later decide to delete the whole vagrant folder. -2. Launch the virtual machine anytime by navigating to your DiViMe folder on your terminal and performing: +## Further information on Step 3, Waking the machine up + +Remember that you will be using a mini-computer within your computer. Typically, the machine will be down - i.e., it will not be running. This is good, because when it is running, it will use memory and other resources from your computer (which we call "the host", because it is hosting the other computer). With this step, you launch the virtual machine: `$ vagrant up` -3. For the SAD tools, type a command like this one: +## Further information on Step 4, Using tools on data + +### Overview of tools + +If all tools passed the test, then you'll be able to automatically add the following types of annotation to your audio files: + +1) Speech activity detection (_when is someone talking?_): The tools available for this task are the following: noisemesSad, tocomboSad, opensmileSad, ldcSad + +2) Talker diarization (_who is talking?_) The tools available for this task are the following: diartkDiar + +3) Role diarization (_what kind of person is talking?_) The tools available for this task are the following: yunitator + +4) Vocal type classification (_what kind of vocalization is this one?_) The tools available for this task are the following: vcm + +5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, ldcSad, diartkDiar, yunitator + +### Overview of "pipelines" + +DiViMe is a platform for tools to analyze naturalistic, unannotated audiorecordings. We consider this process to involve three kinds of processes: + +- speech activity detection and voice activity detection = “detecting vocalizations”, +- diarization = “deciding to whom the vocalizations belong”, and +- “additional annotations” -`$ vagrant ssh -c "launcher/noisemesSad.sh data/"` +Some tools actually combine two of these stages (e.g. a tool may do both speech activity detection and role attribution in one fell swoop). This [flowchart](https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9) may help. -This will create a set of new rttm files, with the name of the tool added at the beginning. For example, imagine you have a file called participant23.wav, and you decide to run two SADs: +We call a *pipeline* a sequence of those processes; i.e., it involves using one tool after another. For example, you may do *speech activity detection* + *talker diarization* + *vocal type classification* + +Starting from an audio file with no annotation, typically, you may want to run a *speech activity detection* tool followed by a *talker diarization* tool; then you will end up with an annotation showing who spoke when. However, you may not know who "talker0" and "talker1" are. (You could decide this by listening to some samples of each, and mapping them to different roles. However, we do not provide tools to do this.) + +Alternatively, we provide a *role diarization* tool that directly segments recordings into 3 main roles, namely child, male adult, female adult; and these separated from silence. + +In both cases, you may want to classify each vocalizations into different types with the *vocal type classification* tool. + +### How to run a Speech or Voice activity detection tool + +For these tools, type a command like this one: + +`$ vagrant ssh -c "noisemesSad.sh data/mydata/"` + +You can read that command as follows: + +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. + +*noisemesSad.sh*: This first argument tells DiViMe which tool to run. The options are: noisemesSad.sh, tocomboSad.sh, opensmileSad.sh, ldcSad.sh + +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. + + +For each input wav file, there will be one rttm file created in the same directory, with the name of the tool added at the beginning. For example, imagine you have put a single file called participant23.wav into ```data/```, and you decided to run two SADs: ``` -$ vagrant ssh -c "launcher/opensmileSad.sh data/" -$ vagrant ssh -c "launcher/noisemesSad.sh data/" +$ vagrant ssh -c "opensmileSad.sh data/" +$ vagrant ssh -c "noisemesSad.sh data/" ``` -This will result in your having the following three files in your /data/ folder: +This will result in your having the following three files in your ```data/``` folder: - participant23.wav - opensmileSad_participant23.rttm @@ -50,46 +117,146 @@ SPEAKER participant23 1 1.38 2.14 speech This means that opensmileSad considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. -4. There is one **pure diarization** tool: diartk. Here is the command to run, for the data/ input folder: +### How to run a Talker diarization tool + +For these tools, type a command like this one: + +`$ vagrant ssh -c "diartk.sh data/mydata/ noisemesSad"` + +You can read that command as follows: + +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. -`$ vagrant ssh -c "launcher/diartk.sh data/ noisemesSad"` +*diartk.sh*: This first argument tells DiViMe which tool to run. The options are: diartk.sh. -Pure diarization tools only perform talker diarization (i.e., *who* speaks) but not speech activity detection (*when* is someone speaking). Therefore, this system requires some form of SAD. The third parameter ('noisemes') tells the system which SAD annotation to use, from among the list: +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. + +*noisemesSad*: Remember that this tool does "talker diarization": Given some speech, attribute it to a speaker. Therefore, this type of tool necessitates speech/voice activity detection. This third argument tells DiViMe what file contains information about which sections of the sound file contain speech. + +You can only use one of the following options: textgrid, eaf, rttm, ldcSad, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. + +You can provide annotations done by a human or in some other way, and encoded as one of the following three file types: -- ldcSad: this means you want the system to use the output of the LDC_SAD system. If you have not run LDC_SAD, the system will run it for you. -- noisemesSad: this means you want the system to use the output of the noisemesSad system. If you have not run LDC_SAD, the system will run it for you. -- opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. -- tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran tocombosad, the system will run it for you. - textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. - eaf: this means you want the system to use your eaf annotations. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. -- rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. +- rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eight column count as such. + + +Alternatively, you can provide use automatic annotations generated by DiViMe's speech/voice activity detection systems, encoded in rttm files. In this case, you would pass one of the following options: + +- ldcSad: this means you want the system to use the output of the ldcSad system. If you have not run this system before, the system will fail. +- this system before: this means you want the system to use the output of the noisemesSad system. If you have not run noisemesSad, the system will fail. +- opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run this system before, the system will fail. +- tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran this system before, the system will fail. + +If the third parameter is not provided, the system will give an error. + +If all three parameters are provided, then the system will first find all the annotation files matching the third parameter (e.g., all the files *.TextGrid; or all the tocomboSad_*.rttm files), and then find the corresponding sound files. For example, imagine you have put into your ```data/mydata/``` folder the following files: + +- participant23.wav +- opensmileSad_participant23.rttm +- participant24.wav +- participant24.TextGrid + + +If you run: + +`$ vagrant ssh -c "diartk.sh data/mydata/ opensmileSad"` + +then only participant23.wav will be analyzed. + + +If you run: + +`$ vagrant ssh -c "diartk.sh data/mydata/ textgrid"` + +then only participant24.wav will be analyzed. + +At the end of the process, there will be an added rttm file for each analyzed file. For instance, if you have just one sound file (participant23.wav) at the beginning and you run opensmileSad followed by diartk, then you will end up with the following three files: + +- participant23.wav: your original sound file +- opensmileSad_participant23.rttm: the output of opensmileSad, which states where there is speech +- diartk_opensmileSad_participant23.rttm: the output of opensmileSad followed by diartk, which states which speech sections belong to which speakers. + +If you look inside a diartk_*.rttm file, it will look as follows: + +``` +SPEAKER file17 1 4.2 0.4 talker0 +SPEAKER file17 1 4.6 1.2 talker0 +SPEAKER file17 1 5.8 1.1 talker1 +SPEAKER file17 1 6.9 1.2 talker0 +SPEAKER file17 1 8.1 0.7 talker1 +``` + +This means that diartk considered that one talker spoke starting at 4.2 seconds for .4 seconds; starting at 4.6 for 1.2 seconds; then someone else spoke starting at 5.8 seconds and for 1.1 seconds; etc. + +### How to run a Role assignment tool + +For these tools, type a command like this one: + +`$ vagrant ssh -c "yunitator.sh data/mydata/"` + +You can read that command as follows: + +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. + +*yunitator.sh*: This first argument tells DiViMe which tool to run. The options are: yunitator. + +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. + +It returns one rttm per sound file, with an estimation of where there are vocalizations by children, female adults, and male adults. + +### How to run a Vocalization classification tool + +NO INFORMATION YET + +### How to run an Evaluation + +If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. + +#### Evaluating Speech/Voice activity detection + +Type a command like the one below: + +`$ vagrant ssh -c "evalSAD.sh data/ noisemesSad"` + +You can read that command as follows: + +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. + +*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. + +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. + +*noisemesSad*: The third argument indicates which tool's output to evaluate (in this case, noisemesSad). All of our Speech/Voice activity detection tools can be evaluated with this. + +For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). + +#### Evaluating Speech/Voice activity detection -Finally, if no parameter is provided, the system will give an error. +Type a command like the one below: -5. There is one **role assignment** tool, which classifies spoken turns into three roles: children, female adults, male adults. It exists in two versions. +`$ vagrant ssh -c "evalDiar.sh data/ diartk_noisemesSad"` -The version we call "yunitator" takes the raw recording as input. To call this one, do +You can read that command as follows: -`$ vagrant ssh -c "launcher/yunitator.sh data/"` +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. +*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. -The version we call "yuniSeg" takes the raw recording as well as a SAD as input. To call this one, do +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. -`$ vagrant ssh -c "launcher/yuniSeg.sh data/ noisemesSad"` +* diartk_noisemesSad*: The third argument indicates which output to evaluate. -Both of them return one rttm per sound file, with an estimation of where there are vocalizations by children, female adults, and male adults. +**THIS NEEDS WORK** -For more information on the model underlying them, see the Yunitator section below. +For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). -6. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: -`$ vagrant ssh -c "launcher/eval.sh data/ noisemesSad"` -Notice there are 2 parameters provided to the evaluation suite. The first parameter tells the system which folder to analyze (in this case, the whole data/ folder). The second parameter indicates which tool's output to evaluate (in this case, noisemesSad). The system will use the .rttm annotations if they exist; or the .eaf ones if the former are missing; or the .textgrid of neither .rttm nor .eaf are found. -If you want to evaluate a diarization produced by the diartk tool, you will have to specify a third parameter, to tell the system which SAD was used to compute the diartk outputs you want to evaluate. E.G. : -`$ vagrant ssh -c "launcher/eval.sh data/ diartk noisemesSad` +## Further information on Step 5, putting DiViMe back to sleep -7. Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: +Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: `$ vagrant halt` From da8f185f1175531d921cdde9e1bfd435ae861664 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Thu, 29 Nov 2018 09:52:39 -0500 Subject: [PATCH 110/299] VCM->vcm --- update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.sh b/update.sh index df73da1..7f08222 100644 --- a/update.sh +++ b/update.sh @@ -16,6 +16,6 @@ release=v1.0 #(cd "ldc_sad_hmm" ; git pull) (cd "dscore" ; git pull) (cd "Yunitator" ; git pull) -(cd "VCM"; git pull) +(cd "vcm"; git pull) (cd "To-Combo-SAD" ; git pull; git checkout $release) ############################################# From ee574ace8e29d9cec18e59beabd33ed1ad733cf3 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Thu, 29 Nov 2018 10:19:16 -0500 Subject: [PATCH 111/299] Eric's latest version --- launcher/test.sh | 98 ++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 58 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index e5d40b6..4f960a7 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -4,12 +4,6 @@ # from a downloaded 5 minute section of the HomeBank VanDam daylong audio sample # ("ACLEW Starter" data) -# this doesn't work because .bashrc exits immediately if not running interactively -#source /home/vagrant/.bashrc -i -# instead: -export PATH=/home/vagrant/anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin -LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH" - KEEPTEMP="" if [ $# -eq 1 ]; then if [ $BASH_ARGV == "--keep-temp" ]; then @@ -17,7 +11,6 @@ if [ $# -eq 1 ]; then fi fi -conda_dir=/home/vagrant/anaconda/bin # Absolute path to this script. /home/vagrant/launcher SCRIPT=$(readlink -f $0) @@ -30,7 +23,7 @@ UTILS=/home/vagrant/utils # Paths to Tools LDC_SAD_DIR=$REPOS/ldc_sad_hmm OPENSATDIR=$REPOS/OpenSAT # noisemes -OPENSMILEDIR=$REPOS/openSMILE-2.1.0/ +OPENSMILEDIR=$REPOS/opensmile-2.3.0/ TOCOMBOSAD=$REPOS/To-Combo-SAD DIARTKDIR=$REPOS/ib_diarization_toolkit #TALNETDIR=$REPOS/TALNet @@ -41,12 +34,14 @@ VCMDIR=$REPOS/vcm FAILURES=false echo "Starting tests" -echo "Downloading test audio..." cd /vagrant/data -# get transcript -wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip -unzip -q -o VanDam-Daylong.zip + +if [ ! -s VanDam-Daylong.zip ]; then + echo "Downloading test transcript..." + wget -q -N https://homebank.talkbank.org/data/Public/VanDam-Daylong.zip + unzip -q -o VanDam-Daylong.zip +fi # This is the working directory for the tests; right beside the input cd VanDam-Daylong/BN32/ @@ -54,6 +49,10 @@ WORKDIR=`pwd` # Get daylong recording from the web wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 +if [ ! -s BN32_010007.mp3 ]; then + echo "Downloading test audio..." + wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 +fi DATADIR=data/VanDam-Daylong/BN32 # relative to /vagrant, used by launcher scripts BASE=BN32_010007 # base filename for test input file, minus .wav or .rttm suffix @@ -82,15 +81,18 @@ else echo " and rename it to HTK.tar.gz? If so, then you may need to re-install it. Run: vagrant ssh -c \"utils/install_htk.sh\" " fi +TESTDIR=$WORKDIR/test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +cp $WORKDIR/$BASETEST.rttm $TESTDIR + # First test in ldc_sad_hmm echo "Testing LDC SAD..." if [ -s $LDC_SAD_DIR/perform_sad.py ]; then cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/ldc_sad-test - rm -rf $TESTDIR; mkdir -p $TESTDIR - $conda_dir/python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} - # convert output to rttm, for diartk. - grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm + + $LAUNCHERS/ldcSad.sh $DATADIR/test $KEEPTEMP >& $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} + if [ -s $TESTDIR/$BASETEST.rttm ]; then echo "LDC SAD passed the test." else @@ -105,11 +107,8 @@ fi # now test Noisemes echo "Testing noisemes..." cd $OPENSATDIR -TESTDIR=$WORKDIR/noisemes-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -#./runDiarNoisemes.sh $TESTDIR > $TESTDIR/noisemes-test.log 2>&1 -$LAUNCHERS/noisemesSad.sh $DATADIR/noisemes-test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} + +$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/noisemes_sad_$BASETEST.rttm ]; then echo "Noisemes passed the test." @@ -117,17 +116,13 @@ else FAILURES=true echo " Noisemes failed - no RTTM output" fi -# clean up -#rm -rf $OPENSATDIR/SSSF/data/feature $OPENSATDIR/SSSF/data/hyp # now test OPENSMILEDIR echo "Testing OpenSmile SAD..." cd $OPENSMILEDIR -TESTDIR=$WORKDIR/opensmile-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -$LAUNCHERS/opensmileSad.sh $DATADIR/opensmile-test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} + +$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then echo "OpenSmile SAD passed the test." @@ -139,10 +134,8 @@ fi # now test TOCOMBOSAD echo "Testing ToCombo SAD..." cd $TOCOMBOSAD -TESTDIR=$WORKDIR/tocombo_sad-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -$LAUNCHERS/tocomboSad.sh $DATADIR/tocombo_sad-test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} + +$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then echo "TOCOMBO SAD passed the test." @@ -152,15 +145,13 @@ else fi -# finally test DIARTK +# test DIARTK echo "Testing DIARTK..." cd $DIARTKDIR -TESTDIR=$WORKDIR/diartk-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR + cp $TEST_RTTM $TESTDIR # run like the wind -$LAUNCHERS/diartk.sh $DATADIR/diartk-test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 +$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 if grep -q "command not found" $TESTDIR/diartk-test.log; then echo " Diartk failed - dependencies (probably HTK)" FAILURES=true @@ -172,17 +163,14 @@ else echo " Diartk failed - no output RTTM" fi fi -rm $TESTDIR/$BASETEST.rttm +#rm $TESTDIR/$BASETEST.rttm -# finally test Yunitator +# test Yunitator echo "Testing Yunitator..." cd $YUNITATORDIR -TESTDIR=$WORKDIR/yunitator-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR + # let 'er rip -#./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -$LAUNCHERS/yunitate.sh $DATADIR/yunitator-test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then echo "Yunitator passed the test." else @@ -194,8 +182,7 @@ fi # Test DSCORE echo "Testing Dscore..." cd $DSCOREDIR -TESTDIR=$WORKDIR/dscore-test -rm -rf $TESTDIR; mkdir -p $TESTDIR + cp -r test_ref test_sys $TESTDIR rm -f test.df python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} @@ -211,9 +198,8 @@ fi echo "Testing LDC evalSAD" if [ -d $LDC_SAD_DIR ]; then cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/opensmile-test - cp $WORKDIR/$BASETEST.rttm $TESTDIR - $LAUNCHERS/eval.sh $DATADIR/opensmile-test opensmileSad $KEEPTEMP > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} + + $LAUNCHERS/eval.sh $DATADIR/test opensmileSad $KEEPTEMP > $WORKDIR/test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/opensmileSad_eval.df ]; then echo "LDC evalSAD passed the test" else @@ -229,12 +215,8 @@ fi # Testing VCM echo "Testing VCM..." cd $VCMDIR -TESTDIR=$WORKDIR/vcm-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -ln -fs $TEST_WAV $TESTDIR -# let 'er rip -#./runYunitator.sh $TESTDIR/$BASETEST.wav > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -$LAUNCHERS/vcm.sh $DATADIR/vcm-test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} + +$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then echo "VCM passed the test." else @@ -251,9 +233,9 @@ fi # results echo "RESULTS:" -for f in /vagrant/$DATADIR/*-test/*.rttm; do $UTILS/sum-rttm.sh $f; done +for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done echo "DSCORE:" -cat /vagrant/data/VanDam-Daylong/BN32/dscore-test/test.df +cat /vagrant/data/VanDam-Daylong/BN32/test/test.df echo "EVAL_SAD:" -cat $TESTDIR/opensmileSad_eval.df +cat $WORKDIR/test/opensmileSad_eval.df From c407dd1d9439eca36e7f4dcbf9961d46b9189e97 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 10:28:27 -0500 Subject: [PATCH 112/299] minor bug fix --- docs/source/usage.md | 2 ++ launcher/evalSAD.sh | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index 0403454..8ccb439 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -252,7 +252,9 @@ You can read that command as follows: For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). +## An alternative for Step 4: using recipes +**THIS NEEDS WORK** ## Further information on Step 5, putting DiViMe back to sleep diff --git a/launcher/evalSAD.sh b/launcher/evalSAD.sh index 010e684..2ca23c2 100755 --- a/launcher/evalSAD.sh +++ b/launcher/evalSAD.sh @@ -37,8 +37,8 @@ if [[ $system = "ldcSad" ]]; then sys_name="ldcSad" elif [[ $system = "noisemesSad" ]]; then sys_name="noisemesSad" -elif [[ $system = "tocombosad" ]]; then - sys_name="tocombo_sad" +elif [[ $system = "tocomboSad" ]]; then + sys_name="tocomboSad" elif [[ $system = "opensmileSad" ]]; then sys_name="opensmileSad" elif [[ $system = "lenaSad" ]]; then From 522b805872ed0b6f0b342888cfa9efa26f02c04f Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Thu, 29 Nov 2018 10:45:50 -0500 Subject: [PATCH 113/299] Don't CD to dirs that don't exist --- launcher/test.sh | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 4f960a7..2f8fa7a 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -22,14 +22,14 @@ UTILS=/home/vagrant/utils # Paths to Tools LDC_SAD_DIR=$REPOS/ldc_sad_hmm -OPENSATDIR=$REPOS/OpenSAT # noisemes -OPENSMILEDIR=$REPOS/opensmile-2.3.0/ -TOCOMBOSAD=$REPOS/To-Combo-SAD -DIARTKDIR=$REPOS/ib_diarization_toolkit +#OPENSATDIR=$REPOS/OpenSAT # noisemes +#OPENSMILEDIR=$REPOS/opensmile-2.3.0/ +#TOCOMBOSAD=$REPOS/To-Combo-SAD +#DIARTKDIR=$REPOS/ib_diarization_toolkit #TALNETDIR=$REPOS/TALNet DSCOREDIR=$REPOS/dscore -YUNITATORDIR=$REPOS/Yunitator -VCMDIR=$REPOS/vcm +#YUNITATORDIR=$REPOS/Yunitator +#VCMDIR=$REPOS/vcm FAILURES=false @@ -89,7 +89,7 @@ cp $WORKDIR/$BASETEST.rttm $TESTDIR # First test in ldc_sad_hmm echo "Testing LDC SAD..." if [ -s $LDC_SAD_DIR/perform_sad.py ]; then - cd $LDC_SAD_DIR +# cd $LDC_SAD_DIR $LAUNCHERS/ldcSad.sh $DATADIR/test $KEEPTEMP >& $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} @@ -106,7 +106,6 @@ fi # now test Noisemes echo "Testing noisemes..." -cd $OPENSATDIR $LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} @@ -120,7 +119,6 @@ fi # now test OPENSMILEDIR echo "Testing OpenSmile SAD..." -cd $OPENSMILEDIR $LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} @@ -133,7 +131,6 @@ fi # now test TOCOMBOSAD echo "Testing ToCombo SAD..." -cd $TOCOMBOSAD $LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} @@ -147,7 +144,6 @@ fi # test DIARTK echo "Testing DIARTK..." -cd $DIARTKDIR cp $TEST_RTTM $TESTDIR # run like the wind @@ -167,7 +163,6 @@ fi # test Yunitator echo "Testing Yunitator..." -cd $YUNITATORDIR # let 'er rip $LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} @@ -197,7 +192,7 @@ fi # testing LDC evalSAD (on opensmile) echo "Testing LDC evalSAD" if [ -d $LDC_SAD_DIR ]; then - cd $LDC_SAD_DIR +# cd $LDC_SAD_DIR $LAUNCHERS/eval.sh $DATADIR/test opensmileSad $KEEPTEMP > $WORKDIR/test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/opensmileSad_eval.df ]; then @@ -214,7 +209,6 @@ fi # Testing VCM echo "Testing VCM..." -cd $VCMDIR $LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then From 3f890323d1653c54f2cd9eb4c390780c3717a24b Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 10:48:18 -0500 Subject: [PATCH 114/299] integrated contributors docs --- docs/source/eval.md | 19 -- .../{furtherInfo.md => further-info.md} | 2 +- docs/source/index.rst | 3 +- docs/source/instructions_for_contributors.md | 216 +++++++++++++----- docs/source/tool_doc.md | 13 +- 5 files changed, 162 insertions(+), 91 deletions(-) delete mode 100755 docs/source/eval.md rename docs/source/{furtherInfo.md => further-info.md} (87%) diff --git a/docs/source/eval.md b/docs/source/eval.md deleted file mode 100755 index 418f967..0000000 --- a/docs/source/eval.md +++ /dev/null @@ -1,19 +0,0 @@ -# LDC Diarization Scoring - -## General intro - -For SAD, we employ the evaluation included in the LDC SAD, which returns the false alarm (FA) rate (proportion of frames labeled as speech that were non-speech in the gold annotation) and missed speech rate (proportion of frames labeled as non-speech that were speech in the gold annotation). For TD, we employ the evaluation developed for the DiHARD Challenge, which returns a Diarization error rate (DER), which sums percentage of speaker error (mismatch in speaker IDs), false alarm speech (non-speech segments assigned to a speaker) and missed speech (unassigned speech). - -One important consideration is in order: What to do with files that have no speech to begin with, or where the system does not return any speech at the SAD stage or any labels at the TD stage. This is not a case that is often discussed in the litera- ture because recordings are typically targeted at moments where there is speech. However, in naturalistic recordings, some ex- tracts may not contain any speech activity, and thus one must adopt a coherent framework for the evaluation of such instances. We opted for the following decisions. - -If the gold annotation was empty, and the SAD system returned no speech labels, then the FA = 0 and M = 0; but if the SAD system returned some speech labels, then FA = 100 and M = 0. Also, if the gold annotation was not empty and the sys- tem did not find any speech, then this was treated as FA = 0 and M=100. - -As for the TD evaluation, the same decisions were used above for FA and M, and the following decisions were made for mismatch. If the gold annotation was empty, regardless of what the system returned, the mismatch rate was treated as 0. If the gold annotation was empty but a pipeline returned no TD labels (either because the SAD in that system did not detect any speech, or because the diarization failed), then this was penalized via a miss of 100 (as above), but not further penalized in terms of talker mismatch, which was set at 0. - -## Main references: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. -Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. - - - diff --git a/docs/source/furtherInfo.md b/docs/source/further-info.md similarity index 87% rename from docs/source/furtherInfo.md rename to docs/source/further-info.md index f6b2ab0..a509f7a 100755 --- a/docs/source/furtherInfo.md +++ b/docs/source/further-info.md @@ -1,6 +1,6 @@ # More information about DiViMe -DiViMe is a virtual machine, whose characteristics and contents are almost completely determined by provisioning scripts found in the DiViMe folder created when you did `git clone https://github.com/srvk/DiViMe/. This section provides information to help you understand the DiViMe structure in conceptual terms (the "pipeline"). We also explain the process of "bootstrapping" or creation of this virtual machine. Finally, we describe the folder structure. If you just want to use the tools in DiViMe, you can probably skip this whole section, or read just the `Pipeline structure` section. +DiViMe is a virtual machine, whose characteristics and contents are almost completely determined by provisioning scripts found in the DiViMe folder created when you did `git clone https://github.com/srvk/DiViMe/.` This section provides information to help you understand the DiViMe structure in conceptual terms (the "pipeline"). We also explain the process of "bootstrapping" or creation of this virtual machine. Finally, we describe the folder structure. If you just want to use the tools in DiViMe, you can probably skip this whole section, or read just the `Pipeline structure` section. ## Pipeline Structure diff --git a/docs/source/index.rst b/docs/source/index.rst index b9e52c7..dc387b7 100755 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,9 +13,10 @@ Welcome to DiViMe's documentation! initial_questions install usage - furterInfo + further-info formats tool_doc + extra-tools troubleshoot instructions_for_contributors references diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index 71c229c..930a5d0 100755 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -1,107 +1,197 @@ -# Contributing / Developing +# Instructions For Contributors +Temporary instructions: +We have reorganized DiViMe to try to facilitate tool incorporation and VM use, but these changes have not yet made it to the main branch. Therefore, all of the following instructions are NOT in the master branch, but in the major_reorganization branch. This should make no difference to you, except that you need to check out the right branch to view the VM fitting with these instructions. We provide the code for doing this below. +## Overview +This detailed guide provides you with step-by-step, specific instructions for adapting a tool into the DiViMe environment. The following is a Summary of the steps: +1) Install the VM for yourself +2) Adapt & test your tools in the VM environment, and build the necessary links to other modules. +3) Put your tools and all your custom scripts somewhere where they can be downloaded (e.g., GitHub repo(s)) +4) Create a bash script to download and install your tools on the VM (the same steps will be added to a Vagrantfile that controls the entire VM installation) +5) ... +## Before You Start -## Before you start +Before you start, you'll need to get the VM up and running to establish the environment in which your tool will run. -Before you start, you'll just generate the VM environment to check you can get your tool working as expected. +1. Install DiViMe as per the [installation instructions](https://divime.readthedocs.io/en/latest/install.html), including the `vagrant up` that wakes the machine up. -1. Install DiViMe as per the installation instructions, including the `vagrant up` that wakes the machine up. +Temporary instructions: +IMPORTANT: After you’ve cloned DiViMe, you should check out the major_reorganization branch, as follows: +``` +$ git checkout remotes/origin/major_reorganization +``` +If ever you want to go back to the master branch, you’d do: +``` +$ git checkout master +``` +If you’ve already built one version of the VM, you’ll need to do: +``` +vagrant destroy +vagrant up +``` + + +2. Run the test.sh routine routine. It downloads audio recordings and annotations that you will need to make sure your tool is compatible with the rest of the workflow. Additionally, it will help you spot any issues there may be in your local environment. + +## Understanding the general structure of DiViMe -2. Run the test.sh routine routine. It downloads audio recordings and annotations that you will need to make sure your tool is compatible with the rest of the work flow. Additionally, it will help you spot any issues there may be. +DiViMe is a virtual machine, whose characteristics and contents are almost completely determined by provisioning scripts found at the top level when you clone DiViMe. That means that if you want to contribute to DiViMe, you need to understand its structure, and bootstrapping of the virtual machine. -## Adapting your tool to the VM environment +In the next section, we will walk you through some stages of modifying the contents of the VM, which you will do initially “by hand”. However, remember the contents of the VM are actually built from reproducible directives ran when you do `vagrant up`. (In technical terms, when the VM is _provisioned_.) Therefore, any changes you make by hand when you are logged into the VM will be lost when you run `vagrant destroy`. Please bear that in mind when trying out the steps in the next section. -1. For this section, you'll be working entirely within the machine. So start by doing `vagrant ssh` to log in. +Additionally, by the end of these instructions you will be ready to propose a revised version of the VM - i.e., a new recipe to _provision_ the VM. Therefore, any changes made by hand that you wish to make permanent in the VM should eventually be added to a file called `util/bootstraph.sh`. So you may want to have a copy of bootstraph.sh open to make notes in there of the steps you take, which should be reproduced when provisioning the VM. -2. Ideally, you will put your tool somewhere public, so that anyone rebuilding the machine will get access to it. You don't need to make your code open source. You can also share a binary executable version (ask us for instructions if you need them). +## Adapting Your Tool to the VM Environment -3. Install your code in the location where it will be within the machine: +1. For this section, you'll be working almost entirely within the virtual machine. So start by doing `vagrant ssh` to log in. This logs you in as the `vagrant` user, which also has sudo privileges to do things like install software, change permissions, etc. in the virtual machine. +2. Decide where your tool is made available so that it can be copied into the VM. Ideally, it will be somewhere public, such as GitHub, so that anyone rebuilding the machine will get access to it. Alternatively, your tool might be stored on a server in a location you control, and then pulled into the virtual machine. Please note that the latter solution only preserves the anonymity of your code temporarily; if you get to the end of this document, when you are proposing a new version of the VM including your tool, then the URL needs to be known to the world, and accessible to everyone. Please note that neither alternative forces you to make your code open source. You can also share a binary executable (ask us for instructions if you need help). + +3. Import your tool into the VM. Once you have decided where to put your tool, install your code by hand in the location where it will be within the machine: `/home/vagrant/repos`. For example if your code is in a public GitHub repository `https://github.com/srvk/OpenSAT`, you would type into the terminal: ``` -cd repos +cd /home/vagrant/repos git clone http://github.com/srvk/OpenSAT ``` -4. Write a wrapper allowing users to call on your tool. - -- The wrapper should be written in bash, and it should be called toolnameStage.sh. -- You choose your own tool's name. Use anything you want except the other names already in use. -- The fixed stages names are: Sad (for both speech activity detection and voice activity detection), Diar (for speaker diarization and role assignment), and Add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use Sad) or the talker role input (then use Add). So for a tool with the toolname 'noisemes' for example, that performs speech activity detection, it's wrapper would be called `noisemesSad.sh` -- Read on for input/output requirements depending on stage. -- This flowchart may help: https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9 -- The wrapper will take at least one argument, namely the name of the folder where the data are stored. Most users will pass "data/" -- The wrapper should process all .wav files inside data/ and, optionally, associated annotation files, which are in rttm format. (For more information on the rttm output, read [NIST's 2009 eval plan](https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf)) -- The wrapper should write its main output into the data/ folder. Typically, this will be one annotation file for each .wav file. If so, this annotation file should respect the rttm format, in particular using the space character (not tab) as a field separator. -- Output files should be named as follows: toolnameStage_basename.rttm. So for example a tool named "noisemes" (toolname="noisemes") that does speech activity (Stage="Sad"), and an input file "RTM20.wav" (basename="RTM20" like the output of the linux command `basename RTM20.wav .wav`), the output filename would be `noisemesSad_RTM20.rttm` -- You probably also generate two types of ancillary files: Intermediary representation files, such as features extracted from the wav files; and log files, with detailed information of what was done and how. Both should be stored in the /vagrant/data/temp/ folder. At the end of the process, Intermediary representation files should be deleted at the end of your wrapper. Log files should also be deleted if they are large (>5MB). As a reminder, our target user may not be technically advanced, and thus including long technical logs may do more to confuse than to help. -- If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named according to the convention above, which will look like this: +If your tool is accessible via URL `https://toolnameurl.com/tool.zip`, you would type into the terminal: ``` -SPEAKER file17 1 0.00 0.77 speech -SPEAKER file17 1 1.38 2.14 speech +cd /home/vagrant/repos +wget -q -N https://toolnameurl.com/toolname.zip +unzip -q -o toolname.zip +``` +In bootstrap.sh, add the same code to make this step permanently reproducible. + + +4. If your code requires certain linux packages that are not installed, first install them ‘by hand’ in the VM with a command like `sudo apt-get install `. Any packages installed this way should be added similarly to one of the `apt-get` lines in bootstraph.sh like: +``` +sudo apt-get install -y libxt-dev libx11-xcb1 ``` -- If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the previous bulletpoint. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then use the default sad/vad (see end of instructions for list of default tools). In both cases, your wrapper should first check these sad/vad exist and if not, execute a command to generate them (see Instructions for use for instructions on how to use DiViMe's included tools). Your diarization-type tool should return one rttm per audio file, following the naming convention toolnameDiar_basename.rttm. For example a diarization tool named "talker" with input file "RTM20.wav" would produce the output filename `talkerDiar_RTM20.rttm`. The output RTTM must look like this: +5. The next step is to install additional dependencies, if any are needed. The VM already includes code to install OpenSmile 2.1, matlab v93, python 3, and anaconda 2.3.0. As in the two previous steps, you can do this by hand within the terminal, but you need to add the step to bootstraph.sh to make it permanent. For instance, if you need the python package `pympi-ling`, you would type `pip install pympi-ling` by hand into the terminal. Additionally, to make this change permanent (and have the dependencies installed when you reprovision the VM or when someone else rebuilds the VM), you need to add it to the Vagrantfile section where python packages are installed, with code like this: -** FIX this table ** ``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling” ``` -- If your tool is not a VAD/SAD but it is a classifier that assumes only raw acoustic input, then declare it as a sad/vad, and follow the instructions for vad/sad above, except that you'll adapt the rttm output to the classes you typically have. For example, one tool classifies audio into noiseme categories. It returns rttm's like this one: +## Write a Wrapper + +In this section, we provide detailed instructions for writing a wrapper that allows users to run your tool in a standardized way. The wrapper should be written in bash. Please look at the other launcher wrappers to have an idea of how to structure it, and read on for important considerations. -** todo: put example here, but make sure that the "type" class is not violated by the contents of the subtype column. For example, this is bad (noise should not be class SPEAKER):** +### Naming Conventions + +- You choose your own tool's name. Use anything you want except the other names already in use. We refer to your tool name later as ‘TOOLNAME’ +- It may be useful to you to decide at what “stage” of diarization your tool operates. A few things will be clearer if you have a good notion of when this is, such as the number of arguments and whether there is already an evaluation/scoring tool that can be re-used with your tool. We explain these things in more detail below. +- To facilitate end users’ understanding of what tool they are using, we have systematically added the stage name to the wrapper’s name, but you don’t have to follow this procedure if you think it will not be useful. +- We have identified three stages with a fixed name: Sad (for both speech activity detection and voice activity detection), Diar (for speaker diarization and role assignment), and Add (for adding annotation dependent on role assignment). +- Other stages or stage combinations do not have fixed names. But please feel free to use these stage names. For instance, if your tool only requires audio files as input, then you can use Sad; if it operates on both audio and speech activity detection, then use Diar; and if it is specific to one talker role as input, use Add. + +### Tool Autonomy + +Tools should be self-aware of where they have been installed, and they should use this awareness to find their dependencies. Said differently, a tool should run "in place" independent of the absolute path it's installed in. Tool dependency paths should be relative to the tool home folder, which should serve as the working directory. Again, please look at the other launcher wrappers to reuse the code present at the top of the wrappers, which correctly reconstructs the absolute path of this folder. + + +### Input, Output, and Parameters + + Your wrapper should take at least one argument, namely the name of a folder containing data. This folder is appended to “/vagrant” so from your script and the VM’s perspective, data appears in /vagrant/data/. This is actually a shared folder, coming from the host computer working directory. Everything in data/ on the host will in /vagrant/data in the VM, and vice-versa. The default wrapper argument, then, is typically "data/", but users could also supply “data/mystudy/” or “data/mystudy/baby1/” as the data folder argument. This supports the notion of having multiple datasets in different folders on the host. You can see how other wrappers use this, typically setting the variable `$audio_dir` to /vagrant/data. For the rest of this explanation, we’ll be referring to this folder as DATAFOLDER. +- The wrapper should process all .wav files inside DATAFOLDER and, optionally, associated annotation files, which are in rttm format. (For more information on the rttm output, read [NIST's 2009 eval plan](https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf)) +- Your wrapper should support processing long sound files. If you have no better way of achieving this, look to utils/chunk.sh as an example; it breaks up long files into smaller 5 minute chunks, then iteratively calls a tool (in this case, yours), and concatenates the results. +- Your tool must process many sound files. This may require some optimization, for example loading very large model files into memory for each sound file is less optimal than loading once, then iterating over many files. +- The wrapper should write its *main output* into DATAFOLDER. Typically, this will be one annotation file for each .wav file. If your tool does VAD, SAD, or diarization, this annotation file should respect the rttm format. Additionally, the output file it should be named according to the pattern: toolname_file_original_name.rttm. If your tool does something other than VAD, SAD, or diarization, use a format that seems reasonable to you. If your tool returns results on individual files (and not e.g., summary statistics over multiple files), we still ask you to name the file toolnameStage_file_original_name.ext -- where “ext” is any extension that is reasonable for the annotation format you have chosen. +- You probably also generate two types of ancillary files: Intermediary representation files, such as features extracted from the wav files; and log files, with detailed information of what was done and how. Both should be initially stored in the DATAFOLDER/temp/TOOLNAME folder. +- Intermediary representation files should be deleted -- with one exception, introduced below. +- It is a good idea to print out a short log accompanying each batch of files analyzed, stating the key parameters, version number, and preferred citation. You may want to write out a lot more information. However, our target user may not be technically advanced, and thus including long technical logs may do more to confuse than to help. Log files should also be deleted if they are large (>5MB) -- with one exception, introduced next. +- Your wrapper should expect an optional argument “--keep-temp”, which is optionally passed in final position. If the last argument to the wrapper is not “--keep-temp”, then ancillary files should be deleted. Code snippet example: ``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi +… +if ! $KEEPTEMP; then + rm -rf $MYTEMP +fi ``` + See any script in `launcher/` for examples. -- If your tool is a classifier that works only on a subtype of speaker (e.g., only on children's speech), then assume that each wav is accompanied by an rttm that has this information noted in column XX. +## Document Your Tool +Add a documentation file to the `DiViMe/docs/` folder on your host, in markdown format, containing at least the following three pieces of information: +A one-paragraph explanation of what your tool does +A reference or citation that people using your tool must employ +A short section explaining how to use it. This will typically include a description of input & output formats, which can be replaced with references to the Format section of the docs. You should also include an example command line of how to run the tool. Often, this will be `vagrant ssh ‘toolname.sh data/`. +Please include any other information that would be useful to users, such as what parameters are available, how to access them, a tiny example input and output, further technical information on how the tool was built, additional references for work using this tool or on which the tool was built, etc. -** todo: add default tool section** +For an example, see the tocomboSad section in the [tools documentation](https://divime.readthedocs.io/en/latest/tool_doc.html). -** todo: address "process multiple files in parallel, if possible (like using sbatch?)"** +## Create a Reproducible Test for Your Tool +DiViMe comes equipped with a test script that downloads a publicly available daylong audio file and transcript, which all tools within DiViMe can process (and many can be evaluated). In this section, we provide instructions for you to add your tool to the test.sh routine. +By default, all launchers are read-only to avoid accidental editing by newbie users. For the next step, you need to change file permissions so as to be able to edit test.sh. From the host machine, type into the terminal: -## Integrating your tool into DiViMe for real +``` +chmod +rw test.sh +``` + +Open the file test.sh, which is inside the launcher folder, and add a section testing your tool, modeling it on the other tests present there. Typically, you will need these lines: + +Under “# Paths to Tools” add a line with the path to your tool, eg: +TOOLNAMEDIR=$REPOS/TOOLNAME + +b) Before “# test finished”, add a section like the following: + +Example for a Sad type tool: +``` +echo "Testing TOOLNAME..." +cd $TOOLNAMEDIR +TESTDIR=$WORKDIR/TOOLNAME-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +$LAUNCHERS/toolnameStage.sh $DATADIR/TOOLNAME-test >$TESTDIR/TOOLNAME-test.log || { echo " TOOLNAME failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/toolnameStage_$BASETEST.rttm ]; then + echo "TOOLNAME passed the test." +else + FAILURES=true + echo " TOOLNAME failed - no RTTM output" +fi +``` +In the above example: +`DATADIR` is predefined as the test 5 minute data folder `data/VanDam-Daylong/BN32` +`TOOLNAME` is whatever human readable name you have given your tool +`toolnameStage` is the pattern for the system/launcher name for your tool, for example `opensmileSad` +`BASETEST` is the basename of a test input file e.g. `BN32_010007_test` for the 5 minute input file `BN32_010007_test.wav` -fork our divime repo -add a line to clone your repo -add lines to add to the environment any dependencies needed -add an md with short description, citation, and instructions for use -pull request -fork our launcher repo -add your wrapper -add a section to the test specific to your tool -pull request +Example for a Diar type tool: +** todo: complete** +Example for an Add type tool: +** todo: complete** -## Updating the documentation -The documentation is written in markdown and compiled into a website using sphynx. -The source of the documentation is in the shared directory ```docs/source```; once rebuilt -locally, the html is in ```docs/build/html/index.html``` + Run test.sh. Only proceed to the next phase if your tool passes the test. -Developers can modify the doc and recompile locally it using: +## Check reproducibility of your version of the VM by reprovisioning + +Throughout the steps above, you have modified `Vagrantfile/bootstrap.sh` to automatically install your code, any required packages, and any required dependencies. If you have been keeping your Vagrantfile/bootstrap.sh in a good state, you should be able to rebuild your version of the virtual machine from scratch. +If necessary, log out from the virtual machine with control+D. Then, from the host machine, run the following code to destroy, re-build, and re-run the test: ``` -vagrant ssh -c "cd /vagrant/docs; make html" +vagrant destroy +vagrant up +vagrant ssh -c “test.sh” ``` -once they are happy with the result, they can commit their changes as described above. +*WARNING:* any changes you made by hand when you were logged into the VM will be lost when you run `vagrant destroy`: to make sure they show up automatically with `vagrant up`, all such dependencies need to be automated (added to Vagrantfile/bootstrap.sh). +If your tool passes the test in this condition, you are ready to integrate your tool to DiViMe for real. +## Integrate Your Tool Into the Public Version of DiViMe +1. Fork the DiViMe repo +2. Feplace Vagrantfile/bootstrap.sh with your version of Vagrantfile/bootstrap.sh +3. Add in the docs/ your tool’s doc +4. Add your wrapper to launcher/ +5. Replace test.sh with your version containing an additional test case specific to your tool +6. Create a pull request to DiViMe requesting your additions be incoporated diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index d7934d6..49318c6 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -306,17 +306,16 @@ There is no official reference for this tool. https://github.com/MilesICL/vcm/issues/ -## TalNet +# Evaluation -### General intro +## Speech/voice activity detection and diarization evaluation -There is no information on this tool. +For SAD, we employ an evaluation, which returns the false alarm (FA) rate (proportion of frames labeled as speech that were non-speech in the gold annotation) and missed speech rate (proportion of frames labeled as non-speech that were speech in the gold annotation). For TD, we employ the evaluation developed for the DiHARD Challenge, which returns a Diarization error rate (DER), which sums percentage of speaker error (mismatch in speaker IDs), false alarm speech (non-speech segments assigned to a speaker) and missed speech (unassigned speech). -### Main references: +One important consideration is in order: What to do with files that have no speech to begin with, or where the system does not return any speech at the SAD stage or any labels at the TD stage. This is not a case that is often discussed in the literature because recordings are typically targeted at moments where there is speech. However, in naturalistic recordings, some extracts may not contain any speech activity, and thus one must adopt a coherent framework for the evaluation of such instances. We opted for the following decisions. -There is no official reference for this tool. +If the gold annotation was empty, and the SAD system returned no speech labels, then the FA = 0 and M = 0; but if the SAD system returned some speech labels, then FA = 100 and M = 0. Also, if the gold annotation was not empty and the system did not find any speech, then this was treated as FA = 0 and M=100. -### Questions and bug reports +As for the TD evaluation, the same decisions were used above for FA and M, and the following decisions were made for mismatch. If the gold annotation was empty, regardless of what the system returned, the mismatch rate was treated as 0. If the gold annotation was empty but a pipeline returned no TD labels (either because the SAD in that system did not detect any speech, or because the diarization failed), then this was penalized via a miss of 100 (as above), but not further penalized in terms of talker mismatch, which was set at 0. -Not available From a03d6efda89ee0d31ba3c2e34c14aedb7300e703 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 10:56:04 -0500 Subject: [PATCH 115/299] minor --- docs/source/install.md | 6 ++---- docs/source/troubleshoot.md | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 48a9924..8f01f1c 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -36,10 +36,8 @@ The very first time you use DiViMe, it is a good idea to run a quick start test, 1. Open a terminal 2. Navigate inside the DiViMe folder -3. Do -`$ vagrant up` -4. Do -`$ vagrant ssh -c "launcher/test.sh"` +3. Do `$ vagrant up` +4. Do `$ vagrant ssh -c "launcher/test.sh"` This should produce the output: diff --git a/docs/source/troubleshoot.md b/docs/source/troubleshoot.md index 7fa47b8..72b1237 100755 --- a/docs/source/troubleshoot.md +++ b/docs/source/troubleshoot.md @@ -28,7 +28,7 @@ You can now try again with `vagrant up` ## Problems with some of the Tools ### LDC SAD, OpenSmile, DiarTK -If ldcSad, OpenSmile, DiarTK don't seem to work after vagrant up, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: +If ldcSad, OpenSmile, DiarTK don't seem to work after `vagrant up`, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: ``` vagrant up --provision ``` From 39f2a72694e8909942d927dfed62b70522545f96 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 11:01:45 -0500 Subject: [PATCH 116/299] step 1 of getting rid of ldcsad --- conf/bootstrap.sh | 4 ---- conf/update.sh | 2 -- launcher/README.md | 1 - launcher/diartk.sh | 6 ------ launcher/eval.sh | 3 +-- launcher/evalDiar.sh | 15 +++++---------- launcher/python3/test.sh | 36 ------------------------------------ launcher/test.sh | 34 ---------------------------------- 8 files changed, 6 insertions(+), 95 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 27bd7fc..c36f299 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -139,10 +139,6 @@ su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" cp /vagrant/conf/.theanorc /home/${user}/ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" -# Install ldc-sad -# run this version 'by hand' in the VM in repos/ using your github username and password -#git clone http://github.com/aclew/ldc_sad_hmm - # Install Yunitator and dependencies git clone https://github.com/srvk/Yunitator su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" diff --git a/conf/update.sh b/conf/update.sh index 84a7b28..aec01e7 100644 --- a/conf/update.sh +++ b/conf/update.sh @@ -8,11 +8,9 @@ fi echo "Check git updates" ############################################# # Get OpenSAT and all the tools -# Install DiarTK, LDC SAD, LDC scoring, Rajat's LENA stuff cd /home/${user}/repos (cd "OpenSAT"; git pull) (cd "ib_diarization_toolkit" ; git pull) -#(cd "ldc_sad_hmm" ; git pull) (cd "dscore" ; git pull) (cd "Yunitator" ; git pull) (cd "vcm"; git pull) diff --git a/launcher/README.md b/launcher/README.md index f4f9ad6..aeec698 100755 --- a/launcher/README.md +++ b/launcher/README.md @@ -5,7 +5,6 @@ This repository contains scripts that launch tools in the ACLEW Diarization VM. ### SAD tools ``` -ldcSad.sh noisemesSad.sh opensmileSad.sh tocomboSad.sh diff --git a/launcher/diartk.sh b/launcher/diartk.sh index cdcb65b..8c96a48 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -11,7 +11,6 @@ if [ $# -lt 1 ] || [ $# -gt 3 ]; then echo "where audio-dir is the name of the folder" echo "containing the wav files" echo "and is one of:" - echo " ldcSad" echo " noisemesSad" echo " tocomboSad" echo " opensmileSad" @@ -59,10 +58,6 @@ for fin in `ls $audio_dir/*.wav`; do # Type file chan tbeg tdur ortho stype name conf Slat # math: convert RTTM seconds to HTK (10ms default) frames = multiply by 100 case $trs_format in - "ldcSad") - sys="ldcSad" - python $UTILS/rttm2scp.py $audio_dir/ldcSad_${basename}.rttm $scpfile - ;; "noisemesSad") sys="noisemesSad" python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile @@ -97,7 +92,6 @@ for fin in `ls $audio_dir/*.wav`; do ;; *) echo "ERROR: please choose SAD system between:" - echo " ldcSad" echo " noisemesSad" echo " tocomboSad" echo " opensmileSad" diff --git a/launcher/eval.sh b/launcher/eval.sh index 8e3e23c..10410ec 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -20,7 +20,6 @@ display_usage() { echo "where data is the folder containing the data" echo "and system is the system you want" echo "to evaluate. Choices are:" - echo " ldcSad" echo " noisemesSad" echo " tocomboSad" echo " opensmileSad" @@ -45,7 +44,7 @@ fi ### SCRIPT STARTS case $system in -"tocomboSad"|"opensmileSad"|"ldcSad"|"noisemesSad|lenaSad") +"tocomboSad"|"opensmileSad"|"noisemesSad|lenaSad") sh $LAUNCHER/evalSAD.sh $audio_dir $system $KEEPTEMP ;; "yunitate"|"lenaDiar") diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index e2f2eef..a922630 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -18,7 +18,6 @@ display_usage() { echo " - diartk" echo " - yunitate" echo "Transcription (mandatory for model == diartk) choices are:" - echo " ldc_sad" echo " noisemes" echo " opensmile" echo " tocombosad" @@ -52,16 +51,13 @@ model=$2 if [[ $model =~ ^(diartk|yuniseg) ]]; then trs_format=$3 case $trs_format in - "ldc_sad") - sys_name=$model"_ldcSad" - ;; - "noisemes") + "noisemesSad") sys_name=$model"_noisemesSad" ;; - "tocombosad") + "tocomboSad") sys_name=$model"_tocomboSad" ;; - "opensmile") + "opensmileSad") sys_name=$model"_opensmileSad" ;; "textgrid") @@ -82,9 +78,8 @@ if [[ $model =~ ^(diartk|yuniseg) ]]; then sys_name=$model"_goldSad" ;; *) - echo "ERROR: You're trying to evaluate diartk, but the transcription system you specified is not recognized :" - echo " ldc_sad" - echo " noisemes" + echo "ERROR: You're trying to evaluate diartk, but the speech activity detection you specified is not recognized:" + echo " noisemesSad" echo " textgrid" echo " eaf" echo " rttm" diff --git a/launcher/python3/test.sh b/launcher/python3/test.sh index 61d67ed..de35bc2 100644 --- a/launcher/python3/test.sh +++ b/launcher/python3/test.sh @@ -21,7 +21,6 @@ export REPOS=/home/vagrant/repos export UTILS=/home/vagrant/utils # Paths to Tools -LDC_SAD_DIR=$REPOS/ldc_sad_hmm export OPENSATDIR=$REPOS/OpenSAT # noisemes OPENSMILEDIR=$REPOS/openSMILE-2.1.0/ TOCOMBOSAD=$REPOS/To-Combo-SAD @@ -76,24 +75,6 @@ else echo " and rename it to HTK.tar.gz ?" fi -# First test in ldc_sad_hmm -echo "Testing LDC SAD..." -if [ -s $LDC_SAD_DIR/perform_sad.py ]; then - cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/ldc_sad-test - rm -rf $TESTDIR; mkdir -p $TESTDIR - python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} - # convert output to rttm, for diartk. - grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm - if [ -s $TESTDIR/$BASETEST.rttm ]; then - echo "LDC SAD passed the test." - else - FAILURES=true - echo " LDC SAD failed - no output RTTM" - fi -else - echo " LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" -fi # now test Noisemes @@ -206,23 +187,6 @@ fi git checkout master -# testing LDC evalSAD (on opensmile) -echo "Testing LDC evalSAD" -if [ -d $LDC_SAD_DIR ]; then - cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/opensmile-test - cp $WORKDIR/$BASETEST.rttm $TESTDIR - $LAUNCHERS/eval.sh $DATADIR/opensmile-test opensmileSad $KEEPTEMP > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} - if [ -s $TESTDIR/opensmileSad_eval.df ]; then - echo "LDC evalSAD passed the test" - else - echo " LDC evalSAD failed - no output .df" - FAILURES=true - fi -else - echo " LDC evalSAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" - FAILURES=true -fi # test finished diff --git a/launcher/test.sh b/launcher/test.sh index 4f960a7..15a105d 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -21,7 +21,6 @@ REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils # Paths to Tools -LDC_SAD_DIR=$REPOS/ldc_sad_hmm OPENSATDIR=$REPOS/OpenSAT # noisemes OPENSMILEDIR=$REPOS/opensmile-2.3.0/ TOCOMBOSAD=$REPOS/To-Combo-SAD @@ -86,22 +85,6 @@ rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR cp $WORKDIR/$BASETEST.rttm $TESTDIR -# First test in ldc_sad_hmm -echo "Testing LDC SAD..." -if [ -s $LDC_SAD_DIR/perform_sad.py ]; then - cd $LDC_SAD_DIR - - $LAUNCHERS/ldcSad.sh $DATADIR/test $KEEPTEMP >& $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} - - if [ -s $TESTDIR/$BASETEST.rttm ]; then - echo "LDC SAD passed the test." - else - FAILURES=true - echo " LDC SAD failed - no output RTTM" - fi -else - echo " LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" -fi # now test Noisemes @@ -194,23 +177,6 @@ else fi -# testing LDC evalSAD (on opensmile) -echo "Testing LDC evalSAD" -if [ -d $LDC_SAD_DIR ]; then - cd $LDC_SAD_DIR - - $LAUNCHERS/eval.sh $DATADIR/test opensmileSad $KEEPTEMP > $WORKDIR/test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} - if [ -s $TESTDIR/opensmileSad_eval.df ]; then - echo "LDC evalSAD passed the test" - else - echo " LDC evalSAD failed - no output .df" - FAILURES=true - fi -else - echo " LDC evalSAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" - FAILURES=true -fi - # Testing VCM echo "Testing VCM..." From 7f8d930db637c5668ea1baeaca9fd9dd9c930716 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 11:21:43 -0500 Subject: [PATCH 117/299] added doc building at end of bootstrap --- conf/bootstrap.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index c36f299..ab84865 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -203,3 +203,6 @@ if ! $HTK_INSTALLED; then echo "Warning: HTK is not installed" echo "*****************************" fi + +# Build the docs +cd /vagrant/docs && make html From 7e6545fcbef16087b8575a939927bdfbe56d129b Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 11:29:40 -0500 Subject: [PATCH 118/299] removing ldc --- docs/source/install.md | 5 +---- docs/source/references.md | 1 - docs/source/tool_doc.md | 20 -------------------- docs/source/troubleshoot.md | 8 ++++---- docs/source/usage.md | 9 ++++----- 5 files changed, 9 insertions(+), 34 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 8f01f1c..5934950 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -42,8 +42,6 @@ The very first time you use DiViMe, it is a good idea to run a quick start test, This should produce the output: ``` -Testing LDC SAD... -LDC SAD passed the test. Testing Speech Activity Detection Using Noisemes... Noisemes passed the test. @@ -64,8 +62,7 @@ Congratulations, everything is OK! ## Common installation errors and fixes -- For ldcSad, you may get an error "ldcSad failed because the code for ldcSad is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include ldcSad. This error means that you cannot use ldcSad, but you can use any other SAD/VAD. (For example, noisemesSad.) -- For ldcSad, noisemesSad, and diartkDiar, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the +- For noisemesSad, and diartkDiar, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. diff --git a/docs/source/references.md b/docs/source/references.md index 7fda6a7..566dbed 100755 --- a/docs/source/references.md +++ b/docs/source/references.md @@ -8,7 +8,6 @@ Our work builds directly on that of others. The main references for tools curren - Eyben, F. Weninger, F., Gross, F. & B. Schuller. (2013). Recent developments in opensmile, the munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. - Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013, May). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. - Räsänen, O., Seshadri, S., & Casillas, M. (2018, June). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. In Interspeech 2018. -- Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. - Sadjadi, S.O. & Hansen, J.H.L. (2013). Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux. IEEE Signal Processing Letters, 20(3), 197-200. - VanDam, M., & Tully, T. (2016, May). Quantity of mothers’ and fathers’ speech to sons and daughters. Talk presented at the 171st Meeting of the Acoustical Society of America, Salt Lake City, UT. - Vijayasenan, D. & Valente, F. (2012) Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings. Thirteenth Annual Conference of the International Speech Communication Association, 2012. diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index 49318c6..eaa8586 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -3,26 +3,6 @@ This section contains documentation from the different Speech or Voice activity detection tools. -## LDC SAD - -### General intro - -LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. - -### Main references: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. - - -### Associated references: - -Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. -Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. - -### Questions and bug reports - -Not available - ## NoisemesSad ### General intro diff --git a/docs/source/troubleshoot.md b/docs/source/troubleshoot.md index 72b1237..1766f17 100755 --- a/docs/source/troubleshoot.md +++ b/docs/source/troubleshoot.md @@ -26,13 +26,13 @@ You can now try again with `vagrant up` ## Problems with some of the Tools -### LDC SAD, OpenSmile, DiarTK +### OpenSmile, DiarTK -If ldcSad, OpenSmile, DiarTK don't seem to work after `vagrant up`, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: +If OpenSmile, DiarTK don't seem to work after `vagrant up`, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: ``` vagrant up --provision ``` -This step will install HTK inside the VM, which is used by several tools including ldcSad. +This step will install HTK inside the VM, which is used by several tools. ### Noisemes If you use the noisemesSad or the noisemes_full tool, one problem you may encounter is that it doesn't treat all of your files and gives you an error that looks like this: @@ -45,7 +45,7 @@ Traceback (most recent call last): MemoryError ``` If this happens to you, it's because you are trying to treat more data than the system/your computer can handle. -What you can do is simply put the remaining files that weren't treated in a seperate folder and treat this folder seperately (and do this until all of your files are treated if it happens again on very big datasets). +What you can do is simply put the remaining files that weren't treated in a separate folder and treat this folder separately (and do this until all of your files are treated if it happens again on very big datasets). After that, you can put back all of your data in the same folder. ### Input Format For Transcriptions diff --git a/docs/source/usage.md b/docs/source/usage.md index 8ccb439..892ccd8 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -50,7 +50,7 @@ Remember that you will be using a mini-computer within your computer. Typically, If all tools passed the test, then you'll be able to automatically add the following types of annotation to your audio files: -1) Speech activity detection (_when is someone talking?_): The tools available for this task are the following: noisemesSad, tocomboSad, opensmileSad, ldcSad +1) Speech activity detection (_when is someone talking?_): The tools available for this task are the following: noisemesSad, tocomboSad, opensmileSad 2) Talker diarization (_who is talking?_) The tools available for this task are the following: diartkDiar @@ -58,7 +58,7 @@ If all tools passed the test, then you'll be able to automatically add the follo 4) Vocal type classification (_what kind of vocalization is this one?_) The tools available for this task are the following: vcm -5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, ldcSad, diartkDiar, yunitator +5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, diartkDiar, yunitator ### Overview of "pipelines" @@ -89,7 +89,7 @@ You can read that command as follows: *vagrant ssh -c*: This tells DiViMe that it needs to run a tool. -*noisemesSad.sh*: This first argument tells DiViMe which tool to run. The options are: noisemesSad.sh, tocomboSad.sh, opensmileSad.sh, ldcSad.sh +*noisemesSad.sh*: This first argument tells DiViMe which tool to run. The options are: noisemesSad.sh, tocomboSad.sh, opensmileSad.sh *data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. @@ -133,7 +133,7 @@ You can read that command as follows: *noisemesSad*: Remember that this tool does "talker diarization": Given some speech, attribute it to a speaker. Therefore, this type of tool necessitates speech/voice activity detection. This third argument tells DiViMe what file contains information about which sections of the sound file contain speech. -You can only use one of the following options: textgrid, eaf, rttm, ldcSad, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. +You can only use one of the following options: textgrid, eaf, rttm, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. You can provide annotations done by a human or in some other way, and encoded as one of the following three file types: @@ -144,7 +144,6 @@ You can provide annotations done by a human or in some other way, and encoded as Alternatively, you can provide use automatic annotations generated by DiViMe's speech/voice activity detection systems, encoded in rttm files. In this case, you would pass one of the following options: -- ldcSad: this means you want the system to use the output of the ldcSad system. If you have not run this system before, the system will fail. - this system before: this means you want the system to use the output of the noisemesSad system. If you have not run noisemesSad, the system will fail. - opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run this system before, the system will fail. - tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran this system before, the system will fail. From 66e36f3242a02eaba574777f5a2e13379c31335f Mon Sep 17 00:00:00 2001 From: MarvinLavechin Date: Thu, 29 Nov 2018 18:10:41 +0100 Subject: [PATCH 119/299] Improved eaf2enriched_txt.sh by allowing the user to enrich just one file --- utils/eaf2enriched_txt.sh | 28 +++++++++++++++++++++++----- utils/eaf2txt.py | 1 - utils/speech_extractor.py | 0 3 files changed, 23 insertions(+), 6 deletions(-) mode change 100644 => 100755 utils/speech_extractor.py diff --git a/utils/eaf2enriched_txt.sh b/utils/eaf2enriched_txt.sh index 26c3ff0..30b09c9 100755 --- a/utils/eaf2enriched_txt.sh +++ b/utils/eaf2enriched_txt.sh @@ -1,5 +1,5 @@ #!/bin/bash -INPUT_FOLDER=$1 +INPUT=$1 LANG=$2 SCRIPT_DIR=$(dirname "$0") @@ -15,7 +15,7 @@ display_usage() { echo -e "\t number of syllables" echo "usage: $0 [input] [language]" - echo " input The folder where to find the eaf files (REQUIRED)." + echo " input The folder where to find the eaf files, or the single eaf file (REQUIRED)." echo " output The language of the transcription : english, spanish or tzeltal (REQUIRED)." exit 1 } @@ -24,8 +24,9 @@ if [ -z "$1" ] || [ -z "$2" ] || ! [[ $LANG =~ ^(english|spanish|tzeltal)$ ]]; t display_usage fi -for eaf_path in /vagrant/$1/*.eaf; do - eaf_path=${eaf_path#/vagrant/} +if [ -f "/vagrant/"$1 ]; then + echo "File found." + eaf_path=${1#/vagrant/} without_extension="${eaf_path%.*}" echo "Converting $eaf_path files to ${without_extension}.txt ..." python $SCRIPT_DIR/eaf2txt.py -i $eaf_path @@ -34,4 +35,21 @@ for eaf_path in /vagrant/$1/*.eaf; do $SCRIPT_DIR/selcha2clean.sh ${without_extension}.txt ${without_extension}_enriched.txt $LANG rm /vagrant/${without_extension}.txt -done \ No newline at end of file +elif [ -d "/vagrant/"$1 ]; then + echo "Directory found." + for eaf_path in /vagrant/$1/*.eaf; do + eaf_path=${eaf_path#/vagrant/} + without_extension="${eaf_path%.*}" + echo "Converting $eaf_path files to ${without_extension}.txt ..." + python $SCRIPT_DIR/eaf2txt.py -i $eaf_path + + echo "Enriching ${without_extension}.txt" + $SCRIPT_DIR/selcha2clean.sh ${without_extension}.txt ${without_extension}_enriched.txt $LANG + + rm /vagrant/${without_extension}.txt + done +else + echo "File or directory not found." + display_usage +fi; + diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py index 354df99..56ca2d5 100755 --- a/utils/eaf2txt.py +++ b/utils/eaf2txt.py @@ -74,7 +74,6 @@ def main(): data_dir = '/vagrant' args.input = os.path.join(data_dir, args.input) output = os.path.join(data_dir, output) - if not os.path.isdir(output): os.mkdir(output) diff --git a/utils/speech_extractor.py b/utils/speech_extractor.py old mode 100644 new mode 100755 From da74a791c6274eddcee7d56b8288f6e1bfa95198 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Thu, 29 Nov 2018 14:09:06 -0500 Subject: [PATCH 120/299] remove display of evalSAD output --- launcher/test.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 15a105d..cc0485a 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -202,6 +202,4 @@ echo "RESULTS:" for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done echo "DSCORE:" cat /vagrant/data/VanDam-Daylong/BN32/test/test.df -echo "EVAL_SAD:" -cat $WORKDIR/test/opensmileSad_eval.df From 567e94e0e8d79ad0cac6c686f99c6f83764ea498 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 14:13:43 -0500 Subject: [PATCH 121/299] removing ldc --- docs/source/install.md | 9 ++++- docs/source/tool_doc.md | 2 +- docs/source/usage.md | 6 ++- launcher/evalDiar.sh | 27 ++++++------- launcher/evalSAD.sh | 87 ----------------------------------------- launcher/ldcSad.sh | 54 ------------------------- 6 files changed, 26 insertions(+), 159 deletions(-) delete mode 100755 launcher/evalSAD.sh delete mode 100755 launcher/ldcSad.sh diff --git a/docs/source/install.md b/docs/source/install.md index 5934950..cec6f6f 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -55,6 +55,13 @@ Threshold Optimized Combo SAD passed the test. Testing DiarTK... DiarTK passed the test. +Testing Yunitator... +Yunitator passed the test. + +Testing DScore... +Yunitator passed the test. + + Congratulations, everything is OK! ``` @@ -62,7 +69,7 @@ Congratulations, everything is OK! ## Common installation errors and fixes -- For noisemesSad, and diartkDiar, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the +- For noisemesSad, and diartk, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index eaa8586..921a233 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -7,7 +7,7 @@ This section contains documentation from the different Speech or Voice activity ### General intro -Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. +Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. The original method in Wang et al. (2016) used 983 features selected using information gain criterion, but we used an updated version from authors Y. Wang and F. Metze in this paper. diff --git a/docs/source/usage.md b/docs/source/usage.md index 892ccd8..120dd57 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -52,13 +52,13 @@ If all tools passed the test, then you'll be able to automatically add the follo 1) Speech activity detection (_when is someone talking?_): The tools available for this task are the following: noisemesSad, tocomboSad, opensmileSad -2) Talker diarization (_who is talking?_) The tools available for this task are the following: diartkDiar +2) Talker diarization (_who is talking?_) The tools available for this task are the following: diartk 3) Role diarization (_what kind of person is talking?_) The tools available for this task are the following: yunitator 4) Vocal type classification (_what kind of vocalization is this one?_) The tools available for this task are the following: vcm -5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, diartkDiar, yunitator +5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, diartk, yunitator ### Overview of "pipelines" @@ -207,6 +207,8 @@ It returns one rttm per sound file, with an estimation of where there are vocali ### How to run a Vocalization classification tool +vcm + NO INFORMATION YET ### How to run an Evaluation diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index a922630..87babc3 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -9,26 +9,25 @@ DSCOREDIR=$(dirname $BASEDIR)/dscore display_usage() { - echo "Usage: evalDiar.sh <>" + echo "Usage: evalDiar.sh " echo "where dirname is the name of the folder" - echo "containing the wav files, and transcription" - echo "specifies which transcription you want to use," - echo "only used if model == diartk." - echo "Model choices are :" - echo " - diartk" + echo "containing the wav files, and system" + echo "specifies which system you want to evaluate" + echo "System choices are :" + echo " - noisemesSad" + echo " - opensmileSad" + echo " - tocomboSad" + echo " - diartk_noisemesSad" + echo " - diartk_opensmileSad" + echo " - diartk_tocomboSad" + echo " - diartk_rttm" echo " - yunitate" - echo "Transcription (mandatory for model == diartk) choices are:" - echo " noisemes" - echo " opensmile" - echo " tocombosad" - echo " textgrid" - echo " eaf" - echo " rttm" + echo " - lena" exit 1; } -if ! [[ $2 =~ ^(diartk|yunitate|lena)$ ]] || [ "$2" == "diartk" ] && [ $# -lt 3 ]; then +if ! [[ $2 =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lena)$ ]] ]; then display_usage fi diff --git a/launcher/evalSAD.sh b/launcher/evalSAD.sh deleted file mode 100755 index 2ca23c2..0000000 --- a/launcher/evalSAD.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash -# Launcher onset routine -SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $SCRIPT` # folder where this script resides. Useless. -REPOS=/home/vagrant/repos -UTILS=/home/vagrant/utils -# end of launcher onset routine - - -### Read in variables from user -# data directory -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" - -# check system to evaluate -system=$2 - -KEEPTEMP=false -if [ $BASH_ARGV == "--keep-temp" ]; then - KEEPTEMP=true -fi - - -### Other variables specific to this script -# Path to scoring tool NOTE: NOT dscore! -ldcSad_DIR=$REPOS/ldc_sad_hmm -# create temp dir -workdir=$audio_dir -mkdir -p $workdir - - -### SCRIPT STARTS -if [[ $system = "ldcSad" ]]; then - sys_name="ldcSad" -elif [[ $system = "noisemesSad" ]]; then - sys_name="noisemesSad" -elif [[ $system = "tocomboSad" ]]; then - sys_name="tocomboSad" -elif [[ $system = "opensmileSad" ]]; then - sys_name="opensmileSad" -elif [[ $system = "lenaSad" ]]; then - sys_name="lenaSad" - -else - echo "Please Specify the System you wish to evaluate." - echo "Choose between ldcSad, noisemeSad, tocomboSad, opensmileSad, lenaSad." - exit -fi - - -# Set CWD to path of scoring tool -cd $ldcSad_DIR - -echo $UTILS/create_ref_sys.sh $1 $sys_name true -$UTILS/create_ref_sys.sh $1 $sys_name true - -echo "evaluating" -# python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys -# create /vagrant/results if it doesn't exist -echo "filename DCF FA MISS" > $audio_dir/${sys_name}_eval.df -for lab in `ls $workdir/temp_sys/*.lab`; do - base=$(basename $lab .lab) - if [ ! -s $workdir/temp_ref/$base.lab ]; then - if [ ! -s $workdir/temp_sys/$base.lab ]; then - echo $base" 0.00% 0.00% 0.00%" >> $audio_dir/${sys_name}_eval.df - else - echo $base" 25.00% 100.00% 0.00%" >> $audio_dir/${sys_name}_eval.df - fi - elif [ ! -s $workdir/temp_sys/$base.lab ] && [ -s $workdir/temp_ref/$base.lab ]; then - echo $base" 75.00% 0.00% 100.00%" >> $audio_dir/${sys_name}_eval.df - else - python score.py $workdir/temp_ref $lab | awk -v var="$base" -F" " '{if ($1=="DCF:") {print var"\t"$2"\t"$4"\t"$6}}' >> $audio_dir/${sys_name}_eval.df - fi - -done -# small detail: remove the commas from the output -sed -i "s/,//g" $audio_dir/${sys_name}_eval.df -echo "done evaluating, check $1/${sys_name}_eval.df for the results" - -# remove temps -if ! $KEEPTEMP; then - rm -rf $workdir/temp_ref $workdir/temp_sys -fi - diff --git a/launcher/ldcSad.sh b/launcher/ldcSad.sh deleted file mode 100755 index 3f5d2c9..0000000 --- a/launcher/ldcSad.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# Launcher onset routine -SCRIPT=$(readlink -f $0) -BASEDIR=/home/vagrant -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -# end of launcher onset routine - -### Read in variables from user -audio_dir=/vagrant/$1 - -### Other variables specific to this script -LDC_SAD_DIR=$REPOS/ldc_sad_hmm -workdir=$audio_dir/temp/diartk -mkdir -p $workdir - -### SCRIPT STARTS -if [ $# -lt 1 ]; then - echo "Usage: ldcSad.sh " - echo "where dirname is the name of the folder" - echo "containing the wav files" - exit 1 -fi - -KEEPTEMP=false -if [ $BASH_ARGV == "--keep-temp" ]; then - KEEPTEMP=true -fi - -# Check audio_dir to see if empty or if contains empty wav -bash $UTILS/check_folder.sh $audio_dir - -# Set CWD as LDC_SAD_HMM -cd $LDC_SAD_DIR - -# launch ldc -python perform_sad.py -L $workdir $audio_dir/*.wav -echo "finished using ldcSad_hmm. Please look inside $1 to see the output in *.rttm format" - -# move all files to name them correctly -for wav in `ls $audio_dir/*.wav`; do - # retrieve filename and remove .wav - base=$(basename $wav .wav) - rttm_out=$workdir/ldcSad_${base}.rttm - if [ -s $workdir/${base}.lab ]; then - grep ' speech' $workdir/${base}.lab | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $rttm_out - else - touch $rttm_out - fi -done - -if ! $KEEPTEMP; then - rm -rf $workdir -fi From e6bc27583144bbc993e467faf07bd3e7adbe0ad8 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 14:16:59 -0500 Subject: [PATCH 122/299] fixed _s to S errors --- launcher/diartk.sh | 6 +++--- launcher/noisemesSad.sh | 5 ++--- launcher/python3/noisemesSad.sh | 5 ++--- launcher/python3/test.sh | 2 +- launcher/test.sh | 2 +- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/launcher/diartk.sh b/launcher/diartk.sh index 8c96a48..83f7638 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -60,15 +60,15 @@ for fin in `ls $audio_dir/*.wav`; do case $trs_format in "noisemesSad") sys="noisemesSad" - python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/noisemesSad_${basename}.rttm $scpfile ;; "tocomboSad") sys="tocomboSad" - python $UTILS/rttm2scp.py $audio_dir/tocombo_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/tocomboSad_${basename}.rttm $scpfile ;; "opensmileSad") sys="opensmileSad" - python $UTILS/rttm2scp.py $audio_dir/opensmile_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/opensmileSad_${basename}.rttm $scpfile ;; "textgrid") sys="goldSad" diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index ca4e6c1..83ba628 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -1,5 +1,4 @@ #!/bin/bash -# noisemes_sad.sh # run OpenSAT with hard coded models & configs found here and in /vagrant @@ -11,7 +10,7 @@ BASEDIR=/home/vagrant OPENSATDIR=/home/vagrant/repos/OpenSAT if [ $# -lt 1 ]; then - echo "Usage: noisemes_sad.sh " + echo "Usage: noisemesSad.sh " echo "where dirname is a folder on the host" echo "containing the wav files (/vagrant/dirname/ in the VM)" exit 1 @@ -52,7 +51,7 @@ echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. for sad in `ls $audio_dir/hyp_sum/*.lab`; do base=$(basename $sad .lab) - rttm_out=noisemes_sad_${base}.rttm + rttm_out=noisemesSad_${base}.rttm if [ -s $sad ]; then grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out else diff --git a/launcher/python3/noisemesSad.sh b/launcher/python3/noisemesSad.sh index 7a10d93..5ddac5a 100755 --- a/launcher/python3/noisemesSad.sh +++ b/launcher/python3/noisemesSad.sh @@ -1,5 +1,4 @@ #!/bin/bash -# noisemes_sad.sh source activate divime # run OpenSAT with hard coded models & configs found here and in /vagrant @@ -14,7 +13,7 @@ BASEDIR=`dirname $SCRIPT` if [ $# -lt 1 ]; then - echo "Usage: noisemes_sad.sh " + echo "Usage: noisemesSad.sh " echo "where dirname is a folder on the host" echo "containing the wav files (/vagrant/dirname/ in the VM)" exit 1 @@ -56,7 +55,7 @@ echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. for sad in `ls $audio_dir/hyp_sum/*.lab`; do base=$(basename $sad .lab) - rttm_out=noisemes_sad_${base}.rttm + rttm_out=noisemesSad_${base}.rttm if [ -s $sad ]; then grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out else diff --git a/launcher/python3/test.sh b/launcher/python3/test.sh index de35bc2..4608f96 100644 --- a/launcher/python3/test.sh +++ b/launcher/python3/test.sh @@ -86,7 +86,7 @@ ln -fs $TEST_WAV $TESTDIR #./runDiarNoisemes.sh $TESTDIR > $TESTDIR/noisemes-test.log 2>&1 $LAUNCHERS/noisemesSad.sh $DATADIR/noisemes-test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/noisemes_sad_$BASETEST.rttm ]; then +if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then echo "Noisemes passed the test." else FAILURES=true diff --git a/launcher/test.sh b/launcher/test.sh index cc0485a..9572358 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -93,7 +93,7 @@ cd $OPENSATDIR $LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/noisemes_sad_$BASETEST.rttm ]; then +if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then echo "Noisemes passed the test." else FAILURES=true From 53af545b61f771e385a2e4ac0c4265a43bc8473b Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 14:40:31 -0500 Subject: [PATCH 123/299] eval may be broken --- launcher/evalDiar.sh | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 87babc3..5dfb82f 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -1,11 +1,11 @@ #!/bin/bash -# Absolute path to this script. /home/user/bin/foo.sh +# Launcher onset routine SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to OpenSAT (go on folder up and to opensat) -DSCOREDIR=$(dirname $BASEDIR)/dscore +BASEDIR=/home/vagrant +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine display_usage() { @@ -27,7 +27,11 @@ display_usage() { } -if ! [[ $2 =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lena)$ ]] ]; then +### Read in variables from user +audio_dir=/vagrant/$1 +model=$2 + +if ! [[ $model =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lena)$ ]] ]; then display_usage fi @@ -36,17 +40,10 @@ if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi -# data directory -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" # Set CWD to path of Dscore cd $DSCOREDIR -model=$2 if [[ $model =~ ^(diartk|yuniseg) ]]; then trs_format=$3 case $trs_format in From 199d5b3e4bde8927460b01c86c1c9c00e059d012 Mon Sep 17 00:00:00 2001 From: Junghan Date: Sun, 2 Dec 2018 14:57:37 -0500 Subject: [PATCH 124/299] pass explicit sphinx build --- conf/bootstrap.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index ab84865..78f8c70 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -205,4 +205,5 @@ if ! $HTK_INSTALLED; then fi # Build the docs -cd /vagrant/docs && make html +cd /vagrant/docs +make SPHINXBUILD=/home/${user}/anaconda/bin/sphinx-build html From 524fc524375f7e788ea681a21f890c252efda328 Mon Sep 17 00:00:00 2001 From: MilesICL Date: Mon, 3 Dec 2018 18:23:51 +0000 Subject: [PATCH 125/299] vcm now can read rttm from yunitator --- launcher/vcm.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/launcher/vcm.sh b/launcher/vcm.sh index dce74b6..a31ce5a 100755 --- a/launcher/vcm.sh +++ b/launcher/vcm.sh @@ -29,6 +29,8 @@ KEEPTEMP=false if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi +mkdir -p $audio_dir/VCMtemp +echo $audio_dir/VCMtemp # let's get our bearings: set CWD to the path of VCM cd $VCMDIR @@ -42,12 +44,6 @@ done echo "$0 finished running" -# take all the .rttm in $audio_dir/VCMtemp/ and move them to /vagrant/data -for vcm in `ls $audio_dir/VCMtemp/*.rttm`; do - _rttm=$(basename $vcm) - rttm=$audio_dir/${_rttm} - mv $vcm $rttm -done # simply remove hyp and feature if ! $KEEPTEMP; then From a07c97b6b576a79f53f546061f6e2c5087fc0f93 Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 5 Dec 2018 12:37:57 -0500 Subject: [PATCH 126/299] Tool update script - Edit version tags as necessary - Usage: `$ vagrant up --provision-with=update` --- conf/update.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/conf/update.sh b/conf/update.sh index aec01e7..949fd22 100644 --- a/conf/update.sh +++ b/conf/update.sh @@ -8,11 +8,18 @@ fi echo "Check git updates" ############################################# # Get OpenSAT and all the tools +# change version tag as necessary for each tools cd /home/${user}/repos -(cd "OpenSAT"; git pull) -(cd "ib_diarization_toolkit" ; git pull) -(cd "dscore" ; git pull) -(cd "Yunitator" ; git pull) -(cd "vcm"; git pull) -(cd "To-Combo-SAD" ; git pull) +(cd "OpenSAT"; git checkout master; git pull) +# (cd "OpenSAT"; git checkout master; git pull; git checkout v2.0) +(cd "ib_diarization_toolkit"; git checkout master; git pull) +# (cd "ib_diarization_toolkit" ; git checkout master; git pull; git checkout v2.0) +(cd "dscore" ; git checkout master; git pull) +# (cd "dscore" ;git checkout master; git pull; git checkout v2.0) +(cd "Yunitator" ;git checkout master; git pull) +# (cd "Yunitator" ; git checkout master; git pull; git checkout v2.0) +(cd "vcm"; git checkout master; git pull) +# (cd "vcm"; git checkout master; git pull; git checkout v2.0) +(cd "To-Combo-SAD" ; git checkout master; git pull) +# (cd "To-Combo-SAD" ; git checkout master; git pull; git checkout v2.0) ############################################# From 465d4a01906010c9248d7ea5195b2a3589cc3b66 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 7 Dec 2018 19:57:54 +0000 Subject: [PATCH 127/299] fix quotation marks --- launcher/eval.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/eval.sh b/launcher/eval.sh index 10410ec..f36098f 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -44,7 +44,7 @@ fi ### SCRIPT STARTS case $system in -"tocomboSad"|"opensmileSad"|"noisemesSad|lenaSad") +"tocomboSad"|"opensmileSad"|"noisemesSad"|"lenaSad") sh $LAUNCHER/evalSAD.sh $audio_dir $system $KEEPTEMP ;; "yunitate"|"lenaDiar") From c0385d9b2a757b9032a56eff7e431d6921a2c2da Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 7 Dec 2018 19:59:13 +0000 Subject: [PATCH 128/299] bracketize audio dir --- launcher/evalDiar.sh | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 5dfb82f..97ebf52 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -5,6 +5,7 @@ SCRIPT=$(readlink -f $0) BASEDIR=/home/vagrant REPOS=$BASEDIR/repos UTILS=$BASEDIR/utils +DSCOREDIR=$REPOS/dscore # end of launcher onset routine @@ -22,7 +23,7 @@ display_usage() { echo " - diartk_tocomboSad" echo " - diartk_rttm" echo " - yunitate" - echo " - lena" + echo " - lenaSad" exit 1; } @@ -31,7 +32,7 @@ display_usage() { audio_dir=/vagrant/$1 model=$2 -if ! [[ $model =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lena)$ ]] ]; then +if ! [[ $model =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lenaSad)$ ]] ]; then display_usage fi @@ -58,16 +59,16 @@ if [[ $model =~ ^(diartk|yuniseg) ]]; then ;; "textgrid") sys_name=$model"_goldSad" - for wav in `ls $audio_dir/*.wav`; do + for wav in `ls ${audio_dir}/*.wav`; do base=$(basename $wav .wav) - python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid $audio_dir/${basename}.rttm + python /home/vagrant/utils/textgrid2rttm.py ${audio_dir}/${basename}.TextGrid ${audio_dir}/${basename}.rttm done ;; "eaf") sys_name=$model"_goldSad" - for wav in `ls $audio_dir/*.wav`; do + for wav in `ls ${audio_dir}/*.wav`; do base=$(basename $wav .wav) - python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf $audio_dir/${basename}.rttm + python /home/vagrant/utils/elan2rttm.py ${audio_dir}/${basename}.eaf ${audio_dir}/${basename}.rttm done ;; "rttm") @@ -85,33 +86,33 @@ if [[ $model =~ ^(diartk|yuniseg) ]]; then esac elif [ "$2" == "yunitate" ]; then sys_name="yunitator" -elif [ "$2" == "lena" ]; then - sys_name="lena" +elif [ "$2" == "lenaSad" ]; then + sys_name="lena_sad" fi -echo $BASEDIR/create_ref_sys.sh $1 $sys_name -$BASEDIR/create_ref_sys.sh $1 $sys_name +echo $UTILS/create_ref_sys.sh $1 $sys_name +$UTILS/create_ref_sys.sh $1 $sys_name echo "evaluating" -python score_batch.py $audio_dir/${sys_name}_eval.df $audio_dir/temp_ref $audio_dir/temp_sys +python score_batch.py ${audio_dir}/${sys_name}_eval.df ${audio_dir}/temp_ref ${audio_dir}/temp_sys # Check if some gold files are empty. If so, add a line in the eval dataframe -for fin in `ls $audio_dir/temp_ref/*.rttm`; do +for fin in `ls ${audio_dir}/temp_ref/*.rttm`; do base=$(basename $fin .rttm) - if [ ! -s $audio_dir/temp_ref/$base.rttm ]; then - if [ ! -s $audio_dir/temp_sys/$base.rttm ]; then - echo $base" 0 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + if [ ! -s ${audio_dir}/temp_ref/$base.rttm ]; then + if [ ! -s ${audio_dir}/temp_sys/$base.rttm ]; then + echo $base" 0 NA NA NA NA NA NA NA NA" >> ${audio_dir}/${sys_name}_eval.df else - echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + echo $base" 100 NA NA NA NA NA NA NA NA" >> ${audio_dir}/${sys_name}_eval.df fi - elif [ ! -s $audio_dir/temp_sys/$base.rttm ] && [ -s $audio_dir/temp_ref/$base.rttm ]; then - echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + elif [ ! -s ${audio_dir}/temp_sys/$base.rttm ] && [ -s ${audio_dir}/temp_ref/$base.rttm ]; then + echo $base" 100 NA NA NA NA NA NA NA NA" >> ${audio_dir}/${sys_name}_eval.df fi done echo "done evaluating, check $1/${sys_name}_eval.df for the results" # remove temps if ! $KEEPTEMP; then - rm -rf $audio_dir/temp_ref $audio_dir/temp_sys + rm -rf ${audio_dir}/temp_ref ${audio_dir}/temp_sys fi From 8098d2374885f9149bc93386867f0ecb78ce2dab Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 7 Dec 2018 20:02:16 +0000 Subject: [PATCH 129/299] bracketize audio dir --- utils/create_ref_sys.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh index 250e882..da59042 100755 --- a/utils/create_ref_sys.sh +++ b/utils/create_ref_sys.sh @@ -28,8 +28,7 @@ if [ -z "$3" ]; then create_lab=false fi - -if ! [[ $model_prefix =~ ^(ldc_sad|noisemesSad|tocomboSad|opensmileSad|lenaSad|lena|yunitator|\ +if ! [[ $model_prefix =~ ^(noisemesSad|tocomboSad|opensmileSad|lenaSad|lena|yunitator|\ diartk_ldcSad|diartk_noisemesSad|diartk_tocomboSad|diartk_opensmileSad|diartk_goldSad|\ yuniseg_ldcSad|yuniseg_noisemesSad|yuniseg_tocomboSad|yuniseg_opensmileSad|yuniseg_goldSad)$ ]]; then echo "You're trying to create folders containing the reference transcriptions, and the predicted ones." @@ -38,9 +37,9 @@ yuniseg_ldcSad|yuniseg_noisemesSad|yuniseg_tocomboSad|yuniseg_opensmileSad|yunis exit 1; fi -echo "audio_dir is: " $audio_dir # Create temp_ref folder +echo mkdir -p $audio_dir/temp_ref mkdir -p $audio_dir/temp_ref for wav in `ls $audio_dir/*.wav`; do base=$(basename $wav .wav) @@ -52,6 +51,7 @@ for wav in `ls $audio_dir/*.wav`; do # Replace two or more occurrences of whitespace by just one sed -i 's/ \+/ /g' $audio_dir/temp_ref/${base}.rttm if [ $create_lab == true ]; then + echo "creating: " $audio_dir/temp_ref/${base}.lab awk '{print $4" "($4+$5)" speech"}' $audio_dir/temp_ref/${base}.rttm > $audio_dir/temp_ref/${base}.lab fi done @@ -70,8 +70,8 @@ for rttm in `ls $audio_dir/${model_prefix}_*.rttm`; do done # check that temp_sys is not empty, otherwise exit and remove it. -if [ -z "$(ls -A $audio_dir/temp_sys)" ]; then +if [ -z "$(ls -A ${audio_dir}/temp_sys)" ]; then echo "Didn't find any transcription from the model prefix you specified. Please get the ${model_prefix}_my_file.rttm before" - rm -rf $audio_dir/temp_sys $audio_dir/temp_ref + rm -rf ${audio_dir}/temp_sys ${audio_dir}/temp_ref exit fi From 07d275cb3eae73856998cfd20b9f2f932df2c9f7 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 7 Dec 2018 20:03:11 +0000 Subject: [PATCH 130/299] Proper RTTM format test ref --- launcher/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/test.sh b/launcher/test.sh index 9572358..769d0a3 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -66,7 +66,7 @@ sox $BASE.mp3 $BASETEST.wav trim $START 5:00 >& /dev/null 2>&1 # silence output $UTILS/chat2stm.sh $BASE.cha > $BASE.stm 2>/dev/null # convert STM to RTTM as e.g. BN32_010007.rttm # shift audio offsets to be 0-relative -cat $BASE.stm | awk -v start=$START -v stop=$STOP -v file=$BASE -e '{if (($4 > start) && ($4 < stop)) print "SPEAKER",file,"1",($4 - start),($5 - $4),"","","","","" }' > $BASETEST.rttm +cat $BASE.stm | awk -v start=$START -v stop=$STOP -v file=$BASE -e '{if (($4 > start) && ($4 < stop)) print "SPEAKER",file"_test","1",($4 - start),($5 - $4),"","","speech","","" }' > $BASETEST.rttm TEST_RTTM=$WORKDIR/$BASETEST.rttm TEST_WAV=$WORKDIR/$BASETEST.wav From 6f20245e0f5d457e71d93bbf4832b903f84daa91 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 7 Dec 2018 20:22:49 +0000 Subject: [PATCH 131/299] use dscore to compute SAD --- launcher/evalSad.sh | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100755 launcher/evalSad.sh diff --git a/launcher/evalSad.sh b/launcher/evalSad.sh new file mode 100755 index 0000000..3a2a2d2 --- /dev/null +++ b/launcher/evalSad.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=/home/vagrant +UTILS=$BASEDIR/utils +REPOS=$BASEDIR/repos +# Path to scoring tool NOTE: NOT dscore! +DSCOREDIR=$REPOS/dscore + + +# data directory +audio_dir=$1 +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") +extension="${filename##*.}" +basename="${filename%.*}" + +# check system to evaluate - either LDC, OpenSAT or "MySystem" +sys_name=$2 + +if ! [[ $sys_name =~ ^(noisemesSad|tocomboSad|opensmileSad|lenaSad)$ ]]; then + echo "Please Specify the System you wish to evaluate." + echo "Choose between noisemesSad, tocomboSad, lenaSad and opensmileSad." + exit +fi + +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + +# Set CWD to path of scoring tool +cd $DSCOREDIR + +# pass vagrant-relative pathname to create_ref_sys +$UTILS/create_ref_sys.sh ${audio_dir} $sys_name true + +# resolve to absolute path for rest of this script +audio_dir=/vagrant/${audio_dir} + +OUTPUT_DF=${audio_dir}/${sys_name}_eval.df +REF=${audio_dir}/temp_ref +SYS=${audio_dir}/temp_sys +echo "evaluating" + +python score_batch.py $OUTPUT_DF $REF $SYS + +# small detail: remove the commas from the output +sed -i "s/,//g" $OUTPUT_DF +echo "done evaluating, check $1/${sys_name}_eval.df for the results" + +# remove temps +if ! $KEEPTEMP; then + rm -rf $REF $SYS +fi From 0fc00e577b78ca0dd61743800ed8edc2c1954dba Mon Sep 17 00:00:00 2001 From: jaden-w Date: Mon, 10 Dec 2018 02:02:35 -0500 Subject: [PATCH 132/299] Testing noisemes full --- launcher/noisemesFull.sh | 3 +++ launcher/noisemesSad.sh | 48 ++++++++++++++++++++++++++++++---------- launcher/yunitate.sh | 8 ++++++- 3 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 launcher/noisemesFull.sh diff --git a/launcher/noisemesFull.sh b/launcher/noisemesFull.sh new file mode 100644 index 0000000..70bafd6 --- /dev/null +++ b/launcher/noisemesFull.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./launcher/noisemesSad.sh $@ --full-classes \ No newline at end of file diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index ccc88a5..6cc4d91 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -24,9 +24,15 @@ if [ $# -lt 1 ]; then fi KEEPTEMP=false -if [ $BASH_ARGV == "--keep-temp" ]; then +FULLCLASSES=false +for a in ${BASH_ARGV[*]} ; do + if [ $a == "--keep-temp" ]; then KEEPTEMP=true -fi + fi + if [ $a == "--full-classes" ]; then + FULLCLASSES=true + fi +done audio_dir=/vagrant/$1 TEMPNAME=feature @@ -47,26 +53,44 @@ mkdir -p $audio_dir/$TEMPNAME # first features echo "extracting features for speech activity detection" -for file in `ls $audio_dir/*.wav`; do - ./extract-htk-vm2.sh $file $TEMPNAME -done +# for file in `ls $audio_dir/*.wav`; do +# ./extract-htk-vm2.sh $file $TEMPNAME +# done + +# Choose chunksize based off memory. Currently this is equivalent to 200 +# frames per 100MB of memory. +# Ex: 3GB -> 6000 frames +# Ex: 2048MB -> 4000 frames +# This setting was chosen arbitrarily and was successful for tests at 2GB-4GB. +chunksize=$(free | awk '/^Mem:/{print $2}') +let chunksize=$chunksize/100000*200 # then confidences #python SSSF/code/predict/1-confidence-vm3.py $1 echo "detecting speech and non speech segments" # $conda_dir/python SSSF/code/predict/1-confidence-vm5.py $audio_dir -python yunified.py noisemes $audio_dir 4000 +python yunified.py noisemes $audio_dir $chunksize echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. for sad in `ls $audio_dir/hyp_sum/*.lab`; do base=$(basename $sad .lab) - rttm_out=noisemes_sad_${base}.rttm - if [ -s $sad ]; then - grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out - else - touch $audio_dir/$rttm_out - fi + + if $FULLCLASSES; then + rttm_out=noisemes_full_${base}.rttm + else + rttm_out=noisemes_sad_${base}.rttm + fi + + if [ -s $sad ]; then + if $FULLCLASSES; then + grep '' $sad | awk -v fname=$base '{print $4 " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out + else + grep ' speech' $sad | awk -v fname=$base '{print $4 " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out + fi + else + touch $audio_dir/$rttm_out + fi done # simple remove hyp and feature diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 2f71de7..3255ab3 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -53,7 +53,13 @@ for f in `ls $audio_dir/*.wav`; do ./extract-htk-vm2.sh $f $TEMPNAME done -python yunified.py yunitator $audio_dir 4000 +# Choose chunksize based off memory. Currently this is equivalent to 200 +# frames per 100MB of memory (for example: 3GB means a chunksize of 6000). +# This setting was chosen arbitrarily and was successful for tests at 2GB-4GB. +chunksize=$(free | awk '/^Mem:/{print $2}') +let chunksize=$chunksize/100000*200 + +python yunified.py yunitator $audio_dir $chunksize for f in `ls $YUNITEMP/*.rttm.sorted`; do filename=$(basename "$f") From a2de89cae36cc8fdf4a4496d8f06e7dfeca9bf26 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Mon, 10 Dec 2018 13:29:15 +0100 Subject: [PATCH 133/299] Fix eaf2txt.py to make it work with path beginning by / --- utils/eaf2txt.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py index 56ca2d5..1623b06 100755 --- a/utils/eaf2txt.py +++ b/utils/eaf2txt.py @@ -64,6 +64,10 @@ def main(): help="path to the input .eaf file or the folder containing eaf files.") args = parser.parse_args() + # Removing extra beginning / that might break the code + if args.input[0] == '/': + args.input = args.input[1:] + # Initialize the output folder as the same folder than the input # if not provided by the user. if args.input[-4:] == '.eaf': @@ -72,7 +76,9 @@ def main(): output = args.input data_dir = '/vagrant' + args.input = os.path.join(data_dir, args.input) + output = os.path.join(data_dir, output) if not os.path.isdir(output): os.mkdir(output) From e01f132f031a853639b6914f357c7785432fce99 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 10 Dec 2018 15:59:18 +0000 Subject: [PATCH 134/299] less verbose --- utils/create_ref_sys.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh index da59042..3317918 100755 --- a/utils/create_ref_sys.sh +++ b/utils/create_ref_sys.sh @@ -39,7 +39,6 @@ fi # Create temp_ref folder -echo mkdir -p $audio_dir/temp_ref mkdir -p $audio_dir/temp_ref for wav in `ls $audio_dir/*.wav`; do base=$(basename $wav .wav) From f2b2d543d5302eed8b5f19580f02dc8ac4d971dd Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 10 Dec 2018 14:00:51 -0500 Subject: [PATCH 135/299] don't redownload audio --- launcher/test.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/launcher/test.sh b/launcher/test.sh index 769d0a3..5569448 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -47,7 +47,6 @@ cd VanDam-Daylong/BN32/ WORKDIR=`pwd` # Get daylong recording from the web -wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 if [ ! -s BN32_010007.mp3 ]; then echo "Downloading test audio..." wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 From a0485a88496bc14963b20c70322a0acf3ebc779d Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 10 Dec 2018 15:07:05 -0500 Subject: [PATCH 136/299] support audio paths with spaces --- launcher/diartk.sh | 24 ++++++++++++------------ launcher/eval.sh | 6 +++--- launcher/noisemesSad.sh | 20 ++++++++++---------- launcher/opensmileSad.sh | 8 ++++---- launcher/talnet.sh | 8 ++++---- launcher/tocomboSad.sh | 16 ++++++++-------- launcher/vcm.sh | 14 +++++++------- launcher/yunitate.sh | 14 +++++++------- utils/create_ref_sys.sh | 28 ++++++++++++++-------------- utils/noisemes_full.sh | 28 ++++++++++++++-------------- utils/runTALNet.sh | 8 ++++---- utils/yuniSeg.sh | 20 ++++++++++---------- 12 files changed, 97 insertions(+), 97 deletions(-) diff --git a/launcher/diartk.sh b/launcher/diartk.sh index 83f7638..a1f3fb4 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -32,7 +32,7 @@ trs_format=$2 ### Other variables specific to this script # create temp dir -workdir=$audio_dir/temp/diartk +workdir=${audio_dir}/temp/diartk mkdir -p $workdir ### SCRIPT STARTS @@ -40,10 +40,10 @@ cd $BASEDIR/repos/ib_diarization_toolkit # Check audio_dir to see if empty or if contains empty wav -bash $UTILS/check_folder.sh $audio_dir +bash $UTILS/check_folder.sh ${audio_dir} -for fin in `ls $audio_dir/*.wav`; do +for fin in `ls ${audio_dir}/*.wav`; do filename=$(basename "$fin") basename="${filename%.*}" echo "treating $basename" @@ -60,25 +60,25 @@ for fin in `ls $audio_dir/*.wav`; do case $trs_format in "noisemesSad") sys="noisemesSad" - python $UTILS/rttm2scp.py $audio_dir/noisemesSad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py ${audio_dir}/noisemesSad_${basename}.rttm $scpfile ;; "tocomboSad") sys="tocomboSad" - python $UTILS/rttm2scp.py $audio_dir/tocomboSad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py ${audio_dir}/tocomboSad_${basename}.rttm $scpfile ;; "opensmileSad") sys="opensmileSad" - python $UTILS/rttm2scp.py $audio_dir/opensmileSad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py ${audio_dir}/opensmileSad_${basename}.rttm $scpfile ;; "textgrid") sys="goldSad" - python /home$UTILS/textgrid2rttm.py $audio_dir/${basename}.TextGrid $workdir/${basename}.rttm + python /home$UTILS/textgrid2rttm.py ${audio_dir}/${basename}.TextGrid $workdir/${basename}.rttm python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile rm $workdir/$basename.rttm ;; "eaf") sys="goldSad" - python /home$UTILS/elan2rttm.py $audio_dir/${basename}.eaf $workdir/${basename}.rttm + python /home$UTILS/elan2rttm.py ${audio_dir}/${basename}.eaf $workdir/${basename}.rttm python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile rm $workdir/$basename.rttm ;; @@ -86,7 +86,7 @@ for fin in `ls $audio_dir/*.wav`; do sys="goldSad" # Since some reference rttm files are spaced rather than tabbed, we need to # tab them before using them. - cp $audio_dir/${basename}.rttm $workdir/${basename}.rttm + cp ${audio_dir}/${basename}.rttm $workdir/${basename}.rttm sed -i 's/ \+/\t/g' $workdir//${basename}.rttm python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile ;; @@ -113,11 +113,11 @@ for fin in `ls $audio_dir/*.wav`; do # print results #cat $workdir/$basename.out - cp $workdir/$basename.rttm $audio_dir/diartk_${sys}_${basename}.rttm + cp $workdir/$basename.rttm ${audio_dir}/diartk_${sys}_${basename}.rttm fi - if [ ! -s $audio_dir/diartk_${sys}_${basename}.rttm ]; then + if [ ! -s ${audio_dir}/diartk_${sys}_${basename}.rttm ]; then # if diarization failed, still write an empty file... - touch $audio_dir/diartk_${sys}_${basename}.rttm + touch ${audio_dir}/diartk_${sys}_${basename}.rttm fi diff --git a/launcher/eval.sh b/launcher/eval.sh index f36098f..6742150 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -45,14 +45,14 @@ fi ### SCRIPT STARTS case $system in "tocomboSad"|"opensmileSad"|"noisemesSad"|"lenaSad") - sh $LAUNCHER/evalSAD.sh $audio_dir $system $KEEPTEMP + sh $LAUNCHER/evalSAD.sh ${audio_dir} $system $KEEPTEMP ;; "yunitate"|"lenaDiar") - sh $LAUNCHER/evalDiar.sh $audio_dir $system $KEEPTEMP + sh $LAUNCHER/evalDiar.sh ${audio_dir} $system $KEEPTEMP ;; "diartk") sad=$3 - sh $LAUNCHER/evalDiar.sh $audio_dir $system $sad $KEEPTEMP + sh $LAUNCHER/evalDiar.sh ${audio_dir} $system $sad $KEEPTEMP ;; *) display_usage diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 83ba628..67b5f58 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -22,44 +22,44 @@ if [ $BASH_ARGV == "--keep-temp" ]; then fi audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/utils/check_folder.sh $audio_dir +bash $BASEDIR/utils/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to path of OpenSAT cd $OPENSATDIR # make output folder for features, below input folder -mkdir -p $audio_dir/feature +mkdir -p ${audio_dir}/feature # first features echo "extracting features for speech activity detection" -for file in `ls $audio_dir/*.wav`; do +for file in `ls ${audio_dir}/*.wav`; do SSSF/code/feature/extract-htk-vm2.sh $file done # then confidences #python SSSF/code/predict/1-confidence-vm3.py $1 echo "detecting speech and non speech segments" -python SSSF/code/predict/1-confidence-vm5.py $audio_dir +python SSSF/code/predict/1-confidence-vm5.py ${audio_dir} echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. -for sad in `ls $audio_dir/hyp_sum/*.lab`; do +for sad in `ls ${audio_dir}/hyp_sum/*.lab`; do base=$(basename $sad .lab) rttm_out=noisemesSad_${base}.rttm if [ -s $sad ]; then - grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out + grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > ${audio_dir}/$rttm_out else - touch $audio_dir/$rttm_out + touch ${audio_dir}/$rttm_out fi done # simple remove hyp and feature if ! $KEEPTEMP; then - rm -rf $audio_dir/hyp_sum $audio_dir/feature + rm -rf ${audio_dir}/hyp_sum ${audio_dir}/feature fi diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 368f204..9c414dd 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -15,7 +15,7 @@ audio_dir=/vagrant/$1 OSHOME=$REPOS/opensmile-2.3.0 CONFIG_FILE=$CONF/vad_segmenter_aclew.conf OPENSMILE=SMILExtract -workdir=$audio_dir/temp/opensmileSad +workdir=${audio_dir}/temp/opensmileSad mkdir -p $workdir ### SCRIPT STARTS @@ -39,12 +39,12 @@ basename="${filename%.*}" cd $OSHOME/scripts/vad # Use OpenSMILE 2.3.0 -for sad in `ls $audio_dir/*.wav`; do +for sad in `ls ${audio_dir}/*.wav`; do file=$sad id=`basename $file` id=${id%.wav} - > $audio_dir/${id}.txt #Make it empty if already present + > ${audio_dir}/${id}.txt #Make it empty if already present echo "Processing $id ..." LD_LIBRARY_PATH=/usr/local/lib \ $OPENSMILE \ @@ -61,7 +61,7 @@ rm -f output_segment_*.wav for output in $(ls $workdir/*.txt); do id=$(basename $output .txt) - awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > $audio_dir/opensmileSad_$id.rttm + awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > ${audio_dir}/opensmileSad_$id.rttm done # Delete temporary folder diff --git a/launcher/talnet.sh b/launcher/talnet.sh index 4f18cf1..ba98015 100755 --- a/launcher/talnet.sh +++ b/launcher/talnet.sh @@ -17,12 +17,12 @@ if [ $# -ne 1 ]; then fi audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} @@ -34,7 +34,7 @@ echo "Starting" for f in `ls ${audio_dir}/*.wav`; do ./runTALNet.sh $f base=$(basename $f .wav) - mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat + mv ${audio_dir}/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat done echo "$0 finished running" diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index f59747d..f54fa17 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -14,7 +14,7 @@ trs_format=$2 ### Other variables specific to this script # create temp dir -workdir=$audio_dir/temp/tocomboSad +workdir=${audio_dir}/temp/tocomboSad mkdir -p $workdir TOCOMBOSADDIR=$REPOS/To-Combo-SAD MCR=/usr/local/MATLAB/MATLAB_Runtime/v93 @@ -33,13 +33,13 @@ if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash /home/vagrant/utils/check_folder.sh $audio_dir +bash /home/vagrant/utils/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to path of ToComboSAD cd $TOCOMBOSADDIR @@ -50,7 +50,7 @@ touch $workdir/filelist.txt # create temp dir to store audio files with 1 channels, if needed (i.e. if audio to treat has 2 or more channels.) # Indeed, To Combo Sad Fails when there are more than 1 channels. -for f in $audio_dir/*.wav; do +for f in ${audio_dir}/*.wav; do # Check if audio has 1 channel or more. If it has more, use sox to create a temp audio file w/ 1 channel. n_chan=$(soxi $f | grep Channels | cut -d ':' -f 2) if [[ $n_chan -gt 1 ]]; then @@ -69,12 +69,12 @@ export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64 ./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt # Retrieve the outputs from the temp folder -mv $workdir/*ToCombo.txt $audio_dir +mv $workdir/*ToCombo.txt ${audio_dir} #convert to rttms -for f in $audio_dir/*.ToCombo.txt; do +for f in ${audio_dir}/*.ToCombo.txt; do bn=`basename $f .wav.ToCombo.txt` - python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > $audio_dir/tocomboSad_$bn.rttm + python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > ${audio_dir}/tocomboSad_$bn.rttm done # Delete temporary folder diff --git a/launcher/vcm.sh b/launcher/vcm.sh index a31ce5a..4394bf1 100755 --- a/launcher/vcm.sh +++ b/launcher/vcm.sh @@ -18,26 +18,26 @@ if [ $# -ne 1 ]; then fi audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} KEEPTEMP=false if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi -mkdir -p $audio_dir/VCMtemp -echo $audio_dir/VCMtemp +mkdir -p ${audio_dir}/VCMtemp +echo ${audio_dir}/VCMtemp # let's get our bearings: set CWD to the path of VCM cd $VCMDIR # Iterate over files echo "Starting" -for f in `ls $audio_dir/*.wav`; do +for f in `ls ${audio_dir}/*.wav`; do echo $f ./runVCM.sh $f done @@ -47,5 +47,5 @@ echo "$0 finished running" # simply remove hyp and feature if ! $KEEPTEMP; then - rm -rf $audio_dir/VCMtemp + rm -rf ${audio_dir}/VCMtemp fi diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index d5db808..479a61a 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -22,13 +22,13 @@ if [ $BASH_ARGV == "--keep-temp" ]; then fi audio_dir=/vagrant/$1 -YUNITEMP=$audio_dir/Yunitemp -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +YUNITEMP=${audio_dir}/Yunitemp +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash /home/vagrant/utils/check_folder.sh $audio_dir +bash /home/vagrant/utils/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to the path of Yunitator @@ -39,7 +39,7 @@ mkdir -p $YUNITEMP # Iterate over files echo "Starting $0" -for f in `ls $audio_dir/*.wav`; do +for f in `ls ${audio_dir}/*.wav`; do basename=`basename $f .wav` # first features @@ -52,10 +52,10 @@ done echo "$0 finished running" -# take all the .rttm in $audio_dir/Yunitemp/ and move them to /vagrant/data +# take all the .rttm in ${audio_dir}/Yunitemp/ and move them to /vagrant/data for sad in `ls $YUNITEMP/*.rttm`; do _rttm=$(basename $sad) - rttm=$audio_dir/yunitator_${_rttm} + rttm=${audio_dir}/yunitator_${_rttm} # Remove not needed SIL lines # sed -i '/ SIL /d' $sad mv $sad $rttm diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh index 3317918..b5c53d0 100755 --- a/utils/create_ref_sys.sh +++ b/utils/create_ref_sys.sh @@ -4,7 +4,7 @@ audio_dir=/vagrant/$1 model_prefix=$2 create_lab=$3 -base_directory=$(echo "$audio_dir" | awk -F "/" '{print $2}') +base_directory=$(echo "${audio_dir}" | awk -F "/" '{print $2}') if [ "$base_directory" != "vagrant" ]; then audio_dir=$1 @@ -39,32 +39,32 @@ fi # Create temp_ref folder -mkdir -p $audio_dir/temp_ref -for wav in `ls $audio_dir/*.wav`; do +mkdir -p ${audio_dir}/temp_ref +for wav in `ls ${audio_dir}/*.wav`; do base=$(basename $wav .wav) - cp $audio_dir/${base}.rttm $audio_dir/temp_ref/${base}.rttm + cp ${audio_dir}/${base}.rttm ${audio_dir}/temp_ref/${base}.rttm # Sort rttm by onset - sort --key 4 --numeric-sort $audio_dir/${base}.rttm -o $audio_dir/temp_ref/${base}.rttm + sort --key 4 --numeric-sort ${audio_dir}/${base}.rttm -o ${audio_dir}/temp_ref/${base}.rttm # Change tabulations to white-spaces - sed -i 's/\t/ /g' $audio_dir/temp_ref/${base}.rttm + sed -i 's/\t/ /g' ${audio_dir}/temp_ref/${base}.rttm # Replace two or more occurrences of whitespace by just one - sed -i 's/ \+/ /g' $audio_dir/temp_ref/${base}.rttm + sed -i 's/ \+/ /g' ${audio_dir}/temp_ref/${base}.rttm if [ $create_lab == true ]; then - echo "creating: " $audio_dir/temp_ref/${base}.lab - awk '{print $4" "($4+$5)" speech"}' $audio_dir/temp_ref/${base}.rttm > $audio_dir/temp_ref/${base}.lab + echo "creating: " ${audio_dir}/temp_ref/${base}.lab + awk '{print $4" "($4+$5)" speech"}' ${audio_dir}/temp_ref/${base}.rttm > ${audio_dir}/temp_ref/${base}.lab fi done # Create temp_sys folder and copy all of the sys rttm inside of it # Remove the model_prefix of it -mkdir -p $audio_dir/temp_sys -for rttm in `ls $audio_dir/${model_prefix}_*.rttm`; do +mkdir -p ${audio_dir}/temp_sys +for rttm in `ls ${audio_dir}/${model_prefix}_*.rttm`; do base=$(basename $rttm .rttm) out=`echo $base | sed "s/${model_prefix}\_//g"` - cp $rttm $audio_dir/temp_sys/${out}.rttm + cp $rttm ${audio_dir}/temp_sys/${out}.rttm if [ $create_lab == true ]; then - echo "creating: " $audio_dir/temp_sys/${out}.lab - awk '{print $4" "($4+$5)" speech"}' $rttm > $audio_dir/temp_sys/${out}.lab + echo "creating: " ${audio_dir}/temp_sys/${out}.lab + awk '{print $4" "($4+$5)" speech"}' $rttm > ${audio_dir}/temp_sys/${out}.lab fi done diff --git a/utils/noisemes_full.sh b/utils/noisemes_full.sh index 9af469b..9d6a2cf 100755 --- a/utils/noisemes_full.sh +++ b/utils/noisemes_full.sh @@ -18,19 +18,19 @@ if [ $# -ne 1 ]; then fi audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to the path of OpenSAT cd $OPENSATDIR # first features echo "extracting features for noisemes_full" -for file in `ls $audio_dir/*.wav`; do +for file in `ls ${audio_dir}/*.wav`; do SSSF/code/feature/extract-htk-vm2.sh $file done @@ -41,31 +41,31 @@ done # python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename echo "predicting classes" # python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename -python SSSF/code/predict/1-confidence-vm4.py $audio_dir +python SSSF/code/predict/1-confidence-vm4.py ${audio_dir} echo "noisemes_full finished running" # take all the .rttm in /vagrant/data/hyp_sum and move them to /vagrant/data - move features and hyp_sum to another folder also. -for sad in `ls $audio_dir/hyp_sum/*.rttm`; do +for sad in `ls ${audio_dir}/hyp_sum/*.rttm`; do _rttm=$(basename $sad) - rttm=$audio_dir/noiseme_full_${_rttm} + rttm=${audio_dir}/noiseme_full_${_rttm} mv $sad $rttm done # simply remove hyp and feature -rm -rf $audio_dir/feature $audio_dir/hyp_sum +rm -rf ${audio_dir}/feature ${audio_dir}/hyp_sum -#if [ ! -d "$audio_dir/noiseme_full_temp" ]; then -# mkdir -p $audio_dir/noiseme_full_temp +#if [ ! -d "${audio_dir}/noiseme_full_temp" ]; then +# mkdir -p ${audio_dir}/noiseme_full_temp #fi # -#if [! -d "$audio_dir/noiseme_full_temp" ]; then -# mv $audio_dir/hyp_sum $audio_dir/noiseme_full_temp +#if [! -d "${audio_dir}/noiseme_full_temp" ]; then +# mv ${audio_dir}/hyp_sum ${audio_dir}/noiseme_full_temp #else # echo "can't move hyp_sum/ folder to noiseme_full_temp/ because temp is already full" #fi # -#if [! -d "$audio_dir/noiseme_full_temp" ]; then -# mv $audio_dir/feature $audio_dir/noiseme_full_temp +#if [! -d "${audio_dir}/noiseme_full_temp" ]; then +# mv ${audio_dir}/feature ${audio_dir}/noiseme_full_temp #else # echo "can't move features/ folder to noiseme_full_temp/ because temp is already full" #fi diff --git a/utils/runTALNet.sh b/utils/runTALNet.sh index df3dd0b..629bb38 100755 --- a/utils/runTALNet.sh +++ b/utils/runTALNet.sh @@ -17,12 +17,12 @@ if [ $# -ne 1 ]; then fi audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to the path of TALNet cd $CLASSIFY @@ -32,7 +32,7 @@ echo "Starting" for f in `ls ${audio_dir}/*.wav`; do ./runTALNet.sh $f base=$(basename $f .wav) - mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat + mv ${audio_dir}/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat done echo "$0 finished running" diff --git a/utils/yuniSeg.sh b/utils/yuniSeg.sh index 7f4ccdb..3ba088a 100755 --- a/utils/yuniSeg.sh +++ b/utils/yuniSeg.sh @@ -32,17 +32,17 @@ audio_dir=/vagrant/$1 trs_format=$2 # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} # Iterate over files echo "Starting" -for f in `ls $audio_dir/*.wav`; do +for f in `ls ${audio_dir}/*.wav`; do filename=$(basename "$f") basename="${filename%.*}" echo "treating $basename" # output filename produced by runYuniSegs - outfile=$audio_dir/$basename.yuniSeg.rttm + outfile=${audio_dir}/$basename.yuniSeg.rttm case $trs_format in "ldc_sad") @@ -71,12 +71,12 @@ for f in `ls $audio_dir/*.wav`; do "textgrid") sys="goldSad" model_prefix=${trs_format}_ - python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid ${trs_format}_${basename}.rttm + python /home/vagrant/utils/textgrid2rttm.py ${audio_dir}/${basename}.TextGrid ${trs_format}_${basename}.rttm ;; "eaf") sys="goldSad" model_prefix=${trs_format}_ - python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf ${trs_format}_${basename}.rttm + python /home/vagrant/utils/elan2rttm.py ${audio_dir}/${basename}.eaf ${trs_format}_${basename}.rttm ;; "rttm") sys="goldSad" @@ -96,12 +96,12 @@ for f in `ls $audio_dir/*.wav`; do ;; esac - ./runYuniSegs.sh $f $audio_dir/${model_prefix}${basename}.rttm - cp $outfile $audio_dir/yuniseg_${sys}_${basename}.rttm + ./runYuniSegs.sh $f ${audio_dir}/${model_prefix}${basename}.rttm + cp $outfile ${audio_dir}/yuniseg_${sys}_${basename}.rttm - if [ ! -s $audio_dir/yuniseg_${sys}_${basename}.rttm ]; then + if [ ! -s ${audio_dir}/yuniseg_${sys}_${basename}.rttm ]; then # if diarization failed, still write an empty file... - touch $audio_dir/yuniseg_${sys}_${basename}.rttm + touch ${audio_dir}/yuniseg_${sys}_${basename}.rttm fi done @@ -109,4 +109,4 @@ echo "$0 finished running" # simply remove hyp and feature rm $outfile -rm -rf $audio_dir/Yunitemp +rm -rf ${audio_dir}/Yunitemp From ea27c50442b2b9a7e7fb74b12201f0d33bc36a58 Mon Sep 17 00:00:00 2001 From: jaden-w Date: Wed, 12 Dec 2018 01:08:18 -0500 Subject: [PATCH 137/299] Clean scripts --- launcher/noisemesSad.sh | 20 ++++++++------------ launcher/yunitate.sh | 9 +++++---- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 6cc4d91..89c45d2 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -3,21 +3,17 @@ # Since the script is built to be launched outside of the vm, source # the .bashrc which is not necessarily sourced! source ~/.bashrc -# conda_dir=/home/vagrant/anaconda/bin -source activate divime -# run OpenSAT with hard coded models & configs found here and in /vagrant +source activate divime # Absolute path to this script. /home/vagrant/launcher/noisemesSad.sh SCRIPT=$(readlink -f $0) # home folder BASEDIR=/home/vagrant -# Path to OpenSAT (go on folder up and to opensat) -# OPENSATDIR=/home/vagrant/repos/OpenSAT YUNITATORDIR=/home/vagrant/repos/Yunitator if [ $# -lt 1 ]; then - echo "Usage: noisemesSad.sh " + echo "Usage: noisemesSad.sh [--keep-temp] [--full-classes]" echo "where dirname is a folder on the host" echo "containing the wav files (/vagrant/dirname/ in the VM)" exit 1 @@ -44,8 +40,7 @@ basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav bash $BASEDIR/utils/check_folder.sh $audio_dir -# let's get our bearings: set CWD to path of OpenSAT -# cd $OPENSATDIR +# let's get our bearings: set CWD to path of Yunitator cd $YUNITATORDIR # make output folder for features, below input folder @@ -53,9 +48,9 @@ mkdir -p $audio_dir/$TEMPNAME # first features echo "extracting features for speech activity detection" -# for file in `ls $audio_dir/*.wav`; do -# ./extract-htk-vm2.sh $file $TEMPNAME -# done +for file in `ls $audio_dir/*.wav`; do + ./extract-htk-vm2.sh $file $TEMPNAME +done # Choose chunksize based off memory. Currently this is equivalent to 200 # frames per 100MB of memory. @@ -68,8 +63,9 @@ let chunksize=$chunksize/100000*200 # then confidences #python SSSF/code/predict/1-confidence-vm3.py $1 echo "detecting speech and non speech segments" -# $conda_dir/python SSSF/code/predict/1-confidence-vm5.py $audio_dir + python yunified.py noisemes $audio_dir $chunksize + echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 3255ab3..61a8f73 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -1,12 +1,11 @@ #!/bin/bash # Since the script is built to be launched outside of the vm, source # the .bashrc which is not necessarily sourced! -#source ~/.bashrc -#conda_dir=/home/vagrant/anaconda/bin +source ~/.bashrc + source activate divime # run Yunitator with hard coded models & configs -# assumes Python environment in /home/vagrant/anaconda/bin # Absolute path to this script. /home/vagrant/launcher/yunitate.sh SCRIPT=$(readlink -f $0) @@ -54,7 +53,9 @@ for f in `ls $audio_dir/*.wav`; do done # Choose chunksize based off memory. Currently this is equivalent to 200 -# frames per 100MB of memory (for example: 3GB means a chunksize of 6000). +# frames per 100MB of memory. +# Ex: 3GB -> 6000 frames +# Ex: 2048MB -> 4000 frames # This setting was chosen arbitrarily and was successful for tests at 2GB-4GB. chunksize=$(free | awk '/^Mem:/{print $2}') let chunksize=$chunksize/100000*200 From 2bf169fdb747c298ed76915d69a96b54c1cfd036 Mon Sep 17 00:00:00 2001 From: jaden-w Date: Wed, 12 Dec 2018 01:08:47 -0500 Subject: [PATCH 138/299] Remove full class noisemes wrapper --- launcher/noisemesFull.sh | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 launcher/noisemesFull.sh diff --git a/launcher/noisemesFull.sh b/launcher/noisemesFull.sh deleted file mode 100644 index 70bafd6..0000000 --- a/launcher/noisemesFull.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -./launcher/noisemesSad.sh $@ --full-classes \ No newline at end of file From c377300f5c1ce08decb2a8f99f834b137480a825 Mon Sep 17 00:00:00 2001 From: jaden-w Date: Wed, 12 Dec 2018 01:13:29 -0500 Subject: [PATCH 139/299] Change bootstrap to clone master of Yunitator --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index e01fe3b..d38f72b 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -108,7 +108,7 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install Yunitator and dependencies -git clone https://github.com/srvk/Yunitator --branch develop/yunified # --branch v1.0 # need Dev +git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" From 23414c9870afe0acfee8cbeac6a5a577b07dc9a0 Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 12 Dec 2018 14:00:14 +0100 Subject: [PATCH 140/299] added info for users to interpret result --- launcher/test.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/launcher/test.sh b/launcher/test.sh index 5569448..f853042 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -197,8 +197,27 @@ else fi # results +echo "######################################################################################" +echo "To wrap up, we will print out the results of the analyses that we ran during the test." +echo "Compare the following results, corresponding to your system, against the reference results printed out below." +echo "If the numbers are similar, then your system is working similarly to the original one." +echo "If you see bigger changes, then please paste this output onto an issue on https://github.com/srvk/DiViMe/issues/." echo "RESULTS:" for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done +echo "****** REFERENCE RESULTS BEGINS ******." +LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm +LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm +LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm +LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm +LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm +LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm +LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm +echo "****** REFERENCE RESULTS ENDS ******." + echo "DSCORE:" cat /vagrant/data/VanDam-Daylong/BN32/test/test.df +echo "****** REFERENCE DSCORE BEGINS ******." +DER B3Precision B3Recall B3F1 TauRefSys TauSysRef CE MI NMI +Phil_Crane 43.38 0.975590490013 0.672338020576 0.796061934402 0.599223772838 0.963770340456 0.103871357212 1.67823036445 0.793181875273 +echo "****** REFERENCE DSCORE ENDS ******." From 566e157314ce7412d063811bf058bdaa3d126566 Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 12 Dec 2018 14:07:30 +0100 Subject: [PATCH 141/299] added info for users to interpret result --- launcher/test.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index f853042..a763f1c 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -205,19 +205,19 @@ echo "If you see bigger changes, then please paste this output onto an issue on echo "RESULTS:" for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done echo "****** REFERENCE RESULTS BEGINS ******." -LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm -LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm -LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm -LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm -LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm -LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm -LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm +echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm" +echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" +echo "LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm" +echo "LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm" +echo "LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm" +echo "LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm" +echo "LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" echo "****** REFERENCE RESULTS ENDS ******." echo "DSCORE:" cat /vagrant/data/VanDam-Daylong/BN32/test/test.df echo "****** REFERENCE DSCORE BEGINS ******." -DER B3Precision B3Recall B3F1 TauRefSys TauSysRef CE MI NMI -Phil_Crane 43.38 0.975590490013 0.672338020576 0.796061934402 0.599223772838 0.963770340456 0.103871357212 1.67823036445 0.793181875273 +echo "DER B3Precision B3Recall B3F1 TauRefSys TauSysRef CE MI NMI" +echo "Phil_Crane 43.38 0.975590490013 0.672338020576 0.796061934402 0.599223772838 0.963770340456 0.103871357212 1.67823036445 0.793181875273" echo "****** REFERENCE DSCORE ENDS ******." From 6c69b11e5436e7f98dd908d1c611d435084852ac Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 12 Dec 2018 14:41:15 +0100 Subject: [PATCH 142/299] added instructions for small machines --- docs/source/formats.md | 11 ++++++++ docs/source/install.md | 52 ++++++++++++++++++++++++++++++++----- docs/source/troubleshoot.md | 39 ++-------------------------- 3 files changed, 59 insertions(+), 43 deletions(-) diff --git a/docs/source/formats.md b/docs/source/formats.md index 41e87e6..03e0db6 100644 --- a/docs/source/formats.md +++ b/docs/source/formats.md @@ -2,6 +2,17 @@ This section explains the input and output formats. Each type of tool returns a different type of output, depending on the key information. +## Overview + +- explain what rttm is & why it's the central format for us +- here, instructions for textgrid and eaf using DAS +- for any other, convert into one of those (eg cha to tg) + + + +If your transcriptions are in TextGrid format but the conversion doesn't seem to work, it's probably because it isn't in the right TextGrid format. +The input TextGrid the system allows is a TextGrid in which all the tiers have speech segments (so remove tiers with no speech segments) and all the annotated segments for each tiers is indeed speech (so remove segments that are noises or other non-speech type). + ### Input: TextGrid TextGrid is a standard format for speech annotation, used by the Praat software. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. diff --git a/docs/source/install.md b/docs/source/install.md index cec6f6f..bb4dcd2 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -1,8 +1,16 @@ # Installing DiViMe -## First installation +## Requirements + +DiViMe can be installed in any operating system and computer. However, you may need to make some adaptations for known issues. Specifically, *before following the instructions under "First Installation"*, you must follow the instructions in the relevant subsection of the Troubleshooting section, at the end of this page, in the following cases: + +- your computer only has one core +- your computer has 15 GB or less of space (e.g., MacBook Air 11") +- your computer is running ubuntu (e.g., 16.04) + + +## First Installation -Try the following first: 1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link and follow the prompted instructions @@ -67,11 +75,7 @@ Congratulations, everything is OK! ``` -## Common installation errors and fixes - -- For noisemesSad, and diartk, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the -If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. ## Updating DiViMe @@ -92,6 +96,42 @@ If you want to get rid of the files completely, you should perform the following $ vagrant destroy $ cd .. $ rm -r -f divime + +## Troubleshooting + +### If your computer only has one core + +Before doing `vagrant up`, open the file called Vagrantfile in a text editor. Change the following line: + +> vbox.cpus = 2 + +into: + +> vbox.cpus = 1 + +Then proceed with the Installation. + +### If your computer has 15 GB or less of space + +If your computer has less than 3 GB of space, then *you cannot build a fully working DiViMe*. + +For computers with 3-15 GB of space, you may need to change the space allocated to the virtual machine. Before doing `vagrant up`, open the file called Vagrantfile in a text editor. Change the following line: + +> vbox.memory = 3072 + +into: + +> vbox.memory = 2048 + +Then proceed with the Installation. + +### If your computer is running ubuntu (16.04) + +There is a known incompatibility between VirtualBox and the 4.13 Linux kernel on ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installationSimple), or install the latest version of virtualbox, which should fix the problem. + +### If something else fails + +Please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. ``` ## References diff --git a/docs/source/troubleshoot.md b/docs/source/troubleshoot.md index 1766f17..3fb54cb 100755 --- a/docs/source/troubleshoot.md +++ b/docs/source/troubleshoot.md @@ -1,40 +1,8 @@ # Troubleshooting -## Installation issues -### Virtual Machine creation -If your computer freezes after `vagrant up`, it may be due to several things. -If your OS is ubuntu 16.04, there's a known incompatibility between VirtualBox and the 4.13 Linux kernel on ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installationSimple), or install the latest version of virtualbox which should fix the problem. -If you are not on ubuntu 16.04, or if the previous fix didn't work, it may also be due to the fact that Vagrant is trying to create a Virtual Machine that asks for too much resources. Please ensure that you have enough space on your computer (you should have at least 15Gb of free space) and check that the memory asked for is okay. If not, you can lower the memory of the VM by changing line 25 of the VagrantFile, -``` -vbox.memory = 3072 -``` -to a lower number, such as -``` -vbox.memory = 2048 -``` -### Resuming the Virtual Machine -If you already used the VM once, shut down your computer, turned it back on and can't seem to be able to do `vagrant up` again, you can simply do -``` -vagrant destroy -``` -and recreate the VM using -``` -vagrant up -``` -If you don't want to destroy it, you can try opening the VirtualBox GUI, go to `File -> Settings or Preferences -> Network `, click on the `Host-only Networks` tab, then click the network card icon with the green plus sign in the right, if there are no networks yet listed. The resulting new default network should appear with the name ‘vboxnet0’. -You can now try again with `vagrant up` - - -## Problems with some of the Tools -### OpenSmile, DiarTK -If OpenSmile, DiarTK don't seem to work after `vagrant up`, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: -``` -vagrant up --provision -``` -This step will install HTK inside the VM, which is used by several tools. +## Noisemes -### Noisemes If you use the noisemesSad or the noisemes_full tool, one problem you may encounter is that it doesn't treat all of your files and gives you an error that looks like this: ``` Traceback (most recent call last): @@ -46,10 +14,7 @@ MemoryError ``` If this happens to you, it's because you are trying to treat more data than the system/your computer can handle. What you can do is simply put the remaining files that weren't treated in a separate folder and treat this folder separately (and do this until all of your files are treated if it happens again on very big datasets). -After that, you can put back all of your data in the same folder. -### Input Format For Transcriptions -If your transcriptions are in TextGrid format but the conversion doesn't seem to work, it's probably because it isn't in the right TextGrid format. -The input TextGrid the system allows is a TextGrid in which all the tiers have speech segments (so remove tiers with no speech segments) and all the annotated segments for each tiers is indeed speech (so remove segments that are noises or other non-speech type). + From 090e19b71f65f871ce374be31ef8c9f04af20496 Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 12 Dec 2018 14:47:41 +0100 Subject: [PATCH 143/299] minor --- docs/source/install.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index bb4dcd2..86060eb 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -2,10 +2,10 @@ ## Requirements -DiViMe can be installed in any operating system and computer. However, you may need to make some adaptations for known issues. Specifically, *before following the instructions under "First Installation"*, you must follow the instructions in the relevant subsection of the Troubleshooting section, at the end of this page, in the following cases: +DiViMe can be installed in any operating system and computer with at least 1 CPU (and occupying 2GB when active). You may need to make some adaptations for known issues. Specifically, *before following the instructions under "First Installation"*, you must follow the instructions in the relevant subsection of the Troubleshooting section, at the end of this page, in the following cases: - your computer only has one core -- your computer has 15 GB or less of space (e.g., MacBook Air 11") +- your computer has 15 GB or less of space - your computer is running ubuntu (e.g., 16.04) @@ -113,9 +113,9 @@ Then proceed with the Installation. ### If your computer has 15 GB or less of space -If your computer has less than 3 GB of space, then *you cannot build a fully working DiViMe*. +If your computer has less than 5 GB of storage space, then *you cannot build a fully working DiViMe* (without crippling your computer). -For computers with 3-15 GB of space, you may need to change the space allocated to the virtual machine. Before doing `vagrant up`, open the file called Vagrantfile in a text editor. Change the following line: +For computers with 5-15 GB of space, you may need to change the space allocated to the virtual machine. Before doing `vagrant up`, open the file called Vagrantfile in a text editor. Change the following line: > vbox.memory = 3072 From f0d4a6542ae4b8de1634c1d2d4986583a1e85dc3 Mon Sep 17 00:00:00 2001 From: MilesICL Date: Wed, 12 Dec 2018 13:48:58 +0000 Subject: [PATCH 144/299] update vcm usage info --- docs/source/usage.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index 120dd57..0cdcacf 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -207,9 +207,28 @@ It returns one rttm per sound file, with an estimation of where there are vocali ### How to run a Vocalization classification tool -vcm +For these tools, type a command like this one: + +`$ vagrant ssh -c "vcm.sh data/mydata/"` + +You can read that command as follows: + +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. + +*vcm.sh*: This first argument tells DiViMe which tool to run. The options are: vcm. -NO INFORMATION YET +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. + +It returns one rttm per sound file, with an estimation for the infant vocalisation to be cannonical syllable (CNS), non-cannoical syllable (NCS), and crying (CRY). + +NOTE: it dependes on the outputs (rttm file) of yunicator. The default path storing rttm file of yunitator is under `data/mydata/` + +``` +SPEAKER FILENAME 1 31.4 1.6 CNS 0.71 +SPEAKER FILENAME 1 34.6 1.1 NCS 0.81 +SPEAKER FILENAME 1 39.0 0.8 CRY 0.80 +SPEAKER FILENAME 1 47.9 0.5 NCS 0.62 +``` ### How to run an Evaluation From cfc0c7f6528189662627c017d4dee0b767c365b6 Mon Sep 17 00:00:00 2001 From: MilesICL Date: Wed, 12 Dec 2018 17:48:37 +0000 Subject: [PATCH 145/299] update vcm usage info --- docs/source/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index 0cdcacf..4022673 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -219,7 +219,7 @@ You can read that command as follows: *data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. -It returns one rttm per sound file, with an estimation for the infant vocalisation to be cannonical syllable (CNS), non-cannoical syllable (NCS), and crying (CRY). +It returns one rttm per sound file, with an estimation for the infant vocalisation to be cannonical syllable (CNS), non-cannoical syllable (NCS), crying (CRY), and others (OTH, normally refer to laughing). NOTE: it dependes on the outputs (rttm file) of yunicator. The default path storing rttm file of yunitator is under `data/mydata/` From a42d2e3b1715a032c2e879953e55cf2285fd7f01 Mon Sep 17 00:00:00 2001 From: alecristia Date: Fri, 14 Dec 2018 03:17:59 +0100 Subject: [PATCH 146/299] instructions conversion in progress --- docs/source/formats.md | 44 +++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/docs/source/formats.md b/docs/source/formats.md index 03e0db6..e1598d6 100644 --- a/docs/source/formats.md +++ b/docs/source/formats.md @@ -1,25 +1,51 @@ # Formats -This section explains the input and output formats. Each type of tool returns a different type of output, depending on the key information. +This section explains the input and output formats for each type of tool, and how to convert your files between them. ## Overview -- explain what rttm is & why it's the central format for us -- here, instructions for textgrid and eaf using DAS -- for any other, convert into one of those (eg cha to tg) +The basic file format within DiViMe is a modified form of rttm, which is standard in key diarization tasks, and which allows us to evaluate all tools using a standardized evaluation routine. The different ways of using this same general format are explained below. +Many users, however, will be interested in knowing how to convert into and out of this format into something that is more commonly used for annotation of day-long and other developmental recordings. DiViMe includes routines to convert from any .TextGrid file (produced by the program [Praat](praat.org)); from any .cha file (produced by the program [CLAN](MISSING LINK)); and from .eaf files (produced by the program [ELAN](MISSING LINK)) that have been generated using the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Users who rely on a different program (or for .eaf, on a different file structure) are advised to use the tools in their program or similar others to convert into one of these, or directly into the rttm format explained below. - -If your transcriptions are in TextGrid format but the conversion doesn't seem to work, it's probably because it isn't in the right TextGrid format. -The input TextGrid the system allows is a TextGrid in which all the tiers have speech segments (so remove tiers with no speech segments) and all the annotated segments for each tiers is indeed speech (so remove segments that are noises or other non-speech type). +The following subsections explain how to convert from each of these input formats into a basic reference rttm. ### Input: TextGrid -TextGrid is a standard format for speech annotation, used by the Praat software. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. +TextGrid is a standard format for speech annotation, used by the Praat software. Our process assumes that you will have the speech of each talker diarized in a different tier, using filled intervals when the person is talking, and empty intervals when they are not talking. + +Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. For example, if you have three tiers associated with a talker, coding e.g., what they say, how they say it, and to whom, you should remove 2 of these three tiers, because otherwise each of these tiers will be treated as a different talker. + +Furthermore, any interval that is empty will be seen as *not* containing vocalizations from that speaker. Thus, if your coding is sparse (i.e., if you have a day-long recording, but have only coded some clips here and there), then you should extract the audio clips and annotations for the sections that have been coded, and not process the whole day long recording. (If you do, then your evaluation will be off, because all the speech systems found in sections you have not coded count towards false positives, as if the system had found speech when none was there.) + +Additionally, the name of the tier is what will be taken to be the speaker's name. Therefore, if you have tiers that code speech of some speaker but are named differently, change the tier's name before starting. In fact, some of the tools assume a specific set of names, and thus the tool's output can only be properly evaluated if you use those names. In particular, the child wearing the recording device should be called "CHI". Other children should be called "XC0", where the X is the child's sex (F for Female, M for Male, U for uncertain/undecided/unknown) and 0 is a number 0-9 to identify a unique child. Similarly, adults should be called "XA0" where the X is the child's sex (F for Female, M for Male, U for uncertain/undecided/unknown) and 0 is a number 0-9 to identify a unique adult. Further, you can also define "XU0", a person of unknown age; and "EE0," a voice from a non-human source, such as a toy, radio, or TV. + +Once you have removed all tiers that do not pertain to speakers, made sure that all the empty intervals really are non-vocalizations, renamed the tiers with the speaker's name, and ideally used this set of names, you are ready to convert your .TextGrid files into rttm. Assuming you have put all the textgrids you want to convert inside the folder data/mydata/, you would next run: + +``` +vagrant ssh -c "textgrid2rttm.py data/mydata/" +``` + +### Input: cha + ### Input: Eaf -Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. +Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. Since .eaf's can vary a lot in structure, we only provide tools to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Assuming you have put all the textgrids you want to convert inside the folder data/mydata/, you would next run: + +``` +vagrant ssh -c "eaf2txt.py data/mydata/" +vagrant ssh -c "eaf2enriched_txt.sh data/mydata/" +``` + +The first line serves to create the rttm that will be used by most tools. The second creates an annotation that will be needed for the WCE. + +If your annotations do not follow the ACLEW Annotation Scheme, please look into converting them into something else (.TextGrid or .cha) using ELAN's conversion tools; or potentially try to modify your annotations to fit the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). + +### Input: its + + + ## Speech or Voice activity detection output From f26f926a9087e872d0332e8e7638bcd8b9e4d4bc Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 27 Nov 2018 12:08:49 -0500 Subject: [PATCH 147/299] Refresh EVAL_SAD --- launcher/test.sh | 87 ++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 2f8fa7a..ebfee38 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -7,7 +7,7 @@ KEEPTEMP="" if [ $# -eq 1 ]; then if [ $BASH_ARGV == "--keep-temp" ]; then - KEEPTEMP="--keep-temp" + KEEPTEMP="--keep-temp" fi fi @@ -21,15 +21,14 @@ REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils # Paths to Tools -LDC_SAD_DIR=$REPOS/ldc_sad_hmm -#OPENSATDIR=$REPOS/OpenSAT # noisemes -#OPENSMILEDIR=$REPOS/opensmile-2.3.0/ -#TOCOMBOSAD=$REPOS/To-Combo-SAD -#DIARTKDIR=$REPOS/ib_diarization_toolkit +OPENSATDIR=$REPOS/OpenSAT # noisemes +OPENSMILEDIR=$REPOS/opensmile-2.3.0/ +TOCOMBOSAD=$REPOS/To-Combo-SAD +DIARTKDIR=$REPOS/ib_diarization_toolkit #TALNETDIR=$REPOS/TALNet DSCOREDIR=$REPOS/dscore -#YUNITATORDIR=$REPOS/Yunitator -#VCMDIR=$REPOS/vcm +YUNITATORDIR=$REPOS/Yunitator +VCMDIR=$REPOS/vcm FAILURES=false @@ -48,7 +47,6 @@ cd VanDam-Daylong/BN32/ WORKDIR=`pwd` # Get daylong recording from the web -wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 if [ ! -s BN32_010007.mp3 ]; then echo "Downloading test audio..." wget -q -N https://media.talkbank.org/homebank/Public/VanDam-Daylong/BN32/BN32_010007.mp3 @@ -67,7 +65,7 @@ sox $BASE.mp3 $BASETEST.wav trim $START 5:00 >& /dev/null 2>&1 # silence output $UTILS/chat2stm.sh $BASE.cha > $BASE.stm 2>/dev/null # convert STM to RTTM as e.g. BN32_010007.rttm # shift audio offsets to be 0-relative -cat $BASE.stm | awk -v start=$START -v stop=$STOP -v file=$BASE -e '{if (($4 > start) && ($4 < stop)) print "SPEAKER",file,"1",($4 - start),($5 - $4),"","","","","" }' > $BASETEST.rttm +cat $BASE.stm | awk -v start=$START -v stop=$STOP -v file=$BASE -e '{if (($4 > start) && ($4 < stop)) print "SPEAKER",file"_test","1",($4 - start),($5 - $4),"","","speech","","" }' > $BASETEST.rttm TEST_RTTM=$WORKDIR/$BASETEST.rttm TEST_WAV=$WORKDIR/$BASETEST.wav @@ -86,30 +84,15 @@ rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR cp $WORKDIR/$BASETEST.rttm $TESTDIR -# First test in ldc_sad_hmm -echo "Testing LDC SAD..." -if [ -s $LDC_SAD_DIR/perform_sad.py ]; then -# cd $LDC_SAD_DIR - - $LAUNCHERS/ldcSad.sh $DATADIR/test $KEEPTEMP >& $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} - - if [ -s $TESTDIR/$BASETEST.rttm ]; then - echo "LDC SAD passed the test." - else - FAILURES=true - echo " LDC SAD failed - no output RTTM" - fi -else - echo " LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" -fi # now test Noisemes echo "Testing noisemes..." +cd $OPENSATDIR $LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/noisemes_sad_$BASETEST.rttm ]; then +if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then echo "Noisemes passed the test." else FAILURES=true @@ -119,6 +102,7 @@ fi # now test OPENSMILEDIR echo "Testing OpenSmile SAD..." +cd $OPENSMILEDIR $LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} @@ -131,6 +115,7 @@ fi # now test TOCOMBOSAD echo "Testing ToCombo SAD..." +cd $TOCOMBOSAD $LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} @@ -144,6 +129,7 @@ fi # test DIARTK echo "Testing DIARTK..." +cd $DIARTKDIR cp $TEST_RTTM $TESTDIR # run like the wind @@ -153,16 +139,17 @@ if grep -q "command not found" $TESTDIR/diartk-test.log; then FAILURES=true else if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then - echo "DiarTK passed the test." + echo "DiarTK passed the test." else - FAILURES=true - echo " Diartk failed - no output RTTM" + FAILURES=true + echo " Diartk failed - no output RTTM" fi fi #rm $TESTDIR/$BASETEST.rttm # test Yunitator echo "Testing Yunitator..." +cd $YUNITATORDIR # let 'er rip $LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} @@ -189,26 +176,10 @@ else fi -# testing LDC evalSAD (on opensmile) -echo "Testing LDC evalSAD" -if [ -d $LDC_SAD_DIR ]; then -# cd $LDC_SAD_DIR - - $LAUNCHERS/eval.sh $DATADIR/test opensmileSad $KEEPTEMP > $WORKDIR/test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} - if [ -s $TESTDIR/opensmileSad_eval.df ]; then - echo "LDC evalSAD passed the test" - else - echo " LDC evalSAD failed - no output .df" - FAILURES=true - fi -else - echo " LDC evalSAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" - FAILURES=true -fi - # Testing VCM echo "Testing VCM..." +cd $VCMDIR $LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then @@ -226,10 +197,26 @@ else fi # results +echo "######################################################################################" +echo "To wrap up, we will print out the results of the analyses that we ran during the test." +echo "Compare the following results, corresponding to your system, against the reference results printed out below." +echo "If the numbers are similar, then your system is working similarly to the original one." +echo "If you see bigger changes, then please paste this output onto an issue on https://github.com/srvk/DiViMe/issues/." echo "RESULTS:" for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done +echo "****** REFERENCE RESULTS BEGINS ******." +echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm" +echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" +echo "LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm" +echo "LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm" +echo "LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm" +echo "LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm" +echo "LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" +echo "****** REFERENCE RESULTS ENDS ******." + echo "DSCORE:" cat /vagrant/data/VanDam-Daylong/BN32/test/test.df -echo "EVAL_SAD:" -cat $WORKDIR/test/opensmileSad_eval.df - +echo "****** REFERENCE DSCORE BEGINS ******." +echo "DER B3Precision B3Recall B3F1 TauRefSys TauSysRef CE MI NMI" +echo "Phil_Crane 43.38 0.975590490013 0.672338020576 0.796061934402 0.599223772838 0.963770340456 0.103871357212 1.67823036445 0.793181875273" +echo "****** REFERENCE DSCORE ENDS ******." \ No newline at end of file From 8c893d04f1f199e11c8fc1a7a20a3468a440a073 Mon Sep 17 00:00:00 2001 From: Junghan Date: Tue, 27 Nov 2018 14:45:56 -0500 Subject: [PATCH 148/299] move config files to conf/ --- Vagrantfile | 6 +++--- Dockerfile => conf/Dockerfile | 0 bootstrap.sh => conf/bootstrap.sh | 13 +++++++------ conf/update.sh | 26 ++++++++++++++++++++++++++ update.sh | 21 --------------------- 5 files changed, 36 insertions(+), 30 deletions(-) rename Dockerfile => conf/Dockerfile (100%) rename bootstrap.sh => conf/bootstrap.sh (94%) create mode 100644 conf/update.sh delete mode 100644 update.sh diff --git a/Vagrantfile b/Vagrantfile index 707e168..827fa7a 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -97,11 +97,11 @@ Vagrant.configure("2") do |config| end config.vm.provision "bootstrap", type: "shell", run: "once" do |s| - s.path = "bootstrap.sh" + s.path = "conf/bootstrap.sh" end - config.vm.provision "update", type: "shell", run: "always" do |s| - s.path = "update.sh" + config.vm.provision "update", type: "shell", run: "never" do |s| + s.path = "conf/update.sh" end end diff --git a/Dockerfile b/conf/Dockerfile similarity index 100% rename from Dockerfile rename to conf/Dockerfile diff --git a/bootstrap.sh b/conf/bootstrap.sh similarity index 94% rename from bootstrap.sh rename to conf/bootstrap.sh index d38f72b..8a40a2d 100755 --- a/bootstrap.sh +++ b/conf/bootstrap.sh @@ -38,7 +38,7 @@ rm -f Anaconda-2.3.0-Linux-x86_64.sh # python3 env # Install Miniconda and python libraries # miniconda=Miniconda3-4.5.11-Linux-x86_64.sh -echo "Checking python3" +echo "Create python3 env" cd /home/$user cp /vagrant/conf/environment.yml /home/${user}/ su ${user} -c "/home/${user}/anaconda/bin/conda env create -f environment.yml" @@ -55,7 +55,7 @@ rm /tmp/MCR_R2017b_glnxa64_installer.zip # Install OpenSMILE echo "Installing OpenSMILE" - su ${user} -c "mkdir -p /home/${user}/repos/" +su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz tar zxvf OpenSMILE-2.1.tar.gz @@ -95,6 +95,7 @@ cd /home/${user}/repos/ # Get OpenSAT=noisemes and dependencies # git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev + su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" cp /vagrant/conf/.theanorc /home/${user}/ @@ -108,7 +109,7 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install Yunitator and dependencies -git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev +git clone https://github.com/srvk/Yunitator su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" @@ -116,14 +117,14 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" git clone https://github.com/MilesICL/vcm #Install to-combo sad and dependencies (matlab runtime environnement) -git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 +git clone https://github.com/srvk/To-Combo-SAD # Install DiarTK -git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 +git clone http://github.com/srvk/ib_diarization_toolkit # Install eval -git clone http://github.com/srvk/dscore #--branch v1.0 +git clone http://github.com/srvk/dscore # Phonemizer installation git clone https://github.com/bootphon/phonemizer diff --git a/conf/update.sh b/conf/update.sh new file mode 100644 index 0000000..2707a56 --- /dev/null +++ b/conf/update.sh @@ -0,0 +1,26 @@ + +if grep --quiet vagrant /etc/passwd +then + user="vagrant" +else + user="ubuntu" +fi + +echo "Check git updates" +############################################# +# Get OpenSAT and all the tools +# change version tag as necessary for each tools +cd /home/${user}/repos +(cd "OpenSAT"; git checkout master; git pull) +# (cd "OpenSAT"; git checkout master; git pull; git checkout v2.0) +(cd "ib_diarization_toolkit"; git checkout master; git pull) +# (cd "ib_diarization_toolkit" ; git checkout master; git pull; git checkout v2.0) +(cd "dscore" ; git checkout master; git pull) +# (cd "dscore" ;git checkout master; git pull; git checkout v2.0) +(cd "Yunitator" ;git checkout master; git pull) +# (cd "Yunitator" ; git checkout master; git pull; git checkout v2.0) +(cd "vcm"; git checkout master; git pull) +# (cd "vcm"; git checkout master; git pull; git checkout v2.0) +(cd "To-Combo-SAD" ; git checkout master; git pull) +# (cd "To-Combo-SAD" ; git checkout master; git pull; git checkout v2.0) +############################################# \ No newline at end of file diff --git a/update.sh b/update.sh deleted file mode 100644 index 7f08222..0000000 --- a/update.sh +++ /dev/null @@ -1,21 +0,0 @@ -if grep --quiet vagrant /etc/passwd -then - user="vagrant" -else - user="ubuntu" -fi - -echo "Check git updates" -############################################# -# Get OpenSAT and all the tools -# Install DiarTK, LDC SAD, LDC scoring, Rajat's LENA stuff -cd /home/${user}/repos -release=v1.0 -(cd "OpenSAT"; git pull) -(cd "ib_diarization_toolkit" ; git pull; git checkout $release) -#(cd "ldc_sad_hmm" ; git pull) -(cd "dscore" ; git pull) -(cd "Yunitator" ; git pull) -(cd "vcm"; git pull) -(cd "To-Combo-SAD" ; git pull; git checkout $release) -############################################# From eeeb631ead350cb30da53d667d58649570ed6271 Mon Sep 17 00:00:00 2001 From: Junghan Date: Tue, 27 Nov 2018 17:09:35 -0500 Subject: [PATCH 149/299] bug fix --- conf/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 8a40a2d..e137268 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -69,7 +69,7 @@ su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz tar zxvf OpenSMILE-2.3.tar.gz -chmod +x openSMILE-2.3.0/bin/linux_x64_standalone_static/SMILExtract +chmod +x opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract rm OpenSMILE-2.3.tar.gz # optionally Install HTK (without it, some other tools will not work) From b3f6d39142d93680976828f7aa55072922e582b5 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 27 Nov 2018 22:36:49 +0000 Subject: [PATCH 150/299] update for OpenSMILE 2.3.0 --- conf/turnDetector.conf.inc | 37 +++++++++++++++++++++ conf/vad_segmenter_aclew.conf | 60 +++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100755 conf/turnDetector.conf.inc create mode 100755 conf/vad_segmenter_aclew.conf diff --git a/conf/turnDetector.conf.inc b/conf/turnDetector.conf.inc new file mode 100755 index 0000000..62c7139 --- /dev/null +++ b/conf/turnDetector.conf.inc @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////////////// +///////// > openSMILE LSTM-RNN voice activity detector< ////////////////// +///////// ////////////////// +///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// +///////// All rights reserverd. ////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + + + + +;; turn detector configuration module + +[componentInstances:cComponentManager] +instance[turn].type=cTurnDetector + +[turn:cTurnDetector] +reader.dmLevel=vad_VAD_voice +writer.dmLevel=isTurn +readVad=1 +threshold = -0.1 +threshold2 = -0.1 +writer.levelconf.noHang=1 +msgInterval = 0 +messageRecp = waveSinkCut +eventRecp = waveSinkCut +statusRecp = waveSinkCut +debug=\cm[turndebug{4}:set this to 1 to see turn/speaking debug messages] +;; examples for constraining the turn length +;; minTurnLengthTurnFrameTimeMessage=0.9 +;; maxTurnLength=10.0 +; default (0) is infinite maximum length +maxTurnLength=0 +maxTurnLengthGrace=1 +nPre = 8 +nPost = 35 + + diff --git a/conf/vad_segmenter_aclew.conf b/conf/vad_segmenter_aclew.conf new file mode 100755 index 0000000..2b07ec4 --- /dev/null +++ b/conf/vad_segmenter_aclew.conf @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////////// +///////// > openSMILE LSTM-RNN voice activity detector< ////////////////// +///////// ////////////////// +///////// (c) audEERING UG (haftungsbeschränkt), ////////////////// +///////// All rights reserverd. ////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + + +[componentInstances:cComponentManager] +instance[dataMemory].type = cDataMemory +instance[waveSource].type = cWaveSource + +[waveSource:cWaveSource] +writer.dmLevel = wave +filename = \cm[inputfile(I){input.wav}:name of input file] +monoMixdown = 1 +start = 0 +end = -1 +endrel = 0 +noHeader = 0 +buffersize_sec = 10 + + + ; inculdes a VAD module +\{vad_opensource.conf.inc} + ; and a turn detector module +\{\cm[turnDetector(T){turnDetector.conf.inc}:filename of turn detector config file]} + + +[componentInstances:cComponentManager] + ; the wave file segmenter +instance[waveSinkCut].type = cWaveSinkCut + ; optional: CSV output +instance[csvSink].type = cCsvSink +printLevelStats = 0 + +[waveSinkCut:cWaveSinkCut] +reader.dmLevel = framesVAD +fileBase = \cm[waveoutput(W){output_segment_}:prefix of WAV output files] +fileExtension = .wav +fileNameFormatString = %s%04d%s +startIndex = 1 +preSil = 0.1 +postSil = 0.1 +multiOut = 1 +sampleFormat = 16bit +; sample rate should be read from the input level +; automatically. In some cases this does not work due to +; round-off errors, so you can force it manually here: +;forceSampleRate = 44100 +;forceSampleRate = 16000 +saveSegmentTimes = \cm[saveSegmentTimes{?}:file to save segment times to] + +[csvSink:cCsvSink] +reader.dmLevel=vad_VAD_voice +filename= \cm[csvoutput{?}:name of VAD output file] +printHeader = 0 +timestamp = 1 +number = 0 + From a2788c95476564977300bc156cebdec5667f6ccd Mon Sep 17 00:00:00 2001 From: Junghan Date: Tue, 27 Nov 2018 18:28:27 -0500 Subject: [PATCH 151/299] Vagrant bootstrapping improvement - remove older version of openSMILE (2.1.0 -> 2.3.0) - add useful warnings/breakpoints inside provisioning --- conf/bootstrap.sh | 62 +++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index e137268..832de3e 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -16,7 +16,6 @@ sudo apt-get install -y git make automake libtool autoconf patch subversion fuse libc6-dev-i386 festival espeak python-setuptools gawk \ libboost-all-dev - # Kaldi and others want bash - otherwise the build process fails [ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh @@ -24,13 +23,20 @@ sudo apt-get install -y git make automake libtool autoconf patch subversion fuse echo "Downloading Anaconda-2.3.0..." cd /home/${user} wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh -#bash Anaconda-2.3.0-Linux-x86_64.sh -b # batch install into /home/vagrant/anaconda echo "Installing Anaconda-2.3.0..." sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" + +# check if anaconda is installed correctly +if ! [ -x "$(command -v /home/${user}/anaconda/bin/conda)" ]; then + echo "*******************************" + echo " conda installation failed" + echo "*******************************" + exit 1 +fi + if ! grep -q -i anaconda .bashrc; then echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc fi -# assume 'conda' is installed now (get path) su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" # clean up big installer in home folder rm -f Anaconda-2.3.0-Linux-x86_64.sh @@ -42,13 +48,24 @@ echo "Create python3 env" cd /home/$user cp /vagrant/conf/environment.yml /home/${user}/ su ${user} -c "/home/${user}/anaconda/bin/conda env create -f environment.yml" - +if [ $? -ne 0 ]; then PYTHON3_INSTALLED=false; fi # install Matlab runtime environment +echo "Download matlab installer" cd /tmp wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip +echo "Install matlab" unzip -q MCR_R2017b_glnxa64_installer.zip ./install -mode silent -agreeToLicense yes + +# check if matlab is installed correctly +if [ $? -ne 0 ]; then + echo "*******************************" + echo " matlab installation failed" + echo "*******************************" + exit 1 +fi + # add Matlab stuff to path echo 'LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH"' >> /home/${user}/.bashrc rm /tmp/MCR_R2017b_glnxa64_installer.zip @@ -57,19 +74,11 @@ rm /tmp/MCR_R2017b_glnxa64_installer.zip echo "Installing OpenSMILE" su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ -wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz -tar zxvf OpenSMILE-2.1.tar.gz -# install SMILExtract system-wide -cp openSMILE-2.1.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin -chmod +x /usr/local/bin/SMILExtract -rm OpenSMILE-2.1.tar.gz - -# Install openSMILE2.3.0 -su ${user} -c "mkdir -p /home/${user}/repos/" -cd /home/${user}/repos/ wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz tar zxvf OpenSMILE-2.3.tar.gz chmod +x opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract +cp opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin +if [ $? -ne 0 ]; then OPENSMILE_INSTALLED=false; fi rm OpenSMILE-2.3.tar.gz # optionally Install HTK (without it, some other tools will not work) @@ -85,11 +94,10 @@ if [ -f /vagrant/HTK.tar.gz ]; then sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile make all make install + if [ $? -eq 0 ]; then HTK_INSTALLED=true; fi fi fi - - # POPOULATE THE REPOSITORY SECTION cd /home/${user}/repos/ @@ -99,15 +107,12 @@ cd /home/${user}/repos/ su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" cp /vagrant/conf/.theanorc /home/${user}/ -export PATH=/home/${user}/anaconda/bin:$PATH su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" - # Install ldc-sad # run this version 'by hand' in the VM in repos/ using your github username and password #git clone http://github.com/aclew/ldc_sad_hmm - # Install Yunitator and dependencies git clone https://github.com/srvk/Yunitator su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" @@ -122,7 +127,6 @@ git clone https://github.com/srvk/To-Combo-SAD # Install DiarTK git clone http://github.com/srvk/ib_diarization_toolkit - # Install eval git clone http://github.com/srvk/dscore @@ -139,7 +143,6 @@ python setup.py install # git clone https://github.com/aclew/utils.git # chmod +x utils/* - # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) # and intervaltree (needed for rttm2scp.py) # and recommonmark (needed to make html in docs/) @@ -157,3 +160,20 @@ touch /home/${user}/.Xauthority # Provisioning runs as root; we want files to belong to '${user}' chown -R ${user}:${user} /home/${user} + +# Installation status +if ! $PYTHON3_INSTALLED; then + echo "*********************************************" + echo "Warning: python3 environment is not installed" + echo "*********************************************" +fi +if ! $OPENSMILE_INSTALLED; then + echo "***********************************" + echo "Warning: OpenSMILE is not installed" + echo "***********************************" +fi +if ! $HTK_INSTALLED; then + echo "*****************************" + echo "Warning: HTK is not installed" + echo "*****************************" +fi From 1165af0246780e1e824114fa2d8ca07fb0c5b1a2 Mon Sep 17 00:00:00 2001 From: Junghan Date: Tue, 27 Nov 2018 18:39:56 -0500 Subject: [PATCH 152/299] opensmilesad 2.3.0 path fix --- launcher/opensmileSad.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 54b01b6..35b15d5 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -13,7 +13,7 @@ UTILS=/home/vagrant/utils audio_dir=/vagrant/$1 ### Other variables specific to this script -OSHOME=$REPOS/openSMILE-2.1.0/ +OSHOME=$REPOS/opensmile-2.3.0/ CONFIG_FILE=$UTILS/vad_segmenter_aclew.conf.txt OPENSMILE=$OSHOME/bin/linux_x64_standalone_static/SMILExtract workdir=$audio_dir/temp/opensmileSad From 043671825c7df9b57c8eaaad176ad55691a9f30a Mon Sep 17 00:00:00 2001 From: MarvinLavechin Date: Wed, 28 Nov 2018 01:11:36 +0100 Subject: [PATCH 153/299] Force the user to install HTK 3.4.1, update doc and install_htk.sh in consequences --- docs/source/install.md | 4 ++-- utils/install_htk.sh | 24 +++++++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 2d46840..2b63eca 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -27,8 +27,8 @@ HTK is used by some of these tools (until we find and implement an open-source r - Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) - Register by following the instructions on the left (under "Getting HTK": Register) - Check that you have received your password via email; you will need it for the next step. -- Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). The download is probably called HTK-3.4.1.tar.gz, although the numbers may change if they update their code. -- Move the HTK-*.tar.gz file into the root folder of this repository (alongside Vagrantfile), and rename it HTK.tar.gz +- Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. +- Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). 5. Type diff --git a/utils/install_htk.sh b/utils/install_htk.sh index d82ca12..91e4993 100755 --- a/utils/install_htk.sh +++ b/utils/install_htk.sh @@ -12,16 +12,22 @@ fi # the idea is to make users independently download HTK installer since # we cannot redistribute cd /home/${user} -if [ -f /vagrant/HTK.tar.gz ]; then - if [[ ! -d htk ]]; then - cd /home/${user}/repos/ - sudo tar zxf /vagrant/HTK.tar.gz - cd htk - sudo ./configure --without-x --disable-hslab - sudo sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile - sudo make all - sudo make install +if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then + if [[ ! -d repos/htk ]]; then + cd /home/${user}/repos/ + sudo tar zxf /vagrant/HTK-3.4.1.tar.gz + cd htk + sudo ./configure --without-x --disable-hslab + sudo sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + sudo make all + sudo make install + else + echo "Visibly htk has been already installed..." + echo "You should try to remove the folder repos/htk within the VM" + echo "and rerun this script." fi +else + echo "Can't find HTK-3.4.1.tar.gz. Check that you installed the right version." fi From 23d3b62723f9815e662eacd8153c115b38d16147 Mon Sep 17 00:00:00 2001 From: MarvinLavechin Date: Wed, 28 Nov 2018 02:05:14 +0100 Subject: [PATCH 154/299] Add a speech extractors which extracts segments annotated as speech by a SAD --- utils/speech_extractor.py | 78 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 utils/speech_extractor.py diff --git a/utils/speech_extractor.py b/utils/speech_extractor.py new file mode 100644 index 0000000..5e76b80 --- /dev/null +++ b/utils/speech_extractor.py @@ -0,0 +1,78 @@ +import argparse +import os +import sys +import subprocess + + +def extracts_speech(wav, sad, out): + """ + Read a .rttm file and extracts segments of the wav files that + have been annotated as being speech. + + :param wav: Path to the audio file (.wav). + :param sad: Path to the rttm file (.rttm). + :param out: Folder where the segments need to be stored. + """ + if not os.path.isfile(wav): + print("The audio file %s has not been found." % wav) + sys.exit(1) + + if not os.path.isfile(sad): + print("The SAD file %s has not been found." % sad) + sys.exit(1) + + with open(sad, 'r') as rttm: + for line in rttm: + # Replace tabulations by spaces + fields = line.replace('\t', ' ') + # Remove several successive spaces + fields = ' '.join(fields.split()) + fields = fields.split(' ') + onset, duration, activity = float(fields[3]), float(fields[4]), fields[7] + offset = onset+duration + if activity == 'speech': + basename = os.path.basename(wav).split('.wav')[0] + output = os.path.join(out, '_'.join([basename, str(onset), str(offset)])+'.wav') + cmd = ['sox', wav, output, + 'trim', str(onset), str(duration)] + print("Cutting %s from %s to %s " % (os.path.basename(wav), str(onset), str(offset))) + subprocess.call(cmd) + +def main(): + parser = argparse.ArgumentParser(description="Extracts segments that have" + "been annotated as speech by" + "a SAD tool.") + parser.add_argument('-i', '--input', type=str, required=True, + help="Path to the .wav files (or to the folder containing wav files).") + parser.add_argument('-s', '--sad', type=str, required=False, default="gold", + choices=["ldc_sad", "noisemes", "opensmile", "tocombosad", "gold"], + help="Indicates which SAD needs to be used to extract the audio file.") + parser.add_argument('-o', '--output', type=str, required=False, + help="Path to the folder where the extracted segments need to be stored. " + "(Relative to the input folder)") + args = parser.parse_args() + + wav = os.path.join("/vagrant", args.input) + if args.output is not None: + out = os.path.join(os.path.dirname(wav), args.output) + else: + out = os.path.dirname(wav) + + if not os.path.exists(out): + os.makedirs(out) + + name_map = { + 'ldc_sad': 'ldcSad_', + 'noisemes': 'noisemes_sad_', + 'opensmile': 'opensmileSad_', + 'tocombosad': 'tocomboSad_', + 'gold': '', + } + + sad = os.path.join(os.path.dirname(wav), name_map[args.sad] + os.path.basename(wav).replace(".wav", ".rttm")) + print(sad) + extracts_speech(wav, sad, out) + + +if __name__ == '__main__': + main() \ No newline at end of file From 7f48b528230540e2d0ea29681e1a194684279085 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 28 Nov 2018 14:20:42 +0000 Subject: [PATCH 155/299] use OS 2.3.0 --- launcher/opensmileSad.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 35b15d5..4f5aefb 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -7,15 +7,16 @@ BASEDIR=`dirname $SCRIPT` # this is the home folder of this script conda_dir=/home/vagrant/anaconda/bin REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils +CONF=/vagrant/conf # end of launcher onset routine ### Read in variables from user audio_dir=/vagrant/$1 ### Other variables specific to this script -OSHOME=$REPOS/opensmile-2.3.0/ -CONFIG_FILE=$UTILS/vad_segmenter_aclew.conf.txt -OPENSMILE=$OSHOME/bin/linux_x64_standalone_static/SMILExtract +OSHOME=$REPOS/opensmile-2.3.0 +CONFIG_FILE=$CONF/vad_segmenter_aclew.conf +OPENSMILE=SMILExtract workdir=$audio_dir/temp/opensmileSad mkdir -p $workdir @@ -39,13 +40,13 @@ basename="${filename%.*}" cd $OSHOME/scripts/vad -# Use OpenSMILE 2.1.0 +# Use OpenSMILE 2.3.0 for sad in `ls $audio_dir/*.wav`; do file=$sad id=`basename $file` id=${id%.wav} -# > $audio_dir/${id}.txt #Make it empty if already present + > $audio_dir/${id}.txt #Make it empty if already present echo "Processing $id ..." LD_LIBRARY_PATH=/usr/local/lib \ $OPENSMILE \ @@ -54,7 +55,7 @@ for sad in `ls $audio_dir/*.wav`; do -turndebug 1 \ -noconsoleoutput 1 \ -saveSegmentTimes $workdir/${id}.txt \ - -logfile $workdir/opensmile-vad.log > /dev/null + -logfile $workdir/opensmile-vad.log done for output in $(ls $workdir/*.txt); do From 60e08d9616aed7164356ab1e50544a4edf754158 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 28 Nov 2018 15:18:21 +0000 Subject: [PATCH 156/299] clean temp WAV files --- launcher/opensmileSad.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 4f5aefb..7b2894b 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -58,6 +58,9 @@ for sad in `ls $audio_dir/*.wav`; do -logfile $workdir/opensmile-vad.log done +# clean up generated WAV files in working directory (tool_home/scripts/vad) +rm -f output_segment_*.wav + for output in $(ls $workdir/*.txt); do id=$(basename $output .txt) awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > $audio_dir/opensmileSad_$id.rttm From b61df53b4130f75927f563b43ffc4ae672d59b9c Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 28 Nov 2018 12:03:33 -0500 Subject: [PATCH 157/299] Remove python path env variables - Default python2 anaconda path is in /home/vagrant/.bashrc - for python2 version, just use python - for python3 version, run `source activate divime` and then use python. Be sure to `source deactivate` if switching back to python2 --- launcher/diartk.sh | 20 +++++++++----------- launcher/eval.sh | 2 -- launcher/evalDiar.sh | 3 --- launcher/evalSAD.sh | 6 ++---- launcher/ldcSad.sh | 4 +--- launcher/noisemesSad.sh | 3 --- launcher/opensmileSad.sh | 2 -- launcher/python3/test.sh | 6 ------ launcher/python3/yunitate.sh | 1 - launcher/talnet.sh | 7 ------- launcher/tocomboSad.sh | 2 -- launcher/vcm.sh | 9 --------- launcher/yunitate.sh | 4 +--- utils/noisemes_full.sh | 14 +++----------- utils/runTALNet.sh | 9 --------- utils/yuniSeg.sh | 13 ++----------- 16 files changed, 18 insertions(+), 87 deletions(-) diff --git a/launcher/diartk.sh b/launcher/diartk.sh index 2e3b1cf..cdcb65b 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=/home/vagrant -conda_dir=$BASEDIR/anaconda/bin REPOS=$BASEDIR/repos UTILS=$BASEDIR/utils # end of launcher onset routine @@ -63,30 +61,30 @@ for fin in `ls $audio_dir/*.wav`; do case $trs_format in "ldcSad") sys="ldcSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/ldcSad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/ldcSad_${basename}.rttm $scpfile ;; "noisemesSad") sys="noisemesSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile ;; "tocomboSad") sys="tocomboSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/tocombo_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/tocombo_sad_${basename}.rttm $scpfile ;; "opensmileSad") sys="opensmileSad" - $conda_dir/python $UTILS/rttm2scp.py $audio_dir/opensmile_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/opensmile_sad_${basename}.rttm $scpfile ;; "textgrid") sys="goldSad" - $conda_dir/python /home$UTILS/textgrid2rttm.py $audio_dir/${basename}.TextGrid $workdir/${basename}.rttm - $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + python /home$UTILS/textgrid2rttm.py $audio_dir/${basename}.TextGrid $workdir/${basename}.rttm + python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile rm $workdir/$basename.rttm ;; "eaf") sys="goldSad" - $conda_dir/python /home$UTILS/elan2rttm.py $audio_dir/${basename}.eaf $workdir/${basename}.rttm - $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + python /home$UTILS/elan2rttm.py $audio_dir/${basename}.eaf $workdir/${basename}.rttm + python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile rm $workdir/$basename.rttm ;; "rttm") @@ -95,7 +93,7 @@ for fin in `ls $audio_dir/*.wav`; do # tab them before using them. cp $audio_dir/${basename}.rttm $workdir/${basename}.rttm sed -i 's/ \+/\t/g' $workdir//${basename}.rttm - $conda_dir/python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile ;; *) echo "ERROR: please choose SAD system between:" diff --git a/launcher/eval.sh b/launcher/eval.sh index 49d95c8..8e3e23c 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=/home/vagrant -conda_dir=$BASEDIR/anaconda/bin REPOS=$BASEDIR/repos UTILS=$BASEDIR/utils LAUNCHER=$BASEDIR/launcher diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 3a478af..e2f2eef 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -1,7 +1,4 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc # Absolute path to this script. /home/user/bin/foo.sh SCRIPT=$(readlink -f $0) diff --git a/launcher/evalSAD.sh b/launcher/evalSAD.sh index 97203f7..010e684 100755 --- a/launcher/evalSAD.sh +++ b/launcher/evalSAD.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=`dirname $SCRIPT` # folder where this script resides. Useless. -conda_dir=/home/vagrant/anaconda/bin REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils # end of launcher onset routine @@ -60,7 +58,7 @@ echo $UTILS/create_ref_sys.sh $1 $sys_name true $UTILS/create_ref_sys.sh $1 $sys_name true echo "evaluating" -#$conda_dir/python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys +# python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys # create /vagrant/results if it doesn't exist echo "filename DCF FA MISS" > $audio_dir/${sys_name}_eval.df for lab in `ls $workdir/temp_sys/*.lab`; do @@ -74,7 +72,7 @@ for lab in `ls $workdir/temp_sys/*.lab`; do elif [ ! -s $workdir/temp_sys/$base.lab ] && [ -s $workdir/temp_ref/$base.lab ]; then echo $base" 75.00% 0.00% 100.00%" >> $audio_dir/${sys_name}_eval.df else - $conda_dir/python score.py $workdir/temp_ref $lab | awk -v var="$base" -F" " '{if ($1=="DCF:") {print var"\t"$2"\t"$4"\t"$6}}' >> $audio_dir/${sys_name}_eval.df + python score.py $workdir/temp_ref $lab | awk -v var="$base" -F" " '{if ($1=="DCF:") {print var"\t"$2"\t"$4"\t"$6}}' >> $audio_dir/${sys_name}_eval.df fi done diff --git a/launcher/ldcSad.sh b/launcher/ldcSad.sh index bba281b..3f5d2c9 100755 --- a/launcher/ldcSad.sh +++ b/launcher/ldcSad.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=/home/vagrant -conda_dir=$BASEDIR/anaconda/bin REPOS=$BASEDIR/repos UTILS=$BASEDIR/utils # end of launcher onset routine @@ -36,7 +34,7 @@ bash $UTILS/check_folder.sh $audio_dir cd $LDC_SAD_DIR # launch ldc -$conda_dir/python perform_sad.py -L $workdir $audio_dir/*.wav +python perform_sad.py -L $workdir $audio_dir/*.wav echo "finished using ldcSad_hmm. Please look inside $1 to see the output in *.rttm format" # move all files to name them correctly diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 89c45d2..c8f0394 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -1,8 +1,5 @@ #!/bin/bash # noisemes_sad.sh -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc source activate divime diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 7b2894b..368f204 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -1,10 +1,8 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=`dirname $SCRIPT` # this is the home folder of this script # not the home folder of the 'vagrant' user in the VM -conda_dir=/home/vagrant/anaconda/bin REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils CONF=/vagrant/conf diff --git a/launcher/python3/test.sh b/launcher/python3/test.sh index 77148b1..61d67ed 100644 --- a/launcher/python3/test.sh +++ b/launcher/python3/test.sh @@ -4,12 +4,6 @@ # from a downloaded 5 minute section of the HomeBank VanDam daylong audio sample # ("ACLEW Starter" data) -# this doesn't work because .bashrc exits immediately if not running interactively -#source /home/vagrant/.bashrc -i -# instead: -export PATH=/home/vagrant/anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin -LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH" - KEEPTEMP="" if [ $# -eq 1 ]; then if [ $BASH_ARGV == "--keep-temp" ]; then diff --git a/launcher/python3/yunitate.sh b/launcher/python3/yunitate.sh index b9dadfd..32ea71e 100755 --- a/launcher/python3/yunitate.sh +++ b/launcher/python3/yunitate.sh @@ -4,7 +4,6 @@ source activate divime # run Yunitator with hard coded models & configs -# assumes Python environment in /home/vagrant/anaconda/bin # Absolute path to this script. /home/vagrant/launcher/yunitate.sh SCRIPT=$(readlink -f $0) diff --git a/launcher/talnet.sh b/launcher/talnet.sh index 6ccc956..4f18cf1 100755 --- a/launcher/talnet.sh +++ b/launcher/talnet.sh @@ -1,11 +1,6 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run 537 class classifier with hard coded models & configs found here -# assumes Python environment in /home/${user}/anaconda/ # Absolute path to this script. /home/user/bin/foo.sh SCRIPT=$(readlink -f $0) @@ -30,8 +25,6 @@ basename="${filename%.*}" bash $BASEDIR/check_folder.sh $audio_dir -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH # let's get our bearings: set CWD to the path of TALNet cd $CLASSIFY diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index 303d66f..f59747d 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -1,9 +1,7 @@ #!/bin/bash # Launcher onset routine -source ~/.bashrc SCRIPT=$(readlink -f $0) BASEDIR=`dirname $SCRIPT` -conda_dir=/home/vagrant/anaconda/bin REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils # end of launcher onset routine diff --git a/launcher/vcm.sh b/launcher/vcm.sh index 8ec9b46..dce74b6 100755 --- a/launcher/vcm.sh +++ b/launcher/vcm.sh @@ -1,8 +1,4 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run OpenSAT with hard coded models & configs found here and in /vagrant # assumes Python environment in /home/${user}/ @@ -34,11 +30,6 @@ if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi - - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - # let's get our bearings: set CWD to the path of VCM cd $VCMDIR diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 61a8f73..81f6afd 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -1,10 +1,8 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc source activate divime + # run Yunitator with hard coded models & configs # Absolute path to this script. /home/vagrant/launcher/yunitate.sh diff --git a/utils/noisemes_full.sh b/utils/noisemes_full.sh index b93fcf5..9af469b 100755 --- a/utils/noisemes_full.sh +++ b/utils/noisemes_full.sh @@ -1,8 +1,4 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run OpenSAT with hard coded models & configs found here and in /vagrant # assumes Python environment in /home/${user}/ @@ -29,10 +25,6 @@ basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav bash $BASEDIR/check_folder.sh $audio_dir - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - # let's get our bearings: set CWD to the path of OpenSAT cd $OPENSATDIR @@ -46,10 +38,10 @@ done # then confidences -#/home/vagrant/anaconda/bin/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename +# python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename echo "predicting classes" -#$conda_dir/python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename -$conda_dir/python SSSF/code/predict/1-confidence-vm4.py $audio_dir +# python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename +python SSSF/code/predict/1-confidence-vm4.py $audio_dir echo "noisemes_full finished running" # take all the .rttm in /vagrant/data/hyp_sum and move them to /vagrant/data - move features and hyp_sum to another folder also. diff --git a/utils/runTALNet.sh b/utils/runTALNet.sh index 6da0d8d..df3dd0b 100755 --- a/utils/runTALNet.sh +++ b/utils/runTALNet.sh @@ -1,11 +1,6 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run 537 class classifier with hard coded models & configs found here -# assumes Python environment in /home/${user}/anaconda/ # Absolute path to this script. /home/user/bin/foo.sh SCRIPT=$(readlink -f $0) @@ -29,10 +24,6 @@ basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav bash $BASEDIR/check_folder.sh $audio_dir - -# this is set in user's login .bashrc -#export PATH=/home/${user}/anaconda/bin:$PATH - # let's get our bearings: set CWD to the path of TALNet cd $CLASSIFY diff --git a/utils/yuniSeg.sh b/utils/yuniSeg.sh index 976b135..7f4ccdb 100755 --- a/utils/yuniSeg.sh +++ b/utils/yuniSeg.sh @@ -1,8 +1,4 @@ #!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc -conda_dir=/home/vagrant/anaconda/bin # run YuniSeg with hard coded models & configs found here and in /vagrant # assumes Python environment in /home/${user}/ @@ -38,11 +34,6 @@ trs_format=$2 # Check audio_dir to see if empty or if contains empty wav bash $BASEDIR/check_folder.sh $audio_dir - -# this is set in user's login .bashrc, but may not be if run from outside VM -export PATH=/home/${user}/anaconda/bin:$PATH - - # Iterate over files echo "Starting" for f in `ls $audio_dir/*.wav`; do @@ -80,12 +71,12 @@ for f in `ls $audio_dir/*.wav`; do "textgrid") sys="goldSad" model_prefix=${trs_format}_ - $conda_dir/python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid ${trs_format}_${basename}.rttm + python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid ${trs_format}_${basename}.rttm ;; "eaf") sys="goldSad" model_prefix=${trs_format}_ - $conda_dir/python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf ${trs_format}_${basename}.rttm + python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf ${trs_format}_${basename}.rttm ;; "rttm") sys="goldSad" From cec90dd2d9504fb0da6f8064ad5a6b15fc058f17 Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 28 Nov 2018 12:05:58 -0500 Subject: [PATCH 158/299] add opensmile installation error --- conf/bootstrap.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 832de3e..eaedd48 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -78,9 +78,17 @@ wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz tar zxvf OpenSMILE-2.3.tar.gz chmod +x opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract cp opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin -if [ $? -ne 0 ]; then OPENSMILE_INSTALLED=false; fi rm OpenSMILE-2.3.tar.gz +# check if opensmile if installed +if ! [ -x "$(command -v SMILExtract)" ]; then + echo "*******************************" + echo " OPENSMILE installation failed" + echo "*******************************" + OPENSMILE_INSTALLED=false; +fi + + # optionally Install HTK (without it, some other tools will not work) # the idea is to make users independently download HTK installer since # we cannot redistribute From 82b60da5af72dabc6bfe958309bdd53780f799be Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 28 Nov 2018 12:16:56 -0500 Subject: [PATCH 159/299] python3 readme --- launcher/README.md | 17 +++++++++++++++++ launcher/python3/README.md | 18 ++++++++++++++++++ launcher/python3/readme.txt | 13 ------------- 3 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 launcher/python3/README.md delete mode 100644 launcher/python3/readme.txt diff --git a/launcher/README.md b/launcher/README.md index a81e2ae..f4f9ad6 100755 --- a/launcher/README.md +++ b/launcher/README.md @@ -34,4 +34,21 @@ evalSAD.sh test.sh ``` +### python3 +``` +# activate divime environment to use python 3.6.5 +# put below in run script +source activate divime + +# list of libararies installed can be found with +# conda list +# to install new packages, edit conf/environment.yml file +# to switch back to python 2, run +source deactivate + +# And to use python3, make sure you use correct syntax +# in python files and/or checkout python3 branch from +# each tool +# see python3/ for examples +``` diff --git a/launcher/python3/README.md b/launcher/python3/README.md new file mode 100644 index 0000000..410aca0 --- /dev/null +++ b/launcher/python3/README.md @@ -0,0 +1,18 @@ +### python3 +``` +# activate divime environment to use python 3.6.5 +# put below in run script +source activate divime + +# list of libararies installed can be found with +# conda list +# to install new packages, edit conf/environment.yml file + +# to switch back to python 2, run +source deactivate + +# And to use python3, make sure you use correct syntax +# in python files and/or checkout python3 branch from +# each tool +# see python3/ for examples +``` \ No newline at end of file diff --git a/launcher/python3/readme.txt b/launcher/python3/readme.txt deleted file mode 100644 index c7fce76..0000000 --- a/launcher/python3/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -# activate divime environment to use python 3.6.5 -source activate divime - -# list of libararies installed can be found with -# conda list -# to install new packages, edit environment.yml file - - -# sample usage -# python [some_file] ... - -# to switch back to python 2 -source deactivate \ No newline at end of file From 15a5fa1c938fe3e0ef387863c3f21e0e8b5f7665 Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 28 Nov 2018 15:10:40 -0500 Subject: [PATCH 160/299] Miniconda for future use - tested with test.sh - uses miniconda2-4.5.11, latest as of Nov 18' --- conf/bootstrap.sh | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index eaedd48..b2b6c56 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -41,9 +41,28 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tab # clean up big installer in home folder rm -f Anaconda-2.3.0-Linux-x86_64.sh +# To use miniconda (~40MB) instead of anaconda (~350MB), uncomment below block +# echo "Downloading Miniconda-4.5.11..." +# wget -q https://repo.continuum.io/miniconda/Miniconda2-4.5.11-Linux-x86_64.sh +# echo "Install miniconda (as Anaconda)" +# sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Miniconda2-4.5.11-Linux-x86_64.sh -b -p /home/${user}/anaconda" +# # check if anaconda is installed correctly +# if ! [ -x "$(command -v /home/${user}/anaconda/bin/conda)" ]; then +# echo "*******************************" +# echo " conda installation failed" +# echo "*******************************" +# exit 1 +# fi + +# if ! grep -q -i anaconda .bashrc; then +# echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc +# fi +# su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib cython=0.22.1" + +# # clean up big installer in home folder +# rm -f Miniconda2-4.5.11-Linux-x86_64.sh + # python3 env -# Install Miniconda and python libraries -# miniconda=Miniconda3-4.5.11-Linux-x86_64.sh echo "Create python3 env" cd /home/$user cp /vagrant/conf/environment.yml /home/${user}/ From 3fe75e3f10ed20cc2d5bc0216c9be50b92e8b6a4 Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 15:48:04 -0500 Subject: [PATCH 161/299] minor --- conf/bootstrap.sh | 24 +++-- docs/source/ldcSad.md | 14 --- docs/source/tool_doc.md | 201 +++++++++++++++++++++++++++++++++++++++- utils/install_htk.sh | 2 - 4 files changed, 214 insertions(+), 27 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index b2b6c56..18bfc52 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -112,19 +112,23 @@ fi # the idea is to make users independently download HTK installer since # we cannot redistribute cd /home/${user} -if [ -f /vagrant/HTK.tar.gz ]; then - if [[ ! -d htk ]]; then - cd /home/${user}/repos/ - su ${user} -c "tar zxf /vagrant/HTK.tar.gz" - cd htk - ./configure --without-x --disable-hslab - sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile - make all - make install - if [ $? -eq 0 ]; then HTK_INSTALLED=true; fi +if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then + if [[ ! -d repos/htk ]]; then + cd /home/${user}/repos/ + sudo tar zxf /vagrant/HTK-3.4.1.tar.gz + cd htk + sudo ./configure --without-x --disable-hslab + sudo sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + sudo make all + sudo make install + else + echo "Visibly htk has been already installed..." fi +else + echo "Can't find HTK-3.4.1.tar.gz. Check that you installed the right version." fi + # POPOULATE THE REPOSITORY SECTION cd /home/${user}/repos/ diff --git a/docs/source/ldcSad.md b/docs/source/ldcSad.md index d8d33b5..e69de29 100755 --- a/docs/source/ldcSad.md +++ b/docs/source/ldcSad.md @@ -1,14 +0,0 @@ -# LDC SAD - -## General intro - -LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. - -## Main references: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. - - -## Associated references: -Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. -Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index ebaf836..34d20b2 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -1,3 +1,202 @@ # Detailed Tools Doc -This section of the documentation gets populated with information from the different working tools. +This section contains documentation from the different tools. + + +# LDC SAD + +## General intro + +LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. + +## Main references: + +Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. + + +## Associated references: + +Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. +Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. + +## Questions and bug reports + +Not available + +# NoisemesSad + +## General intro + +Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. + + + + + +## Instructions for direct use (ATTENTION, MAY BE OUTDATED) + +You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. + +``` +$ vagrant ssh -c "OpenSAT/runOpenSAT.sh data/<$MYFILE>" +``` + +You can also analyze a group of files as follows: + +``` +$ vagrant ssh -c "OpenSAT/runDiarNoisemes.sh data/" +``` + +This will analyze all .wav's inside the "data" folder. + +Created annotations will be stored inside the same "data" folder. + +This system will classify slices of the audio recording into one of 17 noiseme classes: + +- background +- speech +- speech non English +- mumble +- singing alone +- music + singing +- music alone +- human sounds +- cheer +- crowd sounds +- animal sounds +- engine +- noise_ongoing +- noise_pulse +- noise_tone +- noise_nature +- white_noise +- radio + +#### Some more technical details + +For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": + +``` +$ vagrant ssh +$ cd OpenSAT +``` + +The main script is runOpenSAT.sh and takes one argument: an audio file in .wav format. +Upon successful completion, output will be in the folder (relative to ~/OpenSAT) +`SSSF/data/hyp//confidence.pkl.gz` + +The system will grind first creating features for all the .wav files it found, then will place those features in a subfolder `feature`. Then it will load a model, and process all the features generated, producing output in a subfolder `hyp/` two files per input: `.confidence.mat` and `.confidence.pkl.gz` - a confidence matrix in Matlab v5 mat-file format, and a Python compressed data 'pickle' file. Now, as well, in the `hyp/` folder, `.rttm` with labels found from a config file [noisemeclasses.txt](https://github.com/riebling/OpenSAT/blob/master/noisemeclasses.txt) + +-More details on output format- + +The 18 classes are as follows: +``` +0 background +1 speech +2 speech_ne +3 mumble +4 singing +5 musicSing +6 music +7 human +8 cheer +9 crowd +10 animal +11 engine +12 noise_ongoing +13 noise_pulse +14 noise_tone +15 noise_nature +16 white_noise +17 radio +``` +The frame length is 0.1s. The system also uses a 2-second window, so the i-th frame starts at (0.1 * i - 2) seconds and finishes at (0.1 * i) seconds. That's why 60 seconds become 620 frames. 'speech_ne' means non-English speech + +-Sample RTTM output snippet- +``` +SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 +SPEAKER family 1 4.6 1.2 background 0.327808111906 +SPEAKER family 1 5.8 1.1 speech 0.430758684874 +SPEAKER family 1 6.9 1.2 background 0.401730179787 +SPEAKER family 1 8.1 0.7 speech 0.407463937998 +SPEAKER family 1 8.8 1.1 background 0.37258502841 +SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +``` + +The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the more detailed results as seen above. + + + +## Main references: + +Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) + + +## Associated references: + +S.Burger,Q.Jin,P.F.Schulam,andF.Metze,“Noisemes:Man- ual annotation of environmental noise in audio streams,” Carnegie Mellon University, Pittsburgh, PA; U.S.A., Tech. Rep. CMU-LTI- 12-07, 2012. +S.Strassel,A.Morris,J.G.Fiscus,C.Caruso,H.Lee,P.D.Over, J. Fiumara, B. L. Shaw, B. Antonishek, and M. Michel, “Creating havic: Heterogeneous audio visual internet collection,” in Proc. +LREC. Istanbul, Turkey: ELRA, May 2012. +F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia fea- ture extractor,” in Proceedings of the 21st ACM international con- ference on Multimedia. ACM, 2013, pp. 835–838. + +## Questions and bug reports + +http://github.com/srvk/OpenSAT/issues + +# OpenSmile SAD + + +## General intro + +openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coefficient RASTA-PLP plus first order delta features. It then uses a long short-term memory recurrent neural network (see details in Eyben et al., 2013b) that has been pre-trained on two corpora of read and spontaneous speech by adults recorded in laboratory conditions, augmented with various noise types. + +## Some more technical details + +These are the parameters that are being used with values that depart from the openSMILE default settings (quoted material comes from either of the openSMILE manuals): + +monoMixdown = 1, means "mix down all recorded channels to 1 mono channel" +noHeader = 0, means read the RIFF header (don't need to specify the parameters ‘sampleRate’, ‘channels’, and possibly ‘sampleSize’) +preSil = 0.1 "Specifies the amount of silence at the turn beginning in seconds, i.e. the lag of the turn +detector. This is the length of the data that will be added to the current segment prior to +the turn start time received in the message from the turn detector component"; we use a tighter criterion than the default (.2) +postSil = 0.1 "Specifies the amount of silence at the turn end in seconds. This is the length of the data +that will be added to the current segment after to the turn end time received in the message +from the turn detector component."; we use a tighter criterion than the default (.3) + +You can change these parameters locally by doing: +``` +$ vagrant ssh +$ nano /vagrant/conf/vad/vadSegmenter_aclew.conf +``` + +openSMILE manuals consulted: + +- Eyben, F., Woellmer, M., & Schuller, B. (2013). openSMILE: The Munich open Speech and Music Interpretation by Large space Extraction toolkit. Institute for Human-Machine Communication, version 2.0. http://download2.nust.na/pub4/sourceforge/o/project/op/opensmile/openSMILE_book_2.0-rc1.pdf +- Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf + + +## Main references for this tool: + +Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. + +Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. + +## Questions and bug reports + +https://www.audeering.com/technology/opensmile/#support + +# TOCombo SAD + +## General intro + +This tool's name stands for "Threshold-Optimized" "combo" SAD; we explain each part in turn. It is a SAD because the goal is to extract speech activity. It is called "combo" because it combines linearly 4 different aspects of voicing (harmonicity , clarity, prediction gain, periodicity) in addition to one perceptual spectral flux feature (see details in Sadjadi & Hansen, 2013). These are extracted in 32-ms frames (with a 10 ms stride). The specific version included here corresponds to the Combo SAD introduced in Ziaei et al. (2014) and used further in Ziaei et al (2016). In this work, a threshold was optimized for daylong recordings, which typically have long silent periods, in order to avoid the usual overly large false alarm rates found in typical SAD systems provided with these data. + +## Main references: + +Ziaei, A., Sangwan, A., & Hansen, J. H. (2014). A speech system for estimating daily word counts. In Fifteenth Annual Conference of the International Speech Communication Association. http://193.6.4.39/~czap/letoltes/IS14/IS2014/PDF/AUTHOR/IS141028.PDF +A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. +S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. + +## Questions and bug reports + +Not available diff --git a/utils/install_htk.sh b/utils/install_htk.sh index 91e4993..1094b67 100755 --- a/utils/install_htk.sh +++ b/utils/install_htk.sh @@ -23,8 +23,6 @@ if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then sudo make install else echo "Visibly htk has been already installed..." - echo "You should try to remove the folder repos/htk within the VM" - echo "and rerun this script." fi else echo "Can't find HTK-3.4.1.tar.gz. Check that you installed the right version." From aad539899f8ea780d1a795acef8852abd2e6f21d Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 16:07:56 -0500 Subject: [PATCH 162/299] reorganized detailed docs --- docs/source/tool_doc.md | 166 ++++++++++++++++++++++++++++++++++------ 1 file changed, 143 insertions(+), 23 deletions(-) diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index 34d20b2..1ec124f 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -1,31 +1,31 @@ -# Detailed Tools Doc +## Speech or Voice activity detection tools -This section contains documentation from the different tools. +This section contains documentation from the different Speech or Voice activity detection tools. -# LDC SAD +## LDC SAD -## General intro +### General intro LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. -## Main references: +### Main references: Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. -## Associated references: +### Associated references: Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. -## Questions and bug reports +### Questions and bug reports Not available -# NoisemesSad +## NoisemesSad -## General intro +### General intro Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. @@ -33,7 +33,7 @@ Noiseme SAD was actually not specifically built as a SAD but rather as a broade -## Instructions for direct use (ATTENTION, MAY BE OUTDATED) +### Instructions for direct use (ATTENTION, MAY BE OUTDATED) You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. @@ -72,7 +72,7 @@ This system will classify slices of the audio recording into one of 17 noiseme c - white_noise - radio -#### Some more technical details +##### Some more technical details For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": @@ -127,30 +127,30 @@ The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the mor -## Main references: +### Main references: Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) -## Associated references: +### Associated references: S.Burger,Q.Jin,P.F.Schulam,andF.Metze,“Noisemes:Man- ual annotation of environmental noise in audio streams,” Carnegie Mellon University, Pittsburgh, PA; U.S.A., Tech. Rep. CMU-LTI- 12-07, 2012. S.Strassel,A.Morris,J.G.Fiscus,C.Caruso,H.Lee,P.D.Over, J. Fiumara, B. L. Shaw, B. Antonishek, and M. Michel, “Creating havic: Heterogeneous audio visual internet collection,” in Proc. LREC. Istanbul, Turkey: ELRA, May 2012. F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia fea- ture extractor,” in Proceedings of the 21st ACM international con- ference on Multimedia. ACM, 2013, pp. 835–838. -## Questions and bug reports +### Questions and bug reports http://github.com/srvk/OpenSAT/issues -# OpenSmile SAD +## OpenSmile SAD -## General intro +### General intro openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coefficient RASTA-PLP plus first order delta features. It then uses a long short-term memory recurrent neural network (see details in Eyben et al., 2013b) that has been pre-trained on two corpora of read and spontaneous speech by adults recorded in laboratory conditions, augmented with various noise types. -## Some more technical details +### Some more technical details These are the parameters that are being used with values that depart from the openSMILE default settings (quoted material comes from either of the openSMILE manuals): @@ -175,28 +175,148 @@ openSMILE manuals consulted: - Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf -## Main references for this tool: +### Main references for this tool: Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. -## Questions and bug reports +### Questions and bug reports https://www.audeering.com/technology/opensmile/#support -# TOCombo SAD +## TOCombo SAD -## General intro +### General intro This tool's name stands for "Threshold-Optimized" "combo" SAD; we explain each part in turn. It is a SAD because the goal is to extract speech activity. It is called "combo" because it combines linearly 4 different aspects of voicing (harmonicity , clarity, prediction gain, periodicity) in addition to one perceptual spectral flux feature (see details in Sadjadi & Hansen, 2013). These are extracted in 32-ms frames (with a 10 ms stride). The specific version included here corresponds to the Combo SAD introduced in Ziaei et al. (2014) and used further in Ziaei et al (2016). In this work, a threshold was optimized for daylong recordings, which typically have long silent periods, in order to avoid the usual overly large false alarm rates found in typical SAD systems provided with these data. -## Main references: +### Main references: Ziaei, A., Sangwan, A., & Hansen, J. H. (2014). A speech system for estimating daily word counts. In Fifteenth Annual Conference of the International Speech Communication Association. http://193.6.4.39/~czap/letoltes/IS14/IS2014/PDF/AUTHOR/IS141028.PDF A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. -## Questions and bug reports +### Questions and bug reports Not available + +## Talker diarization tools + +This section contains documentation from the different Talker diarization tools (i.e., given a speech segment, decide who speaks). + + +## DiarTK + +### General intro + +This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format, from human annotation, or potentially from one of the SAD or VAD tools included in this VM. + +The DiarTK model imported in the VM is a C++ open source toolkit by Vijayasenan & Valente (2012). The algorithm first extracts MFCC features, then performs non-parametric clustering of the frames using agglomerative information bottleneck clustering. At the end of the process, the resulting clusters correspond to a set of speakers. The most likely Diarization sequence between those speakers is computed by Viterbi realignement. + +We use this tool with the following parameter values: + +- weight MFCC = 1 (default) +- Maximum Segment Duration 250 (default) +- Maximum number of clusters possible: 10 (default) +- Normalized Mutual Information threshold: 0.5 (default) +- Beta value: 10 (passed as parameter) +- Number of threads: 3 (passed as parameter) + + +### Main references: + +D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. https://pdfs.semanticscholar.org/71e3/9d42aadd9ec44a42aa5cd21202fedb5eaec5.pdf + +### Questions and bug reports + +http://htk.eng.cam.ac.uk/bugs/buglist.shtml + + +## Other tools + +This section contains documentation from other tools. + + + +## Yunitator + +### General intro + + +Given that there is no reference for this tool, we provide a more extensive introduction based on a presentation Florian Metze gave on 2018-08-13 in an ACLEW Meeting. + +The data used for training were: + +- ACLEW Starter dataset +- VanDam public 5-min dataset (about 13h; https://homebank.talkbank.org/access/Public/VanDam-5minute.html); noiseme-sad used to detect and remove intraturn silences + +Talker identity annotations collapsed into the following 4 types: + +- children (including both the child wearing the device and other children; class prior: .13) +- female adults (class prior .09) +- male adults (class prior .03) +- non-vocalizations (class prior .75) + +The features were MED (multimedia event detection) feature, extracted with OpenSMILE. They were extracted in 2s windows moving 100ms each step. There were 6,669 dims at first, PCA-ed down to 50 dims + +The model was a RNN, with 1 bidirectional GRU layer and 200 units in each direction. There was a softmax output layer, which therefore doesn't predict overlaps.. + +The training regime used 5-fold cross-validation, with 5 models trained on 4/5 of the data and tested on the remainder. The outputs are poooled together to measure performance. The final model was trained on all the data. + +The loss function was cross entropy with classes weighted by 1/prior. The batch size was 5 sequences of 500 frames. The optimizer was SGD with Nesterov momentum=.9, the inital LR was .01 and the LR schedule was *=0.8 if frame accuracy doesn’t reach new best in 4 epochs + +The resulting F1 for the key classes were: + +- Child .55 (Precision .55, recall .55) +- Male adult .43 (P .31, R .61) +- Female adult .55 (P .5, R .62) + + +### Main references: + +There is no official reference for this tool. + +### Questions and bug reports + +Not available + +## VCM + +### General intro +Two independent models: one (modelLing) to predicts linguistic vs. non-linguistic infant vocalisations; the other one (modelSyll) predicts canonical vs. non-canonical syllables if given a linguistic infant vocalization. + +Specifically, the modelLing was trained on an infant linguistic dataset (refer to this paper: https://static1.squarespace.com/static/591f756559cc68d09fc2e308/t/5b3a94cb758d4645603085db/1530565836736/ZhangEtAl_2018.pdf), and modelSyll was trained on another infant syllable vocalisation dataset (refer to this paper: https://pdfs.semanticscholar.org/2b25/bc84d2c4668e6d17f4f9343106f726198cd0.pdf). + +Feature set: 88 eGeMAPS extracted by openSMILE-2.3.0 on the segment level. + +Model: two hidden layers feed-forward neural networks with 1024 hidden nodes per each hidden layer. A log_softmax layer is stacked as an output layer. The optimiser was set to SGD with a learning rate 0.01, and the batch size is 64. + +Setups: Both the infant linguistic and syllable vocalisation datasets were split into train, development, and test partitions following a speaker independent strategy. + +Results: The results are 67.5% UAR and 76.6% WAR on the test set for the lingustic voc classification; and are 70.4% UAR and 69.2% WAR for the syllable voc classification. + + +### Main references: + +There is no official reference for this tool. + +### Questions and bug reports + +https://github.com/MilesICL/vcm/issues/ + + +## TalNet + +### General intro + +There is no information on this tool. + +### Main references: + +There is no official reference for this tool. + +### Questions and bug reports + +Not available + From 513cebed6a55d8b17263183423fe1bf1691d510e Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 16:08:34 -0500 Subject: [PATCH 163/299] reorganized detailed docs --- docs/source/diartk.md | 21 ------- docs/source/ldcSad.md | 0 docs/source/noisemesSad.md | 115 ------------------------------------ docs/source/opensmileSad.md | 37 ------------ docs/source/tocomboSad.md | 13 ---- docs/source/vcm.md | 19 ------ docs/source/yunitator.md | 37 ------------ 7 files changed, 242 deletions(-) delete mode 100755 docs/source/diartk.md delete mode 100755 docs/source/ldcSad.md delete mode 100755 docs/source/noisemesSad.md delete mode 100755 docs/source/opensmileSad.md delete mode 100755 docs/source/tocomboSad.md delete mode 100755 docs/source/vcm.md delete mode 100755 docs/source/yunitator.md diff --git a/docs/source/diartk.md b/docs/source/diartk.md deleted file mode 100755 index 4ac5160..0000000 --- a/docs/source/diartk.md +++ /dev/null @@ -1,21 +0,0 @@ -# DiarTK - -## General intro - -This tool performs diarization, requiring as input not only .wav audio, but also speech/nonspeech in .rttm format, from human annotation, or potentially from one of the SAD or VAD tools included in this VM. - -The DiarTK model imported in the VM is a C++ open source toolkit by Vijayasenan & Valente (2012). The algorithm first extracts MFCC features, then performs non-parametric clustering of the frames using agglomerative information bottleneck clustering. At the end of the process, the resulting clusters correspond to a set of speakers. The most likely Diarization sequence between those speakers is computed by Viterbi realignement. - -We use this tool with the following parameter values: - -- weight MFCC = 1 (default) -- Maximum Segment Duration 250 (default) -- Maximum number of clusters possible: 10 (default) -- Normalized Mutual Information threshold: 0.5 (default) -- Beta value: 10 (passed as parameter) -- Number of threads: 3 (passed as parameter) - - -## Main references: - -D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings,” in Thirteenth Annual Conference of the International Speech Communication Association, 2012. https://pdfs.semanticscholar.org/71e3/9d42aadd9ec44a42aa5cd21202fedb5eaec5.pdf diff --git a/docs/source/ldcSad.md b/docs/source/ldcSad.md deleted file mode 100755 index e69de29..0000000 diff --git a/docs/source/noisemesSad.md b/docs/source/noisemesSad.md deleted file mode 100755 index 21ecbe6..0000000 --- a/docs/source/noisemesSad.md +++ /dev/null @@ -1,115 +0,0 @@ -# NoisemesSad - -## General intro - -Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. - - - - - -## Instructions for direct use (ATTENTION, MAY BE OUTDATED) - -You can analyze just one file as follows. Imagine that <$MYFILE> is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. - -``` -$ vagrant ssh -c "OpenSAT/runOpenSAT.sh data/<$MYFILE>" -``` - -You can also analyze a group of files as follows: - -``` -$ vagrant ssh -c "OpenSAT/runDiarNoisemes.sh data/" -``` - -This will analyze all .wav's inside the "data" folder. - -Created annotations will be stored inside the same "data" folder. - -This system will classify slices of the audio recording into one of 17 noiseme classes: - -- background -- speech -- speech non English -- mumble -- singing alone -- music + singing -- music alone -- human sounds -- cheer -- crowd sounds -- animal sounds -- engine -- noise_ongoing -- noise_pulse -- noise_tone -- noise_nature -- white_noise -- radio - -#### Some more technical details - -For more fine grained control, you can log into the VM and from a command line, and play around from inside the "Diarization with noisemes" directory, called "OpenSAT": - -``` -$ vagrant ssh -$ cd OpenSAT -``` - -The main script is runOpenSAT.sh and takes one argument: an audio file in .wav format. -Upon successful completion, output will be in the folder (relative to ~/OpenSAT) -`SSSF/data/hyp//confidence.pkl.gz` - -The system will grind first creating features for all the .wav files it found, then will place those features in a subfolder `feature`. Then it will load a model, and process all the features generated, producing output in a subfolder `hyp/` two files per input: `.confidence.mat` and `.confidence.pkl.gz` - a confidence matrix in Matlab v5 mat-file format, and a Python compressed data 'pickle' file. Now, as well, in the `hyp/` folder, `.rttm` with labels found from a config file [noisemeclasses.txt](https://github.com/riebling/OpenSAT/blob/master/noisemeclasses.txt) - --More details on output format- - -The 18 classes are as follows: -``` -0 background -1 speech -2 speech_ne -3 mumble -4 singing -5 musicSing -6 music -7 human -8 cheer -9 crowd -10 animal -11 engine -12 noise_ongoing -13 noise_pulse -14 noise_tone -15 noise_nature -16 white_noise -17 radio -``` -The frame length is 0.1s. The system also uses a 2-second window, so the i-th frame starts at (0.1 * i - 2) seconds and finishes at (0.1 * i) seconds. That's why 60 seconds become 620 frames. 'speech_ne' means non-English speech - --Sample RTTM output snippet- -``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 -``` - -The script `runClasses.sh` works like `runDiarNoisemes.sh`, but produces the more detailed results as seen above. - - - -## Main references: - -Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) - - -## Associated references: - -S.Burger,Q.Jin,P.F.Schulam,andF.Metze,“Noisemes:Man- ual annotation of environmental noise in audio streams,” Carnegie Mellon University, Pittsburgh, PA; U.S.A., Tech. Rep. CMU-LTI- 12-07, 2012. -S.Strassel,A.Morris,J.G.Fiscus,C.Caruso,H.Lee,P.D.Over, J. Fiumara, B. L. Shaw, B. Antonishek, and M. Michel, “Creating havic: Heterogeneous audio visual internet collection,” in Proc. -LREC. Istanbul, Turkey: ELRA, May 2012. -F. Eyben, F. Weninger, F. Gross, and B. Schuller, “Recent developments in opensmile, the munich open-source multimedia fea- ture extractor,” in Proceedings of the 21st ACM international con- ference on Multimedia. ACM, 2013, pp. 835–838. diff --git a/docs/source/opensmileSad.md b/docs/source/opensmileSad.md deleted file mode 100755 index 0994e4c..0000000 --- a/docs/source/opensmileSad.md +++ /dev/null @@ -1,37 +0,0 @@ -# OpenSmile SAD - - -## General intro - -openSMILE SAD relies on openSMILE (Eyben et al., 2013a) to generate an 18-coefficient RASTA-PLP plus first order delta features. It then uses a long short-term memory recurrent neural network (see details in Eyben et al., 2013b) that has been pre-trained on two corpora of read and spontaneous speech by adults recorded in laboratory conditions, augmented with various noise types. - -## Some more technical details - -These are the parameters that are being used with values that depart from the openSMILE default settings (quoted material comes from either of the openSMILE manuals): - -monoMixdown = 1, means "mix down all recorded channels to 1 mono channel" -noHeader = 0, means read the RIFF header (don't need to specify the parameters ‘sampleRate’, ‘channels’, and possibly ‘sampleSize’) -preSil = 0.1 "Specifies the amount of silence at the turn beginning in seconds, i.e. the lag of the turn -detector. This is the length of the data that will be added to the current segment prior to -the turn start time received in the message from the turn detector component"; we use a tighter criterion than the default (.2) -postSil = 0.1 "Specifies the amount of silence at the turn end in seconds. This is the length of the data -that will be added to the current segment after to the turn end time received in the message -from the turn detector component."; we use a tighter criterion than the default (.3) - -You can change these parameters locally by doing: -``` -$ vagrant ssh -$ nano /vagrant/conf/vad/vadSegmenter_aclew.conf -``` - -openSMILE manuals consulted: - -- Eyben, F., Woellmer, M., & Schuller, B. (2013). openSMILE: The Munich open Speech and Music Interpretation by Large space Extraction toolkit. Institute for Human-Machine Communication, version 2.0. http://download2.nust.na/pub4/sourceforge/o/project/op/opensmile/openSMILE_book_2.0-rc1.pdf -- Eyben, F., Woellmer, M., & Schuller, B. (2016). openSMILE: open Source Media Interpretation by Large feture-space Extraction toolkit. Institute for Human-Machine Communication, version 2.3. https://www.audeering.com/research-and-open-source/files/openSMILE-book-latest.pdf - - -## Main references for this tool: - -Eyben, F. Weninger, F. Gross, F., &1 Schuller, B. (2013a). Recent developments in OpenSmile, the Munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. - -Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013b). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. diff --git a/docs/source/tocomboSad.md b/docs/source/tocomboSad.md deleted file mode 100755 index 34fa830..0000000 --- a/docs/source/tocomboSad.md +++ /dev/null @@ -1,13 +0,0 @@ -# TOCombo SAD - -## General intro - -This tool's name stands for "Threshold-Optimized" "combo" SAD; we explain each part in turn. It is a SAD because the goal is to extract speech activity. It is called "combo" because it combines linearly 4 different aspects of voicing (harmonicity , clarity, prediction gain, periodicity) in addition to one perceptual spectral flux feature (see details in Sadjadi & Hansen, 2013). These are extracted in 32-ms frames (with a 10 ms stride). The specific version included here corresponds to the Combo SAD introduced in Ziaei et al. (2014) and used further in Ziaei et al (2016). In this work, a threshold was optimized for daylong recordings, which typically have long silent periods, in order to avoid the usual overly large false alarm rates found in typical SAD systems provided with these data. - -## Main references: - -Ziaei, A., Sangwan, A., & Hansen, J. H. (2014). A speech system for estimating daily word counts. In Fifteenth Annual Conference of the International Speech Communication Association. http://193.6.4.39/~czap/letoltes/IS14/IS2014/PDF/AUTHOR/IS141028.PDF -A. Ziaei, A. Sangwan, J.H.L. Hansen, "Effective word count estimation for long duration daily naturalistic audio recordings," Speech Communication, vol. 84, pp. 15-23, Nov. 2016. -S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux," IEEE Signal Processing Letters, vol. 20, no. 3, pp. 197-200, March 2013. - - diff --git a/docs/source/vcm.md b/docs/source/vcm.md deleted file mode 100755 index fa02fcd..0000000 --- a/docs/source/vcm.md +++ /dev/null @@ -1,19 +0,0 @@ -# VCM - -## General intro -Two independent models: one (modelLing) to predicts lingustic vs. non-linguistic infant vocalisations; the other one (modelSyll) predicts canonical vs. non-canonical syllables if given a lingustic infant vocalication. - -Specifically, the modelLing was trained on Alex's infant lingustic dataset (refer to this paper: https://static1.squarespace.com/static/591f756559cc68d09fc2e308/t/5b3a94cb758d4645603085db/1530565836736/ZhangEtAl_2018.pdf), and modelSyll was trained on Anne's infant syllable vocalisation dataset (refer to this paper: https://pdfs.semanticscholar.org/2b25/bc84d2c4668e6d17f4f9343106f726198cd0.pdf). - -Feature set: 88 eGeMAPS extracted by openSMILE-2.3.0 on the segment level. - -Model: two hidden layers feed-forward neural networks with 1024 hidden nodes per each hidden layer. A log_softmax layer is stacked as an output layer. The optimiser was set to SGD with a learning rate 0.01, and the batch size is 64. - -Setups: Both the infant linguistic and syllable vocalisation datasets were split into train, development, and test partitions following a speaker independent strategy. - -Results: The results are 67.5% UAR and 76.6% WAR on the test set for the lingustic voc classification; and are 70.4% UAR and 69.2% WAR for the syllable voc classification. - - -## Main references: - -There is no official reference for this tool. diff --git a/docs/source/yunitator.md b/docs/source/yunitator.md deleted file mode 100755 index 479f06e..0000000 --- a/docs/source/yunitator.md +++ /dev/null @@ -1,37 +0,0 @@ -# Yunitator - -## General intro - - -Given that there is no reference for this tool, we provide a more extensive introduction based on a presentation Florian Metze gave on 2018-08-13 in an ACLEW Meeting. - -The data used for training were: - -- ACLEW Starter dataset -- VanDam public 5-min dataset (about 13h; https://homebank.talkbank.org/access/Public/VanDam-5minute.html); noiseme-sad used to detect and remove intraturn silences - -Talker identity annotations collapsed into the following 4 types: - -- children (including both the child wearing the device and other children; class prior: .13) -- female adults (class prior .09) -- male adults (class prior .03) -- non-vocalizations (class prior .75) - -The features were MED (multimedia event detection) feature, extracted with OpenSMILE. They were extracted in 2s windows moving 100ms each step. There were 6,669 dims at first, PCA-ed down to 50 dims - -The model was a RNN, with 1 bidirectional GRU layer and 200 units in each direction. There was a softmax output layer, which therefore doesn't predict overlaps.. - -The training regime used 5-fold cross-validation, with 5 models trained on 4/5 of the data and tested on the remainder. The outputs are poooled together to measure performance. The final model was trained on all the data. - -The loss function was cross entropy with classes weighted by 1/prior. The batch size was 5 sequences of 500 frames. The optimizer was SGD with Nesterov momentum=.9, the inital LR was .01 and the LR schedule was *=0.8 if frame accuracy doesn’t reach new best in 4 epochs - -The resulting F1 for the key classes were: - -- Child .55 (Precision .55, recall .55) -- Male adult .43 (P .31, R .61) -- Female adult .55 (P .5, R .62) - - -## Main references: - -There is no official reference for this tool. From 0d4e3841dbe51ac5d0463a6d6cdb51584b6ffd4a Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 16:41:36 -0500 Subject: [PATCH 164/299] reorg --- docs/source/formats.md | 59 ++++++++++++++++++++++----------------- docs/source/index.rst | 1 + docs/source/references.md | 15 ---------- docs/source/usage.md | 2 +- 4 files changed, 36 insertions(+), 41 deletions(-) diff --git a/docs/source/formats.md b/docs/source/formats.md index 081b3ba..41e87e6 100644 --- a/docs/source/formats.md +++ b/docs/source/formats.md @@ -1,8 +1,23 @@ -=========== END ===== +# Formats -TO ADD SOMEWHERE ELSE -Specific examples for the different tool types -- If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named toolnameSad_filename.rttm, which will look like this: +This section explains the input and output formats. Each type of tool returns a different type of output, depending on the key information. + +### Input: TextGrid + +TextGrid is a standard format for speech annotation, used by the Praat software. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. + +### Input: Eaf + +Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. + + +## Speech or Voice activity detection output + +RTTM is an annotation format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) +This format is used by the [DiViMe](https://github.com/srvk/DiViMe). + + +Tools that are of the SAD type (SAD or VAD) return one rttm per audio file, named toolnameSad_filename.rttm, which looks like this: ``` SPEAKER file17 1 0.00 0.77 speech @@ -10,33 +25,27 @@ SPEAKER file17 1 1.38 2.14 speech ``` -- If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the previous bulletpoint. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then provide them with a clear error, such as “TOOLNAME failed because you did not provide a sad/vad annotation file. Please refer to the docs for the list of available sad/vad tools.”. Your diarization-type tool should return one rttm per audio file, named toolnameDiar_filename.rttm, which must look like this: +The fourth column indicates the onset of a speech region; the forth column the duration of that speech region. All other columns may be ignored. Regions of non-speech are all the others (e.g., in this example, between .77 and 1.38). -``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 -``` +## Diarization style (diarization or role assignment) output + +RTTM is an annotation format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) +This format is used by the [DiViMe](https://github.com/srvk/DiViMe). -- If your tool is not a VAD/SAD but it is a classifier that assumes only raw acoustic input, then declare it as a sad/vad, and follow the instructions for vad/sad above, except that you'll adapt the rttm output to the classes you typically have. For example, one tool classifies audio into noiseme categories. It returns rttm's like this one: +Diarization-type tools return one rttm per audio file, named toolnameDiar_filename.rttm, which looks like this: ``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +SPEAKER file17 1 4.2 0.4 talker0 +SPEAKER file17 1 4.6 1.2 talker0 +SPEAKER file17 1 5.8 1.1 talker1 +SPEAKER file17 1 6.9 1.2 talker0 +SPEAKER file17 1 8.1 0.7 talker1 ``` -** todo: expand diar tool section** -- If your tool is a classifier or annotator that works only on a subtype of speaker (e.g., only on children's speech, or only on adults’ speech), then assume that each wav is accompanied by an rttm that has this information noted in column XX. -** todo: expand add tool section** +The fourth column indicates the onset of a region, the identity being indicated in ; the forth column the duration of that speech region. All other columns may be ignored. Regions of non-speech are all the others (e.g., in this example, between .77 and 1.38). + + + diff --git a/docs/source/index.rst b/docs/source/index.rst index 98f3fe8..b9e52c7 100755 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,6 +13,7 @@ Welcome to DiViMe's documentation! initial_questions install usage + furterInfo formats tool_doc troubleshoot diff --git a/docs/source/references.md b/docs/source/references.md index afe8654..7fda6a7 100755 --- a/docs/source/references.md +++ b/docs/source/references.md @@ -1,18 +1,3 @@ -# File Formats - -### RTTM - -RTTM is an annotaion format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) -This format is used by the [DiViMe](https://github.com/srvk/DiViMe). - -### TextGrid - -TextGrid is a standard format for speech annotation, used by the Praat software. - -### Eaf - -Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. - # References diff --git a/docs/source/usage.md b/docs/source/usage.md index ab609fc..2242794 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -61,7 +61,7 @@ Pure diarization tools only perform talker diarization (i.e., *who* speaks) but - opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. - tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran tocombosad, the system will run it for you. - textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. -- eaf: this means you want the system to use your eaf annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your eaf files before you start. Please note that the system will convert your eafs into .rttm in the process. +- eaf: this means you want the system to use your eaf annotations. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. - rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. Finally, if no parameter is provided, the system will give an error. From 8ce4cbc950f47e0f800464798bedc9793f8efed6 Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 28 Nov 2018 18:37:55 -0500 Subject: [PATCH 165/299] gladys recs implemented --- docs/source/furtherInfo.md | 40 ++++++ docs/source/initial_questions.md | 4 +- docs/source/install.md | 41 ++---- docs/source/tool_doc.md | 6 +- docs/source/usage.md | 237 ++++++++++++++++++++++++++----- 5 files changed, 262 insertions(+), 66 deletions(-) create mode 100755 docs/source/furtherInfo.md diff --git a/docs/source/furtherInfo.md b/docs/source/furtherInfo.md new file mode 100755 index 0000000..f6b2ab0 --- /dev/null +++ b/docs/source/furtherInfo.md @@ -0,0 +1,40 @@ +# More information about DiViMe + +DiViMe is a virtual machine, whose characteristics and contents are almost completely determined by provisioning scripts found in the DiViMe folder created when you did `git clone https://github.com/srvk/DiViMe/. This section provides information to help you understand the DiViMe structure in conceptual terms (the "pipeline"). We also explain the process of "bootstrapping" or creation of this virtual machine. Finally, we describe the folder structure. If you just want to use the tools in DiViMe, you can probably skip this whole section, or read just the `Pipeline structure` section. + +## Pipeline Structure + +DiViMe is a platform for tools to analyze naturalistic, unannotated audiorecordings. We consider this process to involve three kinds of processes: + +- speech activity detection and voice activity detection = “detecting vocalizations”, +- diarization = “deciding to whom the vocalizations belong”, and +- “additional annotations” + + +Some tools actually combine two of these stages (e.g. a tool may do both speech activity detection and role attribution in one fell swoop). + +## Building a virtual machine + +The structures and contents of the VM are actually built from reproducible directives which are executed when you do `vagrant up`. In technical terms, this is called VM is _provisioning_. In a nutshell, a file called "Vagrantfile" builds the machine (e.g., creates a virtual machine, allocates memory, installs an operating systems). Another file (conf/bootstrap.sh) installs tools within this virtual machine. For detailed documentation, see https://www.vagrantup.com/docs/vagrantfile/. + + + +## Folder Structure + +By virtue of how DiViMe is provisioned, there is some information that is accessible both from the host machine (i.e., your computer) and the virtual machine (i.e., the minicomputer built inside your computer). These are called `shared folders`. + +*The following folders are shared between the host and the virtual machine, and thus accessible from both:* + +- *utils/* contains ancillary files, typically used across more than one tool +- *launcher/* contains files that target users will use to launch different tools +- *conf/* is for configuration files for two potential reasons: they are shared across more than one tool, or to make them more easily editable from outside the VM +- *data/* folder where users put the data to be analyzed, and recover the automatically annotated files + +From within the virtual machine, these are inside /vagrant: /vagrant/utils, /vagrant/launcher, etc. Some of these are also accessible from the home of the default user, through links, ie, ~/utils and ~/launcher. (the default user is vagrant for virtualbox) + +*The following folders can only be found within the virtual machine*: + +- *repos/* contains any repository that is cloned into the machine, typically tools for the user, but also tools used by other tools to do e.g. feature extraction. + +From within the virtual machine, ~/repos is inside the vagrant user’s home folder, so you can access it as ~/repos/ or /home/vagrant/repos. + diff --git a/docs/source/initial_questions.md b/docs/source/initial_questions.md index a996352..544e226 100755 --- a/docs/source/initial_questions.md +++ b/docs/source/initial_questions.md @@ -10,7 +10,9 @@ It is a collection of speech processing tools allowing users to automatically ad 3) Role diarization (_what kind of person is talking?_) -We are hoping to add more tools in the future, including register detection, syllable quantification, and vocal maturity estimation. +4) Vocal type classification (_what kind of vocalization is this one?_) + +We are hoping to add more tools in the future, including register detection, and syllable quantification. ## Who is the ACLEW DiViMe for? diff --git a/docs/source/install.md b/docs/source/install.md index 2b63eca..48a9924 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -6,33 +6,21 @@ Try the following first: 1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link and follow the prompted instructions -1. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. +2. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. -2. Clone the present repository: +3. Clone the present repository: To do this, you must use a terminal. If you don't know what this means, we recommend that you first follow the [Software Carpentry Shell Tutorial](https://swcarpentry.github.io/shell-novice/) (up to 00:45, namely "Introducing the shell", and "Navigating files and directories"). Next, navigate to the directory in which you want the VM to be hosted and type in: `$ git clone https://github.com/srvk/DiViMe` - - Open a terminal window - - In it, navigate to the directory in which you want the VM to be hosted - - type in: +4. Change into this folder: `$ cd DiViMe` -`$ git clone https://github.com/srvk/DiViMe` +5. Install HTK. HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. -3. Change into it by + - Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) + - Register by following the instructions on the left (under "Getting HTK": Register) + - Check that you have received your password via email; you will need it for the next step. + - Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. + - Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). -`$ cd DiViMe` - -4. Install HTK - -HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. - -- Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) -- Register by following the instructions on the left (under "Getting HTK": Register) -- Check that you have received your password via email; you will need it for the next step. -- Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. -- Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). - -5. Type - -`$ vagrant up` +6. Type `$ vagrant up` The first time you do this, it will take at least 20 minutes to install all the packages that are needed to build the virtual machine. Once the virtual machine will be installed, it will stay stuck at "installation finished" for few minutes. However, the tools are not yet installed at this step. @@ -40,7 +28,7 @@ You will need to wait for the tools to be installed, and to take back the contro The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/srvk/DiViMe/issues), describing your situation. -Advanced topic: [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker) +We are working on [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker), but this option is not yet functional. ## Checking your installation @@ -73,20 +61,19 @@ DiarTK passed the test. Congratulations, everything is OK! -This is the simple test with a few short files. If you would like to run a test for use with daylong recordings, please run $ vagrant ssh -c "launcher/test-daylong.sh". Note that this will download a very large recording. ``` ## Common installation errors and fixes -- For LDC SAD, you may get an error "LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include LDC SAD. This error means that you cannot use LDC SAD, but you can use any other SAD/VAD. (For example, noisemesSad.) -- For LDC SAD, Noisemes, and DiarTK, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. The easiest way to fix it is to install HTK (again). +- For ldcSad, you may get an error "ldcSad failed because the code for ldcSad is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include ldcSad. This error means that you cannot use ldcSad, but you can use any other SAD/VAD. (For example, noisemesSad.) +- For ldcSad, noisemesSad, and diartkDiar, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. ## Updating DiViMe -If there is a new version of DiViMe, you'll need to perform the following 3 steps from within the DiViME folder on your terminal: +If there is a new version of DiViMe, you will need to perform the following 3 steps from within the DiViME folder on your terminal: ``` diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index 1ec124f..d7934d6 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -1,4 +1,4 @@ -## Speech or Voice activity detection tools +# Speech or Voice activity detection tools This section contains documentation from the different Speech or Voice activity detection tools. @@ -201,7 +201,7 @@ S.O. Sadjadi, J.H.L. Hansen, "Unsupervised Speech Activity Detection using Voici Not available -## Talker diarization tools +# Talker diarization tools This section contains documentation from the different Talker diarization tools (i.e., given a speech segment, decide who speaks). @@ -233,7 +233,7 @@ D. Vijayasenan and F. Valente, “Diartk: An open source toolkit for research in http://htk.eng.cam.ac.uk/bugs/buglist.shtml -## Other tools +# Other tools This section contains documentation from other tools. diff --git a/docs/source/usage.md b/docs/source/usage.md index 2242794..0403454 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -6,36 +6,103 @@ This is an overview of the full tool presentation found in the next stage, recap 1. Put your data in the ```data``` shared directory. 2. Do `$ vagrant up` to "wake the machine up" -3. Choose between: running a speech activity detection system followed by a diarization system (steps 3 and 4 below), or a tool that directly segments recordings into 3 main roles, namely child, male adult, female adult (step 5 below) -4. If you have some annotations, you can evaluate how the tools did (step 6 below) -5. Finally, remember to put the machine back to sleep with `$ vagrant halt` + Next we provide instructions for all tools. More detailed information about each tool can be found in separate readme's. -## Short instructions for all tools +Assuming the installation of the virtual machine is complete and some of the tests have passed, you can now use at least some of the tools in the virtual machine. We explain more about each step below, but in a nutshell, the steps to use DiViMe are always the same: + +1. Put the data you want to process in the ```data/``` directory (or any subdirectory within ```data/```) +2. Go to the DiViMe folder +3. Do `$ vagrant up` to "wake the machine up" +4. Use tools on data, typically by doing `vagrant ssh -c "script.sh [arguments]"`. You can also run a recipe. +5. Finally, remember to put DiViMe back to sleep with `$ vagrant halt` + + +## Further information on Step 1, putting your data into the ```data/``` directory + +Put the sound files that you want analyzed (and annotations, if you have any) inside the shared ```data``` folder. It is probably safer to make a copy of your files (rather than moving them), in case you later decide to delete the whole folder. + +You can drop a whole folder into ```data```. You will provide the path to the specific folder to be analyzed when running the tools (as per instructions below). All `.wav` files in that folder will be analyzed. + +If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. + +If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. For more information on these formats, see the Format section. + +IMPORTANT: If you already analyzed a file with a given tool, re-running the tool will result in the previous analysis being overwritten. + +## Further information on Step 2, going to the DiViMe folder + +To interact with the virtual machine, you must use a terminal. If you don't know what this means, we recommend that you first follow the [Software Carpentry Shell Tutorial](https://swcarpentry.github.io/shell-novice/) (up to 00:45, namely "Introducing the shell", and "Navigating files and directories"). -1. Put sound files (and annotations, if you have any) inside the shared ```data``` folder. If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. +Next, navigate in the terminal window to the DiViMe directory that was created when you did `git clone https://github.com/srvk/DiViMe` when installing DiViMe. - If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. It is probably safer to make a copy (rather than moving them), in case you later decide to delete the whole vagrant folder. -2. Launch the virtual machine anytime by navigating to your DiViMe folder on your terminal and performing: +## Further information on Step 3, Waking the machine up + +Remember that you will be using a mini-computer within your computer. Typically, the machine will be down - i.e., it will not be running. This is good, because when it is running, it will use memory and other resources from your computer (which we call "the host", because it is hosting the other computer). With this step, you launch the virtual machine: `$ vagrant up` -3. For the SAD tools, type a command like this one: +## Further information on Step 4, Using tools on data + +### Overview of tools + +If all tools passed the test, then you'll be able to automatically add the following types of annotation to your audio files: + +1) Speech activity detection (_when is someone talking?_): The tools available for this task are the following: noisemesSad, tocomboSad, opensmileSad, ldcSad + +2) Talker diarization (_who is talking?_) The tools available for this task are the following: diartkDiar + +3) Role diarization (_what kind of person is talking?_) The tools available for this task are the following: yunitator + +4) Vocal type classification (_what kind of vocalization is this one?_) The tools available for this task are the following: vcm + +5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, ldcSad, diartkDiar, yunitator + +### Overview of "pipelines" + +DiViMe is a platform for tools to analyze naturalistic, unannotated audiorecordings. We consider this process to involve three kinds of processes: + +- speech activity detection and voice activity detection = “detecting vocalizations”, +- diarization = “deciding to whom the vocalizations belong”, and +- “additional annotations” -`$ vagrant ssh -c "launcher/noisemesSad.sh data/"` +Some tools actually combine two of these stages (e.g. a tool may do both speech activity detection and role attribution in one fell swoop). This [flowchart](https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9) may help. -This will create a set of new rttm files, with the name of the tool added at the beginning. For example, imagine you have a file called participant23.wav, and you decide to run two SADs: +We call a *pipeline* a sequence of those processes; i.e., it involves using one tool after another. For example, you may do *speech activity detection* + *talker diarization* + *vocal type classification* + +Starting from an audio file with no annotation, typically, you may want to run a *speech activity detection* tool followed by a *talker diarization* tool; then you will end up with an annotation showing who spoke when. However, you may not know who "talker0" and "talker1" are. (You could decide this by listening to some samples of each, and mapping them to different roles. However, we do not provide tools to do this.) + +Alternatively, we provide a *role diarization* tool that directly segments recordings into 3 main roles, namely child, male adult, female adult; and these separated from silence. + +In both cases, you may want to classify each vocalizations into different types with the *vocal type classification* tool. + +### How to run a Speech or Voice activity detection tool + +For these tools, type a command like this one: + +`$ vagrant ssh -c "noisemesSad.sh data/mydata/"` + +You can read that command as follows: + +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. + +*noisemesSad.sh*: This first argument tells DiViMe which tool to run. The options are: noisemesSad.sh, tocomboSad.sh, opensmileSad.sh, ldcSad.sh + +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. + + +For each input wav file, there will be one rttm file created in the same directory, with the name of the tool added at the beginning. For example, imagine you have put a single file called participant23.wav into ```data/```, and you decided to run two SADs: ``` -$ vagrant ssh -c "launcher/opensmileSad.sh data/" -$ vagrant ssh -c "launcher/noisemesSad.sh data/" +$ vagrant ssh -c "opensmileSad.sh data/" +$ vagrant ssh -c "noisemesSad.sh data/" ``` -This will result in your having the following three files in your /data/ folder: +This will result in your having the following three files in your ```data/``` folder: - participant23.wav - opensmileSad_participant23.rttm @@ -50,46 +117,146 @@ SPEAKER participant23 1 1.38 2.14 speech This means that opensmileSad considered that the first 770 milliseconds of the audio were speech; followed by 610 milliseconds of non-speech, followed by 2.14 seconds of speech; etc. -4. There is one **pure diarization** tool: diartk. Here is the command to run, for the data/ input folder: +### How to run a Talker diarization tool + +For these tools, type a command like this one: + +`$ vagrant ssh -c "diartk.sh data/mydata/ noisemesSad"` + +You can read that command as follows: + +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. -`$ vagrant ssh -c "launcher/diartk.sh data/ noisemesSad"` +*diartk.sh*: This first argument tells DiViMe which tool to run. The options are: diartk.sh. -Pure diarization tools only perform talker diarization (i.e., *who* speaks) but not speech activity detection (*when* is someone speaking). Therefore, this system requires some form of SAD. The third parameter ('noisemes') tells the system which SAD annotation to use, from among the list: +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. + +*noisemesSad*: Remember that this tool does "talker diarization": Given some speech, attribute it to a speaker. Therefore, this type of tool necessitates speech/voice activity detection. This third argument tells DiViMe what file contains information about which sections of the sound file contain speech. + +You can only use one of the following options: textgrid, eaf, rttm, ldcSad, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. + +You can provide annotations done by a human or in some other way, and encoded as one of the following three file types: -- ldcSad: this means you want the system to use the output of the LDC_SAD system. If you have not run LDC_SAD, the system will run it for you. -- noisemesSad: this means you want the system to use the output of the noisemesSad system. If you have not run LDC_SAD, the system will run it for you. -- opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run opensmile, the system will run it for you. -- tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran tocombosad, the system will run it for you. - textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. - eaf: this means you want the system to use your eaf annotations. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. -- rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eigth column count as such. +- rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eight column count as such. + + +Alternatively, you can provide use automatic annotations generated by DiViMe's speech/voice activity detection systems, encoded in rttm files. In this case, you would pass one of the following options: + +- ldcSad: this means you want the system to use the output of the ldcSad system. If you have not run this system before, the system will fail. +- this system before: this means you want the system to use the output of the noisemesSad system. If you have not run noisemesSad, the system will fail. +- opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run this system before, the system will fail. +- tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran this system before, the system will fail. + +If the third parameter is not provided, the system will give an error. + +If all three parameters are provided, then the system will first find all the annotation files matching the third parameter (e.g., all the files *.TextGrid; or all the tocomboSad_*.rttm files), and then find the corresponding sound files. For example, imagine you have put into your ```data/mydata/``` folder the following files: + +- participant23.wav +- opensmileSad_participant23.rttm +- participant24.wav +- participant24.TextGrid + + +If you run: + +`$ vagrant ssh -c "diartk.sh data/mydata/ opensmileSad"` + +then only participant23.wav will be analyzed. + + +If you run: + +`$ vagrant ssh -c "diartk.sh data/mydata/ textgrid"` + +then only participant24.wav will be analyzed. + +At the end of the process, there will be an added rttm file for each analyzed file. For instance, if you have just one sound file (participant23.wav) at the beginning and you run opensmileSad followed by diartk, then you will end up with the following three files: + +- participant23.wav: your original sound file +- opensmileSad_participant23.rttm: the output of opensmileSad, which states where there is speech +- diartk_opensmileSad_participant23.rttm: the output of opensmileSad followed by diartk, which states which speech sections belong to which speakers. + +If you look inside a diartk_*.rttm file, it will look as follows: + +``` +SPEAKER file17 1 4.2 0.4 talker0 +SPEAKER file17 1 4.6 1.2 talker0 +SPEAKER file17 1 5.8 1.1 talker1 +SPEAKER file17 1 6.9 1.2 talker0 +SPEAKER file17 1 8.1 0.7 talker1 +``` + +This means that diartk considered that one talker spoke starting at 4.2 seconds for .4 seconds; starting at 4.6 for 1.2 seconds; then someone else spoke starting at 5.8 seconds and for 1.1 seconds; etc. + +### How to run a Role assignment tool + +For these tools, type a command like this one: + +`$ vagrant ssh -c "yunitator.sh data/mydata/"` + +You can read that command as follows: + +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. + +*yunitator.sh*: This first argument tells DiViMe which tool to run. The options are: yunitator. + +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. + +It returns one rttm per sound file, with an estimation of where there are vocalizations by children, female adults, and male adults. + +### How to run a Vocalization classification tool + +NO INFORMATION YET + +### How to run an Evaluation + +If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. + +#### Evaluating Speech/Voice activity detection + +Type a command like the one below: + +`$ vagrant ssh -c "evalSAD.sh data/ noisemesSad"` + +You can read that command as follows: + +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. + +*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. + +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. + +*noisemesSad*: The third argument indicates which tool's output to evaluate (in this case, noisemesSad). All of our Speech/Voice activity detection tools can be evaluated with this. + +For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). + +#### Evaluating Speech/Voice activity detection -Finally, if no parameter is provided, the system will give an error. +Type a command like the one below: -5. There is one **role assignment** tool, which classifies spoken turns into three roles: children, female adults, male adults. It exists in two versions. +`$ vagrant ssh -c "evalDiar.sh data/ diartk_noisemesSad"` -The version we call "yunitator" takes the raw recording as input. To call this one, do +You can read that command as follows: -`$ vagrant ssh -c "launcher/yunitator.sh data/"` +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. +*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. -The version we call "yuniSeg" takes the raw recording as well as a SAD as input. To call this one, do +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. -`$ vagrant ssh -c "launcher/yuniSeg.sh data/ noisemesSad"` +* diartk_noisemesSad*: The third argument indicates which output to evaluate. -Both of them return one rttm per sound file, with an estimation of where there are vocalizations by children, female adults, and male adults. +**THIS NEEDS WORK** -For more information on the model underlying them, see the Yunitator section below. +For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). -6. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. To find out, type a command like the one below: -`$ vagrant ssh -c "launcher/eval.sh data/ noisemesSad"` -Notice there are 2 parameters provided to the evaluation suite. The first parameter tells the system which folder to analyze (in this case, the whole data/ folder). The second parameter indicates which tool's output to evaluate (in this case, noisemesSad). The system will use the .rttm annotations if they exist; or the .eaf ones if the former are missing; or the .textgrid of neither .rttm nor .eaf are found. -If you want to evaluate a diarization produced by the diartk tool, you will have to specify a third parameter, to tell the system which SAD was used to compute the diartk outputs you want to evaluate. E.G. : -`$ vagrant ssh -c "launcher/eval.sh data/ diartk noisemesSad` +## Further information on Step 5, putting DiViMe back to sleep -7. Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: +Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: `$ vagrant halt` From cda9a86a6954ee230507894358f95459ab1b66af Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 10:28:27 -0500 Subject: [PATCH 166/299] minor bug fix --- docs/source/usage.md | 2 ++ launcher/evalSAD.sh | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index 0403454..8ccb439 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -252,7 +252,9 @@ You can read that command as follows: For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). +## An alternative for Step 4: using recipes +**THIS NEEDS WORK** ## Further information on Step 5, putting DiViMe back to sleep diff --git a/launcher/evalSAD.sh b/launcher/evalSAD.sh index 010e684..2ca23c2 100755 --- a/launcher/evalSAD.sh +++ b/launcher/evalSAD.sh @@ -37,8 +37,8 @@ if [[ $system = "ldcSad" ]]; then sys_name="ldcSad" elif [[ $system = "noisemesSad" ]]; then sys_name="noisemesSad" -elif [[ $system = "tocombosad" ]]; then - sys_name="tocombo_sad" +elif [[ $system = "tocomboSad" ]]; then + sys_name="tocomboSad" elif [[ $system = "opensmileSad" ]]; then sys_name="opensmileSad" elif [[ $system = "lenaSad" ]]; then From b695cd03280cc16245e19b50efa1d61529717f02 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 10:48:18 -0500 Subject: [PATCH 167/299] integrated contributors docs --- docs/source/eval.md | 19 -- .../{furtherInfo.md => further-info.md} | 2 +- docs/source/index.rst | 3 +- docs/source/instructions_for_contributors.md | 216 +++++++++++++----- docs/source/tool_doc.md | 13 +- 5 files changed, 162 insertions(+), 91 deletions(-) delete mode 100755 docs/source/eval.md rename docs/source/{furtherInfo.md => further-info.md} (87%) diff --git a/docs/source/eval.md b/docs/source/eval.md deleted file mode 100755 index 418f967..0000000 --- a/docs/source/eval.md +++ /dev/null @@ -1,19 +0,0 @@ -# LDC Diarization Scoring - -## General intro - -For SAD, we employ the evaluation included in the LDC SAD, which returns the false alarm (FA) rate (proportion of frames labeled as speech that were non-speech in the gold annotation) and missed speech rate (proportion of frames labeled as non-speech that were speech in the gold annotation). For TD, we employ the evaluation developed for the DiHARD Challenge, which returns a Diarization error rate (DER), which sums percentage of speaker error (mismatch in speaker IDs), false alarm speech (non-speech segments assigned to a speaker) and missed speech (unassigned speech). - -One important consideration is in order: What to do with files that have no speech to begin with, or where the system does not return any speech at the SAD stage or any labels at the TD stage. This is not a case that is often discussed in the litera- ture because recordings are typically targeted at moments where there is speech. However, in naturalistic recordings, some ex- tracts may not contain any speech activity, and thus one must adopt a coherent framework for the evaluation of such instances. We opted for the following decisions. - -If the gold annotation was empty, and the SAD system returned no speech labels, then the FA = 0 and M = 0; but if the SAD system returned some speech labels, then FA = 100 and M = 0. Also, if the gold annotation was not empty and the sys- tem did not find any speech, then this was treated as FA = 0 and M=100. - -As for the TD evaluation, the same decisions were used above for FA and M, and the following decisions were made for mismatch. If the gold annotation was empty, regardless of what the system returned, the mismatch rate was treated as 0. If the gold annotation was empty but a pipeline returned no TD labels (either because the SAD in that system did not detect any speech, or because the diarization failed), then this was penalized via a miss of 100 (as above), but not further penalized in terms of talker mismatch, which was set at 0. - -## Main references: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. -Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. - - - diff --git a/docs/source/furtherInfo.md b/docs/source/further-info.md similarity index 87% rename from docs/source/furtherInfo.md rename to docs/source/further-info.md index f6b2ab0..a509f7a 100755 --- a/docs/source/furtherInfo.md +++ b/docs/source/further-info.md @@ -1,6 +1,6 @@ # More information about DiViMe -DiViMe is a virtual machine, whose characteristics and contents are almost completely determined by provisioning scripts found in the DiViMe folder created when you did `git clone https://github.com/srvk/DiViMe/. This section provides information to help you understand the DiViMe structure in conceptual terms (the "pipeline"). We also explain the process of "bootstrapping" or creation of this virtual machine. Finally, we describe the folder structure. If you just want to use the tools in DiViMe, you can probably skip this whole section, or read just the `Pipeline structure` section. +DiViMe is a virtual machine, whose characteristics and contents are almost completely determined by provisioning scripts found in the DiViMe folder created when you did `git clone https://github.com/srvk/DiViMe/.` This section provides information to help you understand the DiViMe structure in conceptual terms (the "pipeline"). We also explain the process of "bootstrapping" or creation of this virtual machine. Finally, we describe the folder structure. If you just want to use the tools in DiViMe, you can probably skip this whole section, or read just the `Pipeline structure` section. ## Pipeline Structure diff --git a/docs/source/index.rst b/docs/source/index.rst index b9e52c7..dc387b7 100755 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,9 +13,10 @@ Welcome to DiViMe's documentation! initial_questions install usage - furterInfo + further-info formats tool_doc + extra-tools troubleshoot instructions_for_contributors references diff --git a/docs/source/instructions_for_contributors.md b/docs/source/instructions_for_contributors.md index 71c229c..930a5d0 100755 --- a/docs/source/instructions_for_contributors.md +++ b/docs/source/instructions_for_contributors.md @@ -1,107 +1,197 @@ -# Contributing / Developing +# Instructions For Contributors +Temporary instructions: +We have reorganized DiViMe to try to facilitate tool incorporation and VM use, but these changes have not yet made it to the main branch. Therefore, all of the following instructions are NOT in the master branch, but in the major_reorganization branch. This should make no difference to you, except that you need to check out the right branch to view the VM fitting with these instructions. We provide the code for doing this below. +## Overview +This detailed guide provides you with step-by-step, specific instructions for adapting a tool into the DiViMe environment. The following is a Summary of the steps: +1) Install the VM for yourself +2) Adapt & test your tools in the VM environment, and build the necessary links to other modules. +3) Put your tools and all your custom scripts somewhere where they can be downloaded (e.g., GitHub repo(s)) +4) Create a bash script to download and install your tools on the VM (the same steps will be added to a Vagrantfile that controls the entire VM installation) +5) ... +## Before You Start -## Before you start +Before you start, you'll need to get the VM up and running to establish the environment in which your tool will run. -Before you start, you'll just generate the VM environment to check you can get your tool working as expected. +1. Install DiViMe as per the [installation instructions](https://divime.readthedocs.io/en/latest/install.html), including the `vagrant up` that wakes the machine up. -1. Install DiViMe as per the installation instructions, including the `vagrant up` that wakes the machine up. +Temporary instructions: +IMPORTANT: After you’ve cloned DiViMe, you should check out the major_reorganization branch, as follows: +``` +$ git checkout remotes/origin/major_reorganization +``` +If ever you want to go back to the master branch, you’d do: +``` +$ git checkout master +``` +If you’ve already built one version of the VM, you’ll need to do: +``` +vagrant destroy +vagrant up +``` + + +2. Run the test.sh routine routine. It downloads audio recordings and annotations that you will need to make sure your tool is compatible with the rest of the workflow. Additionally, it will help you spot any issues there may be in your local environment. + +## Understanding the general structure of DiViMe -2. Run the test.sh routine routine. It downloads audio recordings and annotations that you will need to make sure your tool is compatible with the rest of the work flow. Additionally, it will help you spot any issues there may be. +DiViMe is a virtual machine, whose characteristics and contents are almost completely determined by provisioning scripts found at the top level when you clone DiViMe. That means that if you want to contribute to DiViMe, you need to understand its structure, and bootstrapping of the virtual machine. -## Adapting your tool to the VM environment +In the next section, we will walk you through some stages of modifying the contents of the VM, which you will do initially “by hand”. However, remember the contents of the VM are actually built from reproducible directives ran when you do `vagrant up`. (In technical terms, when the VM is _provisioned_.) Therefore, any changes you make by hand when you are logged into the VM will be lost when you run `vagrant destroy`. Please bear that in mind when trying out the steps in the next section. -1. For this section, you'll be working entirely within the machine. So start by doing `vagrant ssh` to log in. +Additionally, by the end of these instructions you will be ready to propose a revised version of the VM - i.e., a new recipe to _provision_ the VM. Therefore, any changes made by hand that you wish to make permanent in the VM should eventually be added to a file called `util/bootstraph.sh`. So you may want to have a copy of bootstraph.sh open to make notes in there of the steps you take, which should be reproduced when provisioning the VM. -2. Ideally, you will put your tool somewhere public, so that anyone rebuilding the machine will get access to it. You don't need to make your code open source. You can also share a binary executable version (ask us for instructions if you need them). +## Adapting Your Tool to the VM Environment -3. Install your code in the location where it will be within the machine: +1. For this section, you'll be working almost entirely within the virtual machine. So start by doing `vagrant ssh` to log in. This logs you in as the `vagrant` user, which also has sudo privileges to do things like install software, change permissions, etc. in the virtual machine. +2. Decide where your tool is made available so that it can be copied into the VM. Ideally, it will be somewhere public, such as GitHub, so that anyone rebuilding the machine will get access to it. Alternatively, your tool might be stored on a server in a location you control, and then pulled into the virtual machine. Please note that the latter solution only preserves the anonymity of your code temporarily; if you get to the end of this document, when you are proposing a new version of the VM including your tool, then the URL needs to be known to the world, and accessible to everyone. Please note that neither alternative forces you to make your code open source. You can also share a binary executable (ask us for instructions if you need help). + +3. Import your tool into the VM. Once you have decided where to put your tool, install your code by hand in the location where it will be within the machine: `/home/vagrant/repos`. For example if your code is in a public GitHub repository `https://github.com/srvk/OpenSAT`, you would type into the terminal: ``` -cd repos +cd /home/vagrant/repos git clone http://github.com/srvk/OpenSAT ``` -4. Write a wrapper allowing users to call on your tool. - -- The wrapper should be written in bash, and it should be called toolnameStage.sh. -- You choose your own tool's name. Use anything you want except the other names already in use. -- The fixed stages names are: Sad (for both speech activity detection and voice activity detection), Diar (for speaker diarization and role assignment), and Add (for adding annotation dependent on role assignment). Other tools do not have fixed stages names, but you should consider whether they depend only on the sound file input (then use Sad) or the talker role input (then use Add). So for a tool with the toolname 'noisemes' for example, that performs speech activity detection, it's wrapper would be called `noisemesSad.sh` -- Read on for input/output requirements depending on stage. -- This flowchart may help: https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9 -- The wrapper will take at least one argument, namely the name of the folder where the data are stored. Most users will pass "data/" -- The wrapper should process all .wav files inside data/ and, optionally, associated annotation files, which are in rttm format. (For more information on the rttm output, read [NIST's 2009 eval plan](https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf)) -- The wrapper should write its main output into the data/ folder. Typically, this will be one annotation file for each .wav file. If so, this annotation file should respect the rttm format, in particular using the space character (not tab) as a field separator. -- Output files should be named as follows: toolnameStage_basename.rttm. So for example a tool named "noisemes" (toolname="noisemes") that does speech activity (Stage="Sad"), and an input file "RTM20.wav" (basename="RTM20" like the output of the linux command `basename RTM20.wav .wav`), the output filename would be `noisemesSad_RTM20.rttm` -- You probably also generate two types of ancillary files: Intermediary representation files, such as features extracted from the wav files; and log files, with detailed information of what was done and how. Both should be stored in the /vagrant/data/temp/ folder. At the end of the process, Intermediary representation files should be deleted at the end of your wrapper. Log files should also be deleted if they are large (>5MB). As a reminder, our target user may not be technically advanced, and thus including long technical logs may do more to confuse than to help. -- If your tool is of the SAD type (SAD or VAD), it only requires sound as input. It should return one rttm per audio file, named according to the convention above, which will look like this: +If your tool is accessible via URL `https://toolnameurl.com/tool.zip`, you would type into the terminal: ``` -SPEAKER file17 1 0.00 0.77 speech -SPEAKER file17 1 1.38 2.14 speech +cd /home/vagrant/repos +wget -q -N https://toolnameurl.com/toolname.zip +unzip -q -o toolname.zip +``` +In bootstrap.sh, add the same code to make this step permanently reproducible. + + +4. If your code requires certain linux packages that are not installed, first install them ‘by hand’ in the VM with a command like `sudo apt-get install `. Any packages installed this way should be added similarly to one of the `apt-get` lines in bootstraph.sh like: +``` +sudo apt-get install -y libxt-dev libx11-xcb1 ``` -- If your tool is of the Diarization style (diarization or role assignment), it requires both sound and a SAD/VAD as input. Assume the SAD/VAD will be an rttm like the one exemplified in the previous bulletpoint. Your wrapper should allow the user to pass a sad/vad name tool as parameter. If the user does not provide the vad name, then use the default sad/vad (see end of instructions for list of default tools). In both cases, your wrapper should first check these sad/vad exist and if not, execute a command to generate them (see Instructions for use for instructions on how to use DiViMe's included tools). Your diarization-type tool should return one rttm per audio file, following the naming convention toolnameDiar_basename.rttm. For example a diarization tool named "talker" with input file "RTM20.wav" would produce the output filename `talkerDiar_RTM20.rttm`. The output RTTM must look like this: +5. The next step is to install additional dependencies, if any are needed. The VM already includes code to install OpenSmile 2.1, matlab v93, python 3, and anaconda 2.3.0. As in the two previous steps, you can do this by hand within the terminal, but you need to add the step to bootstraph.sh to make it permanent. For instance, if you need the python package `pympi-ling`, you would type `pip install pympi-ling` by hand into the terminal. Additionally, to make this change permanent (and have the dependencies installed when you reprovision the VM or when someone else rebuilds the VM), you need to add it to the Vagrantfile section where python packages are installed, with code like this: -** FIX this table ** ``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling” ``` -- If your tool is not a VAD/SAD but it is a classifier that assumes only raw acoustic input, then declare it as a sad/vad, and follow the instructions for vad/sad above, except that you'll adapt the rttm output to the classes you typically have. For example, one tool classifies audio into noiseme categories. It returns rttm's like this one: +## Write a Wrapper + +In this section, we provide detailed instructions for writing a wrapper that allows users to run your tool in a standardized way. The wrapper should be written in bash. Please look at the other launcher wrappers to have an idea of how to structure it, and read on for important considerations. -** todo: put example here, but make sure that the "type" class is not violated by the contents of the subtype column. For example, this is bad (noise should not be class SPEAKER):** +### Naming Conventions + +- You choose your own tool's name. Use anything you want except the other names already in use. We refer to your tool name later as ‘TOOLNAME’ +- It may be useful to you to decide at what “stage” of diarization your tool operates. A few things will be clearer if you have a good notion of when this is, such as the number of arguments and whether there is already an evaluation/scoring tool that can be re-used with your tool. We explain these things in more detail below. +- To facilitate end users’ understanding of what tool they are using, we have systematically added the stage name to the wrapper’s name, but you don’t have to follow this procedure if you think it will not be useful. +- We have identified three stages with a fixed name: Sad (for both speech activity detection and voice activity detection), Diar (for speaker diarization and role assignment), and Add (for adding annotation dependent on role assignment). +- Other stages or stage combinations do not have fixed names. But please feel free to use these stage names. For instance, if your tool only requires audio files as input, then you can use Sad; if it operates on both audio and speech activity detection, then use Diar; and if it is specific to one talker role as input, use Add. + +### Tool Autonomy + +Tools should be self-aware of where they have been installed, and they should use this awareness to find their dependencies. Said differently, a tool should run "in place" independent of the absolute path it's installed in. Tool dependency paths should be relative to the tool home folder, which should serve as the working directory. Again, please look at the other launcher wrappers to reuse the code present at the top of the wrappers, which correctly reconstructs the absolute path of this folder. + + +### Input, Output, and Parameters + + Your wrapper should take at least one argument, namely the name of a folder containing data. This folder is appended to “/vagrant” so from your script and the VM’s perspective, data appears in /vagrant/data/. This is actually a shared folder, coming from the host computer working directory. Everything in data/ on the host will in /vagrant/data in the VM, and vice-versa. The default wrapper argument, then, is typically "data/", but users could also supply “data/mystudy/” or “data/mystudy/baby1/” as the data folder argument. This supports the notion of having multiple datasets in different folders on the host. You can see how other wrappers use this, typically setting the variable `$audio_dir` to /vagrant/data. For the rest of this explanation, we’ll be referring to this folder as DATAFOLDER. +- The wrapper should process all .wav files inside DATAFOLDER and, optionally, associated annotation files, which are in rttm format. (For more information on the rttm output, read [NIST's 2009 eval plan](https://web.archive.org/web/20170119114252/http://www.itl.nist.gov/iad/mig/tests/rt/2009/docs/rt09-meeting-eval-plan-v2.pdf)) +- Your wrapper should support processing long sound files. If you have no better way of achieving this, look to utils/chunk.sh as an example; it breaks up long files into smaller 5 minute chunks, then iteratively calls a tool (in this case, yours), and concatenates the results. +- Your tool must process many sound files. This may require some optimization, for example loading very large model files into memory for each sound file is less optimal than loading once, then iterating over many files. +- The wrapper should write its *main output* into DATAFOLDER. Typically, this will be one annotation file for each .wav file. If your tool does VAD, SAD, or diarization, this annotation file should respect the rttm format. Additionally, the output file it should be named according to the pattern: toolname_file_original_name.rttm. If your tool does something other than VAD, SAD, or diarization, use a format that seems reasonable to you. If your tool returns results on individual files (and not e.g., summary statistics over multiple files), we still ask you to name the file toolnameStage_file_original_name.ext -- where “ext” is any extension that is reasonable for the annotation format you have chosen. +- You probably also generate two types of ancillary files: Intermediary representation files, such as features extracted from the wav files; and log files, with detailed information of what was done and how. Both should be initially stored in the DATAFOLDER/temp/TOOLNAME folder. +- Intermediary representation files should be deleted -- with one exception, introduced below. +- It is a good idea to print out a short log accompanying each batch of files analyzed, stating the key parameters, version number, and preferred citation. You may want to write out a lot more information. However, our target user may not be technically advanced, and thus including long technical logs may do more to confuse than to help. Log files should also be deleted if they are large (>5MB) -- with one exception, introduced next. +- Your wrapper should expect an optional argument “--keep-temp”, which is optionally passed in final position. If the last argument to the wrapper is not “--keep-temp”, then ancillary files should be deleted. Code snippet example: ``` -SPEAKER family 1 4.2 0.4 noise_ongoing 0.37730383873 -SPEAKER family 1 4.6 1.2 background 0.327808111906 -SPEAKER family 1 5.8 1.1 speech 0.430758684874 -SPEAKER family 1 6.9 1.2 background 0.401730179787 -SPEAKER family 1 8.1 0.7 speech 0.407463937998 -SPEAKER family 1 8.8 1.1 background 0.37258502841 -SPEAKER family 1 9.9 1.7 noise_ongoing 0.315185159445 +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi +… +if ! $KEEPTEMP; then + rm -rf $MYTEMP +fi ``` + See any script in `launcher/` for examples. -- If your tool is a classifier that works only on a subtype of speaker (e.g., only on children's speech), then assume that each wav is accompanied by an rttm that has this information noted in column XX. +## Document Your Tool +Add a documentation file to the `DiViMe/docs/` folder on your host, in markdown format, containing at least the following three pieces of information: +A one-paragraph explanation of what your tool does +A reference or citation that people using your tool must employ +A short section explaining how to use it. This will typically include a description of input & output formats, which can be replaced with references to the Format section of the docs. You should also include an example command line of how to run the tool. Often, this will be `vagrant ssh ‘toolname.sh data/`. +Please include any other information that would be useful to users, such as what parameters are available, how to access them, a tiny example input and output, further technical information on how the tool was built, additional references for work using this tool or on which the tool was built, etc. -** todo: add default tool section** +For an example, see the tocomboSad section in the [tools documentation](https://divime.readthedocs.io/en/latest/tool_doc.html). -** todo: address "process multiple files in parallel, if possible (like using sbatch?)"** +## Create a Reproducible Test for Your Tool +DiViMe comes equipped with a test script that downloads a publicly available daylong audio file and transcript, which all tools within DiViMe can process (and many can be evaluated). In this section, we provide instructions for you to add your tool to the test.sh routine. +By default, all launchers are read-only to avoid accidental editing by newbie users. For the next step, you need to change file permissions so as to be able to edit test.sh. From the host machine, type into the terminal: -## Integrating your tool into DiViMe for real +``` +chmod +rw test.sh +``` + +Open the file test.sh, which is inside the launcher folder, and add a section testing your tool, modeling it on the other tests present there. Typically, you will need these lines: + +Under “# Paths to Tools” add a line with the path to your tool, eg: +TOOLNAMEDIR=$REPOS/TOOLNAME + +b) Before “# test finished”, add a section like the following: + +Example for a Sad type tool: +``` +echo "Testing TOOLNAME..." +cd $TOOLNAMEDIR +TESTDIR=$WORKDIR/TOOLNAME-test +rm -rf $TESTDIR; mkdir -p $TESTDIR +ln -fs $TEST_WAV $TESTDIR +$LAUNCHERS/toolnameStage.sh $DATADIR/TOOLNAME-test >$TESTDIR/TOOLNAME-test.log || { echo " TOOLNAME failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/toolnameStage_$BASETEST.rttm ]; then + echo "TOOLNAME passed the test." +else + FAILURES=true + echo " TOOLNAME failed - no RTTM output" +fi +``` +In the above example: +`DATADIR` is predefined as the test 5 minute data folder `data/VanDam-Daylong/BN32` +`TOOLNAME` is whatever human readable name you have given your tool +`toolnameStage` is the pattern for the system/launcher name for your tool, for example `opensmileSad` +`BASETEST` is the basename of a test input file e.g. `BN32_010007_test` for the 5 minute input file `BN32_010007_test.wav` -fork our divime repo -add a line to clone your repo -add lines to add to the environment any dependencies needed -add an md with short description, citation, and instructions for use -pull request -fork our launcher repo -add your wrapper -add a section to the test specific to your tool -pull request +Example for a Diar type tool: +** todo: complete** +Example for an Add type tool: +** todo: complete** -## Updating the documentation -The documentation is written in markdown and compiled into a website using sphynx. -The source of the documentation is in the shared directory ```docs/source```; once rebuilt -locally, the html is in ```docs/build/html/index.html``` + Run test.sh. Only proceed to the next phase if your tool passes the test. -Developers can modify the doc and recompile locally it using: +## Check reproducibility of your version of the VM by reprovisioning + +Throughout the steps above, you have modified `Vagrantfile/bootstrap.sh` to automatically install your code, any required packages, and any required dependencies. If you have been keeping your Vagrantfile/bootstrap.sh in a good state, you should be able to rebuild your version of the virtual machine from scratch. +If necessary, log out from the virtual machine with control+D. Then, from the host machine, run the following code to destroy, re-build, and re-run the test: ``` -vagrant ssh -c "cd /vagrant/docs; make html" +vagrant destroy +vagrant up +vagrant ssh -c “test.sh” ``` -once they are happy with the result, they can commit their changes as described above. +*WARNING:* any changes you made by hand when you were logged into the VM will be lost when you run `vagrant destroy`: to make sure they show up automatically with `vagrant up`, all such dependencies need to be automated (added to Vagrantfile/bootstrap.sh). +If your tool passes the test in this condition, you are ready to integrate your tool to DiViMe for real. +## Integrate Your Tool Into the Public Version of DiViMe +1. Fork the DiViMe repo +2. Feplace Vagrantfile/bootstrap.sh with your version of Vagrantfile/bootstrap.sh +3. Add in the docs/ your tool’s doc +4. Add your wrapper to launcher/ +5. Replace test.sh with your version containing an additional test case specific to your tool +6. Create a pull request to DiViMe requesting your additions be incoporated diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index d7934d6..49318c6 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -306,17 +306,16 @@ There is no official reference for this tool. https://github.com/MilesICL/vcm/issues/ -## TalNet +# Evaluation -### General intro +## Speech/voice activity detection and diarization evaluation -There is no information on this tool. +For SAD, we employ an evaluation, which returns the false alarm (FA) rate (proportion of frames labeled as speech that were non-speech in the gold annotation) and missed speech rate (proportion of frames labeled as non-speech that were speech in the gold annotation). For TD, we employ the evaluation developed for the DiHARD Challenge, which returns a Diarization error rate (DER), which sums percentage of speaker error (mismatch in speaker IDs), false alarm speech (non-speech segments assigned to a speaker) and missed speech (unassigned speech). -### Main references: +One important consideration is in order: What to do with files that have no speech to begin with, or where the system does not return any speech at the SAD stage or any labels at the TD stage. This is not a case that is often discussed in the literature because recordings are typically targeted at moments where there is speech. However, in naturalistic recordings, some extracts may not contain any speech activity, and thus one must adopt a coherent framework for the evaluation of such instances. We opted for the following decisions. -There is no official reference for this tool. +If the gold annotation was empty, and the SAD system returned no speech labels, then the FA = 0 and M = 0; but if the SAD system returned some speech labels, then FA = 100 and M = 0. Also, if the gold annotation was not empty and the system did not find any speech, then this was treated as FA = 0 and M=100. -### Questions and bug reports +As for the TD evaluation, the same decisions were used above for FA and M, and the following decisions were made for mismatch. If the gold annotation was empty, regardless of what the system returned, the mismatch rate was treated as 0. If the gold annotation was empty but a pipeline returned no TD labels (either because the SAD in that system did not detect any speech, or because the diarization failed), then this was penalized via a miss of 100 (as above), but not further penalized in terms of talker mismatch, which was set at 0. -Not available From 9975f1a10caa8fef79a25cb16474ea91360bdcab Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 10:56:04 -0500 Subject: [PATCH 168/299] minor --- docs/source/install.md | 6 ++---- docs/source/troubleshoot.md | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 48a9924..8f01f1c 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -36,10 +36,8 @@ The very first time you use DiViMe, it is a good idea to run a quick start test, 1. Open a terminal 2. Navigate inside the DiViMe folder -3. Do -`$ vagrant up` -4. Do -`$ vagrant ssh -c "launcher/test.sh"` +3. Do `$ vagrant up` +4. Do `$ vagrant ssh -c "launcher/test.sh"` This should produce the output: diff --git a/docs/source/troubleshoot.md b/docs/source/troubleshoot.md index 7fa47b8..72b1237 100755 --- a/docs/source/troubleshoot.md +++ b/docs/source/troubleshoot.md @@ -28,7 +28,7 @@ You can now try again with `vagrant up` ## Problems with some of the Tools ### LDC SAD, OpenSmile, DiarTK -If ldcSad, OpenSmile, DiarTK don't seem to work after vagrant up, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: +If ldcSad, OpenSmile, DiarTK don't seem to work after `vagrant up`, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: ``` vagrant up --provision ``` From e041b7e29bd85b9f2611fdec4b2d96a6a139c4de Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 11:01:45 -0500 Subject: [PATCH 169/299] step 1 of getting rid of ldcsad --- conf/bootstrap.sh | 4 ---- conf/update.sh | 1 - launcher/README.md | 1 - launcher/diartk.sh | 6 ------ launcher/eval.sh | 3 +-- launcher/evalDiar.sh | 15 +++++---------- launcher/python3/test.sh | 36 ------------------------------------ 7 files changed, 6 insertions(+), 60 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 18bfc52..a2b4945 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -140,10 +140,6 @@ su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" cp /vagrant/conf/.theanorc /home/${user}/ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" -# Install ldc-sad -# run this version 'by hand' in the VM in repos/ using your github username and password -#git clone http://github.com/aclew/ldc_sad_hmm - # Install Yunitator and dependencies git clone https://github.com/srvk/Yunitator su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" diff --git a/conf/update.sh b/conf/update.sh index 2707a56..a3c392e 100644 --- a/conf/update.sh +++ b/conf/update.sh @@ -1,4 +1,3 @@ - if grep --quiet vagrant /etc/passwd then user="vagrant" diff --git a/launcher/README.md b/launcher/README.md index f4f9ad6..aeec698 100755 --- a/launcher/README.md +++ b/launcher/README.md @@ -5,7 +5,6 @@ This repository contains scripts that launch tools in the ACLEW Diarization VM. ### SAD tools ``` -ldcSad.sh noisemesSad.sh opensmileSad.sh tocomboSad.sh diff --git a/launcher/diartk.sh b/launcher/diartk.sh index cdcb65b..8c96a48 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -11,7 +11,6 @@ if [ $# -lt 1 ] || [ $# -gt 3 ]; then echo "where audio-dir is the name of the folder" echo "containing the wav files" echo "and is one of:" - echo " ldcSad" echo " noisemesSad" echo " tocomboSad" echo " opensmileSad" @@ -59,10 +58,6 @@ for fin in `ls $audio_dir/*.wav`; do # Type file chan tbeg tdur ortho stype name conf Slat # math: convert RTTM seconds to HTK (10ms default) frames = multiply by 100 case $trs_format in - "ldcSad") - sys="ldcSad" - python $UTILS/rttm2scp.py $audio_dir/ldcSad_${basename}.rttm $scpfile - ;; "noisemesSad") sys="noisemesSad" python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile @@ -97,7 +92,6 @@ for fin in `ls $audio_dir/*.wav`; do ;; *) echo "ERROR: please choose SAD system between:" - echo " ldcSad" echo " noisemesSad" echo " tocomboSad" echo " opensmileSad" diff --git a/launcher/eval.sh b/launcher/eval.sh index 8e3e23c..10410ec 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -20,7 +20,6 @@ display_usage() { echo "where data is the folder containing the data" echo "and system is the system you want" echo "to evaluate. Choices are:" - echo " ldcSad" echo " noisemesSad" echo " tocomboSad" echo " opensmileSad" @@ -45,7 +44,7 @@ fi ### SCRIPT STARTS case $system in -"tocomboSad"|"opensmileSad"|"ldcSad"|"noisemesSad|lenaSad") +"tocomboSad"|"opensmileSad"|"noisemesSad|lenaSad") sh $LAUNCHER/evalSAD.sh $audio_dir $system $KEEPTEMP ;; "yunitate"|"lenaDiar") diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index e2f2eef..a922630 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -18,7 +18,6 @@ display_usage() { echo " - diartk" echo " - yunitate" echo "Transcription (mandatory for model == diartk) choices are:" - echo " ldc_sad" echo " noisemes" echo " opensmile" echo " tocombosad" @@ -52,16 +51,13 @@ model=$2 if [[ $model =~ ^(diartk|yuniseg) ]]; then trs_format=$3 case $trs_format in - "ldc_sad") - sys_name=$model"_ldcSad" - ;; - "noisemes") + "noisemesSad") sys_name=$model"_noisemesSad" ;; - "tocombosad") + "tocomboSad") sys_name=$model"_tocomboSad" ;; - "opensmile") + "opensmileSad") sys_name=$model"_opensmileSad" ;; "textgrid") @@ -82,9 +78,8 @@ if [[ $model =~ ^(diartk|yuniseg) ]]; then sys_name=$model"_goldSad" ;; *) - echo "ERROR: You're trying to evaluate diartk, but the transcription system you specified is not recognized :" - echo " ldc_sad" - echo " noisemes" + echo "ERROR: You're trying to evaluate diartk, but the speech activity detection you specified is not recognized:" + echo " noisemesSad" echo " textgrid" echo " eaf" echo " rttm" diff --git a/launcher/python3/test.sh b/launcher/python3/test.sh index 61d67ed..de35bc2 100644 --- a/launcher/python3/test.sh +++ b/launcher/python3/test.sh @@ -21,7 +21,6 @@ export REPOS=/home/vagrant/repos export UTILS=/home/vagrant/utils # Paths to Tools -LDC_SAD_DIR=$REPOS/ldc_sad_hmm export OPENSATDIR=$REPOS/OpenSAT # noisemes OPENSMILEDIR=$REPOS/openSMILE-2.1.0/ TOCOMBOSAD=$REPOS/To-Combo-SAD @@ -76,24 +75,6 @@ else echo " and rename it to HTK.tar.gz ?" fi -# First test in ldc_sad_hmm -echo "Testing LDC SAD..." -if [ -s $LDC_SAD_DIR/perform_sad.py ]; then - cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/ldc_sad-test - rm -rf $TESTDIR; mkdir -p $TESTDIR - python perform_sad.py -L $TESTDIR $TEST_WAV > $TESTDIR/ldc_sad.log 2>&1 || { echo " LDC SAD failed - dependencies"; FAILURES=true;} - # convert output to rttm, for diartk. - grep ' speech' $TESTDIR/$BASETEST.lab | awk -v fname=$BASE '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $TESTDIR/$BASETEST.rttm - if [ -s $TESTDIR/$BASETEST.rttm ]; then - echo "LDC SAD passed the test." - else - FAILURES=true - echo " LDC SAD failed - no output RTTM" - fi -else - echo " LDC SAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" -fi # now test Noisemes @@ -206,23 +187,6 @@ fi git checkout master -# testing LDC evalSAD (on opensmile) -echo "Testing LDC evalSAD" -if [ -d $LDC_SAD_DIR ]; then - cd $LDC_SAD_DIR - TESTDIR=$WORKDIR/opensmile-test - cp $WORKDIR/$BASETEST.rttm $TESTDIR - $LAUNCHERS/eval.sh $DATADIR/opensmile-test opensmileSad $KEEPTEMP > $WORKDIR/ldc_sad-test/ldc_evalSAD.log 2>&1 || { echo " LDC evalSAD failed - dependencies"; FAILURES=true;} - if [ -s $TESTDIR/opensmileSad_eval.df ]; then - echo "LDC evalSAD passed the test" - else - echo " LDC evalSAD failed - no output .df" - FAILURES=true - fi -else - echo " LDC evalSAD failed because the code for LDC SAD is missing. This is normal, as we are still awaiting the official release!" - FAILURES=true -fi # test finished From 0e99c329232a7a3f5eb5b129e4f0b79309d423ed Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 11:21:43 -0500 Subject: [PATCH 170/299] added doc building at end of bootstrap --- conf/bootstrap.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index a2b4945..54dc31e 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -204,3 +204,6 @@ if ! $HTK_INSTALLED; then echo "Warning: HTK is not installed" echo "*****************************" fi + +# Build the docs +cd /vagrant/docs && make html From 9be2c494b717e229f7214c2a2f7b350764a7b5f2 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 11:29:40 -0500 Subject: [PATCH 171/299] removing ldc --- docs/source/install.md | 5 +---- docs/source/references.md | 1 - docs/source/tool_doc.md | 20 -------------------- docs/source/troubleshoot.md | 8 ++++---- docs/source/usage.md | 9 ++++----- 5 files changed, 9 insertions(+), 34 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 8f01f1c..5934950 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -42,8 +42,6 @@ The very first time you use DiViMe, it is a good idea to run a quick start test, This should produce the output: ``` -Testing LDC SAD... -LDC SAD passed the test. Testing Speech Activity Detection Using Noisemes... Noisemes passed the test. @@ -64,8 +62,7 @@ Congratulations, everything is OK! ## Common installation errors and fixes -- For ldcSad, you may get an error "ldcSad failed because the code for ldcSad is missing. This is normal, as we are still awaiting the official release!" There is no fix for this. Unfortunately, we need to wait for the official release before we can include ldcSad. This error means that you cannot use ldcSad, but you can use any other SAD/VAD. (For example, noisemesSad.) -- For ldcSad, noisemesSad, and diartkDiar, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the +- For noisemesSad, and diartkDiar, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. diff --git a/docs/source/references.md b/docs/source/references.md index 7fda6a7..566dbed 100755 --- a/docs/source/references.md +++ b/docs/source/references.md @@ -8,7 +8,6 @@ Our work builds directly on that of others. The main references for tools curren - Eyben, F. Weninger, F., Gross, F. & B. Schuller. (2013). Recent developments in opensmile, the munich open-source multimedia feature extractor. Proceedings of the 21st ACM international conference on Multimedia, 835–838. - Eyben, F., Weninger, F., Squartini, S., & Schuller, B. (2013, May). Real-life voice activity detection with lstm recurrent neural networks and an application to hollywood movies. In Acoustics, Speech and Signal Processing (ICASSP), 2013 IEEE International Conference on (pp. 483-487). IEEE. - Räsänen, O., Seshadri, S., & Casillas, M. (2018, June). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. In Interspeech 2018. -- Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. - Sadjadi, S.O. & Hansen, J.H.L. (2013). Unsupervised Speech Activity Detection using Voicing Measures and Perceptual Spectral Flux. IEEE Signal Processing Letters, 20(3), 197-200. - VanDam, M., & Tully, T. (2016, May). Quantity of mothers’ and fathers’ speech to sons and daughters. Talk presented at the 171st Meeting of the Acoustical Society of America, Salt Lake City, UT. - Vijayasenan, D. & Valente, F. (2012) Diartk: An open source toolkit for research in multistream speaker diarization and its application to meetings recordings. Thirteenth Annual Conference of the International Speech Communication Association, 2012. diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index 49318c6..eaa8586 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -3,26 +3,6 @@ This section contains documentation from the different Speech or Voice activity detection tools. -## LDC SAD - -### General intro - -LDC SAD relies on HTK (Young et al., 2002) to band-pass filter and extract PLP features, prior to applying a broad phonetic class recognizer trained on the Buckeye Corpus (Pitt et al., 2002) using a GMM-HMM model. An official release by the LDC is currently in the works. - -### Main references: - -Ryant, N. (2018). LDC SAD. https://github.com/Linguistic-Data-Consortium, accessed: 2018-06-17. - - -### Associated references: - -Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. -Pitt, M. A., Johnson, K., Hume, E., Kiesling, S., & Raymond, W. (2005). The Buckeye corpus of conversational speech: labeling conventions and a test of transcriber reliability. Speech Communication, 45(1), 89–95. - -### Questions and bug reports - -Not available - ## NoisemesSad ### General intro diff --git a/docs/source/troubleshoot.md b/docs/source/troubleshoot.md index 72b1237..1766f17 100755 --- a/docs/source/troubleshoot.md +++ b/docs/source/troubleshoot.md @@ -26,13 +26,13 @@ You can now try again with `vagrant up` ## Problems with some of the Tools -### LDC SAD, OpenSmile, DiarTK +### OpenSmile, DiarTK -If ldcSad, OpenSmile, DiarTK don't seem to work after `vagrant up`, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: +If OpenSmile, DiarTK don't seem to work after `vagrant up`, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: ``` vagrant up --provision ``` -This step will install HTK inside the VM, which is used by several tools including ldcSad. +This step will install HTK inside the VM, which is used by several tools. ### Noisemes If you use the noisemesSad or the noisemes_full tool, one problem you may encounter is that it doesn't treat all of your files and gives you an error that looks like this: @@ -45,7 +45,7 @@ Traceback (most recent call last): MemoryError ``` If this happens to you, it's because you are trying to treat more data than the system/your computer can handle. -What you can do is simply put the remaining files that weren't treated in a seperate folder and treat this folder seperately (and do this until all of your files are treated if it happens again on very big datasets). +What you can do is simply put the remaining files that weren't treated in a separate folder and treat this folder separately (and do this until all of your files are treated if it happens again on very big datasets). After that, you can put back all of your data in the same folder. ### Input Format For Transcriptions diff --git a/docs/source/usage.md b/docs/source/usage.md index 8ccb439..892ccd8 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -50,7 +50,7 @@ Remember that you will be using a mini-computer within your computer. Typically, If all tools passed the test, then you'll be able to automatically add the following types of annotation to your audio files: -1) Speech activity detection (_when is someone talking?_): The tools available for this task are the following: noisemesSad, tocomboSad, opensmileSad, ldcSad +1) Speech activity detection (_when is someone talking?_): The tools available for this task are the following: noisemesSad, tocomboSad, opensmileSad 2) Talker diarization (_who is talking?_) The tools available for this task are the following: diartkDiar @@ -58,7 +58,7 @@ If all tools passed the test, then you'll be able to automatically add the follo 4) Vocal type classification (_what kind of vocalization is this one?_) The tools available for this task are the following: vcm -5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, ldcSad, diartkDiar, yunitator +5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, diartkDiar, yunitator ### Overview of "pipelines" @@ -89,7 +89,7 @@ You can read that command as follows: *vagrant ssh -c*: This tells DiViMe that it needs to run a tool. -*noisemesSad.sh*: This first argument tells DiViMe which tool to run. The options are: noisemesSad.sh, tocomboSad.sh, opensmileSad.sh, ldcSad.sh +*noisemesSad.sh*: This first argument tells DiViMe which tool to run. The options are: noisemesSad.sh, tocomboSad.sh, opensmileSad.sh *data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. @@ -133,7 +133,7 @@ You can read that command as follows: *noisemesSad*: Remember that this tool does "talker diarization": Given some speech, attribute it to a speaker. Therefore, this type of tool necessitates speech/voice activity detection. This third argument tells DiViMe what file contains information about which sections of the sound file contain speech. -You can only use one of the following options: textgrid, eaf, rttm, ldcSad, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. +You can only use one of the following options: textgrid, eaf, rttm, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. You can provide annotations done by a human or in some other way, and encoded as one of the following three file types: @@ -144,7 +144,6 @@ You can provide annotations done by a human or in some other way, and encoded as Alternatively, you can provide use automatic annotations generated by DiViMe's speech/voice activity detection systems, encoded in rttm files. In this case, you would pass one of the following options: -- ldcSad: this means you want the system to use the output of the ldcSad system. If you have not run this system before, the system will fail. - this system before: this means you want the system to use the output of the noisemesSad system. If you have not run noisemesSad, the system will fail. - opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run this system before, the system will fail. - tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran this system before, the system will fail. From 919fd9f032b7464e9d09f1abc7e8bfc3eff13ce2 Mon Sep 17 00:00:00 2001 From: MarvinLavechin Date: Thu, 29 Nov 2018 18:10:41 +0100 Subject: [PATCH 172/299] Improved eaf2enriched_txt.sh by allowing the user to enrich just one file --- utils/eaf2enriched_txt.sh | 28 +++++++++++++++++++++++----- utils/eaf2txt.py | 1 - utils/speech_extractor.py | 0 3 files changed, 23 insertions(+), 6 deletions(-) mode change 100644 => 100755 utils/speech_extractor.py diff --git a/utils/eaf2enriched_txt.sh b/utils/eaf2enriched_txt.sh index 26c3ff0..30b09c9 100755 --- a/utils/eaf2enriched_txt.sh +++ b/utils/eaf2enriched_txt.sh @@ -1,5 +1,5 @@ #!/bin/bash -INPUT_FOLDER=$1 +INPUT=$1 LANG=$2 SCRIPT_DIR=$(dirname "$0") @@ -15,7 +15,7 @@ display_usage() { echo -e "\t number of syllables" echo "usage: $0 [input] [language]" - echo " input The folder where to find the eaf files (REQUIRED)." + echo " input The folder where to find the eaf files, or the single eaf file (REQUIRED)." echo " output The language of the transcription : english, spanish or tzeltal (REQUIRED)." exit 1 } @@ -24,8 +24,9 @@ if [ -z "$1" ] || [ -z "$2" ] || ! [[ $LANG =~ ^(english|spanish|tzeltal)$ ]]; t display_usage fi -for eaf_path in /vagrant/$1/*.eaf; do - eaf_path=${eaf_path#/vagrant/} +if [ -f "/vagrant/"$1 ]; then + echo "File found." + eaf_path=${1#/vagrant/} without_extension="${eaf_path%.*}" echo "Converting $eaf_path files to ${without_extension}.txt ..." python $SCRIPT_DIR/eaf2txt.py -i $eaf_path @@ -34,4 +35,21 @@ for eaf_path in /vagrant/$1/*.eaf; do $SCRIPT_DIR/selcha2clean.sh ${without_extension}.txt ${without_extension}_enriched.txt $LANG rm /vagrant/${without_extension}.txt -done \ No newline at end of file +elif [ -d "/vagrant/"$1 ]; then + echo "Directory found." + for eaf_path in /vagrant/$1/*.eaf; do + eaf_path=${eaf_path#/vagrant/} + without_extension="${eaf_path%.*}" + echo "Converting $eaf_path files to ${without_extension}.txt ..." + python $SCRIPT_DIR/eaf2txt.py -i $eaf_path + + echo "Enriching ${without_extension}.txt" + $SCRIPT_DIR/selcha2clean.sh ${without_extension}.txt ${without_extension}_enriched.txt $LANG + + rm /vagrant/${without_extension}.txt + done +else + echo "File or directory not found." + display_usage +fi; + diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py index 354df99..56ca2d5 100755 --- a/utils/eaf2txt.py +++ b/utils/eaf2txt.py @@ -74,7 +74,6 @@ def main(): data_dir = '/vagrant' args.input = os.path.join(data_dir, args.input) output = os.path.join(data_dir, output) - if not os.path.isdir(output): os.mkdir(output) diff --git a/utils/speech_extractor.py b/utils/speech_extractor.py old mode 100644 new mode 100755 From 809334b4570f118263919915648a2c971f4bf10b Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 14:13:43 -0500 Subject: [PATCH 173/299] removing ldc --- docs/source/install.md | 9 ++++- docs/source/tool_doc.md | 2 +- docs/source/usage.md | 6 ++- launcher/evalDiar.sh | 27 ++++++------- launcher/evalSAD.sh | 87 ----------------------------------------- launcher/ldcSad.sh | 54 ------------------------- 6 files changed, 26 insertions(+), 159 deletions(-) delete mode 100755 launcher/evalSAD.sh delete mode 100755 launcher/ldcSad.sh diff --git a/docs/source/install.md b/docs/source/install.md index 5934950..cec6f6f 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -55,6 +55,13 @@ Threshold Optimized Combo SAD passed the test. Testing DiarTK... DiarTK passed the test. +Testing Yunitator... +Yunitator passed the test. + +Testing DScore... +Yunitator passed the test. + + Congratulations, everything is OK! ``` @@ -62,7 +69,7 @@ Congratulations, everything is OK! ## Common installation errors and fixes -- For noisemesSad, and diartkDiar, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the +- For noisemesSad, and diartk, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the If something else fails, please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index eaa8586..921a233 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -7,7 +7,7 @@ This section contains documentation from the different Speech or Voice activity ### General intro -Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. +Noiseme SAD was actually not specifically built as a SAD but rather as a broader “noiseme classifier”. It is a neural network that can predict frame-level probabilities of 17 types of sound events (called “noisemes”), including speech, singing, engine noise, etc. The network consists of one single bidirectional LSTM layer with 400 hidden units in each direction. It was trained on 10h of basically web videos data (Strassel et al., 2012), with the Theano toolkit. The OpenSMILE toolkit (Eyben et al., 2013) is used to extract 6,669 low-level acoustic features, which are reduced to 50 dimensions with PCA. For our purposes, we summed the probabilities of the classes “speech” and “speech non-english” and labeled a region as speech if this probability was higher than all others. The original method in Wang et al. (2016) used 983 features selected using information gain criterion, but we used an updated version from authors Y. Wang and F. Metze in this paper. diff --git a/docs/source/usage.md b/docs/source/usage.md index 892ccd8..120dd57 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -52,13 +52,13 @@ If all tools passed the test, then you'll be able to automatically add the follo 1) Speech activity detection (_when is someone talking?_): The tools available for this task are the following: noisemesSad, tocomboSad, opensmileSad -2) Talker diarization (_who is talking?_) The tools available for this task are the following: diartkDiar +2) Talker diarization (_who is talking?_) The tools available for this task are the following: diartk 3) Role diarization (_what kind of person is talking?_) The tools available for this task are the following: yunitator 4) Vocal type classification (_what kind of vocalization is this one?_) The tools available for this task are the following: vcm -5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, diartkDiar, yunitator +5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, diartk, yunitator ### Overview of "pipelines" @@ -207,6 +207,8 @@ It returns one rttm per sound file, with an estimation of where there are vocali ### How to run a Vocalization classification tool +vcm + NO INFORMATION YET ### How to run an Evaluation diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index a922630..87babc3 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -9,26 +9,25 @@ DSCOREDIR=$(dirname $BASEDIR)/dscore display_usage() { - echo "Usage: evalDiar.sh <>" + echo "Usage: evalDiar.sh " echo "where dirname is the name of the folder" - echo "containing the wav files, and transcription" - echo "specifies which transcription you want to use," - echo "only used if model == diartk." - echo "Model choices are :" - echo " - diartk" + echo "containing the wav files, and system" + echo "specifies which system you want to evaluate" + echo "System choices are :" + echo " - noisemesSad" + echo " - opensmileSad" + echo " - tocomboSad" + echo " - diartk_noisemesSad" + echo " - diartk_opensmileSad" + echo " - diartk_tocomboSad" + echo " - diartk_rttm" echo " - yunitate" - echo "Transcription (mandatory for model == diartk) choices are:" - echo " noisemes" - echo " opensmile" - echo " tocombosad" - echo " textgrid" - echo " eaf" - echo " rttm" + echo " - lena" exit 1; } -if ! [[ $2 =~ ^(diartk|yunitate|lena)$ ]] || [ "$2" == "diartk" ] && [ $# -lt 3 ]; then +if ! [[ $2 =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lena)$ ]] ]; then display_usage fi diff --git a/launcher/evalSAD.sh b/launcher/evalSAD.sh deleted file mode 100755 index 2ca23c2..0000000 --- a/launcher/evalSAD.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash -# Launcher onset routine -SCRIPT=$(readlink -f $0) -BASEDIR=`dirname $SCRIPT` # folder where this script resides. Useless. -REPOS=/home/vagrant/repos -UTILS=/home/vagrant/utils -# end of launcher onset routine - - -### Read in variables from user -# data directory -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" - -# check system to evaluate -system=$2 - -KEEPTEMP=false -if [ $BASH_ARGV == "--keep-temp" ]; then - KEEPTEMP=true -fi - - -### Other variables specific to this script -# Path to scoring tool NOTE: NOT dscore! -ldcSad_DIR=$REPOS/ldc_sad_hmm -# create temp dir -workdir=$audio_dir -mkdir -p $workdir - - -### SCRIPT STARTS -if [[ $system = "ldcSad" ]]; then - sys_name="ldcSad" -elif [[ $system = "noisemesSad" ]]; then - sys_name="noisemesSad" -elif [[ $system = "tocomboSad" ]]; then - sys_name="tocomboSad" -elif [[ $system = "opensmileSad" ]]; then - sys_name="opensmileSad" -elif [[ $system = "lenaSad" ]]; then - sys_name="lenaSad" - -else - echo "Please Specify the System you wish to evaluate." - echo "Choose between ldcSad, noisemeSad, tocomboSad, opensmileSad, lenaSad." - exit -fi - - -# Set CWD to path of scoring tool -cd $ldcSad_DIR - -echo $UTILS/create_ref_sys.sh $1 $sys_name true -$UTILS/create_ref_sys.sh $1 $sys_name true - -echo "evaluating" -# python score_batch.py $audio_dir/${sys_name}_eval.df $workdir/temp_ref $workdir/temp_sys -# create /vagrant/results if it doesn't exist -echo "filename DCF FA MISS" > $audio_dir/${sys_name}_eval.df -for lab in `ls $workdir/temp_sys/*.lab`; do - base=$(basename $lab .lab) - if [ ! -s $workdir/temp_ref/$base.lab ]; then - if [ ! -s $workdir/temp_sys/$base.lab ]; then - echo $base" 0.00% 0.00% 0.00%" >> $audio_dir/${sys_name}_eval.df - else - echo $base" 25.00% 100.00% 0.00%" >> $audio_dir/${sys_name}_eval.df - fi - elif [ ! -s $workdir/temp_sys/$base.lab ] && [ -s $workdir/temp_ref/$base.lab ]; then - echo $base" 75.00% 0.00% 100.00%" >> $audio_dir/${sys_name}_eval.df - else - python score.py $workdir/temp_ref $lab | awk -v var="$base" -F" " '{if ($1=="DCF:") {print var"\t"$2"\t"$4"\t"$6}}' >> $audio_dir/${sys_name}_eval.df - fi - -done -# small detail: remove the commas from the output -sed -i "s/,//g" $audio_dir/${sys_name}_eval.df -echo "done evaluating, check $1/${sys_name}_eval.df for the results" - -# remove temps -if ! $KEEPTEMP; then - rm -rf $workdir/temp_ref $workdir/temp_sys -fi - diff --git a/launcher/ldcSad.sh b/launcher/ldcSad.sh deleted file mode 100755 index 3f5d2c9..0000000 --- a/launcher/ldcSad.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# Launcher onset routine -SCRIPT=$(readlink -f $0) -BASEDIR=/home/vagrant -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -# end of launcher onset routine - -### Read in variables from user -audio_dir=/vagrant/$1 - -### Other variables specific to this script -LDC_SAD_DIR=$REPOS/ldc_sad_hmm -workdir=$audio_dir/temp/diartk -mkdir -p $workdir - -### SCRIPT STARTS -if [ $# -lt 1 ]; then - echo "Usage: ldcSad.sh " - echo "where dirname is the name of the folder" - echo "containing the wav files" - exit 1 -fi - -KEEPTEMP=false -if [ $BASH_ARGV == "--keep-temp" ]; then - KEEPTEMP=true -fi - -# Check audio_dir to see if empty or if contains empty wav -bash $UTILS/check_folder.sh $audio_dir - -# Set CWD as LDC_SAD_HMM -cd $LDC_SAD_DIR - -# launch ldc -python perform_sad.py -L $workdir $audio_dir/*.wav -echo "finished using ldcSad_hmm. Please look inside $1 to see the output in *.rttm format" - -# move all files to name them correctly -for wav in `ls $audio_dir/*.wav`; do - # retrieve filename and remove .wav - base=$(basename $wav .wav) - rttm_out=$workdir/ldcSad_${base}.rttm - if [ -s $workdir/${base}.lab ]; then - grep ' speech' $workdir/${base}.lab | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $rttm_out - else - touch $rttm_out - fi -done - -if ! $KEEPTEMP; then - rm -rf $workdir -fi From 1d5aa0bc91bf5ac39dbd64b3c64418a40e345761 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 14:16:59 -0500 Subject: [PATCH 174/299] fixed _s to S errors --- launcher/diartk.sh | 6 +++--- launcher/noisemesSad.sh | 1 - launcher/python3/noisemesSad.sh | 5 ++--- launcher/python3/test.sh | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/launcher/diartk.sh b/launcher/diartk.sh index 8c96a48..83f7638 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -60,15 +60,15 @@ for fin in `ls $audio_dir/*.wav`; do case $trs_format in "noisemesSad") sys="noisemesSad" - python $UTILS/rttm2scp.py $audio_dir/noisemes_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/noisemesSad_${basename}.rttm $scpfile ;; "tocomboSad") sys="tocomboSad" - python $UTILS/rttm2scp.py $audio_dir/tocombo_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/tocomboSad_${basename}.rttm $scpfile ;; "opensmileSad") sys="opensmileSad" - python $UTILS/rttm2scp.py $audio_dir/opensmile_sad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py $audio_dir/opensmileSad_${basename}.rttm $scpfile ;; "textgrid") sys="goldSad" diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index c8f0394..f07d1e4 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -1,5 +1,4 @@ #!/bin/bash -# noisemes_sad.sh source activate divime diff --git a/launcher/python3/noisemesSad.sh b/launcher/python3/noisemesSad.sh index 7a10d93..5ddac5a 100755 --- a/launcher/python3/noisemesSad.sh +++ b/launcher/python3/noisemesSad.sh @@ -1,5 +1,4 @@ #!/bin/bash -# noisemes_sad.sh source activate divime # run OpenSAT with hard coded models & configs found here and in /vagrant @@ -14,7 +13,7 @@ BASEDIR=`dirname $SCRIPT` if [ $# -lt 1 ]; then - echo "Usage: noisemes_sad.sh " + echo "Usage: noisemesSad.sh " echo "where dirname is a folder on the host" echo "containing the wav files (/vagrant/dirname/ in the VM)" exit 1 @@ -56,7 +55,7 @@ echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. for sad in `ls $audio_dir/hyp_sum/*.lab`; do base=$(basename $sad .lab) - rttm_out=noisemes_sad_${base}.rttm + rttm_out=noisemesSad_${base}.rttm if [ -s $sad ]; then grep ' speech' $sad | awk -v fname=$base '{print "SPEAKER" " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out else diff --git a/launcher/python3/test.sh b/launcher/python3/test.sh index de35bc2..4608f96 100644 --- a/launcher/python3/test.sh +++ b/launcher/python3/test.sh @@ -86,7 +86,7 @@ ln -fs $TEST_WAV $TESTDIR #./runDiarNoisemes.sh $TESTDIR > $TESTDIR/noisemes-test.log 2>&1 $LAUNCHERS/noisemesSad.sh $DATADIR/noisemes-test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/noisemes_sad_$BASETEST.rttm ]; then +if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then echo "Noisemes passed the test." else FAILURES=true From f806ee63987d0aa0e699686e6806f7c30ef65529 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 29 Nov 2018 14:40:31 -0500 Subject: [PATCH 175/299] eval may be broken --- launcher/evalDiar.sh | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 87babc3..5dfb82f 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -1,11 +1,11 @@ #!/bin/bash -# Absolute path to this script. /home/user/bin/foo.sh +# Launcher onset routine SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to OpenSAT (go on folder up and to opensat) -DSCOREDIR=$(dirname $BASEDIR)/dscore +BASEDIR=/home/vagrant +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +# end of launcher onset routine display_usage() { @@ -27,7 +27,11 @@ display_usage() { } -if ! [[ $2 =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lena)$ ]] ]; then +### Read in variables from user +audio_dir=/vagrant/$1 +model=$2 + +if ! [[ $model =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lena)$ ]] ]; then display_usage fi @@ -36,17 +40,10 @@ if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi -# data directory -audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") -extension="${filename##*.}" -basename="${filename%.*}" # Set CWD to path of Dscore cd $DSCOREDIR -model=$2 if [[ $model =~ ^(diartk|yuniseg) ]]; then trs_format=$3 case $trs_format in From fb8484ef1dafb7d143c73f9511054570f01a05f4 Mon Sep 17 00:00:00 2001 From: Junghan Date: Sun, 2 Dec 2018 14:57:37 -0500 Subject: [PATCH 176/299] pass explicit sphinx build --- conf/bootstrap.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 54dc31e..6fc9721 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -206,4 +206,5 @@ if ! $HTK_INSTALLED; then fi # Build the docs -cd /vagrant/docs && make html +cd /vagrant/docs +make SPHINXBUILD=/home/${user}/anaconda/bin/sphinx-build html From 13421c39b7f93a9e95e054c11866ee6fe7268ba7 Mon Sep 17 00:00:00 2001 From: MilesICL Date: Mon, 3 Dec 2018 18:23:51 +0000 Subject: [PATCH 177/299] vcm now can read rttm from yunitator --- launcher/vcm.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/launcher/vcm.sh b/launcher/vcm.sh index dce74b6..a31ce5a 100755 --- a/launcher/vcm.sh +++ b/launcher/vcm.sh @@ -29,6 +29,8 @@ KEEPTEMP=false if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi +mkdir -p $audio_dir/VCMtemp +echo $audio_dir/VCMtemp # let's get our bearings: set CWD to the path of VCM cd $VCMDIR @@ -42,12 +44,6 @@ done echo "$0 finished running" -# take all the .rttm in $audio_dir/VCMtemp/ and move them to /vagrant/data -for vcm in `ls $audio_dir/VCMtemp/*.rttm`; do - _rttm=$(basename $vcm) - rttm=$audio_dir/${_rttm} - mv $vcm $rttm -done # simply remove hyp and feature if ! $KEEPTEMP; then From 015a23d9c76914ab0ba906ee3c51acda7bdccb66 Mon Sep 17 00:00:00 2001 From: Junghan Date: Wed, 5 Dec 2018 12:37:57 -0500 Subject: [PATCH 178/299] Tool update script - Edit version tags as necessary - Usage: `$ vagrant up --provision-with=update` --- conf/update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/update.sh b/conf/update.sh index a3c392e..949fd22 100644 --- a/conf/update.sh +++ b/conf/update.sh @@ -22,4 +22,4 @@ cd /home/${user}/repos # (cd "vcm"; git checkout master; git pull; git checkout v2.0) (cd "To-Combo-SAD" ; git checkout master; git pull) # (cd "To-Combo-SAD" ; git checkout master; git pull; git checkout v2.0) -############################################# \ No newline at end of file +############################################# From ddca5af956308762d83aadc064d66c9f24527aed Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 7 Dec 2018 19:57:54 +0000 Subject: [PATCH 179/299] fix quotation marks --- launcher/eval.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/eval.sh b/launcher/eval.sh index 10410ec..f36098f 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -44,7 +44,7 @@ fi ### SCRIPT STARTS case $system in -"tocomboSad"|"opensmileSad"|"noisemesSad|lenaSad") +"tocomboSad"|"opensmileSad"|"noisemesSad"|"lenaSad") sh $LAUNCHER/evalSAD.sh $audio_dir $system $KEEPTEMP ;; "yunitate"|"lenaDiar") From 89b535e8b43e2842bfa659558b558d5eff212e94 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 7 Dec 2018 19:59:13 +0000 Subject: [PATCH 180/299] bracketize audio dir --- launcher/evalDiar.sh | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 5dfb82f..97ebf52 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -5,6 +5,7 @@ SCRIPT=$(readlink -f $0) BASEDIR=/home/vagrant REPOS=$BASEDIR/repos UTILS=$BASEDIR/utils +DSCOREDIR=$REPOS/dscore # end of launcher onset routine @@ -22,7 +23,7 @@ display_usage() { echo " - diartk_tocomboSad" echo " - diartk_rttm" echo " - yunitate" - echo " - lena" + echo " - lenaSad" exit 1; } @@ -31,7 +32,7 @@ display_usage() { audio_dir=/vagrant/$1 model=$2 -if ! [[ $model =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lena)$ ]] ]; then +if ! [[ $model =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lenaSad)$ ]] ]; then display_usage fi @@ -58,16 +59,16 @@ if [[ $model =~ ^(diartk|yuniseg) ]]; then ;; "textgrid") sys_name=$model"_goldSad" - for wav in `ls $audio_dir/*.wav`; do + for wav in `ls ${audio_dir}/*.wav`; do base=$(basename $wav .wav) - python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid $audio_dir/${basename}.rttm + python /home/vagrant/utils/textgrid2rttm.py ${audio_dir}/${basename}.TextGrid ${audio_dir}/${basename}.rttm done ;; "eaf") sys_name=$model"_goldSad" - for wav in `ls $audio_dir/*.wav`; do + for wav in `ls ${audio_dir}/*.wav`; do base=$(basename $wav .wav) - python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf $audio_dir/${basename}.rttm + python /home/vagrant/utils/elan2rttm.py ${audio_dir}/${basename}.eaf ${audio_dir}/${basename}.rttm done ;; "rttm") @@ -85,33 +86,33 @@ if [[ $model =~ ^(diartk|yuniseg) ]]; then esac elif [ "$2" == "yunitate" ]; then sys_name="yunitator" -elif [ "$2" == "lena" ]; then - sys_name="lena" +elif [ "$2" == "lenaSad" ]; then + sys_name="lena_sad" fi -echo $BASEDIR/create_ref_sys.sh $1 $sys_name -$BASEDIR/create_ref_sys.sh $1 $sys_name +echo $UTILS/create_ref_sys.sh $1 $sys_name +$UTILS/create_ref_sys.sh $1 $sys_name echo "evaluating" -python score_batch.py $audio_dir/${sys_name}_eval.df $audio_dir/temp_ref $audio_dir/temp_sys +python score_batch.py ${audio_dir}/${sys_name}_eval.df ${audio_dir}/temp_ref ${audio_dir}/temp_sys # Check if some gold files are empty. If so, add a line in the eval dataframe -for fin in `ls $audio_dir/temp_ref/*.rttm`; do +for fin in `ls ${audio_dir}/temp_ref/*.rttm`; do base=$(basename $fin .rttm) - if [ ! -s $audio_dir/temp_ref/$base.rttm ]; then - if [ ! -s $audio_dir/temp_sys/$base.rttm ]; then - echo $base" 0 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + if [ ! -s ${audio_dir}/temp_ref/$base.rttm ]; then + if [ ! -s ${audio_dir}/temp_sys/$base.rttm ]; then + echo $base" 0 NA NA NA NA NA NA NA NA" >> ${audio_dir}/${sys_name}_eval.df else - echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + echo $base" 100 NA NA NA NA NA NA NA NA" >> ${audio_dir}/${sys_name}_eval.df fi - elif [ ! -s $audio_dir/temp_sys/$base.rttm ] && [ -s $audio_dir/temp_ref/$base.rttm ]; then - echo $base" 100 NA NA NA NA NA NA NA NA" >> $audio_dir/${sys_name}_eval.df + elif [ ! -s ${audio_dir}/temp_sys/$base.rttm ] && [ -s ${audio_dir}/temp_ref/$base.rttm ]; then + echo $base" 100 NA NA NA NA NA NA NA NA" >> ${audio_dir}/${sys_name}_eval.df fi done echo "done evaluating, check $1/${sys_name}_eval.df for the results" # remove temps if ! $KEEPTEMP; then - rm -rf $audio_dir/temp_ref $audio_dir/temp_sys + rm -rf ${audio_dir}/temp_ref ${audio_dir}/temp_sys fi From 1091c6b3f60e536923e03b93686306e8e7e7b248 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 7 Dec 2018 20:02:16 +0000 Subject: [PATCH 181/299] bracketize audio dir --- utils/create_ref_sys.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh index 250e882..da59042 100755 --- a/utils/create_ref_sys.sh +++ b/utils/create_ref_sys.sh @@ -28,8 +28,7 @@ if [ -z "$3" ]; then create_lab=false fi - -if ! [[ $model_prefix =~ ^(ldc_sad|noisemesSad|tocomboSad|opensmileSad|lenaSad|lena|yunitator|\ +if ! [[ $model_prefix =~ ^(noisemesSad|tocomboSad|opensmileSad|lenaSad|lena|yunitator|\ diartk_ldcSad|diartk_noisemesSad|diartk_tocomboSad|diartk_opensmileSad|diartk_goldSad|\ yuniseg_ldcSad|yuniseg_noisemesSad|yuniseg_tocomboSad|yuniseg_opensmileSad|yuniseg_goldSad)$ ]]; then echo "You're trying to create folders containing the reference transcriptions, and the predicted ones." @@ -38,9 +37,9 @@ yuniseg_ldcSad|yuniseg_noisemesSad|yuniseg_tocomboSad|yuniseg_opensmileSad|yunis exit 1; fi -echo "audio_dir is: " $audio_dir # Create temp_ref folder +echo mkdir -p $audio_dir/temp_ref mkdir -p $audio_dir/temp_ref for wav in `ls $audio_dir/*.wav`; do base=$(basename $wav .wav) @@ -52,6 +51,7 @@ for wav in `ls $audio_dir/*.wav`; do # Replace two or more occurrences of whitespace by just one sed -i 's/ \+/ /g' $audio_dir/temp_ref/${base}.rttm if [ $create_lab == true ]; then + echo "creating: " $audio_dir/temp_ref/${base}.lab awk '{print $4" "($4+$5)" speech"}' $audio_dir/temp_ref/${base}.rttm > $audio_dir/temp_ref/${base}.lab fi done @@ -70,8 +70,8 @@ for rttm in `ls $audio_dir/${model_prefix}_*.rttm`; do done # check that temp_sys is not empty, otherwise exit and remove it. -if [ -z "$(ls -A $audio_dir/temp_sys)" ]; then +if [ -z "$(ls -A ${audio_dir}/temp_sys)" ]; then echo "Didn't find any transcription from the model prefix you specified. Please get the ${model_prefix}_my_file.rttm before" - rm -rf $audio_dir/temp_sys $audio_dir/temp_ref + rm -rf ${audio_dir}/temp_sys ${audio_dir}/temp_ref exit fi From c97bf6667b13af55a2b98d5fcd2514e18743f233 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 7 Dec 2018 20:22:49 +0000 Subject: [PATCH 182/299] use dscore to compute SAD --- launcher/evalSad.sh | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100755 launcher/evalSad.sh diff --git a/launcher/evalSad.sh b/launcher/evalSad.sh new file mode 100755 index 0000000..3a2a2d2 --- /dev/null +++ b/launcher/evalSad.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc + +# Absolute path to this script. /home/user/bin/foo.sh +SCRIPT=$(readlink -f $0) +# Absolute path this script is in. /home/user/bin +BASEDIR=/home/vagrant +UTILS=$BASEDIR/utils +REPOS=$BASEDIR/repos +# Path to scoring tool NOTE: NOT dscore! +DSCOREDIR=$REPOS/dscore + + +# data directory +audio_dir=$1 +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") +extension="${filename##*.}" +basename="${filename%.*}" + +# check system to evaluate - either LDC, OpenSAT or "MySystem" +sys_name=$2 + +if ! [[ $sys_name =~ ^(noisemesSad|tocomboSad|opensmileSad|lenaSad)$ ]]; then + echo "Please Specify the System you wish to evaluate." + echo "Choose between noisemesSad, tocomboSad, lenaSad and opensmileSad." + exit +fi + +KEEPTEMP=false +if [ $BASH_ARGV == "--keep-temp" ]; then + KEEPTEMP=true +fi + +# Set CWD to path of scoring tool +cd $DSCOREDIR + +# pass vagrant-relative pathname to create_ref_sys +$UTILS/create_ref_sys.sh ${audio_dir} $sys_name true + +# resolve to absolute path for rest of this script +audio_dir=/vagrant/${audio_dir} + +OUTPUT_DF=${audio_dir}/${sys_name}_eval.df +REF=${audio_dir}/temp_ref +SYS=${audio_dir}/temp_sys +echo "evaluating" + +python score_batch.py $OUTPUT_DF $REF $SYS + +# small detail: remove the commas from the output +sed -i "s/,//g" $OUTPUT_DF +echo "done evaluating, check $1/${sys_name}_eval.df for the results" + +# remove temps +if ! $KEEPTEMP; then + rm -rf $REF $SYS +fi From d32f190909bf54a57c82a0bc310ca65bbd71631b Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Mon, 10 Dec 2018 13:29:15 +0100 Subject: [PATCH 183/299] Fix eaf2txt.py to make it work with path beginning by / --- utils/eaf2txt.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py index 56ca2d5..1623b06 100755 --- a/utils/eaf2txt.py +++ b/utils/eaf2txt.py @@ -64,6 +64,10 @@ def main(): help="path to the input .eaf file or the folder containing eaf files.") args = parser.parse_args() + # Removing extra beginning / that might break the code + if args.input[0] == '/': + args.input = args.input[1:] + # Initialize the output folder as the same folder than the input # if not provided by the user. if args.input[-4:] == '.eaf': @@ -72,7 +76,9 @@ def main(): output = args.input data_dir = '/vagrant' + args.input = os.path.join(data_dir, args.input) + output = os.path.join(data_dir, output) if not os.path.isdir(output): os.mkdir(output) From 62ff49bd946a2e45340afe27008e120559ec30eb Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 10 Dec 2018 15:59:18 +0000 Subject: [PATCH 184/299] less verbose --- utils/create_ref_sys.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh index da59042..3317918 100755 --- a/utils/create_ref_sys.sh +++ b/utils/create_ref_sys.sh @@ -39,7 +39,6 @@ fi # Create temp_ref folder -echo mkdir -p $audio_dir/temp_ref mkdir -p $audio_dir/temp_ref for wav in `ls $audio_dir/*.wav`; do base=$(basename $wav .wav) From af51ece7267c9a64db2daa07a7b89a3208310555 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 10 Dec 2018 15:07:05 -0500 Subject: [PATCH 185/299] support audio paths with spaces --- launcher/diartk.sh | 24 ++++++++++++------------ launcher/eval.sh | 6 +++--- launcher/noisemesSad.sh | 22 +++++++++++----------- launcher/opensmileSad.sh | 8 ++++---- launcher/talnet.sh | 8 ++++---- launcher/tocomboSad.sh | 16 ++++++++-------- launcher/vcm.sh | 14 +++++++------- launcher/yunitate.sh | 14 +++++++------- utils/create_ref_sys.sh | 28 ++++++++++++++-------------- utils/noisemes_full.sh | 28 ++++++++++++++-------------- utils/runTALNet.sh | 8 ++++---- utils/yuniSeg.sh | 20 ++++++++++---------- 12 files changed, 98 insertions(+), 98 deletions(-) diff --git a/launcher/diartk.sh b/launcher/diartk.sh index 83f7638..a1f3fb4 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -32,7 +32,7 @@ trs_format=$2 ### Other variables specific to this script # create temp dir -workdir=$audio_dir/temp/diartk +workdir=${audio_dir}/temp/diartk mkdir -p $workdir ### SCRIPT STARTS @@ -40,10 +40,10 @@ cd $BASEDIR/repos/ib_diarization_toolkit # Check audio_dir to see if empty or if contains empty wav -bash $UTILS/check_folder.sh $audio_dir +bash $UTILS/check_folder.sh ${audio_dir} -for fin in `ls $audio_dir/*.wav`; do +for fin in `ls ${audio_dir}/*.wav`; do filename=$(basename "$fin") basename="${filename%.*}" echo "treating $basename" @@ -60,25 +60,25 @@ for fin in `ls $audio_dir/*.wav`; do case $trs_format in "noisemesSad") sys="noisemesSad" - python $UTILS/rttm2scp.py $audio_dir/noisemesSad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py ${audio_dir}/noisemesSad_${basename}.rttm $scpfile ;; "tocomboSad") sys="tocomboSad" - python $UTILS/rttm2scp.py $audio_dir/tocomboSad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py ${audio_dir}/tocomboSad_${basename}.rttm $scpfile ;; "opensmileSad") sys="opensmileSad" - python $UTILS/rttm2scp.py $audio_dir/opensmileSad_${basename}.rttm $scpfile + python $UTILS/rttm2scp.py ${audio_dir}/opensmileSad_${basename}.rttm $scpfile ;; "textgrid") sys="goldSad" - python /home$UTILS/textgrid2rttm.py $audio_dir/${basename}.TextGrid $workdir/${basename}.rttm + python /home$UTILS/textgrid2rttm.py ${audio_dir}/${basename}.TextGrid $workdir/${basename}.rttm python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile rm $workdir/$basename.rttm ;; "eaf") sys="goldSad" - python /home$UTILS/elan2rttm.py $audio_dir/${basename}.eaf $workdir/${basename}.rttm + python /home$UTILS/elan2rttm.py ${audio_dir}/${basename}.eaf $workdir/${basename}.rttm python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile rm $workdir/$basename.rttm ;; @@ -86,7 +86,7 @@ for fin in `ls $audio_dir/*.wav`; do sys="goldSad" # Since some reference rttm files are spaced rather than tabbed, we need to # tab them before using them. - cp $audio_dir/${basename}.rttm $workdir/${basename}.rttm + cp ${audio_dir}/${basename}.rttm $workdir/${basename}.rttm sed -i 's/ \+/\t/g' $workdir//${basename}.rttm python $UTILS/rttm2scp.py $workdir/${basename}.rttm $scpfile ;; @@ -113,11 +113,11 @@ for fin in `ls $audio_dir/*.wav`; do # print results #cat $workdir/$basename.out - cp $workdir/$basename.rttm $audio_dir/diartk_${sys}_${basename}.rttm + cp $workdir/$basename.rttm ${audio_dir}/diartk_${sys}_${basename}.rttm fi - if [ ! -s $audio_dir/diartk_${sys}_${basename}.rttm ]; then + if [ ! -s ${audio_dir}/diartk_${sys}_${basename}.rttm ]; then # if diarization failed, still write an empty file... - touch $audio_dir/diartk_${sys}_${basename}.rttm + touch ${audio_dir}/diartk_${sys}_${basename}.rttm fi diff --git a/launcher/eval.sh b/launcher/eval.sh index f36098f..6742150 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -45,14 +45,14 @@ fi ### SCRIPT STARTS case $system in "tocomboSad"|"opensmileSad"|"noisemesSad"|"lenaSad") - sh $LAUNCHER/evalSAD.sh $audio_dir $system $KEEPTEMP + sh $LAUNCHER/evalSAD.sh ${audio_dir} $system $KEEPTEMP ;; "yunitate"|"lenaDiar") - sh $LAUNCHER/evalDiar.sh $audio_dir $system $KEEPTEMP + sh $LAUNCHER/evalDiar.sh ${audio_dir} $system $KEEPTEMP ;; "diartk") sad=$3 - sh $LAUNCHER/evalDiar.sh $audio_dir $system $sad $KEEPTEMP + sh $LAUNCHER/evalDiar.sh ${audio_dir} $system $sad $KEEPTEMP ;; *) display_usage diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index f07d1e4..45a81db 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -28,23 +28,23 @@ done audio_dir=/vagrant/$1 TEMPNAME=feature -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/utils/check_folder.sh $audio_dir +bash $BASEDIR/utils/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to path of Yunitator cd $YUNITATORDIR # make output folder for features, below input folder -mkdir -p $audio_dir/$TEMPNAME +mkdir -p ${audio_dir}/$TEMPNAME # first features echo "extracting features for speech activity detection" -for file in `ls $audio_dir/*.wav`; do +for file in `ls ${audio_dir}/*.wav`; do ./extract-htk-vm2.sh $file $TEMPNAME done @@ -60,12 +60,12 @@ let chunksize=$chunksize/100000*200 #python SSSF/code/predict/1-confidence-vm3.py $1 echo "detecting speech and non speech segments" -python yunified.py noisemes $audio_dir $chunksize +python yunified.py noisemes ${audio_dir} $chunksize echo "finished detecting speech and non speech segments" # take all the .rttm in /vagrant/data/hyp and move them to /vagrant/data - move features and hyp to another folder also. -for sad in `ls $audio_dir/hyp_sum/*.lab`; do +for sad in `ls ${audio_dir}/hyp_sum/*.lab`; do base=$(basename $sad .lab) if $FULLCLASSES; then @@ -76,18 +76,18 @@ for sad in `ls $audio_dir/hyp_sum/*.lab`; do if [ -s $sad ]; then if $FULLCLASSES; then - grep '' $sad | awk -v fname=$base '{print $4 " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out + grep '' $sad | awk -v fname=$base '{print $4 " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > ${audio_dir}/$rttm_out else - grep ' speech' $sad | awk -v fname=$base '{print $4 " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > $audio_dir/$rttm_out + grep ' speech' $sad | awk -v fname=$base '{print $4 " " fname " " 1 " " $1 " " $2-$1 " " "" " " "" " " $3 " " ""}' > ${audio_dir}/$rttm_out fi else - touch $audio_dir/$rttm_out + touch ${audio_dir}/$rttm_out fi done # simple remove hyp and feature if ! $KEEPTEMP; then - rm -rf $audio_dir/hyp_sum $audio_dir/$TEMPNAME + rm -rf ${audio_dir}/hyp_sum ${audio_dir}/$TEMPNAME fi source deactivate diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 368f204..9c414dd 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -15,7 +15,7 @@ audio_dir=/vagrant/$1 OSHOME=$REPOS/opensmile-2.3.0 CONFIG_FILE=$CONF/vad_segmenter_aclew.conf OPENSMILE=SMILExtract -workdir=$audio_dir/temp/opensmileSad +workdir=${audio_dir}/temp/opensmileSad mkdir -p $workdir ### SCRIPT STARTS @@ -39,12 +39,12 @@ basename="${filename%.*}" cd $OSHOME/scripts/vad # Use OpenSMILE 2.3.0 -for sad in `ls $audio_dir/*.wav`; do +for sad in `ls ${audio_dir}/*.wav`; do file=$sad id=`basename $file` id=${id%.wav} - > $audio_dir/${id}.txt #Make it empty if already present + > ${audio_dir}/${id}.txt #Make it empty if already present echo "Processing $id ..." LD_LIBRARY_PATH=/usr/local/lib \ $OPENSMILE \ @@ -61,7 +61,7 @@ rm -f output_segment_*.wav for output in $(ls $workdir/*.txt); do id=$(basename $output .txt) - awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > $audio_dir/opensmileSad_$id.rttm + awk -F ';|,' -v FN=$id '{ start_on = $2; start_off = $3 ; print "SPEAKER "FN" 1 "start_on" "(start_off-start_on)" speech " }' $output > ${audio_dir}/opensmileSad_$id.rttm done # Delete temporary folder diff --git a/launcher/talnet.sh b/launcher/talnet.sh index 4f18cf1..ba98015 100755 --- a/launcher/talnet.sh +++ b/launcher/talnet.sh @@ -17,12 +17,12 @@ if [ $# -ne 1 ]; then fi audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} @@ -34,7 +34,7 @@ echo "Starting" for f in `ls ${audio_dir}/*.wav`; do ./runTALNet.sh $f base=$(basename $f .wav) - mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat + mv ${audio_dir}/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat done echo "$0 finished running" diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index f59747d..f54fa17 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -14,7 +14,7 @@ trs_format=$2 ### Other variables specific to this script # create temp dir -workdir=$audio_dir/temp/tocomboSad +workdir=${audio_dir}/temp/tocomboSad mkdir -p $workdir TOCOMBOSADDIR=$REPOS/To-Combo-SAD MCR=/usr/local/MATLAB/MATLAB_Runtime/v93 @@ -33,13 +33,13 @@ if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash /home/vagrant/utils/check_folder.sh $audio_dir +bash /home/vagrant/utils/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to path of ToComboSAD cd $TOCOMBOSADDIR @@ -50,7 +50,7 @@ touch $workdir/filelist.txt # create temp dir to store audio files with 1 channels, if needed (i.e. if audio to treat has 2 or more channels.) # Indeed, To Combo Sad Fails when there are more than 1 channels. -for f in $audio_dir/*.wav; do +for f in ${audio_dir}/*.wav; do # Check if audio has 1 channel or more. If it has more, use sox to create a temp audio file w/ 1 channel. n_chan=$(soxi $f | grep Channels | cut -d ':' -f 2) if [[ $n_chan -gt 1 ]]; then @@ -69,12 +69,12 @@ export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64 ./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt # Retrieve the outputs from the temp folder -mv $workdir/*ToCombo.txt $audio_dir +mv $workdir/*ToCombo.txt ${audio_dir} #convert to rttms -for f in $audio_dir/*.ToCombo.txt; do +for f in ${audio_dir}/*.ToCombo.txt; do bn=`basename $f .wav.ToCombo.txt` - python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > $audio_dir/tocomboSad_$bn.rttm + python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > ${audio_dir}/tocomboSad_$bn.rttm done # Delete temporary folder diff --git a/launcher/vcm.sh b/launcher/vcm.sh index a31ce5a..4394bf1 100755 --- a/launcher/vcm.sh +++ b/launcher/vcm.sh @@ -18,26 +18,26 @@ if [ $# -ne 1 ]; then fi audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} KEEPTEMP=false if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi -mkdir -p $audio_dir/VCMtemp -echo $audio_dir/VCMtemp +mkdir -p ${audio_dir}/VCMtemp +echo ${audio_dir}/VCMtemp # let's get our bearings: set CWD to the path of VCM cd $VCMDIR # Iterate over files echo "Starting" -for f in `ls $audio_dir/*.wav`; do +for f in `ls ${audio_dir}/*.wav`; do echo $f ./runVCM.sh $f done @@ -47,5 +47,5 @@ echo "$0 finished running" # simply remove hyp and feature if ! $KEEPTEMP; then - rm -rf $audio_dir/VCMtemp + rm -rf ${audio_dir}/VCMtemp fi diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 81f6afd..9627545 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -26,13 +26,13 @@ fi audio_dir=/vagrant/$1 TEMPNAME=Yunitemp -YUNITEMP=$audio_dir/$TEMPNAME -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +YUNITEMP=${audio_dir}/$TEMPNAME +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash /home/vagrant/utils/check_folder.sh $audio_dir +bash /home/vagrant/utils/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to the path of Yunitator @@ -43,7 +43,7 @@ mkdir -p $YUNITEMP # Iterate over files echo "Starting $0" -for f in `ls $audio_dir/*.wav`; do +for f in `ls ${audio_dir}/*.wav`; do basename=`basename $f .wav` # first features @@ -69,10 +69,10 @@ done echo "$0 finished running" -# take all the .rttm in $audio_dir/Yunitemp/ and move them to /vagrant/data +# take all the .rttm in ${audio_dir}/Yunitemp/ and move them to /vagrant/data for sad in `ls $YUNITEMP/*.rttm`; do _rttm=$(basename $sad) - rttm=$audio_dir/yunitator_${_rttm} + rttm=${audio_dir}/yunitator_${_rttm} # Remove not needed SIL lines # sed -i '/ SIL /d' $sad mv $sad $rttm diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh index 3317918..b5c53d0 100755 --- a/utils/create_ref_sys.sh +++ b/utils/create_ref_sys.sh @@ -4,7 +4,7 @@ audio_dir=/vagrant/$1 model_prefix=$2 create_lab=$3 -base_directory=$(echo "$audio_dir" | awk -F "/" '{print $2}') +base_directory=$(echo "${audio_dir}" | awk -F "/" '{print $2}') if [ "$base_directory" != "vagrant" ]; then audio_dir=$1 @@ -39,32 +39,32 @@ fi # Create temp_ref folder -mkdir -p $audio_dir/temp_ref -for wav in `ls $audio_dir/*.wav`; do +mkdir -p ${audio_dir}/temp_ref +for wav in `ls ${audio_dir}/*.wav`; do base=$(basename $wav .wav) - cp $audio_dir/${base}.rttm $audio_dir/temp_ref/${base}.rttm + cp ${audio_dir}/${base}.rttm ${audio_dir}/temp_ref/${base}.rttm # Sort rttm by onset - sort --key 4 --numeric-sort $audio_dir/${base}.rttm -o $audio_dir/temp_ref/${base}.rttm + sort --key 4 --numeric-sort ${audio_dir}/${base}.rttm -o ${audio_dir}/temp_ref/${base}.rttm # Change tabulations to white-spaces - sed -i 's/\t/ /g' $audio_dir/temp_ref/${base}.rttm + sed -i 's/\t/ /g' ${audio_dir}/temp_ref/${base}.rttm # Replace two or more occurrences of whitespace by just one - sed -i 's/ \+/ /g' $audio_dir/temp_ref/${base}.rttm + sed -i 's/ \+/ /g' ${audio_dir}/temp_ref/${base}.rttm if [ $create_lab == true ]; then - echo "creating: " $audio_dir/temp_ref/${base}.lab - awk '{print $4" "($4+$5)" speech"}' $audio_dir/temp_ref/${base}.rttm > $audio_dir/temp_ref/${base}.lab + echo "creating: " ${audio_dir}/temp_ref/${base}.lab + awk '{print $4" "($4+$5)" speech"}' ${audio_dir}/temp_ref/${base}.rttm > ${audio_dir}/temp_ref/${base}.lab fi done # Create temp_sys folder and copy all of the sys rttm inside of it # Remove the model_prefix of it -mkdir -p $audio_dir/temp_sys -for rttm in `ls $audio_dir/${model_prefix}_*.rttm`; do +mkdir -p ${audio_dir}/temp_sys +for rttm in `ls ${audio_dir}/${model_prefix}_*.rttm`; do base=$(basename $rttm .rttm) out=`echo $base | sed "s/${model_prefix}\_//g"` - cp $rttm $audio_dir/temp_sys/${out}.rttm + cp $rttm ${audio_dir}/temp_sys/${out}.rttm if [ $create_lab == true ]; then - echo "creating: " $audio_dir/temp_sys/${out}.lab - awk '{print $4" "($4+$5)" speech"}' $rttm > $audio_dir/temp_sys/${out}.lab + echo "creating: " ${audio_dir}/temp_sys/${out}.lab + awk '{print $4" "($4+$5)" speech"}' $rttm > ${audio_dir}/temp_sys/${out}.lab fi done diff --git a/utils/noisemes_full.sh b/utils/noisemes_full.sh index 9af469b..9d6a2cf 100755 --- a/utils/noisemes_full.sh +++ b/utils/noisemes_full.sh @@ -18,19 +18,19 @@ if [ $# -ne 1 ]; then fi audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to the path of OpenSAT cd $OPENSATDIR # first features echo "extracting features for noisemes_full" -for file in `ls $audio_dir/*.wav`; do +for file in `ls ${audio_dir}/*.wav`; do SSSF/code/feature/extract-htk-vm2.sh $file done @@ -41,31 +41,31 @@ done # python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename echo "predicting classes" # python SSSF/code/predict/1-confidence-vm.py $BASEDIR/SSSF/data/feature/evl.med.htk/$basename.htk $basename -python SSSF/code/predict/1-confidence-vm4.py $audio_dir +python SSSF/code/predict/1-confidence-vm4.py ${audio_dir} echo "noisemes_full finished running" # take all the .rttm in /vagrant/data/hyp_sum and move them to /vagrant/data - move features and hyp_sum to another folder also. -for sad in `ls $audio_dir/hyp_sum/*.rttm`; do +for sad in `ls ${audio_dir}/hyp_sum/*.rttm`; do _rttm=$(basename $sad) - rttm=$audio_dir/noiseme_full_${_rttm} + rttm=${audio_dir}/noiseme_full_${_rttm} mv $sad $rttm done # simply remove hyp and feature -rm -rf $audio_dir/feature $audio_dir/hyp_sum +rm -rf ${audio_dir}/feature ${audio_dir}/hyp_sum -#if [ ! -d "$audio_dir/noiseme_full_temp" ]; then -# mkdir -p $audio_dir/noiseme_full_temp +#if [ ! -d "${audio_dir}/noiseme_full_temp" ]; then +# mkdir -p ${audio_dir}/noiseme_full_temp #fi # -#if [! -d "$audio_dir/noiseme_full_temp" ]; then -# mv $audio_dir/hyp_sum $audio_dir/noiseme_full_temp +#if [! -d "${audio_dir}/noiseme_full_temp" ]; then +# mv ${audio_dir}/hyp_sum ${audio_dir}/noiseme_full_temp #else # echo "can't move hyp_sum/ folder to noiseme_full_temp/ because temp is already full" #fi # -#if [! -d "$audio_dir/noiseme_full_temp" ]; then -# mv $audio_dir/feature $audio_dir/noiseme_full_temp +#if [! -d "${audio_dir}/noiseme_full_temp" ]; then +# mv ${audio_dir}/feature ${audio_dir}/noiseme_full_temp #else # echo "can't move features/ folder to noiseme_full_temp/ because temp is already full" #fi diff --git a/utils/runTALNet.sh b/utils/runTALNet.sh index df3dd0b..629bb38 100755 --- a/utils/runTALNet.sh +++ b/utils/runTALNet.sh @@ -17,12 +17,12 @@ if [ $# -ne 1 ]; then fi audio_dir=/vagrant/$1 -filename=$(basename "$audio_dir") -dirname=$(dirname "$audio_dir") +filename=$(basename "${audio_dir}") +dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} # let's get our bearings: set CWD to the path of TALNet cd $CLASSIFY @@ -32,7 +32,7 @@ echo "Starting" for f in `ls ${audio_dir}/*.wav`; do ./runTALNet.sh $f base=$(basename $f .wav) - mv $audio_dir/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat + mv ${audio_dir}/${base}.frame_prob.mat ${audio_dir}/${base}_talnet.frame_prob.mat done echo "$0 finished running" diff --git a/utils/yuniSeg.sh b/utils/yuniSeg.sh index 7f4ccdb..3ba088a 100755 --- a/utils/yuniSeg.sh +++ b/utils/yuniSeg.sh @@ -32,17 +32,17 @@ audio_dir=/vagrant/$1 trs_format=$2 # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh $audio_dir +bash $BASEDIR/check_folder.sh ${audio_dir} # Iterate over files echo "Starting" -for f in `ls $audio_dir/*.wav`; do +for f in `ls ${audio_dir}/*.wav`; do filename=$(basename "$f") basename="${filename%.*}" echo "treating $basename" # output filename produced by runYuniSegs - outfile=$audio_dir/$basename.yuniSeg.rttm + outfile=${audio_dir}/$basename.yuniSeg.rttm case $trs_format in "ldc_sad") @@ -71,12 +71,12 @@ for f in `ls $audio_dir/*.wav`; do "textgrid") sys="goldSad" model_prefix=${trs_format}_ - python /home/vagrant/utils/textgrid2rttm.py $audio_dir/${basename}.TextGrid ${trs_format}_${basename}.rttm + python /home/vagrant/utils/textgrid2rttm.py ${audio_dir}/${basename}.TextGrid ${trs_format}_${basename}.rttm ;; "eaf") sys="goldSad" model_prefix=${trs_format}_ - python /home/vagrant/utils/elan2rttm.py $audio_dir/${basename}.eaf ${trs_format}_${basename}.rttm + python /home/vagrant/utils/elan2rttm.py ${audio_dir}/${basename}.eaf ${trs_format}_${basename}.rttm ;; "rttm") sys="goldSad" @@ -96,12 +96,12 @@ for f in `ls $audio_dir/*.wav`; do ;; esac - ./runYuniSegs.sh $f $audio_dir/${model_prefix}${basename}.rttm - cp $outfile $audio_dir/yuniseg_${sys}_${basename}.rttm + ./runYuniSegs.sh $f ${audio_dir}/${model_prefix}${basename}.rttm + cp $outfile ${audio_dir}/yuniseg_${sys}_${basename}.rttm - if [ ! -s $audio_dir/yuniseg_${sys}_${basename}.rttm ]; then + if [ ! -s ${audio_dir}/yuniseg_${sys}_${basename}.rttm ]; then # if diarization failed, still write an empty file... - touch $audio_dir/yuniseg_${sys}_${basename}.rttm + touch ${audio_dir}/yuniseg_${sys}_${basename}.rttm fi done @@ -109,4 +109,4 @@ echo "$0 finished running" # simply remove hyp and feature rm $outfile -rm -rf $audio_dir/Yunitemp +rm -rf ${audio_dir}/Yunitemp From 18aa8c1095fcdd103ed7cac9760ac4ee8c1d8000 Mon Sep 17 00:00:00 2001 From: jaden-w Date: Tue, 27 Nov 2018 13:48:21 -0500 Subject: [PATCH 186/299] Fixed line endings --- bootstrap.sh | 158 ++++++++++++++++++++++++++++++++++++++++ launcher/noisemesSad.sh | 4 + launcher/yunitate.sh | 12 +-- 3 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 bootstrap.sh diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100644 index 0000000..d38f72b --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,158 @@ +echo "Start bootstraping DiViMe" +apt-get update -y +apt-get upgrade -y + +if grep --quiet vagrant /etc/passwd +then + user="vagrant" +else + user="ubuntu" +fi + +sudo apt-get install -y git make automake libtool autoconf patch subversion fuse \ + libatlas-base-dev libatlas-dev liblapack-dev sox libav-tools g++ \ + zlib1g-dev libsox-fmt-all sshfs gcc-multilib libncurses5-dev unzip bc \ + openjdk-6-jre icedtea-netx-common icedtea-netx libxt-dev libx11-xcb1 \ + libc6-dev-i386 festival espeak python-setuptools gawk \ + libboost-all-dev + + +# Kaldi and others want bash - otherwise the build process fails +[ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh + +# Install Anaconda and Theano +echo "Downloading Anaconda-2.3.0..." +cd /home/${user} +wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh +#bash Anaconda-2.3.0-Linux-x86_64.sh -b # batch install into /home/vagrant/anaconda +echo "Installing Anaconda-2.3.0..." +sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" +if ! grep -q -i anaconda .bashrc; then + echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc +fi +# assume 'conda' is installed now (get path) +su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" +# clean up big installer in home folder +rm -f Anaconda-2.3.0-Linux-x86_64.sh + +# python3 env +# Install Miniconda and python libraries +# miniconda=Miniconda3-4.5.11-Linux-x86_64.sh +echo "Checking python3" +cd /home/$user +cp /vagrant/conf/environment.yml /home/${user}/ +su ${user} -c "/home/${user}/anaconda/bin/conda env create -f environment.yml" + + +# install Matlab runtime environment +cd /tmp +wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip +unzip -q MCR_R2017b_glnxa64_installer.zip +./install -mode silent -agreeToLicense yes +# add Matlab stuff to path +echo 'LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH"' >> /home/${user}/.bashrc +rm /tmp/MCR_R2017b_glnxa64_installer.zip + +# Install OpenSMILE +echo "Installing OpenSMILE" + su ${user} -c "mkdir -p /home/${user}/repos/" +cd /home/${user}/repos/ +wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz +tar zxvf OpenSMILE-2.1.tar.gz +# install SMILExtract system-wide +cp openSMILE-2.1.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin +chmod +x /usr/local/bin/SMILExtract +rm OpenSMILE-2.1.tar.gz + +# Install openSMILE2.3.0 +su ${user} -c "mkdir -p /home/${user}/repos/" +cd /home/${user}/repos/ +wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz +tar zxvf OpenSMILE-2.3.tar.gz +chmod +x openSMILE-2.3.0/bin/linux_x64_standalone_static/SMILExtract +rm OpenSMILE-2.3.tar.gz + +# optionally Install HTK (without it, some other tools will not work) +# the idea is to make users independently download HTK installer since +# we cannot redistribute +cd /home/${user} +if [ -f /vagrant/HTK.tar.gz ]; then + if [[ ! -d htk ]]; then + cd /home/${user}/repos/ + su ${user} -c "tar zxf /vagrant/HTK.tar.gz" + cd htk + ./configure --without-x --disable-hslab + sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + make all + make install + fi +fi + + + +# POPOULATE THE REPOSITORY SECTION +cd /home/${user}/repos/ + + # Get OpenSAT=noisemes and dependencies +# git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev +su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" + +cp /vagrant/conf/.theanorc /home/${user}/ +export PATH=/home/${user}/anaconda/bin:$PATH +su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" + + +# Install ldc-sad +# run this version 'by hand' in the VM in repos/ using your github username and password +#git clone http://github.com/aclew/ldc_sad_hmm + + +# Install Yunitator and dependencies +git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev +su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" +su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" + +# Install VCM +git clone https://github.com/MilesICL/vcm + +#Install to-combo sad and dependencies (matlab runtime environnement) +git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 + +# Install DiarTK +git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 + + +# Install eval +git clone http://github.com/srvk/dscore #--branch v1.0 + +# Phonemizer installation +git clone https://github.com/bootphon/phonemizer +cd phonemizer +python setup.py build +python setup.py install + +#install launcher and utils +# cd /home/${user}/ +# git clone https://github.com/aclew/launcher.git +# chmod +x launcher/* +# git clone https://github.com/aclew/utils.git +# chmod +x utils/* + + +# install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) +# and intervaltree (needed for rttm2scp.py) +# and recommonmark (needed to make html in docs/) +su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" + +# Link /vagrant/launcher and /vagrant/utils to home folder where scripts expect them +ln -s /vagrant/launcher /home/${user}/ +ln -s /vagrant/utils /home/${user}/ + +# Some cleanup +apt-get autoremove -y + +# Silence error message from missing file +touch /home/${user}/.Xauthority + +# Provisioning runs as root; we want files to belong to '${user}' +chown -R ${user}:${user} /home/${user} diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 45a81db..f1756ac 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -1,4 +1,8 @@ #!/bin/bash +# noisemes_sad.sh +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc source activate divime diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 9627545..9f6d9eb 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -1,8 +1,10 @@ #!/bin/bash +# Since the script is built to be launched outside of the vm, source +# the .bashrc which is not necessarily sourced! +source ~/.bashrc source activate divime - # run Yunitator with hard coded models & configs # Absolute path to this script. /home/vagrant/launcher/yunitate.sh @@ -32,7 +34,7 @@ dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash /home/vagrant/utils/check_folder.sh ${audio_dir} +bash /home/vagrant/utils/check_folder.sh $audio_dir # let's get our bearings: set CWD to the path of Yunitator @@ -43,7 +45,7 @@ mkdir -p $YUNITEMP # Iterate over files echo "Starting $0" -for f in `ls ${audio_dir}/*.wav`; do +for f in `ls $audio_dir/*.wav`; do basename=`basename $f .wav` # first features @@ -69,10 +71,10 @@ done echo "$0 finished running" -# take all the .rttm in ${audio_dir}/Yunitemp/ and move them to /vagrant/data +# take all the .rttm in $audio_dir/Yunitemp/ and move them to /vagrant/data for sad in `ls $YUNITEMP/*.rttm`; do _rttm=$(basename $sad) - rttm=${audio_dir}/yunitator_${_rttm} + rttm=$audio_dir/yunitator_${_rttm} # Remove not needed SIL lines # sed -i '/ SIL /d' $sad mv $sad $rttm From 1fe038a28ca2de02db638730fdfdc16db643e1d3 Mon Sep 17 00:00:00 2001 From: jaden-w Date: Tue, 27 Nov 2018 13:57:36 -0500 Subject: [PATCH 187/299] Make bootstrap pull yunified versions of repos --- bootstrap.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bootstrap.sh b/bootstrap.sh index d38f72b..3486b72 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -94,6 +94,7 @@ fi cd /home/${user}/repos/ # Get OpenSAT=noisemes and dependencies + # git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" From 14c3f69a7f9d793dda97a1e8e39dd0d410f27850 Mon Sep 17 00:00:00 2001 From: jaden-w Date: Tue, 27 Nov 2018 17:21:30 -0500 Subject: [PATCH 188/299] Modify yunified scripts for new Yunitator --- bootstrap.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bootstrap.sh b/bootstrap.sh index 3486b72..c0662da 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -110,6 +110,7 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install Yunitator and dependencies git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev + su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" From b245f570eb761489267b7a26176a4d88d5a4e188 Mon Sep 17 00:00:00 2001 From: jaden-w Date: Mon, 10 Dec 2018 02:02:35 -0500 Subject: [PATCH 189/299] Testing noisemes full --- launcher/noisemesFull.sh | 3 +++ launcher/noisemesSad.sh | 1 + 2 files changed, 4 insertions(+) create mode 100644 launcher/noisemesFull.sh diff --git a/launcher/noisemesFull.sh b/launcher/noisemesFull.sh new file mode 100644 index 0000000..70bafd6 --- /dev/null +++ b/launcher/noisemesFull.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./launcher/noisemesSad.sh $@ --full-classes \ No newline at end of file diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index f1756ac..607650f 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -48,6 +48,7 @@ mkdir -p ${audio_dir}/$TEMPNAME # first features echo "extracting features for speech activity detection" + for file in `ls ${audio_dir}/*.wav`; do ./extract-htk-vm2.sh $file $TEMPNAME done From bcda41d9c07cef01d547d7b4b79771dec88298ff Mon Sep 17 00:00:00 2001 From: jaden-w Date: Fri, 14 Dec 2018 03:27:00 -0500 Subject: [PATCH 190/299] Duplicate bootstrap --- bootstrap.sh | 160 --------------------------------------------------- 1 file changed, 160 deletions(-) delete mode 100644 bootstrap.sh diff --git a/bootstrap.sh b/bootstrap.sh deleted file mode 100644 index c0662da..0000000 --- a/bootstrap.sh +++ /dev/null @@ -1,160 +0,0 @@ -echo "Start bootstraping DiViMe" -apt-get update -y -apt-get upgrade -y - -if grep --quiet vagrant /etc/passwd -then - user="vagrant" -else - user="ubuntu" -fi - -sudo apt-get install -y git make automake libtool autoconf patch subversion fuse \ - libatlas-base-dev libatlas-dev liblapack-dev sox libav-tools g++ \ - zlib1g-dev libsox-fmt-all sshfs gcc-multilib libncurses5-dev unzip bc \ - openjdk-6-jre icedtea-netx-common icedtea-netx libxt-dev libx11-xcb1 \ - libc6-dev-i386 festival espeak python-setuptools gawk \ - libboost-all-dev - - -# Kaldi and others want bash - otherwise the build process fails -[ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh - -# Install Anaconda and Theano -echo "Downloading Anaconda-2.3.0..." -cd /home/${user} -wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh -#bash Anaconda-2.3.0-Linux-x86_64.sh -b # batch install into /home/vagrant/anaconda -echo "Installing Anaconda-2.3.0..." -sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" -if ! grep -q -i anaconda .bashrc; then - echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc -fi -# assume 'conda' is installed now (get path) -su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" -# clean up big installer in home folder -rm -f Anaconda-2.3.0-Linux-x86_64.sh - -# python3 env -# Install Miniconda and python libraries -# miniconda=Miniconda3-4.5.11-Linux-x86_64.sh -echo "Checking python3" -cd /home/$user -cp /vagrant/conf/environment.yml /home/${user}/ -su ${user} -c "/home/${user}/anaconda/bin/conda env create -f environment.yml" - - -# install Matlab runtime environment -cd /tmp -wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip -unzip -q MCR_R2017b_glnxa64_installer.zip -./install -mode silent -agreeToLicense yes -# add Matlab stuff to path -echo 'LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH"' >> /home/${user}/.bashrc -rm /tmp/MCR_R2017b_glnxa64_installer.zip - -# Install OpenSMILE -echo "Installing OpenSMILE" - su ${user} -c "mkdir -p /home/${user}/repos/" -cd /home/${user}/repos/ -wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz -tar zxvf OpenSMILE-2.1.tar.gz -# install SMILExtract system-wide -cp openSMILE-2.1.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin -chmod +x /usr/local/bin/SMILExtract -rm OpenSMILE-2.1.tar.gz - -# Install openSMILE2.3.0 -su ${user} -c "mkdir -p /home/${user}/repos/" -cd /home/${user}/repos/ -wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz -tar zxvf OpenSMILE-2.3.tar.gz -chmod +x openSMILE-2.3.0/bin/linux_x64_standalone_static/SMILExtract -rm OpenSMILE-2.3.tar.gz - -# optionally Install HTK (without it, some other tools will not work) -# the idea is to make users independently download HTK installer since -# we cannot redistribute -cd /home/${user} -if [ -f /vagrant/HTK.tar.gz ]; then - if [[ ! -d htk ]]; then - cd /home/${user}/repos/ - su ${user} -c "tar zxf /vagrant/HTK.tar.gz" - cd htk - ./configure --without-x --disable-hslab - sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile - make all - make install - fi -fi - - - -# POPOULATE THE REPOSITORY SECTION -cd /home/${user}/repos/ - - # Get OpenSAT=noisemes and dependencies - -# git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev -su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" - -cp /vagrant/conf/.theanorc /home/${user}/ -export PATH=/home/${user}/anaconda/bin:$PATH -su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" - - -# Install ldc-sad -# run this version 'by hand' in the VM in repos/ using your github username and password -#git clone http://github.com/aclew/ldc_sad_hmm - - -# Install Yunitator and dependencies -git clone https://github.com/srvk/Yunitator # --branch v1.0 # need Dev - -su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" -su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" - -# Install VCM -git clone https://github.com/MilesICL/vcm - -#Install to-combo sad and dependencies (matlab runtime environnement) -git clone https://github.com/srvk/To-Combo-SAD --branch v1.0 - -# Install DiarTK -git clone http://github.com/srvk/ib_diarization_toolkit --branch v1.0 - - -# Install eval -git clone http://github.com/srvk/dscore #--branch v1.0 - -# Phonemizer installation -git clone https://github.com/bootphon/phonemizer -cd phonemizer -python setup.py build -python setup.py install - -#install launcher and utils -# cd /home/${user}/ -# git clone https://github.com/aclew/launcher.git -# chmod +x launcher/* -# git clone https://github.com/aclew/utils.git -# chmod +x utils/* - - -# install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) -# and intervaltree (needed for rttm2scp.py) -# and recommonmark (needed to make html in docs/) -su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" - -# Link /vagrant/launcher and /vagrant/utils to home folder where scripts expect them -ln -s /vagrant/launcher /home/${user}/ -ln -s /vagrant/utils /home/${user}/ - -# Some cleanup -apt-get autoremove -y - -# Silence error message from missing file -touch /home/${user}/.Xauthority - -# Provisioning runs as root; we want files to belong to '${user}' -chown -R ${user}:${user} /home/${user} From 3b6d8427e827916c28ded36f75a29225e64dc5db Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 14 Dec 2018 11:32:49 -0500 Subject: [PATCH 191/299] Update test.sh Remove erroneous instruction to rename to HTK.tar.gz --- launcher/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index a763f1c..8aabcc2 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -75,8 +75,8 @@ echo "Checking for HTK..." if [ -s /usr/local/bin/HCopy ]; then echo "HTK is installed." else - echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml" - echo " and rename it to HTK.tar.gz? If so, then you may need to re-install it. Run: vagrant ssh -c \"utils/install_htk.sh\" " + echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml ?" + echo " If so, then you may need to re-install it. Run: vagrant ssh -c \"utils/install_htk.sh\" " fi TESTDIR=$WORKDIR/test From 95ffb507085bb0b515da46d3ae2ccd188a8a0096 Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 14 Dec 2018 13:50:19 -0500 Subject: [PATCH 192/299] fix for release --- launcher/noisemesSad.sh | 4 ++-- launcher/vcm.sh | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 607650f..6f1f2e1 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -74,9 +74,9 @@ for sad in `ls ${audio_dir}/hyp_sum/*.lab`; do base=$(basename $sad .lab) if $FULLCLASSES; then - rttm_out=noisemes_full_${base}.rttm + rttm_out=noisemesFull_${base}.rttm else - rttm_out=noisemes_sad_${base}.rttm + rttm_out=noisemesSad_${base}.rttm fi if [ -s $sad ]; then diff --git a/launcher/vcm.sh b/launcher/vcm.sh index 4394bf1..18c22db 100755 --- a/launcher/vcm.sh +++ b/launcher/vcm.sh @@ -9,6 +9,7 @@ SCRIPT=$(readlink -f $0) BASEDIR=`dirname $SCRIPT` #| Path to VCM (go one folder up and to VCM) VCMDIR=/home/vagrant/repos/vcm +UTIL=/home/vagrant/utils if [ $# -ne 1 ]; then echo "Usage: $0 " @@ -23,7 +24,7 @@ dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" # Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh ${audio_dir} +bash $UTIL/check_folder.sh ${audio_dir} KEEPTEMP=false if [ $BASH_ARGV == "--keep-temp" ]; then From c402827dc8bf4e9dbd6a6354b5b6b43064679caa Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 14 Dec 2018 13:50:41 -0500 Subject: [PATCH 193/299] fix for release also --- launcher/test.sh | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index ebfee38..2f4fa49 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -7,7 +7,7 @@ KEEPTEMP="" if [ $# -eq 1 ]; then if [ $BASH_ARGV == "--keep-temp" ]; then - KEEPTEMP="--keep-temp" + KEEPTEMP="--keep-temp" fi fi @@ -21,7 +21,7 @@ REPOS=/home/vagrant/repos UTILS=/home/vagrant/utils # Paths to Tools -OPENSATDIR=$REPOS/OpenSAT # noisemes +OPENSATDIR=$REPOS/Yunitator # same code for noisemes and Yunitator OPENSMILEDIR=$REPOS/opensmile-2.3.0/ TOCOMBOSAD=$REPOS/To-Combo-SAD DIARTKDIR=$REPOS/ib_diarization_toolkit @@ -88,7 +88,6 @@ cp $WORKDIR/$BASETEST.rttm $TESTDIR # now test Noisemes echo "Testing noisemes..." -cd $OPENSATDIR $LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} @@ -102,7 +101,6 @@ fi # now test OPENSMILEDIR echo "Testing OpenSmile SAD..." -cd $OPENSMILEDIR $LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} @@ -115,7 +113,6 @@ fi # now test TOCOMBOSAD echo "Testing ToCombo SAD..." -cd $TOCOMBOSAD $LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} @@ -129,7 +126,6 @@ fi # test DIARTK echo "Testing DIARTK..." -cd $DIARTKDIR cp $TEST_RTTM $TESTDIR # run like the wind @@ -139,17 +135,16 @@ if grep -q "command not found" $TESTDIR/diartk-test.log; then FAILURES=true else if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then - echo "DiarTK passed the test." + echo "DiarTK passed the test." else - FAILURES=true - echo " Diartk failed - no output RTTM" + FAILURES=true + echo " Diartk failed - no output RTTM" fi fi #rm $TESTDIR/$BASETEST.rttm # test Yunitator echo "Testing Yunitator..." -cd $YUNITATORDIR # let 'er rip $LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} @@ -179,7 +174,6 @@ fi # Testing VCM echo "Testing VCM..." -cd $VCMDIR $LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then @@ -205,18 +199,18 @@ echo "If you see bigger changes, then please paste this output onto an issue on echo "RESULTS:" for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done echo "****** REFERENCE RESULTS BEGINS ******." -echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm" -echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" -echo "LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm" -echo "LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm" -echo "LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm" -echo "LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm" -echo "LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" +echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm" +echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" +echo "LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm" +echo "LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm" +echo "LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm" +echo "LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm" +echo "LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" echo "****** REFERENCE RESULTS ENDS ******." echo "DSCORE:" cat /vagrant/data/VanDam-Daylong/BN32/test/test.df echo "****** REFERENCE DSCORE BEGINS ******." -echo "DER B3Precision B3Recall B3F1 TauRefSys TauSysRef CE MI NMI" -echo "Phil_Crane 43.38 0.975590490013 0.672338020576 0.796061934402 0.599223772838 0.963770340456 0.103871357212 1.67823036445 0.793181875273" -echo "****** REFERENCE DSCORE ENDS ******." \ No newline at end of file +echo "DER B3Precision B3Recall B3F1 TauRefSys TauSysRef CE MI NMI" +echo "Phil_Crane 43.38 0.975590490013 0.672338020576 0.796061934402 0.599223772838 0.963770340456 0.103871357212 1.67823036445 0.793181875273" +echo "****** REFERENCE DSCORE ENDS ******." From 51158405890c1e53b6e67a4d6a313274f2957a5c Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Fri, 14 Dec 2018 14:17:48 -0500 Subject: [PATCH 194/299] Release v1.1 --- conf/bootstrap.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 6fc9721..eecc2fb 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -141,25 +141,35 @@ cp /vagrant/conf/.theanorc /home/${user}/ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install Yunitator and dependencies -git clone https://github.com/srvk/Yunitator +git clone https://github.com/srvk/Yunitator +(cd Yunitator && git checkout develop/yunified) + + su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" # Install VCM -git clone https://github.com/MilesICL/vcm +git clone https://github.com/MilesICL/vcm +(cd vcm && git checkout 93991b0) #Install to-combo sad and dependencies (matlab runtime environnement) git clone https://github.com/srvk/To-Combo-SAD +(cd To-Combo-SAD && git checkout 2ce2998) # Install DiarTK git clone http://github.com/srvk/ib_diarization_toolkit +(cd ib_diarization_toolkit && git checkout b3e4deb) # Install eval git clone http://github.com/srvk/dscore +# zip to revision for release 1.1 14 Dec 2018 +(cd dscore && git checkout 31d7eca) # Phonemizer installation git clone https://github.com/bootphon/phonemizer cd phonemizer +git checkout 332b8dd + python setup.py build python setup.py install From d905df215df9ad30ea948b9b6dd327c72b3818c1 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Fri, 14 Dec 2018 21:00:33 +0100 Subject: [PATCH 195/299] Update few scripts for data analysis --- launcher/evalDiar.sh | 4 +-- scripts/segments.pl | 58 ++++++++++++++++++++++++++++++++++++++ utils/extract_stats_chi.py | 9 ++++-- utils/txt2rttm.py | 56 ++++++++++++++++++++---------------- 4 files changed, 97 insertions(+), 30 deletions(-) create mode 100755 scripts/segments.pl diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 97ebf52..bbda44b 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -32,7 +32,7 @@ display_usage() { audio_dir=/vagrant/$1 model=$2 -if ! [[ $model =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lenaSad)$ ]] ]; then +if ! [[ $model =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lenaSad)$ ]]; then display_usage fi @@ -87,7 +87,7 @@ if [[ $model =~ ^(diartk|yuniseg) ]]; then elif [ "$2" == "yunitate" ]; then sys_name="yunitator" elif [ "$2" == "lenaSad" ]; then - sys_name="lena_sad" + sys_name="lena" fi echo $UTILS/create_ref_sys.sh $1 $sys_name diff --git a/scripts/segments.pl b/scripts/segments.pl new file mode 100755 index 0000000..04ac994 --- /dev/null +++ b/scripts/segments.pl @@ -0,0 +1,58 @@ +#!/usr/local/bin/perl +# +# Anne S. Warlaumont +# +# This tool allows you to find the start time, end time, and type of vocalization for each vocalization in a LENA recording, using the corresponding .its file. +# The output information is written into .csv file, which is useful for sequence analyses. +# More detailed instructions are available at: https://github.com/HomeBankCode/lena-its-tools/blob/master/Documentation/Using_segments.md +# +# Takes the following command line arguments: +# The path and file name of the input its file (e.g. "~/lena-its-tools/segments.pl) +# The path and csv file name where you want the segment data to be written (e.g. "~/lena-its-results/e20131126_155022_009145_segments.csv" +# +# Instructions: +# 1. Open up a unix shell (e.g. the Terminal application under Utilities on Mac or Cygwin on Windows) +# 2. Navigate to the directory where this file is located (e.g. "~/CodeDirectory/") +# 3. Run segments.pl with the path and file name of the its file as the first argument and the path and name of the desired segments csv output file as the 2nd argument +# (e.g. "perl segments.pl ~/DataDirectory/e20120417_130404_007941.its ~/DataDirectory/e20120417_130404_007941_segments.csv") + +use strict; use warnings; + +open INPUTFILE, $ARGV[0] or die "Could not open input file " . $ARGV[0] . "\n"; +open OUTPUTFILE, ">", $ARGV[1] or die "Could not open output file " . $ARGV[1] . "\n"; + +print OUTPUTFILE "segtype,startsec,endsec\n"; + +while (my $line = ){ + + chomp($line); + + if ($line=~ m/Segment spkr=/){ + + my $segtype = $line; + $segtype =~ s/.*Segment spkr="//g; + $segtype =~ s/".*//g; + if ($segtype =~ m/CHN/){ + if ($line =~ m/startUtt1/){ + $segtype = $segtype . "SP"; + } + else{ + $segtype = $segtype . "NSP"; + } + } + + my $startTime = $line; + $startTime =~ s/.*startTime="PT//g; + $startTime =~ s/S" endTime=.*//g; + + my $endTime = $line; + $endTime =~ s/.*endTime="PT//g; + $endTime =~ s/S".*//g; + + print OUTPUTFILE "$segtype,$startTime,$endTime\n"; + } + +} + +close(INPUTFILE); +close(OUTPUTFILE); \ No newline at end of file diff --git a/utils/extract_stats_chi.py b/utils/extract_stats_chi.py index 6ab3bb3..44bfdd7 100755 --- a/utils/extract_stats_chi.py +++ b/utils/extract_stats_chi.py @@ -16,7 +16,7 @@ def detect_ad_chi_tt(previous_activity, curr_activity, last_silence_dur, chi, ma return 0 -def compute_statistics(rttm_path, chi, mal, fem): +def compute_statistics(rttm_path, chi, mal, fem, trash): chi_dur=0.0 chi_utt=0 ad_dur=0.0 @@ -44,8 +44,9 @@ def compute_statistics(rttm_path, chi, mal, fem): elif curr_activity in mal or curr_activity in fem: ad_dur += dur ad_utt +=1 - else: + elif curr_activity not in trash: print("Activity %s not recognized" % (curr_activity)) + print("In file %s" % (os.path.basename(rttm_path))) sys.exit(1) if onset_prev + dur_prev == onset: @@ -84,6 +85,8 @@ def main(): help="labels that need to be considered as being male adult speech.") parser.add_argument('--fem', nargs='+', type=str, required=True, help="labels that need to be considered as being female adult speech.") + parser.add_argument('--trash', nargs='+', type=str, required=False, default=None, + help="labels that need to not be considered.") args = parser.parse_args() # Below the values that need to be consider when evaluating tsi/lena folder @@ -117,7 +120,7 @@ def main(): if 'cutted' not in fn] list_stats=[] for rttm_path in rttm_files: - list_stats.append(compute_statistics(rttm_path, args.chi, args.mal, args.fem)) + list_stats.append(compute_statistics(rttm_path, args.chi, args.mal, args.fem, args.trash)) write_stats(list_stats, args.folder) if __name__ == '__main__': diff --git a/utils/txt2rttm.py b/utils/txt2rttm.py index cba1ae4..5ecce0c 100755 --- a/utils/txt2rttm.py +++ b/utils/txt2rttm.py @@ -35,30 +35,35 @@ def lena_to_aclew_name(tsi_key_info, basename): ------- The name respecting the ACLEW naming convention """ - onset = basename.split('_')[3] - basename_beg = '_'.join(basename.split('_')[0:3]) # Get the first 3 elements - wb = load_workbook(tsi_key_info,data_only=True) - wb = wb.worksheets[0] - first_row = wb.rows[0] - file_lena_num_col = None - key_num_col = None - - # Get num of the column - for idx in range(0, len(first_row)): - cell = first_row[idx] - if cell.value == "file_lena": - file_lena_num_col = idx - if cell.value == "key": - key_num_col = idx - - # Loop through the cells to look for the basename - if file_lena_num_col is not None and key_num_col is not None: - for row in wb.rows[1:]: - file_lena = row[file_lena_num_col].value - key_num = row[key_num_col].value - if file_lena == basename_beg: - child, good_date = key_num.split('_') - return '_'.join(['lena',child,good_date,onset]) + is_BER_ROW_SOD_WAR = any(substring in basename for substring in ['BER','ROW','SOD','WAR']) + if not is_BER_ROW_SOD_WAR: + # Should come from TSI recordings + onset = basename.split('_')[3] + basename_beg = '_'.join(basename.split('_')[0:3]) # Get the first 3 elements + wb = load_workbook(tsi_key_info,data_only=True) + wb = wb.worksheets[0] + first_row = wb.rows[0] + file_lena_num_col = None + key_num_col = None + + # Get num of the column + for idx in range(0, len(first_row)): + cell = first_row[idx] + if cell.value == "file_lena": + file_lena_num_col = idx + if cell.value == "key": + key_num_col = idx + + # Loop through the cells to look for the basename + if file_lena_num_col is not None and key_num_col is not None: + for row in wb.rows[1:]: + file_lena = row[file_lena_num_col].value + key_num = row[key_num_col].value + if file_lena == basename_beg: + child, good_date = key_num.split('_') + return '_'.join(['lena',child,good_date,onset]) + else: + return '_'.join(['lena',basename.replace('_lena','')]) def txt2rttm(path_to_txt, output_folder, labels_to_keep, lena_mode=False, only_first_letter=False): @@ -105,8 +110,9 @@ def main(): help="indicates whether to use this script in the lena mode or not. If the lena mode" "is activated, it will read the table tsi_key_info.xlsx in the input folder and" "will change the naming convention of the output in consequences") + parser.add_argument('-t', '--to_keep', nargs='+', type=str, required=True, - help='List of labels that needs to be kept.') + help='List of labels that needs to be kept (Only use when --lena_mode is activated).') parser.add_argument('-fl', '--only_first_letter', type=bool, default=False, help='Indicates if the output labels will be produced by keeping only the first letter' 'of the original labels.') From 42a47efa2614202e795ad38ba0993a0e95d83335 Mon Sep 17 00:00:00 2001 From: alecristia Date: Sat, 15 Dec 2018 10:24:23 +0100 Subject: [PATCH 196/299] corrected requirements install --- docs/source/install.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 86060eb..50ed349 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -4,8 +4,9 @@ DiViMe can be installed in any operating system and computer with at least 1 CPU (and occupying 2GB when active). You may need to make some adaptations for known issues. Specifically, *before following the instructions under "First Installation"*, you must follow the instructions in the relevant subsection of the Troubleshooting section, at the end of this page, in the following cases: -- your computer only has one core -- your computer has 15 GB or less of space +- your computer has only one core +- your computer has 20 GB or less of storage space +- your computer has 6 GB or less of RAM - your computer is running ubuntu (e.g., 16.04) @@ -75,11 +76,9 @@ Congratulations, everything is OK! ``` - - ## Updating DiViMe -If there is a new version of DiViMe, you will need to perform the following 3 steps from within the DiViME folder on your terminal: +If you want to install a new release of DiViMe, you will need to perform the following 3 steps from within the DiViME folder on your terminal: ``` @@ -96,6 +95,7 @@ If you want to get rid of the files completely, you should perform the following $ vagrant destroy $ cd .. $ rm -r -f divime +``` ## Troubleshooting @@ -111,11 +111,15 @@ into: Then proceed with the Installation. -### If your computer has 15 GB or less of space +### If your computer has 20 GB or less of storage space + +If your computer has less than 20 GB of storage space, then *you cannot build a fully working DiViMe* (without crippling your computer). In this case, clean up your files to free up space. -If your computer has less than 5 GB of storage space, then *you cannot build a fully working DiViMe* (without crippling your computer). +### If your computer has 6 GB or less of RAM -For computers with 5-15 GB of space, you may need to change the space allocated to the virtual machine. Before doing `vagrant up`, open the file called Vagrantfile in a text editor. Change the following line: +If your computer has less than 4 GB of RAM, then *you cannot build a fully working DiViMe* (without crippling your computer). + +For computers with 4-6 GB of RAM, you need to change the space allocated to the virtual machine. Before doing `vagrant up`, open the file called Vagrantfile in a text editor. Change the following line: > vbox.memory = 3072 @@ -132,7 +136,7 @@ There is a known incompatibility between VirtualBox and the 4.13 Linux kernel on ### If something else fails Please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. -``` + ## References From 3dc0e2b260b1d4d234d99902d895ae7987633a83 Mon Sep 17 00:00:00 2001 From: alecristia Date: Sat, 15 Dec 2018 12:08:16 +0100 Subject: [PATCH 197/299] instructions for format conversion --- docs/source/formats.md | 91 +++++++++++++++++---------- docs/source/usage.md | 63 ++++++------------- utils/chat2rttm_folder.sh | 10 +++ utils/eaf2txt.py | 2 +- utils/eafAAS2rttm_folder.sh | 10 +++ utils/textgrid2rttm.py | 4 +- utils/textgrid2rttm_folder.sh | 1 + utils/yuniSeg.sh | 112 ---------------------------------- 8 files changed, 103 insertions(+), 190 deletions(-) create mode 100755 utils/chat2rttm_folder.sh create mode 100755 utils/eafAAS2rttm_folder.sh create mode 100755 utils/textgrid2rttm_folder.sh delete mode 100755 utils/yuniSeg.sh diff --git a/docs/source/formats.md b/docs/source/formats.md index e1598d6..fb4e456 100644 --- a/docs/source/formats.md +++ b/docs/source/formats.md @@ -4,85 +4,112 @@ This section explains the input and output formats for each type of tool, and ho ## Overview -The basic file format within DiViMe is a modified form of rttm, which is standard in key diarization tasks, and which allows us to evaluate all tools using a standardized evaluation routine. The different ways of using this same general format are explained below. +The basic file format within DiViMe is a modified form of [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf), which is standard in key diarization tasks, and which allows us to evaluate most tools using a standardized evaluation routine. The different ways of using this same general format are explained below. -Many users, however, will be interested in knowing how to convert into and out of this format into something that is more commonly used for annotation of day-long and other developmental recordings. DiViMe includes routines to convert from any .TextGrid file (produced by the program [Praat](praat.org)); from any .cha file (produced by the program [CLAN](MISSING LINK)); and from .eaf files (produced by the program [ELAN](MISSING LINK)) that have been generated using the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Users who rely on a different program (or for .eaf, on a different file structure) are advised to use the tools in their program or similar others to convert into one of these, or directly into the rttm format explained below. +Many users, however, will be interested in knowing how to convert into and out of this format into something that is more commonly used for annotation. DiViMe includes routines to convert from any .TextGrid file (produced by the program [Praat](praat.org)); from any .cha file (produced by the program [CLAN](http://dali.talkbank.org/clan/)); and from .eaf files (produced by the program [ELAN](https://tla.mpi.nl/tools/tla-tools/elan/)) that have been generated using the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/) template. Users who rely on a different program (or for .eaf, on a different template) are advised to use the tools in their program or similar others to convert into one of these, or directly into the [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) format explained further below. We also provide code to convert the .its files outputted by the [LENA(R)](www.lena.org) software, so you can evaluate them against your own coding and/or DiViMe's output. -The following subsections explain how to convert from each of these input formats into a basic reference rttm. +The following subsections explain how to convert from each of these input formats into a basic reference [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf). ### Input: TextGrid -TextGrid is a standard format for speech annotation, used by the Praat software. Our process assumes that you will have the speech of each talker diarized in a different tier, using filled intervals when the person is talking, and empty intervals when they are not talking. +Our process assumes that you will have the speech of each talker diarized in a different tier, using filled intervals when the person is talking, and empty intervals when they are not talking. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. For example, if you have three tiers associated with a talker, coding e.g., what they say, how they say it, and to whom, you should remove 2 of these three tiers, because otherwise each of these tiers will be treated as a different talker. -Furthermore, any interval that is empty will be seen as *not* containing vocalizations from that speaker. Thus, if your coding is sparse (i.e., if you have a day-long recording, but have only coded some clips here and there), then you should extract the audio clips and annotations for the sections that have been coded, and not process the whole day long recording. (If you do, then your evaluation will be off, because all the speech systems found in sections you have not coded count towards false positives, as if the system had found speech when none was there.) +Furthermore, any interval that is empty will be seen as *not* containing vocalizations from that speaker. Thus, if your coding is sparse (i.e., if you have a day-long recording, but have only coded some clips here and there), then you should extract the audio clips and annotations for the sections that have been coded, and not process the whole day-long recording. (If you do, then your evaluation will be off, because all the speech found in sections you have not coded count towards false positives, as if the system had found speech when none was there.) -Additionally, the name of the tier is what will be taken to be the speaker's name. Therefore, if you have tiers that code speech of some speaker but are named differently, change the tier's name before starting. In fact, some of the tools assume a specific set of names, and thus the tool's output can only be properly evaluated if you use those names. In particular, the child wearing the recording device should be called "CHI". Other children should be called "XC0", where the X is the child's sex (F for Female, M for Male, U for uncertain/undecided/unknown) and 0 is a number 0-9 to identify a unique child. Similarly, adults should be called "XA0" where the X is the child's sex (F for Female, M for Male, U for uncertain/undecided/unknown) and 0 is a number 0-9 to identify a unique adult. Further, you can also define "XU0", a person of unknown age; and "EE0," a voice from a non-human source, such as a toy, radio, or TV. +Additionally, the name of the tier is what will be taken to be the speaker's name. Therefore, if you have tiers that code speech by a speaker but are named differently, change the tier's name before starting. In fact, some of the tools assume a specific set of names, and thus the tool's output can only be properly evaluated if you use those names. In particular, the child wearing the recording device should be called "CHI". Other children should be called "XC0", where the X is the child's sex (F for Female, M for Male, U for uncertain/undecided/unknown) and 0 is a number 0-9 to identify a unique child. Similarly, adults should be called "XA0" where the X is the child's sex (F for Female, M for Male, U for uncertain/undecided/unknown) and 0 is a number 0-9 to identify a unique adult. Further, you can also define "XU0", a person of unknown age; and "EE0," a voice from a non-human source, such as a toy, radio, or TV. -Once you have removed all tiers that do not pertain to speakers, made sure that all the empty intervals really are non-vocalizations, renamed the tiers with the speaker's name, and ideally used this set of names, you are ready to convert your .TextGrid files into rttm. Assuming you have put all the textgrids you want to convert inside the folder data/mydata/, you would next run: +Once you have removed all tiers that do not pertain to speakers, made sure that all the empty intervals really are non-vocalizations, renamed the tiers with the speaker's name, and ideally used this set of names, you are ready to convert your .TextGrid files into [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf). After you have put all the files you want to convert inside the folder data/mydata/, you would next run: ``` -vagrant ssh -c "textgrid2rttm.py data/mydata/" +vagrant ssh -c "textgrid2rttm_folder.sh $j" ``` ### Input: cha +Our process extracts time stamps from bullet points, assuming that all vocalizations are coded. Therefore, if some of your entries do not have bullet points (e.g., "*CHI: 0 [=! crying]."), they will be treated as if there was no speech/vocalizations at that point. Furthermore, additional pre-processing steps are necessary if your coding is sparse (i.e., if you have a day-long recording, but have only coded some clips here and there) since our automatic extraction method has no way of knowing that you have skipped sections. If this is the case, then you should extract the audio clips and annotations for the sections that have been coded, and not process the whole day-long recording. (If you do, then your evaluation will be off, because all the speech found in sections you have not coded count towards false positives, as if the system had found speech when none was there.) +Additionally, some of the tools assume a specific set of names, and thus the tool's output can only be properly evaluated if you use those names. In particular, the child wearing the recording device should be called "CHI". Other children should be called "XC0", where the X is the child's sex (F for Female, M for Male, U for uncertain/undecided/unknown) and 0 is a number 0-9 to identify a unique child. Similarly, adults should be called "XA0" where the X is the child's sex (F for Female, M for Male, U for uncertain/undecided/unknown) and 0 is a number 0-9 to identify a unique adult. Further, you can also define "XU0", a person of unknown age; and "EE0," a voice from a non-human source, such as a toy, radio, or TV. + +Once you have made sure that all lines of interest has bullet points, that there are no regions of the recording that have been skipped, and (if you want to use all tools) that your speakers follow this naming convention, you are ready to convert your .cha files into [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf). After you have put all the files you want to convert inside the folder data/mydata/, you would next run: + +``` +vagrant ssh -c "chat2rttm_folder.sh data/mydata/" +``` ### Input: Eaf -Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. Since .eaf's can vary a lot in structure, we only provide tools to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Assuming you have put all the textgrids you want to convert inside the folder data/mydata/, you would next run: +Since .eaf files can vary a lot in structure, we only provide tools to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/) template. One of the perks of using this format is that you can make full use of all tools in DiViMe, including a phonologization of your orthographic transcriptions into phonemic transcriptions, which will allow you to evaluate WCE in your data. For the phonologization stage, you need to provide the language, which can be: spanish, english, tzeltal. + +After you have put all the files you want to convert inside the folder data/mydata/, you would next run (the last parameter is the language): ``` -vagrant ssh -c "eaf2txt.py data/mydata/" -vagrant ssh -c "eaf2enriched_txt.sh data/mydata/" +vagrant ssh -c "eafAAS2rttm_folder.sh data/mydata/ english" ``` -The first line serves to create the rttm that will be used by most tools. The second creates an annotation that will be needed for the WCE. +If your annotations do not follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/), please look into converting them into something else (.TextGrid or .cha) using ELAN's conversion tools; or potentially try to modify your annotations to fit the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). -If your annotations do not follow the ACLEW Annotation Scheme, please look into converting them into something else (.TextGrid or .cha) using ELAN's conversion tools; or potentially try to modify your annotations to fit the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). ### Input: its +After you have put all the files you want to convert inside the folder data/mydata/, you would next run: +``` +vagrant ssh -c "its2rttm.sh data/mydata/" +``` +Please note that this will convert the whole day-long .its file into [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf). If you only have annotations for part of the day, then you need to select only the sections of the .rttm for which you have annotations. We do not at present provide an automatized solution for doing this. -## Speech or Voice activity detection output - -RTTM is an annotation format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) -This format is used by the [DiViMe](https://github.com/srvk/DiViMe). +## Output: rttm's from speech/voice activity detection tools -Tools that are of the SAD type (SAD or VAD) return one rttm per audio file, named toolnameSad_filename.rttm, which looks like this: +Tools that are of the speech/voice activity detection type return one [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) per audio file, named toolnameSad_filename.rttm, which looks like this: ``` -SPEAKER file17 1 0.00 0.77 speech -SPEAKER file17 1 1.38 2.14 speech +SPEAKER file17 1 0.00 0.77 speech +SPEAKER file17 1 1.38 2.14 speech ``` -The fourth column indicates the onset of a speech region; the forth column the duration of that speech region. All other columns may be ignored. Regions of non-speech are all the others (e.g., in this example, between .77 and 1.38). +The third column indicates the onset of a region; the forth column the duration of that region. All other columns may be ignored. Regions of non-speech are all the others (e.g., in this example, between .77 and 1.38). -## Diarization style (diarization or role assignment) output +## Output: rttm's from diarization tools -RTTM is an annotation format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) -This format is used by the [DiViMe](https://github.com/srvk/DiViMe). +Diarization-type tools return one [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) per audio file, named toolnameDiar_filename.rttm, which looks like this: + +``` +SPEAKER file17 1 4.2 0.4 talker0 +SPEAKER file17 1 5.8 1.1 talker1 +SPEAKER file17 1 6.9 1.2 talker2 +SPEAKER file17 1 8.1 0.7 talker1 +``` + +The third column indicates the onset of a region, the forth column the duration of that region; and the identity of the speaker being indicated in the eighth column. All other columns may be ignored. Regions of non-speech are all the others (e.g., in this example, between 4.6 and 5.8). -Diarization-type tools return one rttm per audio file, named toolnameDiar_filename.rttm, which looks like this: +## Output: rttm's from talker type tools + +Talker type tools return one [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) per audio file, named toolname_filename.rttm, which looks like this: ``` -SPEAKER file17 1 4.2 0.4 talker0 -SPEAKER file17 1 4.6 1.2 talker0 -SPEAKER file17 1 5.8 1.1 talker1 -SPEAKER file17 1 6.9 1.2 talker0 -SPEAKER file17 1 8.1 0.7 talker1 +SPEAKER file17 1 4.2 0.4 CHI +SPEAKER file17 1 5.8 1.1 FA +SPEAKER file17 1 6.9 1.2 MA +SPEAKER file17 1 8.1 0.7 FA ``` +The third column indicates the onset of a region, the forth column the duration of that region; and the speaker type being indicated in the eighth column: CHI is the key child, C is a child (target or other), FA is female adult, MA is male adult. All other columns may be ignored. Regions of non-speech are all the others (e.g., in this example, between 4.6 and 5.8). -The fourth column indicates the onset of a region, the identity being indicated in ; the forth column the duration of that speech region. All other columns may be ignored. Regions of non-speech are all the others (e.g., in this example, between .77 and 1.38). - +## Output: rttm's from vocal maturity tools +Vocal maturity tools return one [rttm](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) per audio file, named toolname_filename.rttm, which looks like this: +``` +SPEAKER FILENAME 1 31.4 1.6 CNS 0.71 +SPEAKER FILENAME 1 34.6 1.1 NCS 0.81 +SPEAKER FILENAME 1 39.0 0.8 CRY 0.80 +SPEAKER FILENAME 1 47.9 0.5 NCS 0.62 +``` +The third column indicates the onset of a region, the forth column the duration of that region; and the vocalization type being indicated in the eighth column: canonical syllable (CNS), non-cannoical syllable (NCS), crying (CRY), and others (OTH, normally refer to laughing); followed by the likelihood of that class (higher means the system was more "certain"). All other columns may be ignored. Regions of non-vocalization as well as regions where people other than the child vocalize are not marked (e.g., in this example, between 33 and 34.6). diff --git a/docs/source/usage.md b/docs/source/usage.md index 4022673..35b80da 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -27,7 +27,7 @@ You can drop a whole folder into ```data```. You will provide the path to the sp If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. -If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. For more information on these formats, see the Format section. +If you have any annotations, put them also in the same "data" folder. Annotations must be in .rttm format, and *they should be named exactly as your wav files*. If you have annotations in .cha, .eaf, .textgrid, or .its, see the Format section for instructions on converting them into .rttm. IMPORTANT: If you already analyzed a file with a given tool, re-running the tool will result in the previous analysis being overwritten. @@ -133,29 +133,25 @@ You can read that command as follows: *noisemesSad*: Remember that this tool does "talker diarization": Given some speech, attribute it to a speaker. Therefore, this type of tool necessitates speech/voice activity detection. This third argument tells DiViMe what file contains information about which sections of the sound file contain speech. -You can only use one of the following options: textgrid, eaf, rttm, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. +You can only use one of the following options: rttm, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. -You can provide annotations done by a human or in some other way, and encoded as one of the following three file types: +You can provide annotations done by a human or in some other way, and encoded as rttms. If you have a different format, see the Format section. *What is crucial for this procedure to work is that your rttm's reflection your human-annotation are called exactly like your sound files.* Notice that all annotations that say "speech" in the eighth column count as such. -- textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. -- eaf: this means you want the system to use your eaf annotations. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. -- rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eight column count as such. +Alternatively, you can use automatic annotations generated by DiViMe's speech/voice activity detection systems, encoded in rttm files. In this case, you would pass one of the following options: -Alternatively, you can provide use automatic annotations generated by DiViMe's speech/voice activity detection systems, encoded in rttm files. In this case, you would pass one of the following options: - -- this system before: this means you want the system to use the output of the noisemesSad system. If you have not run noisemesSad, the system will fail. +- noisemesSad: this means you want the system to use the output of the noisemesSad system. If you have not run noisemesSad, the system will fail. - opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run this system before, the system will fail. - tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran this system before, the system will fail. If the third parameter is not provided, the system will give an error. -If all three parameters are provided, then the system will first find all the annotation files matching the third parameter (e.g., all the files *.TextGrid; or all the tocomboSad_*.rttm files), and then find the corresponding sound files. For example, imagine you have put into your ```data/mydata/``` folder the following files: +If all three parameters are provided, then the system will first find all the annotation files matching the third parameter (e.g., all the human-annotated files *.rttm; or all the tocomboSad_*.rttm files), and then find the corresponding sound files. For example, imagine you have put into your ```data/mydata/``` folder the following files: - participant23.wav - opensmileSad_participant23.rttm - participant24.wav -- participant24.TextGrid +- participant24.rttm If you run: @@ -167,7 +163,7 @@ then only participant23.wav will be analyzed. If you run: -`$ vagrant ssh -c "diartk.sh data/mydata/ textgrid"` +`$ vagrant ssh -c "diartk.sh data/mydata/ rttm"` then only participant24.wav will be analyzed. @@ -177,19 +173,9 @@ At the end of the process, there will be an added rttm file for each analyzed fi - opensmileSad_participant23.rttm: the output of opensmileSad, which states where there is speech - diartk_opensmileSad_participant23.rttm: the output of opensmileSad followed by diartk, which states which speech sections belong to which speakers. -If you look inside a diartk_*.rttm file, it will look as follows: - -``` -SPEAKER file17 1 4.2 0.4 talker0 -SPEAKER file17 1 4.6 1.2 talker0 -SPEAKER file17 1 5.8 1.1 talker1 -SPEAKER file17 1 6.9 1.2 talker0 -SPEAKER file17 1 8.1 0.7 talker1 -``` - -This means that diartk considered that one talker spoke starting at 4.2 seconds for .4 seconds; starting at 4.6 for 1.2 seconds; then someone else spoke starting at 5.8 seconds and for 1.1 seconds; etc. +See Format section for explanation on how to read the resulting rttm. -### How to run a Role assignment tool +### How to run a talker type tool For these tools, type a command like this one: @@ -203,7 +189,8 @@ You can read that command as follows: *data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. -It returns one rttm per sound file, with an estimation of where there are vocalizations by children, female adults, and male adults. +It returns one rttm per sound file, with an estimation of where there are vocalizations by children, female adults, and male adults. See Format section for explanation on how to read the resulting rttm. + ### How to run a Vocalization classification tool @@ -219,16 +206,12 @@ You can read that command as follows: *data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. -It returns one rttm per sound file, with an estimation for the infant vocalisation to be cannonical syllable (CNS), non-cannoical syllable (NCS), crying (CRY), and others (OTH, normally refer to laughing). +**The vocalization classification tool depends on the output of the talker type tool yunitator. Therefore, the directory where you put your clips to analyze must contain files called yunitator_*.rttm (e.g., yunitator_participant23.wav).** -NOTE: it dependes on the outputs (rttm file) of yunicator. The default path storing rttm file of yunitator is under `data/mydata/` +The vocalization classification tool returns one rttm per sound file, with an estimation for each CHI vocalzsation to be a canonical syllable (CNS), non-canonical syllable (NCS), crying (CRY), and others (OTH, normally refer to laughing). + +See Format section for explanation on how to read the resulting rttm. -``` -SPEAKER FILENAME 1 31.4 1.6 CNS 0.71 -SPEAKER FILENAME 1 34.6 1.1 NCS 0.81 -SPEAKER FILENAME 1 39.0 0.8 CRY 0.80 -SPEAKER FILENAME 1 47.9 0.5 NCS 0.62 -``` ### How to run an Evaluation @@ -250,9 +233,9 @@ You can read that command as follows: *noisemesSad*: The third argument indicates which tool's output to evaluate (in this case, noisemesSad). All of our Speech/Voice activity detection tools can be evaluated with this. -For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). +For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. -#### Evaluating Speech/Voice activity detection +#### Evaluating Diarization or Talker type Type a command like the one below: @@ -266,11 +249,9 @@ You can read that command as follows: *data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. -* diartk_noisemesSad*: The third argument indicates which output to evaluate. - -**THIS NEEDS WORK** +*diartk_noisemesSad*: The third argument indicates which output to evaluate. Another example: yunitator. -For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). +For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. ## An alternative for Step 4: using recipes @@ -282,7 +263,3 @@ Last but not least, you should **remember to halt the virtual machine**. If you `$ vagrant halt` - - - - diff --git a/utils/chat2rttm_folder.sh b/utils/chat2rttm_folder.sh new file mode 100755 index 0000000..6f57023 --- /dev/null +++ b/utils/chat2rttm_folder.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# +# Shell script to convert all .CHA files inside a folder to .rttm format +# +for j in ${1}/*.cha + do chat2stm.sh $j + file=`echo $j | sed "s/.cha$//"` + cat ${file}.stm | awk '{print "SPEAKER",${file},"1",$4,($5 - $4),"","","speech","","" }' > ${file}.rttm + rm ${file}.stm +done \ No newline at end of file diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py index 1623b06..e238b81 100755 --- a/utils/eaf2txt.py +++ b/utils/eaf2txt.py @@ -23,7 +23,7 @@ def eaf2txt(path_to_eaf, output_folder, cleanup=False): """ Convert an eaf file to the txt format by extracting the onset, offset, ortho, and the speaker tier. Note that the ortho field has been made by a human and needs - to be clean up. + to be cleaned up. Parameters ---------- diff --git a/utils/eafAAS2rttm_folder.sh b/utils/eafAAS2rttm_folder.sh new file mode 100755 index 0000000..d6e0b94 --- /dev/null +++ b/utils/eafAAS2rttm_folder.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# +# Shell script to convert all .eaf files following the ACLEW Annotation Scheme inside a folder to .rttm format +# +for j in ${1}/*.eaf + do elan2rttm.py $j #generate the basic rttms +done + +#extra processing for WCE +eaf2enriched_txt.sh ${1}/ $2 diff --git a/utils/textgrid2rttm.py b/utils/textgrid2rttm.py index ea7e35f..f9bfec2 100755 --- a/utils/textgrid2rttm.py +++ b/utils/textgrid2rttm.py @@ -6,13 +6,13 @@ # to RTTM format. This is useful for evaluating performances of # Speech detection algorithms with the *dscore* package, # in the DiarizationVM virtual machine. -# The 1 and 0 labels are sent to " speech ", and no label / "x" label +# All non-empty labels are written in the output; empty labels # are not written in output (which means it is described as "non speech") import os import argparse # from praatio import tgio -import tgt # tgt is better thant praatio for our application +import tgt # tgt is better than praatio for our application # because it allows to manipulate the timestamps, # which is something we cannot do with praatio. diff --git a/utils/textgrid2rttm_folder.sh b/utils/textgrid2rttm_folder.sh new file mode 100755 index 0000000..ba13e7f --- /dev/null +++ b/utils/textgrid2rttm_folder.sh @@ -0,0 +1 @@ +for j in ${1}/*.TextGrid; do textgrid2rttm.py $j ; done \ No newline at end of file diff --git a/utils/yuniSeg.sh b/utils/yuniSeg.sh deleted file mode 100755 index 3ba088a..0000000 --- a/utils/yuniSeg.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/bash - -# run YuniSeg with hard coded models & configs found here and in /vagrant -# assumes Python environment in /home/${user}/ - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=`dirname $SCRIPT` -# Path to YuniSeg (go one folder up and to Yunitator) -YUNITATDIR=$(dirname $BASEDIR)/Yunitator -# let's get our bearings: set CWD to the path of Yunitator -cd $YUNITATDIR - -if [ $# -ne 2 ]; then - echo "Usage: $0 " - echo "where dirname is the name of the folder" - echo "containing the wav and rttm files" - echo "and SADtoolname is the SAD to use." - echo "Choices are:" - echo " ldc_sad" - echo " noisemes" - echo " tocombosad" - echo " opensmile" - echo " textgrid" - echo " eaf" - echo " rttm" - exit 1 -fi - -audio_dir=/vagrant/$1 -trs_format=$2 - -# Check audio_dir to see if empty or if contains empty wav -bash $BASEDIR/check_folder.sh ${audio_dir} - -# Iterate over files -echo "Starting" -for f in `ls ${audio_dir}/*.wav`; do - filename=$(basename "$f") - basename="${filename%.*}" - echo "treating $basename" - - # output filename produced by runYuniSegs - outfile=${audio_dir}/$basename.yuniSeg.rttm - - case $trs_format in - "ldc_sad") - sys="ldcSad" - model_prefix="ldc_sad_" - ;; - "") - # add default case - echo "Warning: no SAD source specified, using Noisemes by default, at your own risk." - echo "Next time, please specify SAD." - sys="noisemesSad" - model_prefix="noisemes_sad_" - ;; - "noisemes") - sys="noisemesSad" - model_prefix="noisemes_sad_" - ;; - "tocombosad") - sys="tocomboSad" - model_prefix="tocombo_sad_" - ;; - "opensmile") - sys="opensmileSad" - model_prefix="opensmile_sad_" - ;; - "textgrid") - sys="goldSad" - model_prefix=${trs_format}_ - python /home/vagrant/utils/textgrid2rttm.py ${audio_dir}/${basename}.TextGrid ${trs_format}_${basename}.rttm - ;; - "eaf") - sys="goldSad" - model_prefix=${trs_format}_ - python /home/vagrant/utils/elan2rttm.py ${audio_dir}/${basename}.eaf ${trs_format}_${basename}.rttm - ;; - "rttm") - sys="goldSad" - model_prefix="" - ;; - *) - echo "ERROR: please choose SAD system between:" - echo " ldc_sad" - echo " noisemes" - echo " tocombosad" - echo " opensmile" - echo " textgrid" - echo " eaf" - echo " rttm" - echo "Now exiting..." - exit 1 - ;; - esac - - ./runYuniSegs.sh $f ${audio_dir}/${model_prefix}${basename}.rttm - cp $outfile ${audio_dir}/yuniseg_${sys}_${basename}.rttm - - if [ ! -s ${audio_dir}/yuniseg_${sys}_${basename}.rttm ]; then - # if diarization failed, still write an empty file... - touch ${audio_dir}/yuniseg_${sys}_${basename}.rttm - fi -done - -echo "$0 finished running" - -# simply remove hyp and feature -rm $outfile -rm -rf ${audio_dir}/Yunitemp From 352c935d2ad0706f0ed24727ed2548732fecd941 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Tue, 18 Dec 2018 11:52:19 +0100 Subject: [PATCH 198/299] Adds Okko's scripts for WCE --- launcher/WCE_LOSO_eval.sh | 52 ++++++++++++++++++++++++ launcher/WCE_estimate.sh | 18 +++++++++ launcher/WCE_fulltrain.sh | 30 ++++++++++++++ launcher/WCE_preprocess.sh | 83 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+) create mode 100755 launcher/WCE_LOSO_eval.sh create mode 100755 launcher/WCE_estimate.sh create mode 100755 launcher/WCE_fulltrain.sh create mode 100755 launcher/WCE_preprocess.sh diff --git a/launcher/WCE_LOSO_eval.sh b/launcher/WCE_LOSO_eval.sh new file mode 100755 index 0000000..cfb8274 --- /dev/null +++ b/launcher/WCE_LOSO_eval.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +SCRIPT_DIR=$(dirname "$0") +DIROP_FOLDER="/vagrant/data/WCE_VM_TEMP/" + +MATPATH="/usr/local/MATLAB/MATLAB_Runtime/v93/" +FILES_TRAIN="${DIROP_FOLDER}/WAVFILES_TRAIN.txt" +TRAIN_COUNTS="${DIROP_FOLDER}/WORDCOUNTS_TRAIN.txt" +MODEL="~/repos/WCE_VM/models/default_model.mat" +ALPHA="${DIROP_FOLDER}/ALPHA.txt" +CONFIG="~/repos/WCE_VM/configs/config_default.txt" + +FILES_TEST="${DIROP_FOLDER}/WAVFILES_TEST.txt" +TEST_COUNTS="${DIROP_FOLDER}/WORDCOUNTS_TEST.txt" +OUTPUTS_COUNTS="${DIROP_FOLDER}/OUTPUTS_COUNTS.csv" +OUTPUTS_EVAL="${DIROP_FOLDER}/OUTPUTS_EVAL.txt" + + +[ -e "${DIROP_FOLDER}/all_estimates.csv" ] && rm "${DIROP_FOLDER}/all_estimates.csv" +[ -e "${DIROP_FOLDER}/all_references.csv" ] && rm "${DIROP_FOLDER}/all_references.csv" + +c=0 +for en_path in ${DIROP_FOLDER}*_totWords.txt; do + ((c++)) + ids[c]=${en_path##*/} + ids[c]="${ids[c]%_totWords.txt}" # this neglects corpus name, only 4 digits + + line=$(head -n 1 $en_path) + echo $line >> "${DIROP_FOLDER}/all_references.csv" +done + +c=0 +for en_path in ${DIROP_FOLDER}*_totWords.txt; do + #python $SCRIPT_DIR/get_train_LOO_inputs.py ${c} ${DIROP_FOLDER} ${ids[@]} + python ~/repos/WCE_VM/aux_VM/get_train_LOO_inputs.py ${c} ${DIROP_FOLDER} ${ids[@]} + ~/repos/WCE_VM/run_WCEtrain.sh ${MATPATH} ${FILES_TRAIN} ${TRAIN_COUNTS} ${MODEL} ${CONFIG} ${ALPHA} + ~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL} "${DIROP_FOLDER}/OUTPUTS_COUNTS_${c}_ESTIMATE.csv" + python ~/repos/WCE_VM/evaluate_WCE.py "${DIROP_FOLDER}/OUTPUTS_COUNTS_${c}_ESTIMATE.csv" ${TEST_COUNTS} ${DIROP_FOLDER}"/OUTPUTS_EVAL_"${c}".txt" # code to run eval must bre filled + cp ${TEST_COUNTS} "${DIROP_FOLDER}/OUTPUTS_COUNTS_${c}_REFERENCE.csv" + + ((c++)) +done + +c=0 +for en_path in ${DIROP_FOLDER}*_ESTIMATE.csv; do + awk '{ sum += $1 } END { print sum }' "${DIROP_FOLDER}/OUTPUTS_COUNTS_${c}_ESTIMATE.csv" >> "${DIROP_FOLDER}/all_estimates.csv" + ((c++)) +done + +python ~/repos/WCE_VM/evaluate_WCE.py "${DIROP_FOLDER}/all_estimates.csv" "${DIROP_FOLDER}/all_references.csv" ${DIROP_FOLDER}"/OUTPUTS_LOO.txt" # code to run eval must bre filled + +more ${DIROP_FOLDER}"/OUTPUTS_LOO.txt" \ No newline at end of file diff --git a/launcher/WCE_estimate.sh b/launcher/WCE_estimate.sh new file mode 100755 index 0000000..2b0f5ae --- /dev/null +++ b/launcher/WCE_estimate.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +SCRIPT_DIR=$(dirname "$0") + +FILES_TEST=$1 + + +if [ -n "$2" ]; then +OUTPUTFILE = '/vagrant/repos/WCE_VM/outputs/default_output.csv' +else +OUTPUTFILE=$2 +fi + +MATPATH="/usr/local/MATLAB/MATLAB_Runtime/v93/" +MODEL_FINAL="~/repos/WCE_VM/models/model_final.mat" + +#python ... write python code that averages all the results of the speakers +~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL_FINAL} ${OUTPUTFILE} diff --git a/launcher/WCE_fulltrain.sh b/launcher/WCE_fulltrain.sh new file mode 100755 index 0000000..bec111d --- /dev/null +++ b/launcher/WCE_fulltrain.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Perform full training of WCE module using data prepared by WCE_preprocess.sh + +SCRIPT_DIR=$(dirname "$0") +DIROP_FOLDER="/vagrant/data/WCE_VM_TEMP/" + +MATPATH="/usr/local/MATLAB/MATLAB_Runtime/v93/" +FILES_TRAIN="${DIROP_FOLDER}/WAVFILES_TRAIN.txt" +TRAIN_COUNTS="${DIROP_FOLDER}/WORDCOUNTS_TRAIN.txt" +MODEL_FINAL="~/repos/WCE_VM/models/model_final.mat" +ALPHA="${DIROP_FOLDER}/ALPHA.txt" +CONFIG="~/repos/WCE_VM/configs/config_default.txt" + +FILES_TEST="${DIROP_FOLDER}/WAVFILES_TEST.txt" +TEST_COUNTS="${DIROP_FOLDER}/WORDCOUNTS_TEST.txt" +OUTPUTS_COUNTS="${DIROP_FOLDER}/OUTPUTS_COUNTS.csv" +OUTPUTS_EVAL="${DIROP_FOLDER}/OUTPUTS_EVAL.txt" + +c=0 +for en_path in ${DIROP_FOLDER}*_totWords.txt; do + ((c++)) + ids[c]=${en_path##*/} + ids[c]="${ids[c]%_totWords.txt}" +done + +#python ... write python code that averages all the results of the speakers +c=-1 +python $SCRIPT_DIR/get_train_LOO_inputs.py ${c} ${DIROP_FOLDER} ${ids[@]} +~/repos/WCE_VM/run_WCEtrain.sh ${MATPATH} ${FILES_TRAIN} ${TRAIN_COUNTS} ${MODEL_FINAL} ${CONFIG} ${ALPHA} diff --git a/launcher/WCE_preprocess.sh b/launcher/WCE_preprocess.sh new file mode 100755 index 0000000..6fc7a3e --- /dev/null +++ b/launcher/WCE_preprocess.sh @@ -0,0 +1,83 @@ +# Perform pre-porcessing of speech data for WCE module training and/or cross-validation. Requires +# wav-files following ACLEW file naming convention, and .eafs containing daylong annotations. + +SCRIPT_DIR=$(dirname "$0") + +WAV_FOLDER=$1 +EAF_FOLDER=$2 +LANGUAGE=$3 + +display_usage() { + echo "usage: $0 [wav_folder] [eaf_folder] [language] [SAD]" + echo " wav_folder The folder where to find the wav files (REQUIRED)." + echo " eaf_folder The folder where to find the eaf files (REQUIRED)." + echo " language The language of the transcription : english, spanish or tzeltal (REQUIRED)." + echo " SAD The SAD used to detect speech: opensmileSad (DEFAULT), tocomboSad" + echo "" + echo "Wav files have to follow ACLEW file naming conventions:" + echo "COR_baby_yyyyyy_zzzzzz.wav where COR is the three-character ID of the corpus, baby is four-digit" + echo "identifier of the baby, and yyyyyy and zzzzzz are 2/5min segment onsets and offsets in seconds" + echo "measured from the beginning of the daylong file, e.g., BER_0396_005220_005340.wav" + echo "" + echo "Eaf-files must be of form xxxx.eaf, where xxxx is the babyID corerresponding to the .wav files." + exit 1 + } + +if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || ! [[ $LANGUAGE =~ ^(english|spanish|tzeltal)$ ]]; then + display_usage +fi + +if [ -z "$4" ]; then + SAD="opensmileSad" +else + SAD=$4 +fi; + + + +# Check that WCE_VM temp dir exists and create if needed +if [ ! -d "/vagrant/data/WCE_VM_TEMP/" ]; then + mkdir /vagrant/data/WCE_VM_TEMP/ + mkdir /vagrant/data/WCE_VM_TEMP/RTTM/ + mkdir /vagrant/data/WCE_VM_TEMP/ENRICH/ +fi; + + +# 1) Put .wav files to {wav_folder} under {data} and .eafs to another {eaf_folder}. + +# 2) Run: SAD on the data + +echo "Running SAD on the .wav files" + +~/launcher/${SAD}.sh $WAV_FOLDER + +#for file in "/vagrant/${WAV_FOLDER}/*.rttm"; do cp "$file" /vagrant/data/WCE_VM_TEMP/RTTM/;done +#cp "/vagrant/${WAV_FOLDER}*.rttm" /vagrant/data/WCE_VM_TEMP/RTTM/ + +curdir=$(pwd);cd /vagrant/${WAV_FOLDER};cp *.rttm /vagrant/data/WCE_VM_TEMP/RTTM/;cd $curdir + +# 3) Call eaf2enriched.sh to create .rttm files from .eaf files + +echo "Converting .eafs to .rttms..." + +~/utils/eaf2enriched_txt.sh ${EAF_FOLDER} english + +curdir=$(pwd);cd /vagrant/${EAF_FOLDER};cp *enriched.txt /vagrant/data/WCE_VM_TEMP/ENRICH/;cd $curdir + +# 4) Call SADsplit to create annotation file for each SAD output segment + +echo "Creating .wav files and annotation files for each SAD segment..." + +~/repos/WCE_VM/aux_VM/SADsplit.sh /vagrant/data/WCE_VM_TEMP/ENRICH/ /vagrant/data/WCE_VM_TEMP/RTTM/ $WAV_FOLDER + +echo " " +echo "WCE data preprocessing complete. Use WCE_LOSO_eval.sh to run leave-one-subject-out validation +of the system, or WCE_fulltrain.sh to adapt the WCE for all the data." + +# 5) Do leave-one-subject-out validation of the WCE + +#~/launcher/WCE_LOSO_eval.sh + +# 6) Train with all data + +#~/launcher/WCE_fulltrain.sh From 54aa3a318f24e1f2446d288007f796b2da8b84f6 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Tue, 18 Dec 2018 14:31:59 +0100 Subject: [PATCH 199/299] Update bootstrap.sh update.sh and rename Okko's script --- conf/bootstrap.sh | 7 +- conf/update.sh | 2 + launcher/{WCE_estimate.sh => estimateWCE.sh} | 0 .../{WCE_LOSO_eval.sh => evalWCE_LOSO.sh} | 0 .../{WCE_fulltrain.sh => fulltrainWCE.sh} | 0 launcher/test.sh | 211 ++++++++++-------- {launcher => utils}/WCE_preprocess.sh | 0 7 files changed, 120 insertions(+), 100 deletions(-) rename launcher/{WCE_estimate.sh => estimateWCE.sh} (100%) rename launcher/{WCE_LOSO_eval.sh => evalWCE_LOSO.sh} (100%) rename launcher/{WCE_fulltrain.sh => fulltrainWCE.sh} (100%) rename {launcher => utils}/WCE_preprocess.sh (100%) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 78f8c70..34f344c 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -154,7 +154,12 @@ git clone https://github.com/srvk/To-Combo-SAD git clone http://github.com/srvk/ib_diarization_toolkit # Install eval -git clone http://github.com/srvk/dscore +git clone http://github.com/srvk/dscore + +# Install WCE and dependencies +git clone https://github.com/aclew/WCE_VM +su ${user} -c "/home/${user}/anaconda/bin/pip install keras" +su ${user} -c "/home/${user}/anaconda/bin/pip install -U tensorflow" # Phonemizer installation git clone https://github.com/bootphon/phonemizer diff --git a/conf/update.sh b/conf/update.sh index 949fd22..62fe3b1 100644 --- a/conf/update.sh +++ b/conf/update.sh @@ -22,4 +22,6 @@ cd /home/${user}/repos # (cd "vcm"; git checkout master; git pull; git checkout v2.0) (cd "To-Combo-SAD" ; git checkout master; git pull) # (cd "To-Combo-SAD" ; git checkout master; git pull; git checkout v2.0) +(cd "WCE_VM" ; git checkout master; git pull) +# (cd "WCE_VM" ; git checkout master; git pull; git checkout v2.0) ############################################# diff --git a/launcher/WCE_estimate.sh b/launcher/estimateWCE.sh similarity index 100% rename from launcher/WCE_estimate.sh rename to launcher/estimateWCE.sh diff --git a/launcher/WCE_LOSO_eval.sh b/launcher/evalWCE_LOSO.sh similarity index 100% rename from launcher/WCE_LOSO_eval.sh rename to launcher/evalWCE_LOSO.sh diff --git a/launcher/WCE_fulltrain.sh b/launcher/fulltrainWCE.sh similarity index 100% rename from launcher/WCE_fulltrain.sh rename to launcher/fulltrainWCE.sh diff --git a/launcher/test.sh b/launcher/test.sh index 8aabcc2..a70d6e2 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -86,107 +86,120 @@ cp $WORKDIR/$BASETEST.rttm $TESTDIR -# now test Noisemes -echo "Testing noisemes..." -cd $OPENSATDIR - -$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} - -if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then - echo "Noisemes passed the test." -else - FAILURES=true - echo " Noisemes failed - no RTTM output" -fi - - -# now test OPENSMILEDIR -echo "Testing OpenSmile SAD..." -cd $OPENSMILEDIR - -$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} - -if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then - echo "OpenSmile SAD passed the test." -else - FAILURES=true - echo " OpenSmile SAD failed - no RTTM output" -fi - -# now test TOCOMBOSAD -echo "Testing ToCombo SAD..." -cd $TOCOMBOSAD - -$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} - -if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then - echo "TOCOMBO SAD passed the test." -else - FAILURES=true - echo " TOCOMBO SAD failed - no output RTTM" -fi - - -# test DIARTK -echo "Testing DIARTK..." -cd $DIARTKDIR - -cp $TEST_RTTM $TESTDIR -# run like the wind -$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 -if grep -q "command not found" $TESTDIR/diartk-test.log; then - echo " Diartk failed - dependencies (probably HTK)" - FAILURES=true -else - if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then - echo "DiarTK passed the test." - else - FAILURES=true - echo " Diartk failed - no output RTTM" - fi -fi -#rm $TESTDIR/$BASETEST.rttm - -# test Yunitator -echo "Testing Yunitator..." -cd $YUNITATORDIR - -# let 'er rip -$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then - echo "Yunitator passed the test." -else - FAILURES=true - echo " Yunitator failed - no output RTTM" -fi - - -# Test DSCORE -echo "Testing Dscore..." -cd $DSCOREDIR - -cp -r test_ref test_sys $TESTDIR -rm -f test.df -python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/test.df ]; then - echo "DScore passed the test." -else - echo " DScore failed the test - output does not match expected" - FAILURES=true -fi - - - -# Testing VCM -echo "Testing VCM..." -cd $VCMDIR - -$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then - echo "VCM passed the test." +## now test Noisemes +#echo "Testing noisemes..." +#cd $OPENSATDIR +# +#$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} +# +#if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then +# echo "Noisemes passed the test." +#else +# FAILURES=true +# echo " Noisemes failed - no RTTM output" +#fi +# +# +## now test OPENSMILEDIR +#echo "Testing OpenSmile SAD..." +#cd $OPENSMILEDIR +# +#$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} +# +#if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then +# echo "OpenSmile SAD passed the test." +#else +# FAILURES=true +# echo " OpenSmile SAD failed - no RTTM output" +#fi +# +## now test TOCOMBOSAD +#echo "Testing ToCombo SAD..." +#cd $TOCOMBOSAD +# +#$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} +# +#if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then +# echo "TOCOMBO SAD passed the test." +#else +# FAILURES=true +# echo " TOCOMBO SAD failed - no output RTTM" +#fi +# +# +## test DIARTK +#echo "Testing DIARTK..." +#cd $DIARTKDIR +# +#cp $TEST_RTTM $TESTDIR +# +## run like the wind +#$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 +#if grep -q "command not found" $TESTDIR/diartk-test.log; then +# echo " Diartk failed - dependencies (probably HTK)" +# FAILURES=true +#else +# if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then +# echo "DiarTK passed the test." +# else +# FAILURES=true +# echo " Diartk failed - no output RTTM" +# fi +#fi +##rm $TESTDIR/$BASETEST.rttm +# +## test Yunitator +#echo "Testing Yunitator..." +#cd $YUNITATORDIR +# +## let 'er rip +#$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +#if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then +# echo "Yunitator passed the test." +#else +# FAILURES=true +# echo " Yunitator failed - no output RTTM" +#fi +# +# +## Test DSCORE +#echo "Testing Dscore..." +#cd $DSCOREDIR +# +#cp -r test_ref test_sys $TESTDIR +#rm -f test.df +#python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} +#if [ -s $TESTDIR/test.df ]; then +# echo "DScore passed the test." +#else +# echo " DScore failed the test - output does not match expected" +# FAILURES=true +#fi +# +## Testing VCM +#echo "Testing VCM..." +#cd $VCMDIR +# +#$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} +#if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then +# echo "VCM passed the test." +#else +# FAILURES=true +# echo " VCM failed - no output RTTM" +#fi + +# Testing WCE +echo "Testing WCE..." +WCEDIR=$REPOS/WCE_VM/ +cd $WCEDIR + +./run_WCEtrain.sh /usr/local/MATLAB/MATLAB_Runtime/v93/ demofiles.txt democounts.txt models/mymodel.mat configs/config_default.txt > $TESTDIR/wce-test.log || { echo " WCE failed - dependencies"; FAILURES=true;} +WCE_OUTPUT=$(awk '/adaptation completed/{ print NR; exit }' $TESTDIR/wce-test.log) +if [ $WCE_OUTPUT > 0 ]; then + echo "WCE passed the test" else FAILURES=true - echo " VCM failed - no output RTTM" + echo "WCE failed - no successful adaptation" fi # test finished diff --git a/launcher/WCE_preprocess.sh b/utils/WCE_preprocess.sh similarity index 100% rename from launcher/WCE_preprocess.sh rename to utils/WCE_preprocess.sh From f61da526797347c9a5cbf5c42d2eb570e4eacac6 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Tue, 18 Dec 2018 14:37:39 +0100 Subject: [PATCH 200/299] Uncomment modif test.sh --- launcher/test.sh | 202 +++++++++++++++++++++++------------------------ 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index a70d6e2..3c5dfb8 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -86,107 +86,107 @@ cp $WORKDIR/$BASETEST.rttm $TESTDIR -## now test Noisemes -#echo "Testing noisemes..." -#cd $OPENSATDIR -# -#$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} -# -#if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then -# echo "Noisemes passed the test." -#else -# FAILURES=true -# echo " Noisemes failed - no RTTM output" -#fi -# -# -## now test OPENSMILEDIR -#echo "Testing OpenSmile SAD..." -#cd $OPENSMILEDIR -# -#$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} -# -#if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then -# echo "OpenSmile SAD passed the test." -#else -# FAILURES=true -# echo " OpenSmile SAD failed - no RTTM output" -#fi -# -## now test TOCOMBOSAD -#echo "Testing ToCombo SAD..." -#cd $TOCOMBOSAD -# -#$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} -# -#if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then -# echo "TOCOMBO SAD passed the test." -#else -# FAILURES=true -# echo " TOCOMBO SAD failed - no output RTTM" -#fi -# -# -## test DIARTK -#echo "Testing DIARTK..." -#cd $DIARTKDIR -# -#cp $TEST_RTTM $TESTDIR -# -## run like the wind -#$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 -#if grep -q "command not found" $TESTDIR/diartk-test.log; then -# echo " Diartk failed - dependencies (probably HTK)" -# FAILURES=true -#else -# if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then -# echo "DiarTK passed the test." -# else -# FAILURES=true -# echo " Diartk failed - no output RTTM" -# fi -#fi -##rm $TESTDIR/$BASETEST.rttm -# -## test Yunitator -#echo "Testing Yunitator..." -#cd $YUNITATORDIR -# -## let 'er rip -#$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -#if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then -# echo "Yunitator passed the test." -#else -# FAILURES=true -# echo " Yunitator failed - no output RTTM" -#fi -# -# -## Test DSCORE -#echo "Testing Dscore..." -#cd $DSCOREDIR -# -#cp -r test_ref test_sys $TESTDIR -#rm -f test.df -#python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} -#if [ -s $TESTDIR/test.df ]; then -# echo "DScore passed the test." -#else -# echo " DScore failed the test - output does not match expected" -# FAILURES=true -#fi -# -## Testing VCM -#echo "Testing VCM..." -#cd $VCMDIR -# -#$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} -#if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then -# echo "VCM passed the test." -#else -# FAILURES=true -# echo " VCM failed - no output RTTM" -#fi +# now test Noisemes +echo "Testing noisemes..." +cd $OPENSATDIR + +$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then + echo "Noisemes passed the test." +else + FAILURES=true + echo " Noisemes failed - no RTTM output" +fi + + +# now test OPENSMILEDIR +echo "Testing OpenSmile SAD..." +cd $OPENSMILEDIR + +$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then + echo "OpenSmile SAD passed the test." +else + FAILURES=true + echo " OpenSmile SAD failed - no RTTM output" +fi + +# now test TOCOMBOSAD +echo "Testing ToCombo SAD..." +cd $TOCOMBOSAD + +$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then + echo "TOCOMBO SAD passed the test." +else + FAILURES=true + echo " TOCOMBO SAD failed - no output RTTM" +fi + + +# test DIARTK +echo "Testing DIARTK..." +cd $DIARTKDIR + +cp $TEST_RTTM $TESTDIR + +# run like the wind +$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 +if grep -q "command not found" $TESTDIR/diartk-test.log; then + echo " Diartk failed - dependencies (probably HTK)" + FAILURES=true +else + if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then + echo "DiarTK passed the test." + else + FAILURES=true + echo " Diartk failed - no output RTTM" + fi +fi +#rm $TESTDIR/$BASETEST.rttm + +# test Yunitator +echo "Testing Yunitator..." +cd $YUNITATORDIR + +# let 'er rip +$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then + echo "Yunitator passed the test." +else + FAILURES=true + echo " Yunitator failed - no output RTTM" +fi + + +# Test DSCORE +echo "Testing Dscore..." +cd $DSCOREDIR + +cp -r test_ref test_sys $TESTDIR +rm -f test.df +python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/test.df ]; then + echo "DScore passed the test." +else + echo " DScore failed the test - output does not match expected" + FAILURES=true +fi + +# Testing VCM +echo "Testing VCM..." +cd $VCMDIR + +$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then + echo "VCM passed the test." +else + FAILURES=true + echo " VCM failed - no output RTTM" +fi # Testing WCE echo "Testing WCE..." From e8150053d81996d5961134c1a5d79af91d92105b Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Fri, 21 Dec 2018 16:06:48 +0100 Subject: [PATCH 201/299] Repair opensmile link --- conf/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 34f344c..eea1162 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -93,7 +93,7 @@ rm /tmp/MCR_R2017b_glnxa64_installer.zip echo "Installing OpenSMILE" su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ -wget -q https://www.audeering.com/download/1318 -O OpenSMILE-2.3.tar.gz +wget -q --no-check-certificate https://www.audeering.com/download/opensmile-2-3-0-tar-gz/?wpdmdl=4782 -O OpenSMILE-2.3.tar.gz tar zxvf OpenSMILE-2.3.tar.gz chmod +x opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract cp opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin From 419ee6bdaffb05fc4fb8842f110c5de57a33be9e Mon Sep 17 00:00:00 2001 From: alecristia Date: Wed, 26 Dec 2018 16:58:23 +0100 Subject: [PATCH 202/299] correction --- docs/source/formats.md | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/docs/source/formats.md b/docs/source/formats.md index 0927ebe..ac98215 100644 --- a/docs/source/formats.md +++ b/docs/source/formats.md @@ -1,23 +1,6 @@ # Formats -This section explains the input and output formats. Each type of tool returns a different type of output, depending on the key information. - -### Input: TextGrid - -TextGrid is a standard format for speech annotation, used by the Praat software. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. - -### Input: Eaf - -Eaf is a standard format for speech annotation, that allows for rich annotation, used by the Elan software. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. - - -## Speech or Voice activity detection output - -RTTM is an annotation format for audio files well designed for diarization. Explanations about how to write and read .rttm files can be found [here](https://catalog.ldc.upenn.edu/docs/LDC2004T12/RTTM-format-v13.pdf) -This format is used by the [DiViMe](https://github.com/srvk/DiViMe). - - -Tools that are of the SAD type (SAD or VAD) return one rttm per audio file, named toolnameSad_filename.rttm, which looks like this: +This section explains the input and output formats. ## Overview From 0569021ff66914d14c082f87129ff6d7867c6f9f Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Thu, 3 Jan 2019 16:43:39 +0100 Subject: [PATCH 203/299] Add WCE dependencies in bootstrap.sh --- conf/bootstrap.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 451e623..854c64c 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -165,6 +165,11 @@ git clone http://github.com/srvk/dscore # zip to revision for release 1.1 14 Dec 2018 (cd dscore && git checkout 31d7eca) +# Install WCE and dependencies +git clone https://github.com/aclew/WCE_VM +su ${user} -c "/home/${user}/anaconda/bin/pip install keras" +su ${user} -c "/home/${user}/anaconda/bin/pip install -U tensorflow" + # Phonemizer installation git clone https://github.com/bootphon/phonemizer cd phonemizer From bf0120e6dabf7ccde7e2859123a5a14e43c03c97 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Tue, 8 Jan 2019 18:11:22 +0100 Subject: [PATCH 204/299] Handle special characters encoded in utf-8 --- utils/eaf2txt.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py index e238b81..3f43e5d 100755 --- a/utils/eaf2txt.py +++ b/utils/eaf2txt.py @@ -17,7 +17,9 @@ import argparse import os import glob - +import sys +reload(sys) +sys.setdefaultencoding('utf8') def eaf2txt(path_to_eaf, output_folder, cleanup=False): """ @@ -55,7 +57,7 @@ def eaf2txt(path_to_eaf, output_folder, cleanup=False): if cleanup: transcript = clean_up_annotation(transcript) - output_file.write("%d\t%d\t%s\t%s\t%s\n" % (onset, offset, receiver, transcript, speaker)) + output_file.write("%d\t%d\t%s\t%s\t%s\n" % (onset, offset, str(receiver), str(transcript), str(speaker))) output_file.close() def main(): From b724abec6031839afedd3702f9094e136433916d Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 8 Jan 2019 15:17:30 -0500 Subject: [PATCH 205/299] speechkitchen.org -> speech-kitchen.org AWS box --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 827fa7a..e0411dc 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -52,7 +52,7 @@ Vagrant.configure("2") do |config| override.vm.synced_folder ".", "/vagrant", type: "sshfs", ssh_username: ENV['USER'], ssh_port: "22", prompt_for_password: "true" - override.vm.box = "http://speechkitchen.org/dummy.box" + override.vm.box = "http://speech-kitchen.org/dummy.box" # it is assumed these environment variables were set by ". aws.sh" aws.access_key_id = ENV['AWS_KEY'] From 84f4cfb1a741e390a1149f2542774b66e045024a Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 17 Jan 2019 08:16:24 +0000 Subject: [PATCH 206/299] updated estimateWCE.sh to match WCE out-of-the-box requirements --- launcher/estimateWCE.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/estimateWCE.sh b/launcher/estimateWCE.sh index 2b0f5ae..65f5701 100755 --- a/launcher/estimateWCE.sh +++ b/launcher/estimateWCE.sh @@ -12,7 +12,7 @@ OUTPUTFILE=$2 fi MATPATH="/usr/local/MATLAB/MATLAB_Runtime/v93/" -MODEL_FINAL="~/repos/WCE_VM/models/model_final.mat" +MODEL_FINAL="~/repos/WCE_VM/models/model_default.mat" #python ... write python code that averages all the results of the speakers ~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL_FINAL} ${OUTPUTFILE} From 23b56c14a011465e2e4f107f4d6f25d2328d575b Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 17 Jan 2019 09:17:23 +0000 Subject: [PATCH 207/299] updated estimateWCE.sh to support directories --- launcher/estimateWCE.sh | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/launcher/estimateWCE.sh b/launcher/estimateWCE.sh index 65f5701..b611489 100755 --- a/launcher/estimateWCE.sh +++ b/launcher/estimateWCE.sh @@ -4,15 +4,37 @@ SCRIPT_DIR=$(dirname "$0") FILES_TEST=$1 +if [ "$#" -ne 1 ] && [ "$#" -ne 2 ] && [ "$#" -ne 3 ] ; then +echo "Usage: $0 (optional) (optional)" +echo "Example:" +echo "$0 /vagrant/data/my_audiodata/ ~/my_WCE_output.txt" +echo "or" +echo "$0 /vagrant/data/list_of_audiofiles.txt ~/my_WCE_output.txt" +exit 1 +fi + +if [[ -d $1 ]]; then + find $1*.wav > ~/repos/WCE_VM/file_list.txt + FILES_TEST=~/repos/WCE_VM/file_list.txt +fi + if [ -n "$2" ]; then -OUTPUTFILE = '/vagrant/repos/WCE_VM/outputs/default_output.csv' + OUTPUTFILE=$2 else -OUTPUTFILE=$2 + OUTPUTFILE='/vagrant/repos/WCE_VM/outputs/default_output.csv' +fi + +if [ -n "$3" ]; then + MODEL=$3 +else + MODEL="~/repos/WCE_VM/models/model_default.mat" fi MATPATH="/usr/local/MATLAB/MATLAB_Runtime/v93/" -MODEL_FINAL="~/repos/WCE_VM/models/model_default.mat" -#python ... write python code that averages all the results of the speakers -~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL_FINAL} ${OUTPUTFILE} +echo $MODEL +echo $OUTPUTFILE + + +~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL} ${OUTPUTFILE} From 6ffc331dd6e1c63d9591fc107f4bd4563d775180 Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 17 Jan 2019 11:07:32 +0000 Subject: [PATCH 208/299] updated estimateWCE to support DiViMe data structure --- launcher/estimateWCE.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/launcher/estimateWCE.sh b/launcher/estimateWCE.sh index b611489..ad0de66 100755 --- a/launcher/estimateWCE.sh +++ b/launcher/estimateWCE.sh @@ -13,16 +13,25 @@ echo "$0 /vagrant/data/list_of_audiofiles.txt ~/my_WCE_output.txt" exit 1 fi + + if [[ -d $1 ]]; then find $1*.wav > ~/repos/WCE_VM/file_list.txt FILES_TEST=~/repos/WCE_VM/file_list.txt +elif [ ! -d "$1" ] && [ ! -f $1 ]; then + if [[ -d /vagrant/$1 ]]; then + find /vagrant/$1*.wav > ~/repos/WCE_VM/file_list.txt + FILES_TEST=~/repos/WCE_VM/file_list.txt + fi fi if [ -n "$2" ]; then OUTPUTFILE=$2 + OUTPUTFILE=${OUTPUTFILE/"data/"/"/vagrant/data/"} + OUTPUTFILE=${OUTPUTFILE/"/vagrant//vagrant/"/"/vagrant/"} else - OUTPUTFILE='/vagrant/repos/WCE_VM/outputs/default_output.csv' + OUTPUTFILE='~/repos/WCE_VM/outputs/default_output.csv' fi if [ -n "$3" ]; then @@ -33,8 +42,7 @@ fi MATPATH="/usr/local/MATLAB/MATLAB_Runtime/v93/" -echo $MODEL -echo $OUTPUTFILE - +echo "Running WCE module (this might take a while...)" +~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL} ${OUTPUTFILE} > ~/repos/WCE_VM/process_log.log -~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL} ${OUTPUTFILE} +echo "WCE processing complete. Wrote output to $OUTPUTFILE" From 8d7a47307473584e053cdfbd5691974f1de56aa7 Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 17 Jan 2019 11:10:10 +0000 Subject: [PATCH 209/299] updated estimateWCE to support DiViMe data structure --- launcher/estimateWCE.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/estimateWCE.sh b/launcher/estimateWCE.sh index ad0de66..f0ca073 100755 --- a/launcher/estimateWCE.sh +++ b/launcher/estimateWCE.sh @@ -43,6 +43,6 @@ fi MATPATH="/usr/local/MATLAB/MATLAB_Runtime/v93/" echo "Running WCE module (this might take a while...)" -~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL} ${OUTPUTFILE} > ~/repos/WCE_VM/process_log.log +~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL} ${OUTPUTFILE} > /vagrant/data/WCE_VM_TEMP/WCE_process_log.log echo "WCE processing complete. Wrote output to $OUTPUTFILE" From 1e2d4bc2fe807a72872d546d70e3dc3a16ff3244 Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 17 Jan 2019 11:34:51 +0000 Subject: [PATCH 210/299] updated estimateWCE.sh to be compatible with DiViMe input data syntax --- launcher/estimateWCE.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/launcher/estimateWCE.sh b/launcher/estimateWCE.sh index f0ca073..c453f70 100755 --- a/launcher/estimateWCE.sh +++ b/launcher/estimateWCE.sh @@ -14,7 +14,8 @@ exit 1 fi - +# If input is a directory, find all .wavs in it and write to a file to be used as input +# to the WCE tool if [[ -d $1 ]]; then find $1*.wav > ~/repos/WCE_VM/file_list.txt FILES_TEST=~/repos/WCE_VM/file_list.txt @@ -26,6 +27,7 @@ elif [ ! -d "$1" ] && [ ! -f $1 ]; then fi +# Replace DiViMe way of addressing data-folder with an absolute path if [ -n "$2" ]; then OUTPUTFILE=$2 OUTPUTFILE=${OUTPUTFILE/"data/"/"/vagrant/data/"} @@ -40,9 +42,19 @@ else MODEL="~/repos/WCE_VM/models/model_default.mat" fi +if [ ! -d "/vagrant/data/WCE_VM_TEMP/" ]; then + mkdir -p /vagrant/data/WCE_VM_TEMP/ +fi + MATPATH="/usr/local/MATLAB/MATLAB_Runtime/v93/" echo "Running WCE module (this might take a while...)" ~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL} ${OUTPUTFILE} > /vagrant/data/WCE_VM_TEMP/WCE_process_log.log +# Combine filenames and output counts into one file +paste -d ', ' $FILES_TEST $OUTPUTFILE > /vagrant/data/WCE_VM_TEMP/tempout.txt +cp /vagrant/data/WCE_VM_TEMP/tempout.txt $OUTPUTFILE +sed -i 's+/vagrant/data/+data/+g' $OUTPUTFILE + + echo "WCE processing complete. Wrote output to $OUTPUTFILE" From 2b034d52ddb7870c88b1aa7df8de208c6439d28f Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 17 Jan 2019 13:43:42 +0200 Subject: [PATCH 211/299] added WCE documentation --- docs/source/WCEtool.md | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 docs/source/WCEtool.md diff --git a/docs/source/WCEtool.md b/docs/source/WCEtool.md new file mode 100644 index 0000000..f6bbdd1 --- /dev/null +++ b/docs/source/WCEtool.md @@ -0,0 +1,47 @@ +# Word count estimation (WCE) tool + +This section contains documentation for word count estimation tool. + + +## Basic description + +The purpose of the WCE tool is to provide an estimate of the number of words in an utterance that is provided as an input to the algorithm. It is based on automatic syllabification of speech, followed by mapping of syllable counts + a number of other acoustic features to word counts. The basic functionality is described in Räsänen et al. (submitted). + +There are two basic ways to use the current tool: + +1) An out-of-the-box version that can be used directly on any speech data , and +2) An adapted version, where the WCE system is first adapted to data provided by the user, and then performs more accurately on similar data. + +In practice, out-of-the-box variant provides only syllable count estimates for the input data, while the adaptation mode can be used +to re-train the system to provide meaningful word count estimates in any language or other data domain. These two operation modes are detailed further below. + +Note that the tool assumes that the incoming signals are already segmented into utterances (e.g., using a SAD and/or a diarization tool), as it does not +have an internal module for separating speech from non-speech contents. + + +## Instructions for direct use (out-of-the-box version) + +To get syllable count estimates on your audio files, run + +vagrant ssh -c "~/launcher/estimateWCE.sh data/my_audiofolder/ data/WCE_output.txt" + +which will run WCE on all .wav files in data/my_audiofolder/ and output results to data/WCE_output.txt. + +## Instructions for adapting the WCE to new language (DOCUMENTATION INCOMPLETE) + +NOTE: This requires audio files and .eaf annotation files in ACLEW DAS annotation format. + + +## Changing configuration files (DOCUMENTATION INCOMPLETE) + + +### Main references for this tool: + +Räsänen, O., Seshadri, S. & Casillas, M. (2018). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. Proc. Interspeech-201, Hyderabad, India, pp. 1200–1204. + +Räsänen, O. et al. (submitted). Automatic word count estimation from daylong child-centered recordings in various language environments using language-independent syllabification of speech. In review. + + +### Questions and bug reports + +Send questions & Bug reports to Okko Räsänen (firstname.surname @ aalto.fi) From 8f4ccedf0594fce5179ad87f7e25b44faf250cba Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 17 Jan 2019 13:45:10 +0200 Subject: [PATCH 212/299] added WCE documentation --- docs/source/WCEtool.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/WCEtool.md b/docs/source/WCEtool.md index f6bbdd1..371e516 100644 --- a/docs/source/WCEtool.md +++ b/docs/source/WCEtool.md @@ -35,13 +35,13 @@ NOTE: This requires audio files and .eaf annotation files in ACLEW DAS annotatio ## Changing configuration files (DOCUMENTATION INCOMPLETE) -### Main references for this tool: +## Main references for this tool: Räsänen, O., Seshadri, S. & Casillas, M. (2018). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. Proc. Interspeech-201, Hyderabad, India, pp. 1200–1204. Räsänen, O. et al. (submitted). Automatic word count estimation from daylong child-centered recordings in various language environments using language-independent syllabification of speech. In review. -### Questions and bug reports +## Questions and bug reports Send questions & Bug reports to Okko Räsänen (firstname.surname @ aalto.fi) From 90d39e1cfa5bc9eb02646f63fda9ea2f93de9481 Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 17 Jan 2019 13:46:25 +0200 Subject: [PATCH 213/299] Update index.rst --- docs/source/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/index.rst b/docs/source/index.rst index dc387b7..7856954 100755 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -16,6 +16,7 @@ Welcome to DiViMe's documentation! further-info formats tool_doc + WCEtool extra-tools troubleshoot instructions_for_contributors From e706563666a51befd698c0a11ec0ea07171a346a Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 17 Jan 2019 13:55:18 +0200 Subject: [PATCH 214/299] added WCE documentation --- docs/source/WCEtool.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/docs/source/WCEtool.md b/docs/source/WCEtool.md index 371e516..1401e7b 100644 --- a/docs/source/WCEtool.md +++ b/docs/source/WCEtool.md @@ -18,6 +18,13 @@ to re-train the system to provide meaningful word count estimates in any languag Note that the tool assumes that the incoming signals are already segmented into utterances (e.g., using a SAD and/or a diarization tool), as it does not have an internal module for separating speech from non-speech contents. +By default, the WCE tool is using a bi-directional long short-term memory (LSTM) -based syllabifier, trained on four different languages. The package also +contains a syllabifier stage from speaking-rate estimator published by Wang & Narayanan (2007), as implemented for MATLAB in Räsänen et al. (2018), and an +oscillator-based syllabifier described in Räsänen et al. (2018). The default syllabifier can be changed from configuration files (see "Changing configuration"). + +All research or other use utilizing this WCE tool should cite the following paper: + +Räsänen, O., Seshadri, S., Karadayi, J., Riebling, E., Bunce, J., Cristia, A., Metze, F., Casillas, M., Rosemberg, C., Bergelson, E., & Soderstrom, M. (submitted). Automatic word count estimation from daylong child-centered recordings in various language environments using language-independent syllabification of speech. In review. ## Instructions for direct use (out-of-the-box version) @@ -27,19 +34,27 @@ vagrant ssh -c "~/launcher/estimateWCE.sh data/my_audiofolder/ data/WCE_output.t which will run WCE on all .wav files in data/my_audiofolder/ and output results to data/WCE_output.txt. -## Instructions for adapting the WCE to new language (DOCUMENTATION INCOMPLETE) +## Instructions for adapting the WCE to new language + +NOTE: DOCUMENTATION INCOMPLETE NOTE: This requires audio files and .eaf annotation files in ACLEW DAS annotation format. -## Changing configuration files (DOCUMENTATION INCOMPLETE) +## Changing configuration + +NOTE: DOCUMENTATION INCOMPLETE ## Main references for this tool: Räsänen, O., Seshadri, S. & Casillas, M. (2018). Comparison of Syllabification Algorithms and Training Strategies for Robust Word Count Estimation across Different Languages and Recording Conditions. Proc. Interspeech-201, Hyderabad, India, pp. 1200–1204. -Räsänen, O. et al. (submitted). Automatic word count estimation from daylong child-centered recordings in various language environments using language-independent syllabification of speech. In review. +Räsänen, O., Seshadri, S., Karadayi, J., Riebling, E., Bunce, J., Cristia, A., Metze, F., Casillas, M., Rosemberg, C., Bergelson, E., & Soderstrom, M. (submitted). Automatic word count estimation from daylong child-centered recordings in various language environments using language-independent syllabification of speech. In review. + +Räsänen, O., Doyle, G., & Frank, M. C. (2018). Pre-linguistic segmentation of speech into syllable-like units. Cognition, 171, 130–150. + +Wang, D., & Narayanan, S. (2007). Robust speech rate estimation for spontaneous speech. IEEE Transactions on Audio, Speech, and Language Processing, 15, 2190–2201. ## Questions and bug reports From 7186c3a6fb4724bacd11dd4911fa5c5c9aba288f Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Mon, 4 Feb 2019 11:24:51 -0500 Subject: [PATCH 215/299] Update Dockerfile --- conf/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/Dockerfile b/conf/Dockerfile index 4e35753..2200a56 100755 --- a/conf/Dockerfile +++ b/conf/Dockerfile @@ -52,7 +52,7 @@ RUN wget -q http://audeering.com/download/1131/ -O OpenSMILE-2.1.tar.gz && tar # we cannot redistribute WORKDIR /home/vagrant USER root -RUN wget http://speechkitchen.org/vms/Data/HTK.tar.gz && tar zxf HTK.tar.gz --no-same-owner +RUN wget http://speech-kitchen.org/vms/Data/HTK.tar.gz && tar zxf HTK.tar.gz --no-same-owner WORKDIR /home/vagrant/htk RUN ./configure --without-x --disable-hslab # Fix bad Makefile @@ -108,4 +108,4 @@ RUN touch /home/vagrant/.Xauthority && chown -R vagrant:vagrant /home/vagrant # Open up HTTP / HTTPS ports #EXPOSE 80 443 -CMD ["/bin/bash"] \ No newline at end of file +CMD ["/bin/bash"] From 30c8897f018d6a93fa9f4ddd940c372a7cf2feca Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Tue, 5 Feb 2019 17:05:11 +0000 Subject: [PATCH 216/299] add sphinx to python packages --- conf/bootstrap.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 854c64c..558a78b 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -37,7 +37,7 @@ fi if ! grep -q -i anaconda .bashrc; then echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc fi -su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib" +su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib sphinx" # clean up big installer in home folder rm -f Anaconda-2.3.0-Linux-x86_64.sh @@ -57,7 +57,7 @@ rm -f Anaconda-2.3.0-Linux-x86_64.sh # if ! grep -q -i anaconda .bashrc; then # echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc # fi -# su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib cython=0.22.1" +# su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib cython=0.22.1 sphinx" # # clean up big installer in home folder # rm -f Miniconda2-4.5.11-Linux-x86_64.sh From 37c26e0c3165e306bb14e22402749f23ca74914a Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Wed, 6 Feb 2019 11:15:22 +0100 Subject: [PATCH 217/299] Update some utils scripts to handle the LENA evaluation easier --- launcher/evalDiar.sh | 8 +++---- utils/frame_cutter.py | 52 +++++++++++++++++++++++++------------------ utils/rttm2labels.py | 2 +- utils/txt2rttm.py | 20 ++++------------- 4 files changed, 38 insertions(+), 44 deletions(-) diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh index 97ebf52..676ad65 100755 --- a/launcher/evalDiar.sh +++ b/launcher/evalDiar.sh @@ -31,8 +31,8 @@ display_usage() { ### Read in variables from user audio_dir=/vagrant/$1 model=$2 - -if ! [[ $model =~ ^(noisemesSad| opensmileSad| tocomboSad | diartk_noisemesSad | diartk_opensmileSad | diartk_rttm |yunitate|lenaSad)$ ]] ]; then +echo $2 +if ! [[ $model =~ ^(noisemesSad|opensmileSad|tocomboSad|diartk_noisemesSad|diartk_opensmileSad|diartk_rttm|yunitate|lenaSad)$ ]]; then display_usage fi @@ -44,7 +44,6 @@ fi # Set CWD to path of Dscore cd $DSCOREDIR - if [[ $model =~ ^(diartk|yuniseg) ]]; then trs_format=$3 case $trs_format in @@ -87,14 +86,13 @@ if [[ $model =~ ^(diartk|yuniseg) ]]; then elif [ "$2" == "yunitate" ]; then sys_name="yunitator" elif [ "$2" == "lenaSad" ]; then - sys_name="lena_sad" + sys_name="lena" fi echo $UTILS/create_ref_sys.sh $1 $sys_name $UTILS/create_ref_sys.sh $1 $sys_name echo "evaluating" - python score_batch.py ${audio_dir}/${sys_name}_eval.df ${audio_dir}/temp_ref ${audio_dir}/temp_sys # Check if some gold files are empty. If so, add a line in the eval dataframe diff --git a/utils/frame_cutter.py b/utils/frame_cutter.py index b181e90..fd9c424 100755 --- a/utils/frame_cutter.py +++ b/utils/frame_cutter.py @@ -5,6 +5,7 @@ import glob import numpy as np from scipy.io import wavfile +import math def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): """ @@ -24,7 +25,7 @@ def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): Write a rttm whose name is the same than the rttm's one suffixed by _cutted.rttm """ basename = os.path.splitext(os.path.basename(path_to_rttm))[0] - if prefix != "": + if prefix != "" and prefix in basename: basename = basename.split(prefix)[1] dirname = os.path.dirname(path_to_rttm) wav_path = os.path.join(dirname,basename+'.wav') @@ -36,17 +37,11 @@ def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): sys.exit(1) frame_length_s = float(frame_length)/1000.0 - frames = np.arange(0.0, tot_dur_s, frame_length_s) - # We don't want to loose any data - if frames[-1] < tot_dur_s: - frames = np.append(frames, frames[-1]+frame_length_s) with open(path_to_rttm, 'r') as rttm: with open(output_file, 'w') as output: onset_prev_s = 0.0 dur_prev_s = 0.0 - act_prev = None - append_prev = False onset_s = None for line in rttm: @@ -62,15 +57,11 @@ def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): onset_sil_s = onset_prev_s + dur_prev_s single_activity_cutter(basename, output, frame_length_s, sil_dur_s, onset_sil_s, 'SIL', tot_dur_s, labels_map) - act_prev = 'SIL' - dur_prev_s = sil_dur_s - onset_prev_s = onset_sil_s single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, curr_activity, tot_dur_s, labels_map) # Update previous fields - act_prev = curr_activity dur_prev_s = dur_s onset_prev_s = onset_s @@ -81,6 +72,7 @@ def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): dur_s = 0.0 if onset_s + dur_s < tot_dur_s: + sil_dur_s = tot_dur_s - onset_s-dur_s onset_sil_s = onset_s + dur_s single_activity_cutter(basename, output, frame_length_s, @@ -102,14 +94,16 @@ def single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, cur labels_map : To map the labels from original rttm (values) to the output rttm (keys). """ + # We don't want to consider any fake labels generated after the duration of the wav file if onset_s + dur_s > tot_dur_s: dur_s = max(tot_dur_s - onset_s, 0) if onset_s > tot_dur_s: onset_s = 0.0 - diff_s = onset_s - int(onset_s / frame_length_s) * frame_length_s - onset_s = int(onset_s / frame_length_s) * frame_length_s + diff_s = onset_s - int(round(onset_s / frame_length_s)) * frame_length_s + + onset_s = int(round(onset_s / frame_length_s)) * frame_length_s n_frames = int((dur_s+diff_s) / frame_length_s) # Get the output label (we want a full match or nothing) activity = [k for k,v in labels_map.items() if re.match("("+v+")\Z", curr_activity) is not None] @@ -124,7 +118,7 @@ def single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, cur (basename, onset_s + frame_length_s * i, str(frame_length_s), activity)) - if not np.isclose(onset_s + frame_length_s * n_frames, onset_s+dur_s+diff_s, rtol=1e-05, atol=1e-08, equal_nan=False): + if (not np.isclose(onset_s + frame_length_s * n_frames, onset_s+dur_s+diff_s, rtol=1e-05, atol=1e-08, equal_nan=False)) and (onset_s + frame_length_s * n_frames < tot_dur_s): output.write("SPEAKER %s 1 %s %s %s \n" % \ (basename, onset_s + frame_length_s * n_frames, str(frame_length_s), activity)) @@ -155,6 +149,8 @@ def aggregate_overlap(path_to_rttm, output_file): line_j = lines[j].split() onset_j, dur_j, act_j = line_j[3], line_j[4], line_j[7] if onset_k != onset_j: + if len(frame_activity) >= 2 and 'SIL' in frame_activity: + frame_activity.remove("SIL") output.write("SPEAKER %s 1 %s %s %s \n" % \ (basename, onset_k, dur_k, '/'.join(frame_activity))) break @@ -166,6 +162,8 @@ def aggregate_overlap(path_to_rttm, output_file): j += 1 k += 1 + if len(frame_activity) >= 2 and 'SIL' in frame_activity: + frame_activity.remove("SIL") output.write("SPEAKER %s 1 %s %s %s \n" % \ (basename, onset_k, dur_k, '/'.join(frame_activity))) @@ -176,17 +174,28 @@ def main(): parser = argparse.ArgumentParser(description="convert a rttm file into another rttm cutted in frames.") parser.add_argument('-i', '--input', type=str, required=True, help="path to the input .rttm file or the folder containing rttm files.") - parser.add_argument('-l', '--length', type=float, required=False, default=100.0, - help="the frame length in ms (Default to 100 ms).") + parser.add_argument('-l', '--length', type=float, required=False, default=10.0, + help="the frame length in ms (Default to 10 ms).") parser.add_argument('-p', '--prefix', type=str, default="", help="the prefix that needs to be removed to map the rttm to the wav.") args = parser.parse_args() - labels_map = {"CHI": "CHI.?|CXN|CHN|C.?", - "FEM": "FAN|FAF|FEM|F|MOT.?|FA.?", - "MAL": "MAL|M|MAN|MA.?", - "SIL": "SIL|S"} - + # labels_map = {"CHI": "CHI.?|CXN|CHN|C.?", + # "FEM": "FAN|FAF|FEM|F|MOT.?|FA.?", + # "MAL": "MAL|M|MAN|MA.?", + # "SIL": "SIL|S"} + labels_map = {"CHF":"CHF", + "CHI":"CHI", + "CHN":"CHN", + "FAF":"FAF", + "FAN":"FAN", + "FEM":"FEM", + "MAF":"MAF", + "MAL":"MAL", + "MAN":"MAN", + "OLF":"OLF", + "OLN":"OLN", + "SIL":"SIL"} # Initialize the output folder as the same folder than the input # if not provided by the user. if args.input[-5:] == '.rttm': @@ -203,7 +212,6 @@ def main(): if args.input[-5:] == '.rttm': # A single file has been provided by the user output = os.path.splitext(args.input)[0]+'_cutted.rttm' - print(output) cutter(args.input, args.length, output+'.tmp', args.prefix, labels_map) aggregate_overlap(output+'.tmp', output) os.remove(output+'.tmp') diff --git a/utils/rttm2labels.py b/utils/rttm2labels.py index 0cca5f4..c1b90bf 100755 --- a/utils/rttm2labels.py +++ b/utils/rttm2labels.py @@ -19,7 +19,7 @@ def printbuf (begin, end, text): for l in sys.stdin: - m = re.match("^(.*) (.*) (.*) (\S+) (\S+) (.*) (.*) (.*) (.*)$", l) + m = re.match("^(.*)\t(.*)\t(.*)\t(\S+)\t(\S+)\t(.*)\t(.*)\t(.*)\t(.*)$", l) if m: type, file = m.group(1, 2) channel = int(m.group(3)) diff --git a/utils/txt2rttm.py b/utils/txt2rttm.py index 5ecce0c..262bb0c 100755 --- a/utils/txt2rttm.py +++ b/utils/txt2rttm.py @@ -66,7 +66,7 @@ def lena_to_aclew_name(tsi_key_info, basename): return '_'.join(['lena',basename.replace('_lena','')]) -def txt2rttm(path_to_txt, output_folder, labels_to_keep, lena_mode=False, only_first_letter=False): +def txt2rttm(path_to_txt, output_folder, lena_mode=False): """ Convert an txt file to the rttm format by extracting the Parameters @@ -94,12 +94,7 @@ def txt2rttm(path_to_txt, output_folder, labels_to_keep, lena_mode=False, only_f activity, onset, offset = line.rstrip().split('\t') dur = float(offset)-float(onset) - if lena_mode and activity in labels_to_keep: - if only_first_letter: - activity = activity[0] - rttm.write("SPEAKER %s 1 %s %s %s \n" % (output_basename, onset, str(dur), activity)) - elif not lena_mode: - rttm.write("SPEAKER %s 1 %s %s %s \n" % (output_basename, onset, str(dur), activity)) + rttm.write("SPEAKER\t%s\t1\t%s\t%s\t\t\t%s\t\n" % (output_basename, onset, str(dur), activity)) def main(): @@ -110,12 +105,6 @@ def main(): help="indicates whether to use this script in the lena mode or not. If the lena mode" "is activated, it will read the table tsi_key_info.xlsx in the input folder and" "will change the naming convention of the output in consequences") - - parser.add_argument('-t', '--to_keep', nargs='+', type=str, required=True, - help='List of labels that needs to be kept (Only use when --lena_mode is activated).') - parser.add_argument('-fl', '--only_first_letter', type=bool, default=False, - help='Indicates if the output labels will be produced by keeping only the first letter' - 'of the original labels.') args = parser.parse_args() @@ -132,14 +121,13 @@ def main(): if not os.path.isdir(output): os.mkdir(output) - if args.input[-4:] == '.txt': # A single file has been provided by the user - txt2rttm(args.input, output, args.to_keep, args.lena_mode, args.only_first_letter) + txt2rttm(args.input, output, args.to_keep, args.lena_mode) else: # A whole folder has been provided txt_files = glob.iglob(os.path.join(args.input, '*.txt')) for txt_path in txt_files: print("Processing %s" % txt_path) - txt2rttm(txt_path, output, args.to_keep, args.lena_mode, args.only_first_letter) + txt2rttm(txt_path, output, args.lena_mode) if __name__ == '__main__': From 1ab917095786f164b2042d1c72e642b56a7e18cd Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 6 Feb 2019 10:02:20 -0500 Subject: [PATCH 218/299] update Torch version, pass tests --- conf/bootstrap.sh | 20 ++++++++++---------- conf/environment.yml | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 558a78b..bc47d9a 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -9,7 +9,7 @@ else user="ubuntu" fi -sudo apt-get install -y git make automake libtool autoconf patch subversion fuse \ +apt-get install -y git make automake libtool autoconf patch subversion fuse \ libatlas-base-dev libatlas-dev liblapack-dev sox libav-tools g++ \ zlib1g-dev libsox-fmt-all sshfs gcc-multilib libncurses5-dev unzip bc \ openjdk-6-jre icedtea-netx-common icedtea-netx libxt-dev libx11-xcb1 \ @@ -24,7 +24,7 @@ echo "Downloading Anaconda-2.3.0..." cd /home/${user} wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh echo "Installing Anaconda-2.3.0..." -sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" + sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" # check if anaconda is installed correctly if ! [ -x "$(command -v /home/${user}/anaconda/bin/conda)" ]; then @@ -115,12 +115,12 @@ cd /home/${user} if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then if [[ ! -d repos/htk ]]; then cd /home/${user}/repos/ - sudo tar zxf /vagrant/HTK-3.4.1.tar.gz + tar zxf /vagrant/HTK-3.4.1.tar.gz cd htk - sudo ./configure --without-x --disable-hslab - sudo sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile - sudo make all - sudo make install + ./configure --without-x --disable-hslab + sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + make all + make install else echo "Visibly htk has been already installed..." fi @@ -144,9 +144,9 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" git clone https://github.com/srvk/Yunitator (cd Yunitator && git checkout develop/yunified) - -su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" -su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" +# these are only used by Python3 environment 'divime' +#su ${user} -c "/home/${user}/anaconda/envs/divime/bin/conda install cudatoolkit" +su ${user} -c "/home/${user}/anaconda/envs/divime/bin/conda install pytorch-cpu -c pytorch" # Install VCM git clone https://github.com/MilesICL/vcm diff --git a/conf/environment.yml b/conf/environment.yml index cb0e4a2..7534d32 100644 --- a/conf/environment.yml +++ b/conf/environment.yml @@ -4,7 +4,7 @@ channels: - conda-forge - pytorch dependencies: - - python=3.6.5 # python2 dependency + - python=3.6.8 # python2 dependency - cython - numpy - scipy @@ -14,7 +14,7 @@ dependencies: - tabulate - joblib - cudatoolkit - - pytorch-cpu + - pytorch-cpu=1.0.1 - scikit-learn - pip: - theano # install theano From 6d0a0d55c5c13b71a98b3a75e92bde1ca25396fd Mon Sep 17 00:00:00 2001 From: Eric Riebling Date: Wed, 6 Feb 2019 10:11:52 -0500 Subject: [PATCH 219/299] add newline at EOF --- docs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index c5a8db1..bfa2234 100755 --- a/docs/Makefile +++ b/docs/Makefile @@ -17,4 +17,4 @@ help: # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) From f70324b09ef54bb3526b156356361aa66e5b4c13 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Wed, 6 Feb 2019 17:49:55 +0100 Subject: [PATCH 220/299] Add DER and Stats metrics --- utils/compute_metrics.py | 107 +++++++++++++++++ utils/own_metrics.py | 243 ++++++++++++++++++++++++++++++++++++++ utils/train_test_split.py | 146 ----------------------- 3 files changed, 350 insertions(+), 146 deletions(-) create mode 100644 utils/compute_metrics.py create mode 100644 utils/own_metrics.py delete mode 100755 utils/train_test_split.py diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py new file mode 100644 index 0000000..afc3a0a --- /dev/null +++ b/utils/compute_metrics.py @@ -0,0 +1,107 @@ +from pyannote.core import Segment, Timeline, Annotation +from pyannote.metrics.diarization import DiarizationErrorRate +import os, glob, errno +import argparse +from own_metrics import StatSpkr + +def rttm_to_annotation(input_rttm): + """ + Given a path to a rttm file, create the corresponding Annotation objects + containing the triplets (t_beg, t_end, activity) + + Parameters + ---------- + input_rttm + A path to a rttm file that must exist. + + Returns + ------- + An Annotation object. + """ + anno = Annotation(uri=input_rttm) # Maybe remove the prefix here ? + if os.path.isfile(input_rttm): + with open(input_rttm) as fn: + for line in fn: + row = line.split('\t') + t_beg, t_dur, spkr = float(row[3]), float(row[4]), row[7] + anno[Segment(t_beg, t_beg+t_dur)] = spkr + return anno + + +def run_metrics(references_f, hypothesis_f, metrics): + if len(references_f) != len(hypothesis_f) : + raise ValueError("The number of reference files and hypothesis files must match ! (%d != %d)" + % (len(references_f), len(hypothesis_f))) + + for ref_f, hyp_f in zip(references_f, hypothesis_f): + ref, hyp = rttm_to_annotation(ref_f), rttm_to_annotation(hyp_f) + basename = os.path.basename(ref_f) + # Set the uri as the basename for both reference and hypothesis + ref.uri, hyp.uri = basename, basename + # Let's accumulate the score for each metrics + for m in metrics.values(): + m(ref, hyp) + return metrics + + +def get_couple_files(ref_path, hyp_path=None, prefix=None): + # If hyp_path is None, then the hyp files are stored where the ref files are + if prefix is not None: + prefix = prefix + "_" + + ref_path = os.path.join("/vagrant", ref_path) + if hyp_path is None: + hyp_files = list(glob.iglob(os.path.join(ref_path, prefix+'*.rttm'))) + ref_files = [f.replace(prefix, '') for f in hyp_files] + else: + # Hyp files are stored in a different place, we check if a folder has been provided or if it just a single file + if os.path.isdir(hyp_path): + hyp_files = list(glob.iglob(os.path.join(hyp_path, prefix+'*.rttm'))) + ref_files = [f.replace(prefix, '').replace(hyp_files, ref_path) for f in hyp_files] + elif os.path.isfile(hyp_path): + hyp_files = [hyp_path] + else: + raise ValueError("%s doesn't exist" % hyp_path) + + return sorted(ref_files), sorted(hyp_files) + +def main(): + parser = argparse.ArgumentParser(description="Scripts that computes metrics between reference and hypothesis files." + "Inputs can be both path to folders or single file.") + parser.add_argument('-ref', '--reference', type=str, required=True, + help="Path of the reference.") + parser.add_argument('-hyp', '--hypothesis', type=str, required=False, default=None, + help="Path of the hypothesis" + "If None, consider that the hypothesis is stored where the reference is.") + parser.add_argument('-p', '--prefix', required=True, choices=["lena", "noisemesSad", "opensmileSad", + "tocomboSad", "yunitate", "diartk_noisemesSad", + "diartk_tocomboSad","diartk_opensmileSad", + "diartk_goldSad", "yuniseg_noisemesSad", + "yuniseg_opensmileSad", "yuniseg_tocomboSad", + "yuniseg_goldSad"], + help="Prefix that filenames of the hypothesis must match.") + parser.add_argument('-m', '--metrics', required=True, nargs='+', type=str, choices=["DER", "act", "c", "d"], + help="Metrics that need to be run.") + args = parser.parse_args() + + # Let's create the metrics + metrics = {} + for m in args.metrics: + if m == "DER": + metrics[m] = DiarizationErrorRate(parallel=True) + elif m == "act": + metrics[m] = StatSpkr(parallel=True) + + # Get files and run the metrics + references_f, hypothesis_f = get_couple_files(args.reference, args.hypothesis, args.prefix) + metrics = run_metrics(references_f, hypothesis_f, metrics) + + # Display a report for each metrics + for name, m in metrics.items(): + print("%s report" % name) + m.report(display=True) + + +if __name__ == '__main__': + main() + diff --git a/utils/own_metrics.py b/utils/own_metrics.py new file mode 100644 index 0000000..fb1a7b3 --- /dev/null +++ b/utils/own_metrics.py @@ -0,0 +1,243 @@ +from pyannote.metrics.base import BaseMetric +import pandas as pd + +# This metric is for computing % of CHI speech, % of MAL speech, % of FEM speech. + +# Further improvements : +# - Computing % overlap + +label_map = { + 'Autre': 'NONE', + 'ADU': 'NONE', + 'Bro': 'CHI', # Brother + 'BRO': 'CHI', + 'C1': 'CHI', + 'C2': 'CHI', + 'Chi': 'CHI', + 'CHI': 'CHI', + 'CHF': 'CHI', + 'CXF': 'CHI', + 'CHI2': 'CHI', + 'CHNNSP': 'CHI', + 'CHNSP': 'CHI', + 'CXN': 'CHI', + 'CHI*': 'CHI', + 'EE1': 'NONE', # electronic + 'FA1': 'FEM', # female adult + 'FA2': 'FEM', + 'FA3': 'FEM', + 'FA4': 'FEM', + 'FA5': 'FEM', + 'FA6': 'FEM', + 'FA7': 'FEM', + 'FA8': 'FEM', + 'FAE': 'NONE', # female adult electronic + 'FAN': 'FEM', + 'MAN': 'MAL', + 'FAF': 'FEM', + 'FAT': 'MAL', # father + 'FC1': 'CHI', # female child + 'FC2': 'CHI', + 'FC3': 'CHI', + 'FC4': 'CHI', + 'FEM': 'FEM', + 'FEM2': 'FEM', + 'Gra': 'NONE', + 'GRF': 'MAL', # Grand-father + 'GRM': 'FEM', # Grand-mother + 'IN1': 'NONE', # Investigator + 'IN2': 'NONE', + 'Inv': 'NONE', + 'INV': 'NONE', + 'lui': 'MAL', + 'LF2P': 'NONE', + 'MA1': 'MAL', + 'MA2': 'MAL', + 'MA3': 'MAL', + 'MA4': 'MAL', + 'MA5': 'MAL', + 'MA6': 'MAL', + 'MAE': 'NONE', # Male adult electronic + 'MAF': 'MAL', + 'MAL': 'MAL', + 'MC1': 'CHI', # Male child + 'MC2': 'CHI', + 'MC3': 'CHI', + 'MC4': 'CHI', + 'MC5': 'CHI', + 'MC6': 'CHI', + 'MI1': 'MAL', + 'Mot': 'FEM', # Mother + 'MOT': 'FEM', + 'MOT*': 'FEM', + 'NOF': 'None', + 'NON': 'None', + 'TVF': 'None', + 'TVN': 'None', + 'UA1': 'None', # Unknown adult + 'UC1': 'CHI', # Unknown child + 'UC2': 'CHI', + 'UC3': 'CHI', + 'UC4': 'CHI', + 'UC5': 'CHI', + 'UC6': 'CHI', + 'UU1': 'NONE', # Unknown unknown + 'OCH': 'CHI', # other child + 'OLF': 'None', + 'OLN': 'None', + 'OTH': 'None', + 'Sis': 'CHI', # Sister + 'SIS': 'CHI', + 'Uni': 'NONE', # Unidentified + 'silences': 'NONE', + '2POPMT': 'NONE', + '': 'NONE', + '': 'NONE', + 'SIL': 'NONE' +} + + +def is_CHI(speaker_name): + # black magic that returns True if speaker is a man, False otherwise + return label_map[speaker_name] == 'CHI' + + +def is_MAL(speaker_name): + return label_map[speaker_name] == 'MAL' + + +def is_FEM(speaker_name): + return label_map[speaker_name] == 'FEM' + + +class StatSpkr(BaseMetric): + @classmethod + def metric_name(cls): + # Return human-readable name of the metric + return 'speaker activity' + + @classmethod + def metric_components(cls): + # Return component names from which the metric is computed + return ['CHI_ref', 'MAL_ref', 'FEM_ref', 'CHI_hyp', 'MAL_hyp', 'FEM_hyp'] + + def compute_components(self, reference, hypothesis, **kwargs): + # Actually compute the value of each component + total_duration_hyp, total_duration_ref = 0.0, 0.0 + components = {'CHI_ref': 0., 'MAL_ref': 0., 'FEM_ref': 0., + 'CHI_hyp': 0., 'MAL_hyp': 0., 'FEM_hyp': 0.} + + for segment, _, speaker_name in hypothesis.itertracks(yield_label=True): + if is_CHI(speaker_name): + components['CHI_hyp'] += segment.duration + total_duration_hyp += segment.duration + elif is_MAL(speaker_name): + components['MAL_hyp'] += segment.duration + total_duration_hyp += segment.duration + elif is_FEM(speaker_name): + components['FEM_hyp'] += segment.duration + total_duration_hyp += segment.duration + + for segment, _, speaker_name in reference.itertracks(yield_label=True): + if is_CHI(speaker_name): + components['CHI_ref'] += segment.duration + total_duration_ref += segment.duration + elif is_MAL(speaker_name): + components['MAL_ref'] += segment.duration + total_duration_ref += segment.duration + elif is_FEM(speaker_name): + components['FEM_ref'] += segment.duration + total_duration_ref += segment.duration + + if total_duration_hyp != 0.0: + components['CHI_hyp'] /= total_duration_hyp + components['MAL_hyp'] /= total_duration_hyp + components['FEM_hyp'] /= total_duration_hyp + else: + components['CHI_hyp'] = 0.0 + components['MAL_hyp'] = 0.0 + components['FEM_hyp'] = 0.0 + + if total_duration_ref != 0.0: + components['CHI_ref'] /= total_duration_ref + components['MAL_ref'] /= total_duration_ref + components['FEM_ref'] /= total_duration_ref + else: + components['CHI_ref'] = 0.0 + components['MAL_ref'] = 0.0 + components['FEM_ref'] = 0.0 + + return components + + def compute_metric(self, components): + # Actually compute the metric based on the component values + return '' + + def report(self, display=False): + """Evaluation report + Parameters + ---------- + display : bool, optional + Set to True to print the report to stdout. + Returns + ------- + report : pandas.DataFrame + Dataframe with one column per metric component, one row per + evaluated item, and one final row for accumulated results. + """ + + report = [] + uris = [] + + percent = 'total' in self.metric_components() + + for uri, components in self.results_: + row = {} + if percent: + total = components['total'] + for key, value in components.items(): + if key == self.name: + row[key, '%'] = 100 * value + else: + row[key, ''] = 100 * value + if percent: + if total > 0: + row[key, '%'] = 100 * value / total + else: + row[key, '%'] = np.NaN + + report.append(row) + uris.append(uri) + + row = {} + components = self.accumulated_ + + if percent: + total = components['total'] + + for key, value in components.items(): + if key == self.name: + row[key, '%'] = 100 * value + elif key == 'total': + row[key, ''] = value + else: + row[key, ''] = value + if percent: + row[key, '%'] = 100 * value / total + row[self.name, '%'] = 100 * abs(self) + report.append(row) + uris.append('AVERAGE') + + df = pd.DataFrame(report) + + df['item'] = uris + df = df.set_index('item') + + df.columns = pd.MultiIndex.from_tuples(df.columns) + + df = df[[self.name] + self.metric_components()] + + if display: + print(df.to_string(index=True, sparsify=False, justify='right', + float_format=lambda f: '{0:.2f}'.format(f))) + return df diff --git a/utils/train_test_split.py b/utils/train_test_split.py deleted file mode 100755 index 64ad008..0000000 --- a/utils/train_test_split.py +++ /dev/null @@ -1,146 +0,0 @@ -import os -import glob -import shutil -import numpy as np -import argparse -from math import floor, ceil - -### GLOBAL VARIABLE -default_test_prop = 0.5 - -def _create_empty_train_test(input_folder): - """ - Given an input folder, create a train and test folder. - If these folders already exist, move their content to the input folder before creating new train and test folders. - - Parameters - ---------- - input_folder path to the input folder - - Returns - ------- - path of the train folder and path of the test folder - """ - train_folder, test_folder = os.path.join(input_folder, 'train'), os.path.join(input_folder, 'test') - - # Bring back files to the parent directory - files = glob.glob(os.path.join(train_folder, '*'))+glob.glob(os.path.join(test_folder, '*')) - for path_f in files: - basename = os.path.basename(path_f) - shutil.move(path_f, os.path.join(input_folder, basename)) - - # Delete train and test folder - if os.path.isdir(train_folder): - shutil.rmtree(train_folder) - - if os.path.isdir(test_folder): - shutil.rmtree(test_folder) - - # Create new ones - os.makedirs(train_folder) - os.makedirs(test_folder) - - return train_folder, test_folder - - -def split(input_folder, test_prop, train_prop): - """ - Given an input folder, a proportion for the test set, a proportion for the training set, split the pairs - (.wav/.rttm) into a training folder and a test folder. - - Parameters - ---------- - input_folder the path to the input folder (containing wav and rttm files) - test_prop the proportion of the data that will be included in the test set - train_prop the proportion of the data that will be included in the training set - """ - # Create empty train and test directories. - # Move their content to the parent directory if they already exist - train_folder, test_folder = _create_empty_train_test(input_folder) - - # Check for all the wav into the the input_folder - wav = np.array(glob.glob(os.path.join(input_folder, "*.wav"))) - np.random.shuffle(wav) - - n_samples = len(wav) - n_train, n_test = np.int(floor(train_prop*n_samples)), np.int(ceil(test_prop*n_samples)) - - training_idx = np.arange(n_train) - test_idx = np.arange(n_train, n_train + n_test) - - train, test = wav[training_idx], wav[test_idx] - - # Move wav files ONLY if an associated rttm is found - for train_f in train: - basename = os.path.splitext(os.path.basename(train_f))[0] - old_path = os.path.join(input_folder, basename) - new_path = os.path.join(train_folder, basename) - if os.path.exists(old_path+'.rttm'): - os.rename(old_path+'.rttm', new_path+'.rttm') - os.rename(old_path+'.wav', new_path+'.wav') - else: - print("Ignoring file %s whose rttm has not been found." % (basename+'.wav')) - - for test_f in test: - basename = os.path.splitext(os.path.basename(test_f))[0] - old_path = os.path.join(input_folder, basename) - new_path = os.path.join(test_folder, basename) - if os.path.exists(old_path+'.rttm'): - os.rename(old_path+'.rttm', new_path+'.rttm') - os.rename(old_path+'.wav', new_path+'.wav') - else: - print("Ignoring file %s whose rttm has not been found." % (basename+'.wav')) - - n_real_train = len([f for f in glob.glob(os.path.join(train_folder, '*')) if os.path.isfile(f)]) / 2 - n_real_test = len([f for f in glob.glob(os.path.join(test_folder, '*')) if os.path.isfile(f)]) / 2 - - if n_real_train == 0: - print("Warning : The training set that you generated is empty !") - if n_real_test == 0: - print("Warning : The test set that you generated is empty !") - - - - - -def main(): - parser = argparse.ArgumentParser(description="Split a folder into a train set and a test set.") - parser.add_argument('-f', '--folder', type=str, required=True, - help='path to the folder that needs to be splitted.') - parser.add_argument('--test_prop', type=float, default=None, - help='''a float between 0.0 and 1.0 representing the proportion of the - dataset to include in the test set. If not specfied, the - value is automatically set to the complement of the - --train_prop. If --train_prop is not specified, --test_prop is set to - {}'''.format(default_test_prop)) - parser.add_argument('--train_prop', default=None, type=float, - help='''a float between 0.0 and 1.0 representing the proportion of the - dataset to include in the train set. If not specified, the - value is automatically set to the complement of --test_prop''') - parser.add_argument('-r', '--random_seed', default=None, type=int, - help='Seed the generator (for reproducible results)') - args = parser.parse_args() - - if args.train_prop is None: - test_prop = default_test_prop if args.test_prop is None else args.test_prop - else: - test_prop = 1.0-args.train_prop if args.test_prop is None else args.test_prop - train_prop = args.train_prop - - if test_prop < 0.0 or test_prop > 1.0 or train_prop < 0.0 or train_prop > 1.0: - raise ValueError("The test proportion and the train proportion must be between 0 and 1") - - data_dir = "/vagrant" - input_folder = os.path.join(data_dir, args.folder) - if not os.path.isdir(input_folder): - raise ValueError("The folder that you want to split is not found. Please check the path that you provided.") - - # Set the random seed - if args.random_seed is not None: - np.random.seed(args.random_seed) - - split(input_folder, test_prop, train_prop) - - -if __name__ == '__main__': - main() \ No newline at end of file From 0ab5474f055973fd26ba768267a8a324740d2f8f Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Thu, 7 Feb 2019 17:23:57 +0100 Subject: [PATCH 221/299] Add visualization module --- utils/compute_metrics.py | 111 ++++++++++++++++-- utils/own_metrics.py | 243 --------------------------------------- 2 files changed, 101 insertions(+), 253 deletions(-) delete mode 100644 utils/own_metrics.py diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py index afc3a0a..f1edef6 100644 --- a/utils/compute_metrics.py +++ b/utils/compute_metrics.py @@ -1,8 +1,47 @@ from pyannote.core import Segment, Timeline, Annotation -from pyannote.metrics.diarization import DiarizationErrorRate +from pyannote.metrics.errors.identification import IdentificationErrorAnalysis +import pyannote.metrics.diarization as diarization +import pyannote.metrics.identification as identification +import pyannote.metrics.detection as detection +import pyannote.core.notebook as notebook +import matplotlib.pyplot as plt import os, glob, errno import argparse -from own_metrics import StatSpkr +import numpy as np +import warnings +warnings.filterwarnings("ignore", category=UserWarning, module='pyannote') +# Here, we want to filter the following warning : +# UserWarning: 'uem' was approximated by the union of 'reference' and 'hypothesis' extents. +# "'uem' was approximated by the union of 'reference'" + +def get_best_start(beginnings, durations, tot_duration): + STEP_SIZE = 10 + beginnings = np.array(beginnings) + lst = list(range(0, int(tot_duration), STEP_SIZE)) + best_sum_speech = 0.0 + best_start = 0 + for i in range(0, len(lst)): + if i+7 > len(lst): + break + beg, end = lst[i], lst[i+6] + condition = (beginnings > beg) & (beginnings < end) + sum_speech = np.sum(np.extract(condition, durations)) + if sum_speech > best_sum_speech: + best_start = beg + best_sum_speech = sum_speech + return best_start + +def find_1mn_highest_volubility(annotation): + support = list(annotation.get_timeline().support().__iter__()) + if len(support) > 0: + tot_duration = support[-1].end + if tot_duration <= 60.0: + return 0.0, 60.0 + else: + durations = [seg.duration for seg in support] + beginnings = [seg.start for seg in support] + best_start = get_best_start(beginnings, durations, tot_duration) + return best_start, best_start + 60 def rttm_to_annotation(input_rttm): """ @@ -18,7 +57,7 @@ def rttm_to_annotation(input_rttm): ------- An Annotation object. """ - anno = Annotation(uri=input_rttm) # Maybe remove the prefix here ? + anno = Annotation(uri=input_rttm) if os.path.isfile(input_rttm): with open(input_rttm) as fn: for line in fn: @@ -28,7 +67,7 @@ def rttm_to_annotation(input_rttm): return anno -def run_metrics(references_f, hypothesis_f, metrics): +def run_metrics(references_f, hypothesis_f, metrics, visualization=False): if len(references_f) != len(hypothesis_f) : raise ValueError("The number of reference files and hypothesis files must match ! (%d != %d)" % (len(references_f), len(hypothesis_f))) @@ -41,6 +80,29 @@ def run_metrics(references_f, hypothesis_f, metrics): # Let's accumulate the score for each metrics for m in metrics.values(): m(ref, hyp) + + # Let's generate a visualization of the results + if visualization: + moment = find_1mn_highest_volubility(ref) + if moment is not None: + # Set figure size, and crop the annotation + # for the highest volubile moment + start, end = moment[0], moment[1] + notebook.width = end / 4 + plt.rcParams['figure.figsize'] = (notebook.width, 10) + notebook.crop = Segment(start, end) + + # Plot reference + plt.subplot(211) + notebook.plot_annotation(ref, legend=True, time=True) + plt.gca().text(0.6, 0.15, 'reference', fontsize=16) + + # Plot hypothesis + plt.subplot(212) + notebook.plot_annotation(hyp, legend=True, time=True) + plt.gca().text(0.6, 0.15, 'hypothesis', fontsize=16) + plt.savefig(hyp_f.replace('.rttm', '.png')) + plt.close() return metrics @@ -80,21 +142,50 @@ def main(): "yuniseg_opensmileSad", "yuniseg_tocomboSad", "yuniseg_goldSad"], help="Prefix that filenames of the hypothesis must match.") - parser.add_argument('-m', '--metrics', required=True, nargs='+', type=str, choices=["DER", "act", "c", "d"], + parser.add_argument('-t', '--task', type=str, required=True, choices=["detection", "diarization", "identification"]) + parser.add_argument('-m', '--metrics', required=True, nargs='+', type=str, choices=["diaer", "coverage", + "completeness", "homogeneity", + "purity", "accuracy", + "precision", "recall", "deter", + "ider","idea"], help="Metrics that need to be run.") + parser.add_argument('-v', '--visualization', action='store_true') args = parser.parse_args() # Let's create the metrics metrics = {} for m in args.metrics: - if m == "DER": - metrics[m] = DiarizationErrorRate(parallel=True) - elif m == "act": - metrics[m] = StatSpkr(parallel=True) + if args.task == "diarization": + if m == "diaer": + metrics[m] = diarization.DiarizationErrorRate(parallel=True) + elif m == "coverage": + metrics[m] = diarization.DiarizationCoverage(parallel=True) + elif m == "completeness": + metrics[m] = diarization.DiarizationCompleteness(parallel=True) + elif m == "homogeneity": + metrics[m] = diarization.DiarizationHomogeneity(parallel=True) + elif m == "purity": + metrics[m] = diarization.DiarizationPurity(parallel=True) + elif args.task == "detection": + if m == "accuracy": + metrics[m] = detection.DetectionAccuracy(parallel=True) + elif m == "precision": + metrics[m] = detection.DetectionPrecision(parallel=True) + elif m == "recall": + metrics[m] = detection.DetectionPrecision(parallel=True) + elif m == "deter": + metrics[m] = detection.DetectionErrorRate(parallel=True) + elif args.task == "identification": + if m == "ider": + metrics[m] = identification.IdentificationErrorRate(parallel=True) + elif m == "precision": + metrics[m] = identification.IdentificationPrecision(parallel=True) + elif m == "recall": + metrics[m] = identification.IdentificationRecall(parallel=True) # Get files and run the metrics references_f, hypothesis_f = get_couple_files(args.reference, args.hypothesis, args.prefix) - metrics = run_metrics(references_f, hypothesis_f, metrics) + metrics = run_metrics(references_f, hypothesis_f, metrics, args.visualization) # Display a report for each metrics for name, m in metrics.items(): diff --git a/utils/own_metrics.py b/utils/own_metrics.py deleted file mode 100644 index fb1a7b3..0000000 --- a/utils/own_metrics.py +++ /dev/null @@ -1,243 +0,0 @@ -from pyannote.metrics.base import BaseMetric -import pandas as pd - -# This metric is for computing % of CHI speech, % of MAL speech, % of FEM speech. - -# Further improvements : -# - Computing % overlap - -label_map = { - 'Autre': 'NONE', - 'ADU': 'NONE', - 'Bro': 'CHI', # Brother - 'BRO': 'CHI', - 'C1': 'CHI', - 'C2': 'CHI', - 'Chi': 'CHI', - 'CHI': 'CHI', - 'CHF': 'CHI', - 'CXF': 'CHI', - 'CHI2': 'CHI', - 'CHNNSP': 'CHI', - 'CHNSP': 'CHI', - 'CXN': 'CHI', - 'CHI*': 'CHI', - 'EE1': 'NONE', # electronic - 'FA1': 'FEM', # female adult - 'FA2': 'FEM', - 'FA3': 'FEM', - 'FA4': 'FEM', - 'FA5': 'FEM', - 'FA6': 'FEM', - 'FA7': 'FEM', - 'FA8': 'FEM', - 'FAE': 'NONE', # female adult electronic - 'FAN': 'FEM', - 'MAN': 'MAL', - 'FAF': 'FEM', - 'FAT': 'MAL', # father - 'FC1': 'CHI', # female child - 'FC2': 'CHI', - 'FC3': 'CHI', - 'FC4': 'CHI', - 'FEM': 'FEM', - 'FEM2': 'FEM', - 'Gra': 'NONE', - 'GRF': 'MAL', # Grand-father - 'GRM': 'FEM', # Grand-mother - 'IN1': 'NONE', # Investigator - 'IN2': 'NONE', - 'Inv': 'NONE', - 'INV': 'NONE', - 'lui': 'MAL', - 'LF2P': 'NONE', - 'MA1': 'MAL', - 'MA2': 'MAL', - 'MA3': 'MAL', - 'MA4': 'MAL', - 'MA5': 'MAL', - 'MA6': 'MAL', - 'MAE': 'NONE', # Male adult electronic - 'MAF': 'MAL', - 'MAL': 'MAL', - 'MC1': 'CHI', # Male child - 'MC2': 'CHI', - 'MC3': 'CHI', - 'MC4': 'CHI', - 'MC5': 'CHI', - 'MC6': 'CHI', - 'MI1': 'MAL', - 'Mot': 'FEM', # Mother - 'MOT': 'FEM', - 'MOT*': 'FEM', - 'NOF': 'None', - 'NON': 'None', - 'TVF': 'None', - 'TVN': 'None', - 'UA1': 'None', # Unknown adult - 'UC1': 'CHI', # Unknown child - 'UC2': 'CHI', - 'UC3': 'CHI', - 'UC4': 'CHI', - 'UC5': 'CHI', - 'UC6': 'CHI', - 'UU1': 'NONE', # Unknown unknown - 'OCH': 'CHI', # other child - 'OLF': 'None', - 'OLN': 'None', - 'OTH': 'None', - 'Sis': 'CHI', # Sister - 'SIS': 'CHI', - 'Uni': 'NONE', # Unidentified - 'silences': 'NONE', - '2POPMT': 'NONE', - '': 'NONE', - '': 'NONE', - 'SIL': 'NONE' -} - - -def is_CHI(speaker_name): - # black magic that returns True if speaker is a man, False otherwise - return label_map[speaker_name] == 'CHI' - - -def is_MAL(speaker_name): - return label_map[speaker_name] == 'MAL' - - -def is_FEM(speaker_name): - return label_map[speaker_name] == 'FEM' - - -class StatSpkr(BaseMetric): - @classmethod - def metric_name(cls): - # Return human-readable name of the metric - return 'speaker activity' - - @classmethod - def metric_components(cls): - # Return component names from which the metric is computed - return ['CHI_ref', 'MAL_ref', 'FEM_ref', 'CHI_hyp', 'MAL_hyp', 'FEM_hyp'] - - def compute_components(self, reference, hypothesis, **kwargs): - # Actually compute the value of each component - total_duration_hyp, total_duration_ref = 0.0, 0.0 - components = {'CHI_ref': 0., 'MAL_ref': 0., 'FEM_ref': 0., - 'CHI_hyp': 0., 'MAL_hyp': 0., 'FEM_hyp': 0.} - - for segment, _, speaker_name in hypothesis.itertracks(yield_label=True): - if is_CHI(speaker_name): - components['CHI_hyp'] += segment.duration - total_duration_hyp += segment.duration - elif is_MAL(speaker_name): - components['MAL_hyp'] += segment.duration - total_duration_hyp += segment.duration - elif is_FEM(speaker_name): - components['FEM_hyp'] += segment.duration - total_duration_hyp += segment.duration - - for segment, _, speaker_name in reference.itertracks(yield_label=True): - if is_CHI(speaker_name): - components['CHI_ref'] += segment.duration - total_duration_ref += segment.duration - elif is_MAL(speaker_name): - components['MAL_ref'] += segment.duration - total_duration_ref += segment.duration - elif is_FEM(speaker_name): - components['FEM_ref'] += segment.duration - total_duration_ref += segment.duration - - if total_duration_hyp != 0.0: - components['CHI_hyp'] /= total_duration_hyp - components['MAL_hyp'] /= total_duration_hyp - components['FEM_hyp'] /= total_duration_hyp - else: - components['CHI_hyp'] = 0.0 - components['MAL_hyp'] = 0.0 - components['FEM_hyp'] = 0.0 - - if total_duration_ref != 0.0: - components['CHI_ref'] /= total_duration_ref - components['MAL_ref'] /= total_duration_ref - components['FEM_ref'] /= total_duration_ref - else: - components['CHI_ref'] = 0.0 - components['MAL_ref'] = 0.0 - components['FEM_ref'] = 0.0 - - return components - - def compute_metric(self, components): - # Actually compute the metric based on the component values - return '' - - def report(self, display=False): - """Evaluation report - Parameters - ---------- - display : bool, optional - Set to True to print the report to stdout. - Returns - ------- - report : pandas.DataFrame - Dataframe with one column per metric component, one row per - evaluated item, and one final row for accumulated results. - """ - - report = [] - uris = [] - - percent = 'total' in self.metric_components() - - for uri, components in self.results_: - row = {} - if percent: - total = components['total'] - for key, value in components.items(): - if key == self.name: - row[key, '%'] = 100 * value - else: - row[key, ''] = 100 * value - if percent: - if total > 0: - row[key, '%'] = 100 * value / total - else: - row[key, '%'] = np.NaN - - report.append(row) - uris.append(uri) - - row = {} - components = self.accumulated_ - - if percent: - total = components['total'] - - for key, value in components.items(): - if key == self.name: - row[key, '%'] = 100 * value - elif key == 'total': - row[key, ''] = value - else: - row[key, ''] = value - if percent: - row[key, '%'] = 100 * value / total - row[self.name, '%'] = 100 * abs(self) - report.append(row) - uris.append('AVERAGE') - - df = pd.DataFrame(report) - - df['item'] = uris - df = df.set_index('item') - - df.columns = pd.MultiIndex.from_tuples(df.columns) - - df = df[[self.name] + self.metric_components()] - - if display: - print(df.to_string(index=True, sparsify=False, justify='right', - float_format=lambda f: '{0:.2f}'.format(f))) - return df From c879e48c59c6fb6df0aaa855b729bbd5a25be320 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Fri, 8 Feb 2019 17:43:56 +0100 Subject: [PATCH 222/299] Finish integration pyannote + minor fixes --- conf/Dockerfile | 1 - conf/bootstrap.sh | 18 ++- conf/update.sh | 2 - docs/source/install.md | 2 +- docs/source/references.md | 2 +- launcher/diartk.sh | 7 - launcher/eval.sh | 118 ++++++++++------- launcher/evalDiar.sh | 116 ---------------- launcher/evalSad.sh | 60 --------- launcher/python3/test.sh | 21 +-- launcher/test.sh | 269 ++++++++++++++++++-------------------- launcher/tocomboSad.sh | 8 +- utils/compute_metrics.py | 59 ++++++--- utils/create_ref_sys.sh | 76 ----------- utils/rttm2scp.py | 109 +++++++-------- 15 files changed, 310 insertions(+), 558 deletions(-) delete mode 100755 launcher/evalDiar.sh delete mode 100755 launcher/evalSad.sh delete mode 100755 utils/create_ref_sys.sh diff --git a/conf/Dockerfile b/conf/Dockerfile index 2200a56..d91f7d3 100755 --- a/conf/Dockerfile +++ b/conf/Dockerfile @@ -68,7 +68,6 @@ USER vagrant WORKDIR /home/vagrant RUN git clone http://github.com/srvk/OpenSAT && cp -f OpenSAT/theanorc /home/vagrant/.theanorc && \ git clone http://github.com/srvk/ib_diarization_toolkit && \ - git clone http://github.com/srvk/dscore && \ git clone https://github.com/rajatkuls/lena-clean && \ git clone https://github.com/srvk/Yunitator && \ git clone https://github.com/srvk/To-Combo-SAD && \ diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 558a78b..50c2062 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -128,12 +128,16 @@ else echo "Can't find HTK-3.4.1.tar.gz. Check that you installed the right version." fi +# Install pyannote (python 3) +source activate divime +pip install pyannote.metrics +source deactivate -# POPOULATE THE REPOSITORY SECTION +# POPULATE THE REPOSITORY SECTION cd /home/${user}/repos/ - # Get OpenSAT=noisemes and dependencies -# git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev +# Get OpenSAT=noisemes and dependencies +git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" @@ -142,8 +146,7 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install Yunitator and dependencies git clone https://github.com/srvk/Yunitator -(cd Yunitator && git checkout develop/yunified) - +(cd /home/${user}/repos/Yunitator && git checkout develop/yunified) su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" @@ -160,11 +163,6 @@ git clone https://github.com/srvk/To-Combo-SAD git clone http://github.com/srvk/ib_diarization_toolkit (cd ib_diarization_toolkit && git checkout b3e4deb) -# Install eval -git clone http://github.com/srvk/dscore -# zip to revision for release 1.1 14 Dec 2018 -(cd dscore && git checkout 31d7eca) - # Install WCE and dependencies git clone https://github.com/aclew/WCE_VM su ${user} -c "/home/${user}/anaconda/bin/pip install keras" diff --git a/conf/update.sh b/conf/update.sh index 41c9ef2..fe1506f 100644 --- a/conf/update.sh +++ b/conf/update.sh @@ -14,8 +14,6 @@ cd /home/${user}/repos # (cd "OpenSAT"; git checkout master; git pull; git checkout v2.0) (cd "ib_diarization_toolkit"; git checkout master; git pull) # (cd "ib_diarization_toolkit" ; git checkout master; git pull; git checkout v2.0) -(cd "dscore" ; git checkout master; git pull) -# (cd "dscore" ;git checkout master; git pull; git checkout v2.0) (cd "Yunitator" ;git checkout master; git pull) # (cd "Yunitator" ; git checkout master; git pull; git checkout v2.0) (cd "vcm"; git checkout master; git pull) diff --git a/docs/source/install.md b/docs/source/install.md index 7cf2d2e..3f7c215 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -58,7 +58,7 @@ DiarTK passed the test. Testing Yunitator... Yunitator passed the test. -Testing DScore... +Testing evaluation pipeline... Yunitator passed the test. diff --git a/docs/source/references.md b/docs/source/references.md index 566dbed..f441f5a 100755 --- a/docs/source/references.md +++ b/docs/source/references.md @@ -14,4 +14,4 @@ Our work builds directly on that of others. The main references for tools curren - Wang, Y., Neves, L., & Metze, F. (2016, March). Audio-based multimedia event detection using deep recurrent neural networks. In Acoustics, Speech and Signal Processing (ICASSP), 2016 IEEE International Conference on (pp. 2742-2746). IEEE. [pdf](http://www.cs.cmu.edu/~yunwang/papers/icassp16.pdf) - Young, S., Evermann, G., Gales, M., Hain, T. , Kershaw, D., Liu, X., Moore, G., Odell, J., Ollason, D., Povey,D. et al. (2002) The HTK book. Cambridge University Engineering Department. - Ziaei, A. Sangwan, A., & Hansen, J.H.L. (2016). Effective word count estimation for long duration daily naturalistic audio recordings. Speech Communication, 84, 15-23. -- Ryant, N. (2018). Diarization evaluation. https://github.com/nryant/dscore, accessed: 2018-06-17. +- Bredin, H. (2017). A toolkit for reproducible evaluation, diagnostic, and error analysis of speaker diarization systems, https://github.com/pyannote/pyannote-metrics diff --git a/launcher/diartk.sh b/launcher/diartk.sh index a1f3fb4..3bc3109 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -115,13 +115,6 @@ for fin in `ls ${audio_dir}/*.wav`; do #cat $workdir/$basename.out cp $workdir/$basename.rttm ${audio_dir}/diartk_${sys}_${basename}.rttm fi - if [ ! -s ${audio_dir}/diartk_${sys}_${basename}.rttm ]; then - # if diarization failed, still write an empty file... - touch ${audio_dir}/diartk_${sys}_${basename}.rttm - fi - - - done # Delete temporary folder diff --git a/launcher/eval.sh b/launcher/eval.sh index 6742150..262669c 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -1,61 +1,89 @@ -#!/bin/bash -# Launcher onset routine -SCRIPT=$(readlink -f $0) -BASEDIR=/home/vagrant -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -LAUNCHER=$BASEDIR/launcher -# end of launcher onset routine - -### Read in variables from user -#audio_dir=/vagrant/$1 -audio_dir=$1 -system=$2 - -### Other variables specific to this script -#none +#!/usr/bin/env bash display_usage() { - echo "Usage: eval.sh <>" - echo "where data is the folder containing the data" - echo "and system is the system you want" - echo "to evaluate. Choices are:" - echo " noisemesSad" - echo " tocomboSad" - echo " opensmileSad" - echo " lenaSad" - echo " diartk" - echo " yunitate" - echo " lenaDiar" + echo "Usage: eval.sh " + echo "where :" + echo -e "\tdata is the folder containing the data" + echo -e "\tmodel is the model that needs to be evaluated" + echo -e "\tmetrics is a list of metrics that will assess the performances" + echo -e "\toptional flags, are the flags that change the behaviour of this script :" + echo -e "\t\t --identification to assess the model as an identification task (when the labels are same in the reference and the hypothesis)" + echo -e "\t\t --visualization to generate .png files showing the alignement between the reference and the hypothesis.\n\n" + echo "Choices for the model are:" + echo -e "\t - noisemesSad" + echo -e "\t - tocomboSad" + echo -e "\t - opensmileSad" + echo -e "\t - diartk" + echo -e "\t - yunitate" echo "If evaluating diartk, please give which flavour" echo "of SAD you used to produce the transcription" echo "you want to evaluate" + echo -e "\nChoices for the metrics are:" + echo -e "\t- for the speech activity detection task :" + echo -e "\t\t accuracy, deter, precision, recall" + echo -e "\t- for the diarization task :" + echo -e "\t\t completeness, coverage, diaer, homogeneity, purity" + echo -e "\t- for the identification task :" + echo -e "\t\t ider, precision, recall" exit 1 } -if [ $# -eq 0 ] ; then - display_usage -fi +### Read in variables from user +DATA=$1 +MODEL=$2 +shift; shift; +if [[ "$MODEL" == "diartk" ]]; then + MODEL=${MODEL}_$1 + shift; +fi; + +# Read metrics +METRICS=() +while [ ! -z $1 ] && [ ! ${1:0:2} == "--" ]; do + METRICS+=("$1") + shift ; +done -KEEPTEMP="" -if [ $BASH_ARGV == "--keep-temp" ]; then - KEEPTEMP="--keep-temp" -fi +# Read optional flags that are used to run +# the script in a "non-classical" way. +FLAGS=() +while true ; do + case "$1" in + --identification) + FLAGS+=("--identification") + shift ;; + --visualization) + FLAGS+=("--visualization") + shift ;; + *) + if [[ ! $1 == "" ]]; then + echo "Flag $1 not recognized." + exit 1 + fi + break;; + esac +done -### SCRIPT STARTS -case $system in -"tocomboSad"|"opensmileSad"|"noisemesSad"|"lenaSad") - sh $LAUNCHER/evalSAD.sh ${audio_dir} $system $KEEPTEMP - ;; -"yunitate"|"lenaDiar") - sh $LAUNCHER/evalDiar.sh ${audio_dir} $system $KEEPTEMP +echo -e "\nEvaluating ${MODEL} on ${DATA} with respect to : ${METRICS[*]}" +echo -e "${FLAGS[*]}" +### Launcher onset routine +SCRIPT=$(readlink -f $0) +BASEDIR=/home/vagrant +REPOS=$BASEDIR/repos +UTILS=$BASEDIR/utils +LAUNCHER=$BASEDIR/launcher +############################### + +#### SCRIPT STARTS +source activate divime +case $MODEL in +"tocomboSad"|"opensmileSad"|"noisemesSad") + python $UTILS/compute_metrics.py --reference $DATA --prefix $MODEL --task detection --metrics ${METRICS[*]} ${FLAGS[*]} ;; -"diartk") - sad=$3 - sh $LAUNCHER/evalDiar.sh ${audio_dir} $system $sad $KEEPTEMP +"yunitator"|"lena"|"diartk_noisemesSad"|"diartk_tocomboSad"|"diartk_opensmileSad"|"diartk_goldSad") + python $UTILS/compute_metrics.py --reference $DATA --prefix $MODEL --task diarization --metrics ${METRICS[*]} ${FLAGS[*]} ;; *) display_usage ;; - esac diff --git a/launcher/evalDiar.sh b/launcher/evalDiar.sh deleted file mode 100755 index 676ad65..0000000 --- a/launcher/evalDiar.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash - -# Launcher onset routine -SCRIPT=$(readlink -f $0) -BASEDIR=/home/vagrant -REPOS=$BASEDIR/repos -UTILS=$BASEDIR/utils -DSCOREDIR=$REPOS/dscore -# end of launcher onset routine - - -display_usage() { - echo "Usage: evalDiar.sh " - echo "where dirname is the name of the folder" - echo "containing the wav files, and system" - echo "specifies which system you want to evaluate" - echo "System choices are :" - echo " - noisemesSad" - echo " - opensmileSad" - echo " - tocomboSad" - echo " - diartk_noisemesSad" - echo " - diartk_opensmileSad" - echo " - diartk_tocomboSad" - echo " - diartk_rttm" - echo " - yunitate" - echo " - lenaSad" - exit 1; - -} - -### Read in variables from user -audio_dir=/vagrant/$1 -model=$2 -echo $2 -if ! [[ $model =~ ^(noisemesSad|opensmileSad|tocomboSad|diartk_noisemesSad|diartk_opensmileSad|diartk_rttm|yunitate|lenaSad)$ ]]; then - display_usage -fi - -KEEPTEMP=false -if [ $BASH_ARGV == "--keep-temp" ]; then - KEEPTEMP=true -fi - - -# Set CWD to path of Dscore -cd $DSCOREDIR -if [[ $model =~ ^(diartk|yuniseg) ]]; then - trs_format=$3 - case $trs_format in - "noisemesSad") - sys_name=$model"_noisemesSad" - ;; - "tocomboSad") - sys_name=$model"_tocomboSad" - ;; - "opensmileSad") - sys_name=$model"_opensmileSad" - ;; - "textgrid") - sys_name=$model"_goldSad" - for wav in `ls ${audio_dir}/*.wav`; do - base=$(basename $wav .wav) - python /home/vagrant/utils/textgrid2rttm.py ${audio_dir}/${basename}.TextGrid ${audio_dir}/${basename}.rttm - done - ;; - "eaf") - sys_name=$model"_goldSad" - for wav in `ls ${audio_dir}/*.wav`; do - base=$(basename $wav .wav) - python /home/vagrant/utils/elan2rttm.py ${audio_dir}/${basename}.eaf ${audio_dir}/${basename}.rttm - done - ;; - "rttm") - sys_name=$model"_goldSad" - ;; - *) - echo "ERROR: You're trying to evaluate diartk, but the speech activity detection you specified is not recognized:" - echo " noisemesSad" - echo " textgrid" - echo " eaf" - echo " rttm" - echo "Now exiting..." - exit 1 - ;; - esac -elif [ "$2" == "yunitate" ]; then - sys_name="yunitator" -elif [ "$2" == "lenaSad" ]; then - sys_name="lena" -fi - -echo $UTILS/create_ref_sys.sh $1 $sys_name -$UTILS/create_ref_sys.sh $1 $sys_name - -echo "evaluating" -python score_batch.py ${audio_dir}/${sys_name}_eval.df ${audio_dir}/temp_ref ${audio_dir}/temp_sys - -# Check if some gold files are empty. If so, add a line in the eval dataframe -for fin in `ls ${audio_dir}/temp_ref/*.rttm`; do - base=$(basename $fin .rttm) - if [ ! -s ${audio_dir}/temp_ref/$base.rttm ]; then - if [ ! -s ${audio_dir}/temp_sys/$base.rttm ]; then - echo $base" 0 NA NA NA NA NA NA NA NA" >> ${audio_dir}/${sys_name}_eval.df - else - echo $base" 100 NA NA NA NA NA NA NA NA" >> ${audio_dir}/${sys_name}_eval.df - fi - elif [ ! -s ${audio_dir}/temp_sys/$base.rttm ] && [ -s ${audio_dir}/temp_ref/$base.rttm ]; then - echo $base" 100 NA NA NA NA NA NA NA NA" >> ${audio_dir}/${sys_name}_eval.df - fi -done - -echo "done evaluating, check $1/${sys_name}_eval.df for the results" -# remove temps -if ! $KEEPTEMP; then - rm -rf ${audio_dir}/temp_ref ${audio_dir}/temp_sys -fi diff --git a/launcher/evalSad.sh b/launcher/evalSad.sh deleted file mode 100755 index 3a2a2d2..0000000 --- a/launcher/evalSad.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -# Since the script is built to be launched outside of the vm, source -# the .bashrc which is not necessarily sourced! -source ~/.bashrc - -# Absolute path to this script. /home/user/bin/foo.sh -SCRIPT=$(readlink -f $0) -# Absolute path this script is in. /home/user/bin -BASEDIR=/home/vagrant -UTILS=$BASEDIR/utils -REPOS=$BASEDIR/repos -# Path to scoring tool NOTE: NOT dscore! -DSCOREDIR=$REPOS/dscore - - -# data directory -audio_dir=$1 -filename=$(basename "${audio_dir}") -dirname=$(dirname "${audio_dir}") -extension="${filename##*.}" -basename="${filename%.*}" - -# check system to evaluate - either LDC, OpenSAT or "MySystem" -sys_name=$2 - -if ! [[ $sys_name =~ ^(noisemesSad|tocomboSad|opensmileSad|lenaSad)$ ]]; then - echo "Please Specify the System you wish to evaluate." - echo "Choose between noisemesSad, tocomboSad, lenaSad and opensmileSad." - exit -fi - -KEEPTEMP=false -if [ $BASH_ARGV == "--keep-temp" ]; then - KEEPTEMP=true -fi - -# Set CWD to path of scoring tool -cd $DSCOREDIR - -# pass vagrant-relative pathname to create_ref_sys -$UTILS/create_ref_sys.sh ${audio_dir} $sys_name true - -# resolve to absolute path for rest of this script -audio_dir=/vagrant/${audio_dir} - -OUTPUT_DF=${audio_dir}/${sys_name}_eval.df -REF=${audio_dir}/temp_ref -SYS=${audio_dir}/temp_sys -echo "evaluating" - -python score_batch.py $OUTPUT_DF $REF $SYS - -# small detail: remove the commas from the output -sed -i "s/,//g" $OUTPUT_DF -echo "done evaluating, check $1/${sys_name}_eval.df for the results" - -# remove temps -if ! $KEEPTEMP; then - rm -rf $REF $SYS -fi diff --git a/launcher/python3/test.sh b/launcher/python3/test.sh index 4608f96..f149624 100644 --- a/launcher/python3/test.sh +++ b/launcher/python3/test.sh @@ -26,7 +26,6 @@ OPENSMILEDIR=$REPOS/openSMILE-2.1.0/ TOCOMBOSAD=$REPOS/To-Combo-SAD DIARTKDIR=$REPOS/ib_diarization_toolkit #TALNETDIR=$REPOS/TALNet -DSCOREDIR=$REPOS/dscore YUNITATORDIR=$REPOS/Yunitator FAILURES=false @@ -167,23 +166,7 @@ else fi -# Test DSCORE -echo "Testing Dscore..." -cd $DSCOREDIR -git checkout develop/python3 -TESTDIR=$WORKDIR/dscore-test -rm -rf $TESTDIR; mkdir -p $TESTDIR -cp -r test_ref test_sys $TESTDIR -rm -f test.df -source activate divime -python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} -source deactivate -if [ -s $TESTDIR/test.df ]; then - echo "DScore passed the test." -else - echo " DScore failed the test - output does not match expected" - FAILURES=true -fi + git checkout master @@ -199,7 +182,5 @@ fi # results echo "RESULTS:" for f in /vagrant/$DATADIR/*-test/*.rttm; do $UTILS/sum-rttm.sh $f; done -echo "DSCORE:" -cat /vagrant/data/VanDam-Daylong/BN32/dscore-test/test.df echo "EVAL_SAD:" cat $TESTDIR/opensmileSad_eval.df diff --git a/launcher/test.sh b/launcher/test.sh index 858a349..9fba10a 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -26,7 +26,6 @@ OPENSMILEDIR=$REPOS/opensmile-2.3.0/ TOCOMBOSAD=$REPOS/To-Combo-SAD DIARTKDIR=$REPOS/ib_diarization_toolkit #TALNETDIR=$REPOS/TALNet -DSCOREDIR=$REPOS/dscore YUNITATORDIR=$REPOS/Yunitator VCMDIR=$REPOS/vcm @@ -86,145 +85,129 @@ cp $WORKDIR/$BASETEST.rttm $TESTDIR -# now test Noisemes -echo "Testing noisemes..." - -$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} - -if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then - echo "Noisemes passed the test." -else - FAILURES=true - echo " Noisemes failed - no RTTM output" -fi - - -# now test OPENSMILEDIR -echo "Testing OpenSmile SAD..." - -$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} - -if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then - echo "OpenSmile SAD passed the test." -else - FAILURES=true - echo " OpenSmile SAD failed - no RTTM output" -fi - -# now test TOCOMBOSAD -echo "Testing ToCombo SAD..." - -$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} - -if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then - echo "TOCOMBO SAD passed the test." -else - FAILURES=true - echo " TOCOMBO SAD failed - no output RTTM" -fi - - -# test DIARTK -echo "Testing DIARTK..." - -cp $TEST_RTTM $TESTDIR - -# run like the wind -$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 -if grep -q "command not found" $TESTDIR/diartk-test.log; then - echo " Diartk failed - dependencies (probably HTK)" - FAILURES=true -else - if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then - echo "DiarTK passed the test." - else - FAILURES=true - echo " Diartk failed - no output RTTM" - fi -fi -#rm $TESTDIR/$BASETEST.rttm - -# test Yunitator -echo "Testing Yunitator..." - -# let 'er rip -$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then - echo "Yunitator passed the test." -else - FAILURES=true - echo " Yunitator failed - no output RTTM" -fi - - -# Test DSCORE -echo "Testing Dscore..." -cd $DSCOREDIR - -cp -r test_ref test_sys $TESTDIR -rm -f test.df -python score_batch.py $TESTDIR/test.df $TESTDIR/test_ref $TESTDIR/test_sys > $TESTDIR/dscore-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/test.df ]; then - echo "DScore passed the test." -else - echo " DScore failed the test - output does not match expected" - FAILURES=true -fi - - -# Testing VCM -echo "Testing VCM..." - -$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then - echo "VCM passed the test." -else - FAILURES=true - echo " VCM failed - no output RTTM" -fi - -# Testing WCE -echo "Testing WCE..." -WCEDIR=$REPOS/WCE_VM/ -cd $WCEDIR - -./run_WCEtrain.sh /usr/local/MATLAB/MATLAB_Runtime/v93/ demofiles.txt democounts.txt models/mymodel.mat configs/config_default.txt > $TESTDIR/wce-test.log || { echo " WCE failed - dependencies"; FAILURES=true;} -WCE_OUTPUT=$(awk '/adaptation completed/{ print NR; exit }' $TESTDIR/wce-test.log) -if [ $WCE_OUTPUT > 0 ]; then - echo "WCE passed the test" -else - FAILURES=true - echo "WCE failed - no successful adaptation" -fi - -# test finished -if $FAILURES; then - echo "Some tools did not pass the test, but you can still use others" -else - echo "Congratulations, everything is OK!" -fi - -# results -echo "######################################################################################" -echo "To wrap up, we will print out the results of the analyses that we ran during the test." -echo "Compare the following results, corresponding to your system, against the reference results printed out below." -echo "If the numbers are similar, then your system is working similarly to the original one." -echo "If you see bigger changes, then please paste this output onto an issue on https://github.com/srvk/DiViMe/issues/." -echo "RESULTS:" -for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done -echo "****** REFERENCE RESULTS BEGINS ******." -echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm" -echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" -echo "LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm" -echo "LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm" -echo "LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm" -echo "LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm" -echo "LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" -echo "****** REFERENCE RESULTS ENDS ******." - -echo "DSCORE:" -cat /vagrant/data/VanDam-Daylong/BN32/test/test.df -echo "****** REFERENCE DSCORE BEGINS ******." -echo "DER B3Precision B3Recall B3F1 TauRefSys TauSysRef CE MI NMI" -echo "Phil_Crane 43.38 0.975590490013 0.672338020576 0.796061934402 0.599223772838 0.963770340456 0.103871357212 1.67823036445 0.793181875273" -echo "****** REFERENCE DSCORE ENDS ******." +## now test Noisemes +#echo "Testing noisemes..." +# +#$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} +# +#if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then +# echo "Noisemes passed the test." +#else +# FAILURES=true +# echo " Noisemes failed - no RTTM output" +#fi +# +# +## now test OPENSMILEDIR +#echo "Testing OpenSmile SAD..." +# +#$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} +# +#if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then +# echo "OpenSmile SAD passed the test." +#else +# FAILURES=true +# echo " OpenSmile SAD failed - no RTTM output" +#fi +# +## now test TOCOMBOSAD +#echo "Testing ToCombo SAD..." +# +#$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} +# +#if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then +# echo "TOCOMBO SAD passed the test." +#else +# FAILURES=true +# echo " TOCOMBO SAD failed - no output RTTM" +#fi +# +# +## test DIARTK +#echo "Testing DIARTK..." +# +#cp $TEST_RTTM $TESTDIR +# +## run like the wind +#$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 +#if grep -q "command not found" $TESTDIR/diartk-test.log; then +# echo " Diartk failed - dependencies (probably HTK)" +# FAILURES=true +#else +# if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then +# echo "DiarTK passed the test." +# else +# FAILURES=true +# echo " Diartk failed - no output RTTM" +# fi +#fi +##rm $TESTDIR/$BASETEST.rttm +# +## test Yunitator +#echo "Testing Yunitator..." +# +## let 'er rip +#$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +#if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then +# echo "Yunitator passed the test." +#else +# FAILURES=true +# echo " Yunitator failed - no output RTTM" +#fi + +## Testing VCM +#echo "Testing VCM..." +# +#$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} +#if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then +# echo "VCM passed the test." +#else +# FAILURES=true +# echo " VCM failed - no output RTTM" +#fi +# +## Testing WCE +#echo "Testing WCE..." +#WCEDIR=$REPOS/WCE_VM/ +#cd $WCEDIR +# +#./run_WCEtrain.sh /usr/local/MATLAB/MATLAB_Runtime/v93/ demofiles.txt democounts.txt models/mymodel.mat configs/config_default.txt > $TESTDIR/wce-test.log || { echo " WCE failed - dependencies"; FAILURES=true;} +#WCE_OUTPUT=$(awk '/adaptation completed/{ print NR; exit }' $TESTDIR/wce-test.log) +#if [ $WCE_OUTPUT > 0 ]; then +# echo "WCE passed the test" +#else +# FAILURES=true +# echo "WCE failed - no successful adaptation" +#fi +# +## test finished +#if $FAILURES; then +# echo "Some tools did not pass the test, but you can still use others" +#else +# echo "Congratulations, everything is OK!" +#fi +# +## results +#echo "######################################################################################" +#echo "To wrap up, we will print out the results of the analyses that we ran during the test." +#echo "Compare the following results, corresponding to your system, against the reference results printed out below." +#echo "If the numbers are similar, then your system is working similarly to the original one." +#echo "If you see bigger changes, then please paste this output onto an issue on https://github.com/srvk/DiViMe/issues/." +#echo "RESULTS:" +#for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done +#echo "****** REFERENCE RESULTS BEGINS ******." +#echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm" +#echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" +#echo "LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm" +#echo "LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm" +#echo "LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm" +#echo "LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm" +#echo "LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" +#echo "****** REFERENCE RESULTS ENDS ******." +# +#echo "DSCORE:" +#cat /vagrant/data/VanDam-Daylong/BN32/test/test.df +#echo "****** REFERENCE DSCORE BEGINS ******." +#echo "DER B3Precision B3Recall B3F1 TauRefSys TauSysRef CE MI NMI" +#echo "Phil_Crane 43.38 0.975590490013 0.672338020576 0.796061934402 0.599223772838 0.963770340456 0.103871357212 1.67823036445 0.793181875273" +#echo "****** REFERENCE DSCORE ENDS ******." diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index f54fa17..4164803 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -14,7 +14,7 @@ trs_format=$2 ### Other variables specific to this script # create temp dir -workdir=${audio_dir}/temp/tocomboSad +workdir=${audio_dir}/temp mkdir -p $workdir TOCOMBOSADDIR=$REPOS/To-Combo-SAD MCR=/usr/local/MATLAB/MATLAB_Runtime/v93 @@ -68,16 +68,14 @@ export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64 ./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt -# Retrieve the outputs from the temp folder -mv $workdir/*ToCombo.txt ${audio_dir} - #convert to rttms for f in ${audio_dir}/*.ToCombo.txt; do bn=`basename $f .wav.ToCombo.txt` python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > ${audio_dir}/tocomboSad_$bn.rttm done -# Delete temporary folder +# move the txt files and delete temporary folder +mv ${audio_dir}/*ToCombo.txt $workdir if ! $KEEPTEMP; then rm -rf $workdir fi diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py index f1edef6..a4a737d 100644 --- a/utils/compute_metrics.py +++ b/utils/compute_metrics.py @@ -43,7 +43,7 @@ def find_1mn_highest_volubility(annotation): best_start = get_best_start(beginnings, durations, tot_duration) return best_start, best_start + 60 -def rttm_to_annotation(input_rttm): +def rttm_to_annotation(input_rttm, collapse_to_speech=False): """ Given a path to a rttm file, create the corresponding Annotation objects containing the triplets (t_beg, t_end, activity) @@ -61,17 +61,25 @@ def rttm_to_annotation(input_rttm): if os.path.isfile(input_rttm): with open(input_rttm) as fn: for line in fn: - row = line.split('\t') + row = line.replace('\t', ' ').split(' ') t_beg, t_dur, spkr = float(row[3]), float(row[4]), row[7] - anno[Segment(t_beg, t_beg+t_dur)] = spkr + if collapse_to_speech: + anno[Segment(t_beg, t_beg+t_dur)] = "speech" + else: + anno[Segment(t_beg, t_beg + t_dur)] = spkr return anno def run_metrics(references_f, hypothesis_f, metrics, visualization=False): - if len(references_f) != len(hypothesis_f) : + if len(references_f) != len(hypothesis_f): raise ValueError("The number of reference files and hypothesis files must match ! (%d != %d)" % (len(references_f), len(hypothesis_f))) + if visualization: + visualization_dir = os.path.join(os.path.dirname(hypothesis_f[0]), "visualization") + if not os.path.exists(visualization_dir): + os.makedirs(visualization_dir) + for ref_f, hyp_f in zip(references_f, hypothesis_f): ref, hyp = rttm_to_annotation(ref_f), rttm_to_annotation(hyp_f) basename = os.path.basename(ref_f) @@ -92,17 +100,20 @@ def run_metrics(references_f, hypothesis_f, metrics, visualization=False): plt.rcParams['figure.figsize'] = (notebook.width, 10) notebook.crop = Segment(start, end) - # Plot reference - plt.subplot(211) - notebook.plot_annotation(ref, legend=True, time=True) - plt.gca().text(0.6, 0.15, 'reference', fontsize=16) - - # Plot hypothesis - plt.subplot(212) - notebook.plot_annotation(hyp, legend=True, time=True) - plt.gca().text(0.6, 0.15, 'hypothesis', fontsize=16) - plt.savefig(hyp_f.replace('.rttm', '.png')) - plt.close() + if visualization: + # Plot reference + plt.subplot(211) + plt.title(os.path.basename(hyp_f).replace('.rttm', ''), y=1.15, fontdict={'fontsize':18}) + notebook.plot_annotation(ref, legend=True, time=False) + plt.gca().text(11, 0.4, 'reference', fontsize=26) + + # Plot hypothesis + plt.subplot(212) + notebook.plot_annotation(hyp, legend=True, time=True) + plt.gca().text(11, 0.4, 'hypothesis', fontsize=26) + + plt.savefig(os.path.join(visualization_dir, os.path.basename(hyp_f).replace('.rttm', '.png'))) + plt.close() return metrics @@ -125,8 +136,11 @@ def get_couple_files(ref_path, hyp_path=None, prefix=None): else: raise ValueError("%s doesn't exist" % hyp_path) + if len(ref_files) == 0 or len(hyp_files) == 0: + raise FileNotFoundError("No reference, or no hypothesis found were found.") return sorted(ref_files), sorted(hyp_files) + def main(): parser = argparse.ArgumentParser(description="Scripts that computes metrics between reference and hypothesis files." "Inputs can be both path to folders or single file.") @@ -149,9 +163,13 @@ def main(): "precision", "recall", "deter", "ider","idea"], help="Metrics that need to be run.") - parser.add_argument('-v', '--visualization', action='store_true') + parser.add_argument('--visualization', action='store_true') + parser.add_argument('--identification', action='store_true') args = parser.parse_args() + if args.identification: + args.task = "identification" + # Let's create the metrics metrics = {} for m in args.metrics: @@ -166,6 +184,8 @@ def main(): metrics[m] = diarization.DiarizationHomogeneity(parallel=True) elif m == "purity": metrics[m] = diarization.DiarizationPurity(parallel=True) + else: + print("Filtering out %s, which is not available for the %s task." % (m, args.task)) elif args.task == "detection": if m == "accuracy": metrics[m] = detection.DetectionAccuracy(parallel=True) @@ -175,6 +195,8 @@ def main(): metrics[m] = detection.DetectionPrecision(parallel=True) elif m == "deter": metrics[m] = detection.DetectionErrorRate(parallel=True) + else: + print("Filtering out %s, which is not available for the %s task." % (m, args.task)) elif args.task == "identification": if m == "ider": metrics[m] = identification.IdentificationErrorRate(parallel=True) @@ -182,6 +204,8 @@ def main(): metrics[m] = identification.IdentificationPrecision(parallel=True) elif m == "recall": metrics[m] = identification.IdentificationRecall(parallel=True) + else: + print("Filtering out %s, which is not available for the %s task." % (m, args.task)) # Get files and run the metrics references_f, hypothesis_f = get_couple_files(args.reference, args.hypothesis, args.prefix) @@ -190,7 +214,8 @@ def main(): # Display a report for each metrics for name, m in metrics.items(): print("%s report" % name) - m.report(display=True) + rep = m.report(display=True) + rep.to_csv(os.path.join("/vagrant", args.reference, name+'_'+args.prefix+"_report.csv")) if __name__ == '__main__': diff --git a/utils/create_ref_sys.sh b/utils/create_ref_sys.sh deleted file mode 100755 index b5c53d0..0000000 --- a/utils/create_ref_sys.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash - -audio_dir=/vagrant/$1 -model_prefix=$2 -create_lab=$3 - -base_directory=$(echo "${audio_dir}" | awk -F "/" '{print $2}') - -if [ "$base_directory" != "vagrant" ]; then - audio_dir=$1 -fi - -display_usage() { - echo "Given a folder, and a model prefix, creates a folder that contains the reference transcriptions" - echo "and another folder containing the predicted transcriptions." - echo "usage: $0 [audio_dir] [model_prefix] [create_lab]" - echo " audio_dir The directory that contains the audio files and the transcription." - echo " model_prefix The model prefix (beginning of the files generated by the model)." - echo " create_lab (Optional, true or false) Indicates whether to create .lab files in the reference folder." - exit 1 - } - -if ! [[ $# =~ ^(2|3)$ ]]; then - display_usage -fi - -if [ -z "$3" ]; then - create_lab=false -fi - -if ! [[ $model_prefix =~ ^(noisemesSad|tocomboSad|opensmileSad|lenaSad|lena|yunitator|\ -diartk_ldcSad|diartk_noisemesSad|diartk_tocomboSad|diartk_opensmileSad|diartk_goldSad|\ -yuniseg_ldcSad|yuniseg_noisemesSad|yuniseg_tocomboSad|yuniseg_opensmileSad|yuniseg_goldSad)$ ]]; then - echo "You're trying to create folders containing the reference transcriptions, and the predicted ones." - echo "However, you specified a wrong tool name." - echo "Please, check the name of the SAD/diarization tool." - exit 1; -fi - - -# Create temp_ref folder -mkdir -p ${audio_dir}/temp_ref -for wav in `ls ${audio_dir}/*.wav`; do - base=$(basename $wav .wav) - cp ${audio_dir}/${base}.rttm ${audio_dir}/temp_ref/${base}.rttm - # Sort rttm by onset - sort --key 4 --numeric-sort ${audio_dir}/${base}.rttm -o ${audio_dir}/temp_ref/${base}.rttm - # Change tabulations to white-spaces - sed -i 's/\t/ /g' ${audio_dir}/temp_ref/${base}.rttm - # Replace two or more occurrences of whitespace by just one - sed -i 's/ \+/ /g' ${audio_dir}/temp_ref/${base}.rttm - if [ $create_lab == true ]; then - echo "creating: " ${audio_dir}/temp_ref/${base}.lab - awk '{print $4" "($4+$5)" speech"}' ${audio_dir}/temp_ref/${base}.rttm > ${audio_dir}/temp_ref/${base}.lab - fi -done - -# Create temp_sys folder and copy all of the sys rttm inside of it -# Remove the model_prefix of it -mkdir -p ${audio_dir}/temp_sys -for rttm in `ls ${audio_dir}/${model_prefix}_*.rttm`; do - base=$(basename $rttm .rttm) - out=`echo $base | sed "s/${model_prefix}\_//g"` - cp $rttm ${audio_dir}/temp_sys/${out}.rttm - if [ $create_lab == true ]; then - echo "creating: " ${audio_dir}/temp_sys/${out}.lab - awk '{print $4" "($4+$5)" speech"}' $rttm > ${audio_dir}/temp_sys/${out}.lab - fi -done - -# check that temp_sys is not empty, otherwise exit and remove it. -if [ -z "$(ls -A ${audio_dir}/temp_sys)" ]; then - echo "Didn't find any transcription from the model prefix you specified. Please get the ${model_prefix}_my_file.rttm before" - rm -rf ${audio_dir}/temp_sys ${audio_dir}/temp_ref - exit -fi diff --git a/utils/rttm2scp.py b/utils/rttm2scp.py index f7b0008..cf8fba8 100755 --- a/utils/rttm2scp.py +++ b/utils/rttm2scp.py @@ -9,75 +9,76 @@ # and to sort the intervals by onsets. import os -import sys import argparse -from intervaltree import IntervalTree, Interval -from operator import itemgetter +import errno def read_rttm(input_path): """Read a RTTM file indicating gold diarization""" - with open(input_path, 'r') as fin: - # RTTM format is - # SPEAKER fname 1 onset duration spkr - rttm = fin.readlines() - #sad = IntervalTree() - all_intervals = [] - fname = "" - for line in rttm: - row = line.strip('\n').split() - fname, onset, dur = row[1], row[3], row[4] - if float(dur) == 0: - # Remove empty intervals - continue - elif float(dur) < 0: - print("{} shows an interval with negative duration." - " Please inspect file, this shouldn't happen".format( - line)) + if os.path.isfile(input_path): + with open(input_path, 'r') as fin: + # RTTM format is + # SPEAKER fname 1 onset duration spkr + rttm = fin.readlines() + #sad = IntervalTree() + all_intervals = [] + fname = "" + for line in rttm: + row = line.strip('\n').split() + fname, onset, dur = row[1], row[3], row[4] + if float(dur) == 0: + # Remove empty intervals + continue + elif float(dur) < 0: + print("{} shows an interval with negative duration." + " Please inspect file, this shouldn't happen".format( + line)) + continue + + # add interval to list + all_intervals.append((float(onset), float(onset) + float(dur))) + + # sort intervals by their onset + all_intervals.sort() + + # look at each interval, add them in growing order of onset, + # trim the beginning if it overlaps with previous interval, + # and completely delete if it is contained by the previous interval. + sad = [] + prev_on = 0 + prev_off = 0 + for onset, offset in all_intervals: + if len(sad) == 0: + # don't check anything for first interval + sad.append((onset, offset)) + prev_on = onset + prev_off = offset continue - # add interval to list - all_intervals.append((float(onset), float(onset) + float(dur))) + if onset < prev_off: + if offset <= prev_off: + # interval is completely contained in the previous one + continue + onset = prev_off - # sort intervals by their onset - all_intervals.sort() - - # look at each interval, add them in growing order of onset, - # trim the beginning if it overlaps with previous interval, - # and completely delete if it is contained by the previous interval. - sad = [] - prev_on = 0 - prev_off = 0 - for onset, offset in all_intervals: - if len(sad) == 0: - # don't check anything for first interval sad.append((onset, offset)) prev_on = onset prev_off = offset - continue - - if onset < prev_off: - if offset <= prev_off: - # interval is completely contained in the previous one - continue - onset = prev_off - - sad.append((onset, offset)) - prev_on = onset - prev_off = offset - return sad, fname + return sad, fname + else: + raise IOError(errno.ENOENT, os.strerror(errno.ENOENT), input_path) def write_scp(out_intervals, fname, output): """Write output in SCP format""" + if len(out_intervals) != 0: + with open(output, 'w') as fout: + fout.write(u'') # write empty string in case out_intervals is empty + for onset, offset in out_intervals: + fout.write(u'{fname}_{on}_{off}={fname}.fea[{on},{off}]\n'.format( + fname=fname, + on=int(onset*100), + off=int(offset*100))) - with open(output, 'w') as fout: - fout.write(u'') # write empty string in case out_intervals is empty - for onset, offset in out_intervals: - fout.write(u'{fname}_{on}_{off}={fname}.fea[{on},{off}]\n'.format( - fname=fname, - on=int(onset*100), - off=int(offset*100))) - def main(): """Take diarization in RTTM format as input, and write """ """SAD in scp format, with ordered intervals, as output.""" From da72f7b4b632f315870369f59733979f4eaa7ae1 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Fri, 8 Feb 2019 19:09:29 +0100 Subject: [PATCH 223/299] Update doc + add image --- docs/images/example_visu.png | Bin 0 -> 33462 bytes docs/source/install.md | 4 +- docs/source/usage.md | 78 +++++++++++++++++++++++++++++++++++ utils/compute_metrics.py | 17 +++----- 4 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 docs/images/example_visu.png diff --git a/docs/images/example_visu.png b/docs/images/example_visu.png new file mode 100644 index 0000000000000000000000000000000000000000..5a7c1328f876d2a0a605e26d74707629b11f1cc5 GIT binary patch literal 33462 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 Date: Mon, 11 Feb 2019 10:58:48 +0100 Subject: [PATCH 224/299] Add a test for the evaluation pipeline --- conf/bootstrap.sh | 12 +-- launcher/eval.sh | 1 + launcher/test.sh | 266 ++++++++++++++++++++++++---------------------- 3 files changed, 147 insertions(+), 132 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 50c2062..f498296 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -128,11 +128,6 @@ else echo "Can't find HTK-3.4.1.tar.gz. Check that you installed the right version." fi -# Install pyannote (python 3) -source activate divime -pip install pyannote.metrics -source deactivate - # POPULATE THE REPOSITORY SECTION cd /home/${user}/repos/ @@ -172,10 +167,15 @@ su ${user} -c "/home/${user}/anaconda/bin/pip install -U tensorflow" git clone https://github.com/bootphon/phonemizer cd phonemizer git checkout 332b8dd - python setup.py build python setup.py install + +# Install pyannote (python 3) +source activate divime +pip install pyannote.metrics +conda deactivate + #install launcher and utils # cd /home/${user}/ # git clone https://github.com/aclew/launcher.git diff --git a/launcher/eval.sh b/launcher/eval.sh index 262669c..b89f387 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -87,3 +87,4 @@ case $MODEL in display_usage ;; esac +conda deactivate diff --git a/launcher/test.sh b/launcher/test.sh index 9fba10a..71c0255 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -26,6 +26,7 @@ OPENSMILEDIR=$REPOS/opensmile-2.3.0/ TOCOMBOSAD=$REPOS/To-Combo-SAD DIARTKDIR=$REPOS/ib_diarization_toolkit #TALNETDIR=$REPOS/TALNet +DSCOREDIR=$REPOS/dscore YUNITATORDIR=$REPOS/Yunitator VCMDIR=$REPOS/vcm @@ -85,129 +86,142 @@ cp $WORKDIR/$BASETEST.rttm $TESTDIR -## now test Noisemes -#echo "Testing noisemes..." -# -#$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} -# -#if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then -# echo "Noisemes passed the test." -#else -# FAILURES=true -# echo " Noisemes failed - no RTTM output" -#fi -# -# -## now test OPENSMILEDIR -#echo "Testing OpenSmile SAD..." -# -#$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} -# -#if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then -# echo "OpenSmile SAD passed the test." -#else -# FAILURES=true -# echo " OpenSmile SAD failed - no RTTM output" -#fi -# -## now test TOCOMBOSAD -#echo "Testing ToCombo SAD..." -# -#$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} -# -#if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then -# echo "TOCOMBO SAD passed the test." -#else -# FAILURES=true -# echo " TOCOMBO SAD failed - no output RTTM" -#fi -# -# -## test DIARTK -#echo "Testing DIARTK..." -# -#cp $TEST_RTTM $TESTDIR -# -## run like the wind -#$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 -#if grep -q "command not found" $TESTDIR/diartk-test.log; then -# echo " Diartk failed - dependencies (probably HTK)" -# FAILURES=true -#else -# if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then -# echo "DiarTK passed the test." -# else -# FAILURES=true -# echo " Diartk failed - no output RTTM" -# fi -#fi -##rm $TESTDIR/$BASETEST.rttm -# -## test Yunitator -#echo "Testing Yunitator..." -# -## let 'er rip -#$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -#if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then -# echo "Yunitator passed the test." -#else -# FAILURES=true -# echo " Yunitator failed - no output RTTM" -#fi - -## Testing VCM -#echo "Testing VCM..." -# -#$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} -#if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then -# echo "VCM passed the test." -#else -# FAILURES=true -# echo " VCM failed - no output RTTM" -#fi -# -## Testing WCE -#echo "Testing WCE..." -#WCEDIR=$REPOS/WCE_VM/ -#cd $WCEDIR -# -#./run_WCEtrain.sh /usr/local/MATLAB/MATLAB_Runtime/v93/ demofiles.txt democounts.txt models/mymodel.mat configs/config_default.txt > $TESTDIR/wce-test.log || { echo " WCE failed - dependencies"; FAILURES=true;} -#WCE_OUTPUT=$(awk '/adaptation completed/{ print NR; exit }' $TESTDIR/wce-test.log) -#if [ $WCE_OUTPUT > 0 ]; then -# echo "WCE passed the test" -#else -# FAILURES=true -# echo "WCE failed - no successful adaptation" -#fi -# -## test finished -#if $FAILURES; then -# echo "Some tools did not pass the test, but you can still use others" -#else -# echo "Congratulations, everything is OK!" -#fi -# -## results -#echo "######################################################################################" -#echo "To wrap up, we will print out the results of the analyses that we ran during the test." -#echo "Compare the following results, corresponding to your system, against the reference results printed out below." -#echo "If the numbers are similar, then your system is working similarly to the original one." -#echo "If you see bigger changes, then please paste this output onto an issue on https://github.com/srvk/DiViMe/issues/." -#echo "RESULTS:" -#for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done -#echo "****** REFERENCE RESULTS BEGINS ******." -#echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm" -#echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" -#echo "LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm" -#echo "LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm" -#echo "LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm" -#echo "LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm" -#echo "LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" -#echo "****** REFERENCE RESULTS ENDS ******." -# -#echo "DSCORE:" -#cat /vagrant/data/VanDam-Daylong/BN32/test/test.df -#echo "****** REFERENCE DSCORE BEGINS ******." -#echo "DER B3Precision B3Recall B3F1 TauRefSys TauSysRef CE MI NMI" -#echo "Phil_Crane 43.38 0.975590490013 0.672338020576 0.796061934402 0.599223772838 0.963770340456 0.103871357212 1.67823036445 0.793181875273" -#echo "****** REFERENCE DSCORE ENDS ******." +# now test Noisemes +echo "Testing noisemes..." + +$LAUNCHERS/noisemesSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/noisemes-test.log 2>&1 || { echo " Noisemes failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/noisemesSad_$BASETEST.rttm ]; then + echo "Noisemes passed the test." +else + FAILURES=true + echo " Noisemes failed - no RTTM output" +fi + + +# now test OPENSMILEDIR +echo "Testing OpenSmile SAD..." + +$LAUNCHERS/opensmileSad.sh $DATADIR/test $KEEPTEMP >$TESTDIR/opensmile-test.log || { echo " OpenSmile SAD failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/opensmileSad_$BASETEST.rttm ]; then + echo "OpenSmile SAD passed the test." +else + FAILURES=true + echo " OpenSmile SAD failed - no RTTM output" +fi + +# now test TOCOMBOSAD +echo "Testing ToCombo SAD..." + +$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} + +if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then + echo "TOCOMBO SAD passed the test." +else + FAILURES=true + echo " TOCOMBO SAD failed - no output RTTM" +fi + + +# test DIARTK +echo "Testing DIARTK..." + +cp $TEST_RTTM $TESTDIR + +# run like the wind +$LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 +if grep -q "command not found" $TESTDIR/diartk-test.log; then + echo " Diartk failed - dependencies (probably HTK)" + FAILURES=true +else + if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then + echo "DiarTK passed the test." + else + FAILURES=true + echo " Diartk failed - no output RTTM" + fi +fi +#rm $TESTDIR/$BASETEST.rttm + +# test Yunitator +echo "Testing Yunitator..." + +# let 'er rip +$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then + echo "Yunitator passed the test." +else + FAILURES=true + echo " Yunitator failed - no output RTTM" +fi + +# Test the evaluation +echo "Testing the evaluation pipeline..." +rm $TESTDIR/accuracy_noisemesSad_report.csv +$LAUNCHERS/eval.sh $TESTDIR noisemesSad accuracy > $TESTDIR/eval-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/accuracy_noisemesSad_report.csv ]; then + echo "The evaluation pipeline passed the test." +else + echo " The evaluation pipeline failed the test - output does not match expected" + FAILURES=true +fi + +# Testing VCM +echo "Testing VCM..." + +$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} +if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then + echo "VCM passed the test." +else + FAILURES=true + echo " VCM failed - no output RTTM" +fi + +# Testing WCE +echo "Testing WCE..." +WCEDIR=$REPOS/WCE_VM/ +cd $WCEDIR + +./run_WCEtrain.sh /usr/local/MATLAB/MATLAB_Runtime/v93/ demofiles.txt democounts.txt models/mymodel.mat configs/config_default.txt > $TESTDIR/wce-test.log || { echo " WCE failed - dependencies"; FAILURES=true;} +WCE_OUTPUT=$(awk '/adaptation completed/{ print NR; exit }' $TESTDIR/wce-test.log) +if [ $WCE_OUTPUT > 0 ]; then + echo "WCE passed the test" +else + FAILURES=true + echo "WCE failed - no successful adaptation" +fi + +# test finished +if $FAILURES; then + echo "Some tools did not pass the test, but you can still use others" +else + echo "Congratulations, everything is OK!" +fi + +# results +echo "######################################################################################" +echo "To wrap up, we will print out the results of the analyses that we ran during the test." +echo "Compare the following results, corresponding to your system, against the reference results printed out below." +echo "If the numbers are similar, then your system is working similarly to the original one." +echo "If you see bigger changes, then please paste this output onto an issue on https://github.com/srvk/DiViMe/issues/." +echo "RESULTS:" +for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done +echo "****** REFERENCE RESULTS BEGINS ******." +echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm" +echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" +echo "LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm" +echo "LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm" +echo "LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm" +echo "LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm" +echo "LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" +echo "****** REFERENCE RESULTS ENDS ******." + +echo "Evaluation pipeline:" +cat /vagrant/data/VanDam-Daylong/BN32/test/eval-test.log +echo "accuracy report" +echo " detection accuracy true positive true negative false positive false " +echo " % " +echo "item " +echo "BN32_010007_test.rttm 11.24 30.80 3.11 0.20 267.57" +echo "TOTAL 11.24 30.80 3.11 0.20 267.57" \ No newline at end of file From 4265eda58eb87e5355014e7ba29221808be4e7bc Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Mon, 11 Feb 2019 12:25:24 +0100 Subject: [PATCH 225/299] Update doc --- docs/images/example_visu.png | Bin 33462 -> 30459 bytes docs/source/conf.py | 4 +- docs/source/extra-tools.md | 2 - docs/source/install.md | 2 +- docs/source/tool_doc.md | 2 - docs/source/usage.md | 80 +++++++++-------------------------- 6 files changed, 24 insertions(+), 66 deletions(-) diff --git a/docs/images/example_visu.png b/docs/images/example_visu.png index 5a7c1328f876d2a0a605e26d74707629b11f1cc5..5492cf5f9b165e7d6a1e561b587399adcf8c7f6d 100644 GIT binary patch literal 30459 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 is the name of the file you want to analyze, which you've put inside the `data/` folder in the current working directory. diff --git a/docs/source/usage.md b/docs/source/usage.md index 916826e..28d5e88 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -316,7 +316,7 @@ The vocalization classification tool returns one rttm per sound file, with an es See Format section for explanation on how to read the resulting rttm. -### How to run an Evaluation +### How to evaluate models If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. @@ -354,20 +354,27 @@ Note that this table will be saved in the .csv format in the *data/* folder. Here, all the metrics that are implemented : -| Task | Speech Activity Detection | Diarization | Identification | | -|---|---|---|---|---| -| | Accuracy | Completeness | Identification Error Rate | | -| | Detection Error Rate | Coverage | Precision | | -| | Precision | Diarization Error Rate | Recall | | -| | Recall | Homogeneity | | | -| | | Purity | | | +

+ +| Speech Activity Detection | Diarization | Identification | +|---|---|---| +| Accuracy | Completeness | Identification Error Rate | +| Detection Error Rate | Coverage | Precision | +| Precision | Diarization Error Rate | Recall | +| Recall | Homogeneity | | +| | Purity | | + + +
-Where the identification task is the same as the diarization task when the one-to-one mapping between the reference talkers and the hypothesis ones is know. +  + +Where the identification task is the same as the diarization task when the one-to-one mapping between the reference talkers and the hypothesis ones is known. To assess a diarization model's performances in the identification mode, you need to type the following command : `$ vagrant ssh -c "eval.sh data/ diartk_tocomboSad completeness --identification"` -If the flag *--identification* is not passed, the script will run in the diarization mode. +If the flag *-\-identification* is not passed, the script will run in the diarization mode. Note that you can ask to compute several metrics at once by typing : @@ -375,65 +382,18 @@ Note that you can ask to compute several metrics at once by typing : It will generate a report for each metric. -If you're not a math person, you can add the --visualization flag by typing : +If you're not a math person, you can add the -\-visualization flag by typing : `$ vagrant ssh -c "eval.sh data/ tocomboSad accuracy precision recall --visualization"` It will extract the minute that contains the most speech for each file and align the reference and the hypothesis segments : -![One minute alignement that has been obtained by adding the flag --visualization](../images/example_visu.png) +![
One minute alignement that has been obtained by adding the flag --visualization
](../images/example_visu.png) + Note that the process of calcuting the minute that contains the most speech can be time-consuming. We therefore advise you to use this flag only when processing little data. - - - - - - - - - - - - -#### Evaluating Speech/Voice activity detection - -Type a command like the one below: - -`$ vagrant ssh -c "evalSAD.sh data/ noisemesSad"` - -You can read that command as follows: - -*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. - -*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. - -*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. - -*noisemesSad*: The third argument indicates which tool's output to evaluate (in this case, noisemesSad). All of our Speech/Voice activity detection tools can be evaluated with this. - -For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. - -#### Evaluating Diarization or Talker type - -Type a command like the one below: - -`$ vagrant ssh -c "evalDiar.sh data/ diartk_noisemesSad"` - -You can read that command as follows: - -*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. - -*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. - -*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. - -*diartk_noisemesSad*: The third argument indicates which output to evaluate. Another example: yunitator. - -For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. - ## An alternative for Step 4: using recipes **THIS NEEDS WORK** From c19fa1413117a58bc0f22e01e69db139826a9ca5 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Mon, 11 Feb 2019 13:46:40 +0100 Subject: [PATCH 226/299] Minor fixes in comments with source deactivate which is deprecated + doc --- launcher/README.md | 2 +- launcher/noisemesSad.sh | 2 +- launcher/python3/README.md | 2 +- launcher/test.sh | 2 +- launcher/yunitate.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/launcher/README.md b/launcher/README.md index aeec698..0988f81 100755 --- a/launcher/README.md +++ b/launcher/README.md @@ -44,7 +44,7 @@ source activate divime # to install new packages, edit conf/environment.yml file # to switch back to python 2, run -source deactivate +conda deactivate # And to use python3, make sure you use correct syntax # in python files and/or checkout python3 branch from diff --git a/launcher/noisemesSad.sh b/launcher/noisemesSad.sh index 6f1f2e1..ff8e008 100755 --- a/launcher/noisemesSad.sh +++ b/launcher/noisemesSad.sh @@ -95,4 +95,4 @@ if ! $KEEPTEMP; then rm -rf ${audio_dir}/hyp_sum ${audio_dir}/$TEMPNAME fi -source deactivate +conda deactivate diff --git a/launcher/python3/README.md b/launcher/python3/README.md index 410aca0..413b7c7 100644 --- a/launcher/python3/README.md +++ b/launcher/python3/README.md @@ -9,7 +9,7 @@ source activate divime # to install new packages, edit conf/environment.yml file # to switch back to python 2, run -source deactivate +conda deactivate # And to use python3, make sure you use correct syntax # in python files and/or checkout python3 branch from diff --git a/launcher/test.sh b/launcher/test.sh index 71c0255..5fa4ef8 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -159,7 +159,7 @@ fi # Test the evaluation echo "Testing the evaluation pipeline..." rm $TESTDIR/accuracy_noisemesSad_report.csv -$LAUNCHERS/eval.sh $TESTDIR noisemesSad accuracy > $TESTDIR/eval-test.log || { echo " Dscore failed - dependencies"; FAILURES=true;} +$LAUNCHERS/eval.sh $TESTDIR noisemesSad accuracy > $TESTDIR/eval-test.log || { echo " The evaluation pipeline failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/accuracy_noisemesSad_report.csv ]; then echo "The evaluation pipeline passed the test." else diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 6a94a89..9457f2c 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -85,4 +85,4 @@ if ! $KEEPTEMP; then rm -rf $YUNITEMP fi -source deactivate +conda deactivate From cfbf04be284fa70f77564cff7add5662b772188e Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Mon, 11 Feb 2019 14:37:13 +0100 Subject: [PATCH 227/299] Add requirements.txt for readthedocs dependencies --- docs/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/requirements.txt diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..5f0d84a --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1 @@ +sphinx-markdown-tables From a80928fbfe949f6ed9b5209c405d4f28f09bf830 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Tue, 12 Feb 2019 12:00:51 +0100 Subject: [PATCH 228/299] Install sphinx-markdown-tables in bootstrap.sh --- conf/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index ed72e75..99a6575 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -185,7 +185,7 @@ conda deactivate # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) # and intervaltree (needed for rttm2scp.py) # and recommonmark (needed to make html in docs/) -su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark" +su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark sphinx-markdown-tables" # Link /vagrant/launcher and /vagrant/utils to home folder where scripts expect them ln -s /vagrant/launcher /home/${user}/ From 7824ea043c7e41ec82fc9518f92711a544d03a27 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Tue, 12 Feb 2019 18:00:50 +0100 Subject: [PATCH 229/299] Install pyannote.metrics with root privileges --- conf/bootstrap.sh | 2 +- launcher/test.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 99a6575..e8fb209 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -172,7 +172,7 @@ python setup.py install # Install pyannote (python 3) source activate divime -pip install pyannote.metrics +su ${user} -c "/home/${user}/anaconda/bin/pip install pyannote.metrics" conda deactivate #install launcher and utils diff --git a/launcher/test.sh b/launcher/test.sh index 5fa4ef8..e802307 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -158,6 +158,7 @@ fi # Test the evaluation echo "Testing the evaluation pipeline..." +source activate divime rm $TESTDIR/accuracy_noisemesSad_report.csv $LAUNCHERS/eval.sh $TESTDIR noisemesSad accuracy > $TESTDIR/eval-test.log || { echo " The evaluation pipeline failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/accuracy_noisemesSad_report.csv ]; then @@ -166,6 +167,7 @@ else echo " The evaluation pipeline failed the test - output does not match expected" FAILURES=true fi +conda deactivate # Testing VCM echo "Testing VCM..." From 1fb0afe57f3f06209166d35bff498a5a8dc2d771 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Wed, 13 Feb 2019 15:22:54 +0100 Subject: [PATCH 230/299] Add conda to the path to able to switch to python3 environment during the bootstrap --- conf/bootstrap.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index e8fb209..350040f 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -1,3 +1,5 @@ +# Please note that the bootstrap.sh script runs as root and not the vagrant user + echo "Start bootstraping DiViMe" apt-get update -y apt-get upgrade -y @@ -35,7 +37,7 @@ if ! [ -x "$(command -v /home/${user}/anaconda/bin/conda)" ]; then fi if ! grep -q -i anaconda .bashrc; then - echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc + echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc fi su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib sphinx" # clean up big installer in home folder @@ -169,10 +171,11 @@ git checkout 332b8dd python setup.py build python setup.py install - # Install pyannote (python 3) +## Need to add anaconda to the PATH to be able to activate divime. +export PATH=/home/vagrant/anaconda/bin:$PATH source activate divime -su ${user} -c "/home/${user}/anaconda/bin/pip install pyannote.metrics" +pip install pyannote.metrics conda deactivate #install launcher and utils From 0f0f34ebfcae2216ecc79a65df2a9fca51eb482e Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Wed, 20 Feb 2019 14:04:32 +0100 Subject: [PATCH 231/299] Few changes to integrate new versions of Yunitator --- conf/bootstrap.sh | 1 - launcher/yunitate.sh | 27 ++++++++++++++++++++------- utils/compute_metrics.py | 33 ++++++++++++++++++++------------- utils/frame_cutter.py | 1 + 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 350040f..819c3e6 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -143,7 +143,6 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" # Install Yunitator and dependencies git clone https://github.com/srvk/Yunitator -(cd /home/${user}/repos/Yunitator && git checkout develop/yunified) su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 9457f2c..15e0700 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -14,10 +14,11 @@ BASEDIR=`dirname $SCRIPT` # Path to Yunitator (go one folder up and to Yunitator) YUNITATDIR=/home/vagrant/repos/Yunitator -if [ $# -lt 1 ] || [ $# -gt 2 ]; then - echo "Usage: $0 " +if [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 " echo "where dirname is the name of the folder" - echo "containing the wav files" + echo "containing the wav files, and the second parameter (optional)" + echo "whether to use the old model, the english model, or the universal one." exit 1 fi @@ -26,6 +27,19 @@ if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi +MODE=$2 # old english or universal +if [[ $MODE == "" ]]; then + MODE="old" +fi + +case $MODE in + old|english|universal) + ;; + *) + echo "MODE = $MODE but needs to be amongst {old, english, universal}"; + exit 1;; +esac + audio_dir=/vagrant/$1 TEMPNAME=Yunitemp YUNITEMP=${audio_dir}/$TEMPNAME @@ -46,7 +60,6 @@ mkdir -p $YUNITEMP # Iterate over files echo "Starting $0" for f in `ls ${audio_dir}/*.wav`; do - basename=`basename $f .wav` # first features ./extract-htk-vm2.sh $f $TEMPNAME @@ -60,7 +73,7 @@ done chunksize=$(free | awk '/^Mem:/{print $2}') let chunksize=$chunksize/100000*200 -python yunified.py yunitator $audio_dir $chunksize +python yunified.py yunitator $audio_dir $chunksize $MODE # MODE equal to old, english or universal for f in `ls $YUNITEMP/*.rttm.sorted`; do filename=$(basename "$f") @@ -74,9 +87,9 @@ echo "$0 finished running" # take all the .rttm in ${audio_dir}/Yunitemp/ and move them to /vagrant/data for sad in `ls $YUNITEMP/*.rttm`; do _rttm=$(basename $sad) - rttm=${audio_dir}/yunitator_${_rttm} + rttm=${audio_dir}/yunitator_${MODE}_${_rttm} # Remove not needed SIL lines - # sed -i '/ SIL /d' $sad + sed -i '/ SIL /d' $sad mv $sad $rttm done diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py index c19ef67..8219685 100644 --- a/utils/compute_metrics.py +++ b/utils/compute_metrics.py @@ -82,8 +82,10 @@ def run_metrics(references_f, hypothesis_f, metrics, visualization=False): # Set the uri as the basename for both reference and hypothesis ref.uri, hyp.uri = basename, basename # Let's accumulate the score for each metrics + # Let's accumulate the score for each metrics + for m in metrics.values(): - m(ref, hyp) + res = m(ref, hyp) # Let's generate a visualization of the results if visualization: @@ -96,19 +98,18 @@ def run_metrics(references_f, hypothesis_f, metrics, visualization=False): plt.rcParams['figure.figsize'] = (notebook.width, 10) notebook.crop = Segment(start, end) - if visualization: - # Plot reference - plt.subplot(211) - notebook.plot_annotation(ref, legend=True, time=False) - plt.gca().set_title('reference '+ os.path.basename(ref_f).replace('.rttm', ''), fontdict={'fontsize':18}) + # Plot reference + plt.subplot(211) + notebook.plot_annotation(ref, legend=True, time=False) + plt.gca().set_title('reference '+ os.path.basename(ref_f).replace('.rttm', ''), fontdict={'fontsize':18}) - # Plot hypothesis - plt.subplot(212) - notebook.plot_annotation(hyp, legend=True, time=True) - plt.gca().set_title('hypothesis '+os.path.basename(hyp_f).replace('.rttm', ''), fontdict={'fontsize':18}) + # Plot hypothesis + plt.subplot(212) + notebook.plot_annotation(hyp, legend=True, time=True) + plt.gca().set_title('hypothesis '+os.path.basename(hyp_f).replace('.rttm', ''), fontdict={'fontsize':18}) - plt.savefig(os.path.join(visualization_dir, os.path.basename(hyp_f).replace('.rttm', '.png'))) - plt.close() + plt.savefig(os.path.join(visualization_dir, os.path.basename(hyp_f).replace('.rttm', '.png'))) + plt.close() return metrics @@ -120,7 +121,7 @@ def get_couple_files(ref_path, hyp_path=None, prefix=None): ref_path = os.path.join("/vagrant", ref_path) if hyp_path is None: hyp_files = list(glob.iglob(os.path.join(ref_path, prefix+'*.rttm'))) - ref_files = [f.replace(prefix, '') for f in hyp_files] + ref_files = [os.path.join(os.path.dirname(f), os.path.basename(f).replace(prefix, '')) for f in hyp_files] else: # Hyp files are stored in a different place, we check if a folder has been provided or if it just a single file if os.path.isdir(hyp_path): @@ -204,11 +205,17 @@ def main(): # Get files and run the metrics references_f, hypothesis_f = get_couple_files(args.reference, args.hypothesis, args.prefix) + + print("Pairs that have been found : ") + for ref, hyp in zip(references_f, hypothesis_f): + print("%s / %s "% (os.path.basename(ref), os.path.basename(hyp))) + metrics = run_metrics(references_f, hypothesis_f, metrics, args.visualization) # Display a report for each metrics for name, m in metrics.items(): print("\n%s report" % name) + print(m) rep = m.report(display=True) rep.to_csv(os.path.join("/vagrant", args.reference, name+'_'+args.prefix+"_report.csv")) diff --git a/utils/frame_cutter.py b/utils/frame_cutter.py index fd9c424..789a638 100755 --- a/utils/frame_cutter.py +++ b/utils/frame_cutter.py @@ -186,6 +186,7 @@ def main(): # "SIL": "SIL|S"} labels_map = {"CHF":"CHF", "CHI":"CHI", + "OCHI": "OCHI", "CHN":"CHN", "FAF":"FAF", "FAN":"FAN", From be9d0d9e758b5f11a47943e534854ebafefca6f0 Mon Sep 17 00:00:00 2001 From: Marvin Lavechin Date: Wed, 20 Feb 2019 15:07:27 +0100 Subject: [PATCH 232/299] Make rttm2labels.py easier to read --- utils/rttm2labels.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/utils/rttm2labels.py b/utils/rttm2labels.py index c1b90bf..3f593dd 100755 --- a/utils/rttm2labels.py +++ b/utils/rttm2labels.py @@ -18,17 +18,16 @@ def printbuf (begin, end, text): for l in sys.stdin: - - m = re.match("^(.*)\t(.*)\t(.*)\t(\S+)\t(\S+)\t(.*)\t(.*)\t(.*)\t(.*)$", l) + m = l.split(' ') if m: - type, file = m.group(1, 2) - channel = int(m.group(3)) - starttime = float(m.group(4)) - duration = float(m.group(5)) - ortho = m.group(6) - stype = m.group(7) - name = m.group(8) - conf = m.group(9) + type, file = m[0], m[1] + channel = int(m[2]) + starttime = float(m[3]) + duration = float(m[4]) + ortho = m[5] + stype = m[6] + name = m[7] + conf = m[8] printbuf (starttime, starttime+duration, name) begin = starttime From f00b2295e2387278441c1966e66b5f3698ad3886 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Mon, 25 Feb 2019 17:47:53 +0100 Subject: [PATCH 233/299] Correct tocomboSad bug : no output with multi channels + minor changes eval --- launcher/eval.sh | 14 ++++++---- launcher/tocomboSad.sh | 13 +++++++-- scripts/segments.pl | 58 ---------------------------------------- utils/compute_metrics.py | 38 +++++++++++++++----------- 4 files changed, 42 insertions(+), 81 deletions(-) delete mode 100755 scripts/segments.pl diff --git a/launcher/eval.sh b/launcher/eval.sh index b89f387..75d9d71 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -14,8 +14,8 @@ display_usage() { echo -e "\t - tocomboSad" echo -e "\t - opensmileSad" echo -e "\t - diartk" - echo -e "\t - yunitate" - echo "If evaluating diartk, please give which flavour" + echo -e "\t - yunitator" + echo "If evaluating diartk or yunitator, please give which flavour" echo "of SAD you used to produce the transcription" echo "you want to evaluate" echo -e "\nChoices for the metrics are:" @@ -32,8 +32,12 @@ display_usage() { DATA=$1 MODEL=$2 shift; shift; -if [[ "$MODEL" == "diartk" ]]; then - MODEL=${MODEL}_$1 +if [[ "$MODEL" == "diartk" ]] || [[ "$MODEL" == "yunitator" ]]; then + if [[ "$1" == "rttm" ]]; then + MODEL=${MODEL}_goldSad + else + MODEL=${MODEL}_$1 + fi shift; fi; @@ -80,7 +84,7 @@ case $MODEL in "tocomboSad"|"opensmileSad"|"noisemesSad") python $UTILS/compute_metrics.py --reference $DATA --prefix $MODEL --task detection --metrics ${METRICS[*]} ${FLAGS[*]} ;; -"yunitator"|"lena"|"diartk_noisemesSad"|"diartk_tocomboSad"|"diartk_opensmileSad"|"diartk_goldSad") +"yunitator_old"|"yunitator_english"|"yunitator_universal"|"lena"|"diartk_noisemesSad"|"diartk_tocomboSad"|"diartk_opensmileSad"|"diartk_goldSad") python $UTILS/compute_metrics.py --reference $DATA --prefix $MODEL --task diarization --metrics ${METRICS[*]} ${FLAGS[*]} ;; *) diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index 4164803..2a99729 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -53,7 +53,7 @@ touch $workdir/filelist.txt for f in ${audio_dir}/*.wav; do # Check if audio has 1 channel or more. If it has more, use sox to create a temp audio file w/ 1 channel. n_chan=$(soxi $f | grep Channels | cut -d ':' -f 2) - if [[ $n_chan -gt 1 ]]; then + if [[ $n_chan -gt 1 ]]; then base=$(basename $f) sox -c $n_chan $f -c 1 $workdir/$base f=$workdir/$base @@ -71,9 +71,18 @@ export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64 #convert to rttms for f in ${audio_dir}/*.ToCombo.txt; do bn=`basename $f .wav.ToCombo.txt` - python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > ${audio_dir}/tocomboSad_$bn.rttm + python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > ${workdir}/tocomboSad_$bn.rttm done +# same in the temp folder which has the .wav that were not monochannel +for f in ${workdir}/*.ToCombo.txt; do + bn=`basename $f .wav.ToCombo.txt` + python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > ${workdir}/tocomboSad_$bn.rttm +done + +# get the rttm +mv ${workdir}/*.rttm ${audio_dir} + # move the txt files and delete temporary folder mv ${audio_dir}/*ToCombo.txt $workdir if ! $KEEPTEMP; then diff --git a/scripts/segments.pl b/scripts/segments.pl deleted file mode 100755 index 04ac994..0000000 --- a/scripts/segments.pl +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/local/bin/perl -# -# Anne S. Warlaumont -# -# This tool allows you to find the start time, end time, and type of vocalization for each vocalization in a LENA recording, using the corresponding .its file. -# The output information is written into .csv file, which is useful for sequence analyses. -# More detailed instructions are available at: https://github.com/HomeBankCode/lena-its-tools/blob/master/Documentation/Using_segments.md -# -# Takes the following command line arguments: -# The path and file name of the input its file (e.g. "~/lena-its-tools/segments.pl) -# The path and csv file name where you want the segment data to be written (e.g. "~/lena-its-results/e20131126_155022_009145_segments.csv" -# -# Instructions: -# 1. Open up a unix shell (e.g. the Terminal application under Utilities on Mac or Cygwin on Windows) -# 2. Navigate to the directory where this file is located (e.g. "~/CodeDirectory/") -# 3. Run segments.pl with the path and file name of the its file as the first argument and the path and name of the desired segments csv output file as the 2nd argument -# (e.g. "perl segments.pl ~/DataDirectory/e20120417_130404_007941.its ~/DataDirectory/e20120417_130404_007941_segments.csv") - -use strict; use warnings; - -open INPUTFILE, $ARGV[0] or die "Could not open input file " . $ARGV[0] . "\n"; -open OUTPUTFILE, ">", $ARGV[1] or die "Could not open output file " . $ARGV[1] . "\n"; - -print OUTPUTFILE "segtype,startsec,endsec\n"; - -while (my $line = ){ - - chomp($line); - - if ($line=~ m/Segment spkr=/){ - - my $segtype = $line; - $segtype =~ s/.*Segment spkr="//g; - $segtype =~ s/".*//g; - if ($segtype =~ m/CHN/){ - if ($line =~ m/startUtt1/){ - $segtype = $segtype . "SP"; - } - else{ - $segtype = $segtype . "NSP"; - } - } - - my $startTime = $line; - $startTime =~ s/.*startTime="PT//g; - $startTime =~ s/S" endTime=.*//g; - - my $endTime = $line; - $endTime =~ s/.*endTime="PT//g; - $endTime =~ s/S".*//g; - - print OUTPUTFILE "$segtype,$startTime,$endTime\n"; - } - -} - -close(INPUTFILE); -close(OUTPUTFILE); \ No newline at end of file diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py index 8219685..707c901 100644 --- a/utils/compute_metrics.py +++ b/utils/compute_metrics.py @@ -146,7 +146,8 @@ def main(): help="Path of the hypothesis" "If None, consider that the hypothesis is stored where the reference is.") parser.add_argument('-p', '--prefix', required=True, choices=["lena", "noisemesSad", "opensmileSad", - "tocomboSad", "yunitate", "diartk_noisemesSad", + "tocomboSad", "yunitator_old", "yunitator_english", + "yunitator_universal", "diartk_noisemesSad", "diartk_tocomboSad","diartk_opensmileSad", "diartk_goldSad", "yuniseg_noisemesSad", "yuniseg_opensmileSad", "yuniseg_tocomboSad", @@ -169,7 +170,15 @@ def main(): # Let's create the metrics metrics = {} for m in args.metrics: - if args.task == "diarization": + if m == "accuracy": # All the 3 tasks can be evaluated as a detection task + metrics[m] = detection.DetectionAccuracy(parallel=True) + elif m == "precision": + metrics[m] = detection.DetectionPrecision(parallel=True) + elif m == "recall": + metrics[m] = detection.DetectionRecall(parallel=True) + elif m == "deter": + metrics[m] = detection.DetectionErrorRate(parallel=True) + elif args.task == "diarization" or args.task == "identification": # The diarization and the identification task can be both evaluated as a diarization task if m == "diaer": metrics[m] = diarization.DiarizationErrorRate(parallel=True) elif m == "coverage": @@ -180,28 +189,25 @@ def main(): metrics[m] = diarization.DiarizationHomogeneity(parallel=True) elif m == "purity": metrics[m] = diarization.DiarizationPurity(parallel=True) - else: - print("Filtering out %s, which is not available for the %s task." % (m, args.task)) - elif args.task == "detection": - if m == "accuracy": + elif m == "accuracy": metrics[m] = detection.DetectionAccuracy(parallel=True) elif m == "precision": metrics[m] = detection.DetectionPrecision(parallel=True) elif m == "recall": - metrics[m] = detection.DetectionPrecision(parallel=True) + metrics[m] = detection.DetectionRecall(parallel=True) elif m == "deter": metrics[m] = detection.DetectionErrorRate(parallel=True) + elif args.task == "identification": # Only the identification task can be evaluated as an identification task + if m == "ider": + metrics[m] = identification.IdentificationErrorRate(parallel=True) + elif m == "precision": + metrics[m] = identification.IdentificationPrecision(parallel=True) + elif m == "recall": + metrics[m] = identification.IdentificationRecall(parallel=True) else: print("Filtering out %s, which is not available for the %s task." % (m, args.task)) - elif args.task == "identification": - if m == "ider": - metrics[m] = identification.IdentificationErrorRate(parallel=True) - elif m == "precision": - metrics[m] = identification.IdentificationPrecision(parallel=True) - elif m == "recall": - metrics[m] = identification.IdentificationRecall(parallel=True) - else: - print("Filtering out %s, which is not available for the %s task." % (m, args.task)) + else: + print("Filtering out %s, which is not available for the %s task." % (m, args.task)) # Get files and run the metrics references_f, hypothesis_f = get_couple_files(args.reference, args.hypothesis, args.prefix) From b0aacb47350d40d4600b19b41d85c00ad0f340b9 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Mon, 25 Feb 2019 18:28:09 +0100 Subject: [PATCH 234/299] opensmile creates empty rttm if nothing is produced by the model --- launcher/opensmileSad.sh | 8 +++++++- launcher/yunitate.sh | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/launcher/opensmileSad.sh b/launcher/opensmileSad.sh index 9c414dd..85739fe 100755 --- a/launcher/opensmileSad.sh +++ b/launcher/opensmileSad.sh @@ -40,12 +40,12 @@ cd $OSHOME/scripts/vad # Use OpenSMILE 2.3.0 for sad in `ls ${audio_dir}/*.wav`; do - file=$sad id=`basename $file` id=${id%.wav} > ${audio_dir}/${id}.txt #Make it empty if already present echo "Processing $id ..." + echo $workdir/${id}.txt LD_LIBRARY_PATH=/usr/local/lib \ $OPENSMILE \ -C $CONFIG_FILE \ @@ -54,6 +54,12 @@ for sad in `ls ${audio_dir}/*.wav`; do -noconsoleoutput 1 \ -saveSegmentTimes $workdir/${id}.txt \ -logfile $workdir/opensmile-vad.log + + if [[ ! -f $workdir/${id}.txt ]]; then + echo "No output produced by opensmileSad." + echo "Generating empty rttm... (check the log file)" + touch $workdir/${id}.txt + fi done # clean up generated WAV files in working directory (tool_home/scripts/vad) diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 15e0700..d251f69 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -15,7 +15,7 @@ BASEDIR=`dirname $SCRIPT` YUNITATDIR=/home/vagrant/repos/Yunitator if [ $# -lt 1 ] || [ $# -gt 3 ]; then - echo "Usage: $0 " + echo "Usage: $0 " echo "where dirname is the name of the folder" echo "containing the wav files, and the second parameter (optional)" echo "whether to use the old model, the english model, or the universal one." From 8ffe2e7c6ecc6eefdcff2237093b733a2fe7539d Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Mon, 25 Feb 2019 18:35:30 +0100 Subject: [PATCH 235/299] Diartk produces empty rttm when the SAD is empty (it was producing nothing before) --- launcher/diartk.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/diartk.sh b/launcher/diartk.sh index 3bc3109..165b7fe 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -114,6 +114,9 @@ for fin in `ls ${audio_dir}/*.wav`; do # print results #cat $workdir/$basename.out cp $workdir/$basename.rttm ${audio_dir}/diartk_${sys}_${basename}.rttm + else + # Create empty output file + touch ${audio_dir}/diartk_${sys}_${basename}.rttm fi done From 055a13e09fa2ea15258d3e00cdcb53d93f4627e4 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Tue, 26 Feb 2019 11:32:23 +0100 Subject: [PATCH 236/299] Flatten multi-index dataframe of metric report --- utils/compute_metrics.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py index 707c901..ad65232 100644 --- a/utils/compute_metrics.py +++ b/utils/compute_metrics.py @@ -223,6 +223,12 @@ def main(): print("\n%s report" % name) print(m) rep = m.report(display=True) + colnames = list(rep.columns.get_level_values(0)) + percent_or_count = rep.columns.get_level_values(1) + for i in range(0,len(percent_or_count)): + if percent_or_count[i] == '%': + colnames[i] = colnames[i] +' %' + rep.columns = colnames rep.to_csv(os.path.join("/vagrant", args.reference, name+'_'+args.prefix+"_report.csv")) From 8cdfd02e904847032242952fbb57bc2fb6583b4d Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Fri, 1 Mar 2019 14:16:49 +0100 Subject: [PATCH 237/299] Modify and fix textgrid2rttm and chat2rttm --- utils/chat2rttm_folder.sh | 11 ++--- utils/easy_chat2rttm.sh | 77 +++++++++++++++++++++++++++++++++++ utils/textgrid2rttm.py | 60 +++++++++------------------ utils/textgrid2rttm_folder.sh | 1 - 4 files changed, 102 insertions(+), 47 deletions(-) create mode 100755 utils/easy_chat2rttm.sh delete mode 100755 utils/textgrid2rttm_folder.sh diff --git a/utils/chat2rttm_folder.sh b/utils/chat2rttm_folder.sh index 6f57023..762e474 100755 --- a/utils/chat2rttm_folder.sh +++ b/utils/chat2rttm_folder.sh @@ -2,9 +2,10 @@ # # Shell script to convert all .CHA files inside a folder to .rttm format # -for j in ${1}/*.cha - do chat2stm.sh $j - file=`echo $j | sed "s/.cha$//"` - cat ${file}.stm | awk '{print "SPEAKER",${file},"1",$4,($5 - $4),"","","speech","","" }' > ${file}.rttm - rm ${file}.stm +for j in ${1}/*.cha; do + stm=${j/.cha/.stm} + rttm=${j/.cha/.rttm} + chat2stm.sh $j >> $stm + cat $stm | awk -v file="$(basename ${rttm/.rttm/})" '{print "SPEAKER",file,"1",$4,($5 - $4),"","",$2,"","" }' > $rttm +# rm ${j/.cha/.stm} done \ No newline at end of file diff --git a/utils/easy_chat2rttm.sh b/utils/easy_chat2rttm.sh new file mode 100755 index 0000000..2f3c2f8 --- /dev/null +++ b/utils/easy_chat2rttm.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +INPUT=$1 + +display_usage() { + echo "Given a folder containing .cha files, convert them into .rttm files." + echo "usage: $0 [input] [optional flag]" + echo " input The folder where to find the .cha files, or the single .cha file (REQUIRED)." + echo " --add_age Add the age of the child in the output files (OPTIONAL)." + exit 1 +} + +cha_2_rttm() { + if [ "$#" -eq 0 ]; then + echo "Illegal number of parameters" + exit 1 + else + filename=$1 + fi + + if [ ! -f $filename ]; then + echo "File not found" + exit 1 + fi +# # Read header +# header="$(cat $filename | grep "^@")" +# NB_PARTICIPANTS=$(echo "${header,,}" | grep "^@participants" | awk -F"," '{print NF}') +# +# PARTICIPANTS=$(echo "${header,,}" | grep "^@id") +# PARTICIPANTS=$(echo "$PARTICIPANTS" | awk -F"|" '{print "p_"$3 " a_"$4}') +# >&2 echo "Number of participants : $NB_PARTICIPANTS" +# >&2 echo "Participants & their age: ${PARTICIPANTS//$'\n'/, }" + + new_file=$(basename $filename) + new_file=${new_file%.*}.rttm + + # Read body + body="$(cat $filename | sed ':a;N;s/\n\t/ok/;ta;P;D' | grep "^*")" # Ensuring that one transcript = one and only one line + while IFS= read -r line; do + # Get class + SPKR=$(grep -oP '(?<=\*).*?(?=:)' <<< "$line") + + # Get onset / offset + ONOFF=$(echo $line | grep -oP '(?<=\025)\d+_\d+(?=\025)') + ONSET=${ONOFF%_*} + OFFSET=${ONOFF#*_} + + if [ "$ONSET" == "" ] || [ "$OFFSET" == "" ]; then + >&2 echo "Can't parse line : $line in $(basename $filename)" + else + # Get seconds instead of ms + ONSET=$(echo "scale=4; $ONSET/1000.0" | bc -l) + OFFSET=$(echo "scale=4; $OFFSET/1000.0" | bc -l) + DURATION=$(echo "scale=4; $OFFSET-$ONSET" | bc -l) + echo -e "SPEAKER\t${new_file%.*}\t1\t$ONSET\t$OFFSET\t\t\t$SPKR\t\t" + fi + done < <(printf '%s\n' "$body") > $(dirname $filename)/$new_file +} + +if [ -z "$1" ]; then + display_usage +fi + + +if [ -f "/vagrant/"$1 ]; then + echo "File found." + cha_2_rttm $cha_path +elif [ -d "/vagrant/"$1 ]; then + echo "Directory found." + for cha_path in /vagrant/$1/*.cha; do + cha_2_rttm $cha_path + done +else + echo "File or directory not found." + display_usage +fi; + diff --git a/utils/textgrid2rttm.py b/utils/textgrid2rttm.py index f9bfec2..9797665 100755 --- a/utils/textgrid2rttm.py +++ b/utils/textgrid2rttm.py @@ -11,12 +11,11 @@ import os import argparse -# from praatio import tgio import tgt # tgt is better than praatio for our application # because it allows to manipulate the timestamps, # which is something we cannot do with praatio. - - +import glob +import sys def textgrid2rttm(textgrid): ''' @@ -27,28 +26,16 @@ def textgrid2rttm(textgrid): # init output rttm_out = dict() - # open textgrid - #tg = tgio.openTextgrid(textgrid) - tg = tgt.read_textgrid(textgrid) - + tg = tgt.io.read_textgrid(textgrid) # loop over all speakers in this text grid - #for spkr in tg.tierNameList: for spkr in tg.get_tier_names(): - spkr_timestamps = [] # loop over all annotations for this speaker - #for interval in tg.tierDict[spkr].entryList: for _interval in tg.get_tiers_by_name(spkr): for interval in _interval: - bg, ed, label = interval.start_time,\ interval.end_time,\ interval.text - - #if label == "x": - # continue - #elif label == "1" or label == "2": - # spkr_timestamps.append((bg, ed-bg)) spkr_timestamps.append((bg, ed-bg)) # add list of onsets, durations for each speakers @@ -63,7 +50,7 @@ def write_rttm(rttm_out, basename_whole): ''' # write one rttm file for the whole wav, indicating # only regions of speech, and not the speaker - with open(basename_whole + '.rttm', 'w') as fout: + with open(basename_whole, 'w') as fout: for spkr in rttm_out: for bg, dur in rttm_out[spkr]: fout.write(u'SPEAKER {} 1 {} {} ' @@ -74,30 +61,21 @@ def write_rttm(rttm_out, basename_whole): if __name__ == '__main__': command_example = "python textgrid2rttm.py /folder/" parser = argparse.ArgumentParser(epilog=command_example) - parser.add_argument('input_file', - help=''' Input File ''') - parser.add_argument('output_file', - help='''Name of the output file in which to write''') + parser.add_argument('input', help=''' Input file, or folder containing .TextGrid files''') args = parser.parse_args() - rttm_out = textgrid2rttm(args.input_file) - write_rttm(rttm_out, args.output_file) - #if not os.path.isdir(args.output_folder_whole): - # os.makedirs(args.output_folder_whole) - - #for fold in os.listdir(args.input_folder): - # for fin in os.listdir(os.path.join(args.input_folder, fold)): - # if not fin.endswith('m1.TextGrid'): - # # read only text grids with full anotation - # # in this folder - # continue - - # tg_in = os.path.join(args.input_folder, fold, fin) - # basename_whole = os.path.join(args.output_folder_whole, - # '_'.join(fin.split('_')[0:3])) - - # # extract begining/durations of speech intervals - # rttm_out = textgrid2rttm(tg_in) - # # write 1 rttm per spkr transcribed in this text grid - # write_rttm(rttm_out, basename_whole) + if os.path.isfile(args.input): + print("File found. Converting it.") + rttm = textgrid2rttm(args.input) + write_rttm(rttm, args.input.replace(".TextGrid", ".rttm")) + elif os.path.isdir(args.input): + print("Folder found. Scanning .TextGrid files.") + for txtgr in glob.glob(os.path.join(args.input, "*.TextGrid")): + print("Converting %s" % os.path.basename(txtgr)) + rttm = textgrid2rttm(txtgr) + write_rttm(rttm, txtgr.replace(".TextGrid", ".rttm")) + else: + print("Nothing found.") + sys.exit(1) + print("Done.") \ No newline at end of file diff --git a/utils/textgrid2rttm_folder.sh b/utils/textgrid2rttm_folder.sh deleted file mode 100755 index ba13e7f..0000000 --- a/utils/textgrid2rttm_folder.sh +++ /dev/null @@ -1 +0,0 @@ -for j in ${1}/*.TextGrid; do textgrid2rttm.py $j ; done \ No newline at end of file From 5b38749317be87e4b250e2bd330a177bfb6d040a Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Thu, 7 Mar 2019 18:11:49 +0100 Subject: [PATCH 238/299] Modify chat2rttm to output the duration instead of the onset --- utils/compute_metrics.py | 8 -------- utils/easy_chat2rttm.sh | 8 +++++--- utils/textgrid2rttm.py | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py index ad65232..745a90a 100644 --- a/utils/compute_metrics.py +++ b/utils/compute_metrics.py @@ -189,14 +189,6 @@ def main(): metrics[m] = diarization.DiarizationHomogeneity(parallel=True) elif m == "purity": metrics[m] = diarization.DiarizationPurity(parallel=True) - elif m == "accuracy": - metrics[m] = detection.DetectionAccuracy(parallel=True) - elif m == "precision": - metrics[m] = detection.DetectionPrecision(parallel=True) - elif m == "recall": - metrics[m] = detection.DetectionRecall(parallel=True) - elif m == "deter": - metrics[m] = detection.DetectionErrorRate(parallel=True) elif args.task == "identification": # Only the identification task can be evaluated as an identification task if m == "ider": metrics[m] = identification.IdentificationErrorRate(parallel=True) diff --git a/utils/easy_chat2rttm.sh b/utils/easy_chat2rttm.sh index 2f3c2f8..cf1c485 100755 --- a/utils/easy_chat2rttm.sh +++ b/utils/easy_chat2rttm.sh @@ -1,4 +1,6 @@ #!/bin/bash +# Done in bash thinking that it would be faster. +# Maybe need to redo it in Python. INPUT=$1 @@ -6,7 +8,6 @@ display_usage() { echo "Given a folder containing .cha files, convert them into .rttm files." echo "usage: $0 [input] [optional flag]" echo " input The folder where to find the .cha files, or the single .cha file (REQUIRED)." - echo " --add_age Add the age of the child in the output files (OPTIONAL)." exit 1 } @@ -46,15 +47,16 @@ cha_2_rttm() { OFFSET=${ONOFF#*_} if [ "$ONSET" == "" ] || [ "$OFFSET" == "" ]; then - >&2 echo "Can't parse line : $line in $(basename $filename)" + echo -e "SPEAKER\t${new_file%.*}\t1\t-1.0\t-1.0\t\t\t$SPKR\t\t" else # Get seconds instead of ms ONSET=$(echo "scale=4; $ONSET/1000.0" | bc -l) OFFSET=$(echo "scale=4; $OFFSET/1000.0" | bc -l) DURATION=$(echo "scale=4; $OFFSET-$ONSET" | bc -l) - echo -e "SPEAKER\t${new_file%.*}\t1\t$ONSET\t$OFFSET\t\t\t$SPKR\t\t" + echo -e "SPEAKER\t${new_file%.*}\t1\t$ONSET\t$DURATION\t\t\t$SPKR\t\t" fi done < <(printf '%s\n' "$body") > $(dirname $filename)/$new_file + >&2 echo "Done ${new_file%.*}" } if [ -z "$1" ]; then diff --git a/utils/textgrid2rttm.py b/utils/textgrid2rttm.py index 9797665..7c2634e 100755 --- a/utils/textgrid2rttm.py +++ b/utils/textgrid2rttm.py @@ -55,7 +55,7 @@ def write_rttm(rttm_out, basename_whole): for bg, dur in rttm_out[spkr]: fout.write(u'SPEAKER {} 1 {} {} ' ' {} \n'.format( - basename_whole.split('/')[-1], bg, dur, spkr)) + basename_whole.split('/')[-1].replace('.rttm',''), bg, dur, spkr)) if __name__ == '__main__': From d9040021993720341d6fc573dcaacb419c8f7414 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Mon, 1 Apr 2019 15:02:26 +0200 Subject: [PATCH 239/299] Update test.sh and few other modifications --- .idea/vcs.xml | 7 +++++++ Vagrantfile | 2 +- launcher/test.sh | 8 +++++--- utils/compute_metrics.py | 4 +++- utils/elan2rttm.py | 7 ++++--- utils/high_volubility.py | 31 ++++++++++++------------------- 6 files changed, 32 insertions(+), 27 deletions(-) create mode 100644 .idea/vcs.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..e6e3d41 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Vagrantfile b/Vagrantfile index e0411dc..f9a7298 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -32,7 +32,7 @@ Vagrant.configure("2") do |config| config.vm.network "private_network", ip: "192.168.56.101" vbox.cpus = 2 - vbox.memory = 3072 + vbox.memory = 6144 end config.vm.provider "docker" do |d, override| diff --git a/launcher/test.sh b/launcher/test.sh index e802307..a1bf9ed 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -68,6 +68,7 @@ $UTILS/chat2stm.sh $BASE.cha > $BASE.stm 2>/dev/null cat $BASE.stm | awk -v start=$START -v stop=$STOP -v file=$BASE -e '{if (($4 > start) && ($4 < stop)) print "SPEAKER",file"_test","1",($4 - start),($5 - $4),"","","speech","","" }' > $BASETEST.rttm TEST_RTTM=$WORKDIR/$BASETEST.rttm TEST_WAV=$WORKDIR/$BASETEST.wav +TESTDIR=$WORKDIR/test # Check for HTK @@ -79,7 +80,6 @@ else echo " If so, then you may need to re-install it. Run: vagrant ssh -c \"utils/install_htk.sh\" " fi -TESTDIR=$WORKDIR/test rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR cp $WORKDIR/$BASETEST.rttm $TESTDIR @@ -142,14 +142,16 @@ else echo " Diartk failed - no output RTTM" fi fi -#rm $TESTDIR/$BASETEST.rttm +rm $TESTDIR/$BASETEST.rttm # test Yunitator echo "Testing Yunitator..." # let 'er rip $LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/yunitator_$BASETEST.rttm ]; then +echo "TEST DIR" +echo $TESTDIR/yunitator-test.log +if [ -s $TESTDIR/yunitator_old_$BASETEST.rttm ]; then echo "Yunitator passed the test." else FAILURES=true diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py index 745a90a..d83c585 100644 --- a/utils/compute_metrics.py +++ b/utils/compute_metrics.py @@ -62,8 +62,10 @@ def rttm_to_annotation(input_rttm, collapse_to_speech=False): if os.path.isfile(input_rttm): with open(input_rttm) as fn: for line in fn: - row = re.sub(' +', ' ', line).replace('\t', ' ').split(' ') + row = re.sub(' +', ' ', line).replace('\t', ' ').replace(' ', ' ').split(' ') t_beg, t_dur, spkr = float(row[3]), float(row[4]), row[7] + if row[7] == "": + raise ValueError("Speaker role is empty in %s" % os.path.basename(input_rttm)) anno[Segment(t_beg, t_beg + t_dur)] = spkr return anno diff --git a/utils/elan2rttm.py b/utils/elan2rttm.py index 0b917be..d832279 100755 --- a/utils/elan2rttm.py +++ b/utils/elan2rttm.py @@ -30,7 +30,7 @@ def eaf2rttm(path_to_eaf, path_to_write_rttm): EAF = pmp.Elan.Eaf(path_to_eaf) participants = [] - + for k in EAF.tiers.keys(): if 'PARTICIPANT' in EAF.tiers[k][2].keys(): @@ -40,7 +40,6 @@ def eaf2rttm(path_to_eaf, path_to_write_rttm): participants.append(EAF.tiers[k][2]['PARTICIPANT']) print('participants: {}'.format(participants)) - base = os.path.basename(path_to_eaf) name = os.path.splitext(base)[0] @@ -49,7 +48,9 @@ def eaf2rttm(path_to_eaf, path_to_write_rttm): with open(os.path.join(path_to_write_rttm, name + ".rttm"), "w") as rttm: for participant in participants: - + if participant not in EAF.tiers.keys(): + continue + for _, val in EAF.tiers[participant][0].items(): start = val[0] diff --git a/utils/high_volubility.py b/utils/high_volubility.py index 609ba5b..326f33e 100755 --- a/utils/high_volubility.py +++ b/utils/high_volubility.py @@ -7,16 +7,16 @@ and runs them through a SAD or diarization tool to detect chunks of audio with : 1) a lot of speech. ---> python tools/high_volubility.py file_path.wav --sad noisemes_sad +--> python utils/high_volubility.py file_path.wav --sad noisemes_sad 2) a lot of child speech ---> python tools/high_volubility.py file_path.wav --diar yunitate --mode CHI +--> python utils/high_volubility.py file_path.wav --diar yunitator --mode CHI 3) a lot of parent-child conversations ---> python tools/high_volubility.py file_path.wav --diar yunitate --mode PCCONV +--> python utils/high_volubility.py file_path.wav --diar yunitator --mode PCCONV 4) a lot of adults conversations with a child minimally aware ---> python tools/high_volubility.py file_path.wav --diar yunitate --mode ACCA +--> python utils/high_volubility.py file_path.wav --diar yunitator --mode ACCA """ import os @@ -30,6 +30,7 @@ from operator import itemgetter +LAUCHER_FOLDER = "~/launcher" def get_audio_length(wav): """ Return duration of Wave file. @@ -49,7 +50,6 @@ def get_audio_length(wav): return duration - def select_onsets(duration, step): """ Return list of onsets on which this script will extract the chunks of 10s @@ -132,13 +132,13 @@ def run_Model(temp_rel, temp_abs, sad, diar=None): """ if diar is not None: # Diarization mode if diar == 'yunitate': - cmd = ['tools/{}.sh'.format(diar), '{}'.format(temp_rel)] + cmd = [os.path.join(LAUCHER_FOLDER, '{}.sh').format(diar), '{}'.format(temp_rel)] elif diar == 'diartk': - cmd = ['tools/{}.sh'.format(diar), '{}'.format(temp_rel), '{}'.format(sad)] + cmd = [os.path.join(LAUCHER_FOLDER, '{}.sh').format(diar), '{}'.format(temp_rel), '{}'.format(sad)] else: cmd = ['exit 1'] else: # SAD mode - cmd = ['tools/{}.sh'.format(sad), '{}'.format(temp_rel)] + cmd = [os.path.join(LAUCHER_FOLDER, '{}.sh').format(sad), '{}'.format(temp_rel)] subprocess.call(cmd) @@ -266,8 +266,6 @@ def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False) # total duration of the speech of interest tot_dur = 0.0 - # duration of the last silence - silence_dur = 0.0 # type of the last activity previous_activity = None onset_prev = 0.0 @@ -281,18 +279,16 @@ def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False) onset = float(anno_fields[3]) curr_activity = anno_fields[7] - if onset_prev+dur_prev == onset: silence_dur = 0.0 else: silence_dur = onset-onset_prev-dur_prev - if not diar_mode: # SAD mode tot_dur += dur - elif diar_mode and mode == 'CHI' and curr_activity == 'CHI': # Child detection mode + elif diar_mode and mode == 'CHI' and curr_activity == 'CHI': # Child detection mode tot_dur += 1 - elif diar_mode and mode == 'PCCONV': # Parent-child detection mode + elif diar_mode and mode == 'PCCONV': # Parent-child detection mode if detect_parent_child_conv(previous_activity, curr_activity, silence_dur): # Here we consider more an objective function (number of turn-taking) that # we want to maximize. That comes from the fact that adults speak during a @@ -430,7 +426,7 @@ def main(): '''these are again analysed by the SAD tool, the 10%% that ''' ''' contain the most speech are kept, and 300.0s chunks ''' ''' are finally extracted around these kept chunks.''') - parser.add_argument('--percentage', default=10, type=float, + parser.add_argument('--nb_chunks', default=1, type=float, help='''(Optional) Percentage of snippets to keep at each stage. ''' '''By default, we keep 10%% of snippets each time.\n''' '''For a 15h long recording, we have 90x10s snippets, ''' @@ -469,7 +465,7 @@ def main(): # check if temp dir exist and create it if not temp_abs = os.path.join(data_dir, args.temp) - temp_rel = args.temp # to launch SAD tool we need the relative path to temp + temp_rel = args.temp # to launch SAD tool we need the relative path to temp if not os.path.isdir(temp_abs): os.makedirs(temp_abs) @@ -480,9 +476,6 @@ def main(): # get percentage perc = args.percentage / 100.0 - # get path to current (tools/) dir - useful to call the SAD tool - dir_path = os.path.dirname(os.path.realpath(__file__)) - # get duration duration = get_audio_length(wav_abs) From 433199a32864db5f1284d4fc12fecc71a6964fd3 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Mon, 1 Apr 2019 16:52:28 +0200 Subject: [PATCH 240/299] Remove git checkout on vcm (now that it has been forked) --- conf/bootstrap.sh | 3 +-- docs/source/tool_doc.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 819c3e6..969dd48 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -147,8 +147,7 @@ su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" # Install VCM -git clone https://github.com/MilesICL/vcm -(cd vcm && git checkout 93991b0) +git clone https://github.com/srvk/vcm #Install to-combo sad and dependencies (matlab runtime environnement) git clone https://github.com/srvk/To-Combo-SAD diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index 1f06403..adcfd25 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -281,7 +281,7 @@ There is no official reference for this tool. ### Questions and bug reports -https://github.com/MilesICL/vcm/issues/ +https://github.com/srvk/vcm/issues/ # Evaluation From 8b548384072b2c5311806352e11635afdc891bbf Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Mon, 1 Apr 2019 21:19:13 +0200 Subject: [PATCH 241/299] Update high_volubility --- utils/high_volubility.py | 168 ++++++++++++++++++++++++++++----------- 1 file changed, 121 insertions(+), 47 deletions(-) diff --git a/utils/high_volubility.py b/utils/high_volubility.py index 326f33e..b9ddc34 100755 --- a/utils/high_volubility.py +++ b/utils/high_volubility.py @@ -7,16 +7,16 @@ and runs them through a SAD or diarization tool to detect chunks of audio with : 1) a lot of speech. ---> python utils/high_volubility.py file_path.wav --sad noisemes_sad +--> python utils/high_volubility.py file_path.wav --sad noisemesSad 2) a lot of child speech ---> python utils/high_volubility.py file_path.wav --diar yunitator --mode CHI +--> python utils/high_volubility.py file_path.wav --diar yunitator_old --mode CHI --nb_chunks 3 3) a lot of parent-child conversations ---> python utils/high_volubility.py file_path.wav --diar yunitator --mode PCCONV +--> python utils/high_volubility.py file_path.wav --diar yunitator_english --mode PCCONV 4) a lot of adults conversations with a child minimally aware ---> python utils/high_volubility.py file_path.wav --diar yunitator --mode ACCA +--> python utils/high_volubility.py file_path.wav --diar yunitator_universal --mode ACCA """ import os @@ -25,17 +25,18 @@ import wave import math import numpy +import shutil import argparse import subprocess - +import collections from operator import itemgetter -LAUCHER_FOLDER = "~/launcher" +LAUCHER_FOLDER = "/home/vagrant/launcher" def get_audio_length(wav): """ Return duration of Wave file. - Input: + Input: wav: path to the wav file. Output: @@ -66,7 +67,7 @@ def select_onsets(duration, step): def extract_chunks(wav, onset_list, chunk_size, temp): """ Given a list of onset and a length in seconds, extract a snippet of - audio at each onset of this length. The extraction will be done using + audio at each onset of this length. The extraction will be done using SoX, called by subprocess. Input: @@ -77,9 +78,9 @@ def extract_chunks(wav, onset_list, chunk_size, temp): will extract. Output: - 'temp': the output of this function is the set of small wav file of + 'temp': the output of this function is the set of small wav file of 'chunk_size' seconds in the temp folder. - The name of the wav files will be: + The name of the wav files will be: id_onset_length.wav where id is the name of the original wav file, onset is the onset at which the chunk occurs in the original wav file, and @@ -97,6 +98,13 @@ def extract_chunks(wav, onset_list, chunk_size, temp): str_on = (6 - len(str(on))) * '0' + str(on) str_off = (6 - len(str(off))) * '0' + str(off) + chunk_duration = float(str_off) - float(str_on) + if chunk_duration != chunk_size: + missed_duration = chunk_size - chunk_duration + if float(str_on) == 0.0: + str_off = str(float(str_off)+missed_duration) + else: + str_on = str(float(str_on)-missed_duration) chunk_name = '_'.join([basename, str_on, str_off]) # call subprocess @@ -106,7 +114,7 @@ def extract_chunks(wav, onset_list, chunk_size, temp): subprocess.call(cmd) -def run_Model(temp_rel, temp_abs, sad, diar=None): +def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None): """ When all the snippets of sound are extracted, and stored in the temp file, run them through a sad or diar tool, and keep the 10%% that have the most speech. @@ -131,8 +139,12 @@ def run_Model(temp_rel, temp_abs, sad, diar=None): _: In temp, the SAD analyses will be written in RTTM format. """ if diar is not None: # Diarization mode - if diar == 'yunitate': - cmd = [os.path.join(LAUCHER_FOLDER, '{}.sh').format(diar), '{}'.format(temp_rel)] + if diar.startswith('yunitator'): + mode = diar.split("_")[1] + available_flavors = ["old", "english", "universal"] + if mode not in available_flavors: + raise ValueError("Yunitator's flavor not recognized. Should be in %s" % available_flavors) + cmd = [os.path.join(LAUCHER_FOLDER, 'yunitate.sh'), '{}'.format(temp_rel), '{}'.format(mode)] elif diar == 'diartk': cmd = [os.path.join(LAUCHER_FOLDER, '{}.sh').format(diar), '{}'.format(temp_rel), '{}'.format(sad)] else: @@ -142,10 +154,20 @@ def run_Model(temp_rel, temp_abs, sad, diar=None): subprocess.call(cmd) - # After the model has finished running, remove the wav files - for fin in os.listdir(temp_abs): - if fin.endswith('.wav'): - os.remove(os.path.join(temp_abs, fin)) + #After the model has finished running, remove the wav files + if output_dir is None: + for fin in os.listdir(temp_abs): + if fin.endswith('.wav'): + os.remove(os.path.join(temp_abs, fin)) + else: + output_files = [] + for fin in os.listdir(temp_abs): + if not os.path.isfile(os.path.join(output_dir, fin)): + shutil.move(os.path.join(temp_abs, fin), output_dir) + if fin[-5:] == ".rttm": + output_files.append(os.path.join(output_dir, fin)) + return output_files + def extract_base_name(filename, diar): @@ -161,9 +183,9 @@ def extract_base_name(filename, diar): Output: base : wavfilename_tbeg_tdur """ - if diar == 'yunitate': + if diar in ["noisemesSad", "tocomboSad", "opensmileSad"]: base = filename.split('_')[1:] - else: + else: # diartk and yunitator base = filename.split('_')[2:] base = os.path.splitext('_'.join(base))[0] @@ -216,7 +238,7 @@ def detect_adults_conv(previous_activity, curr_activity, last_silence_dur): return True return False -def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False): +def read_analyses(temp_abs, sad, nb_chunks, diar=None, mode='CHI', child_aware=False, keep_rttm=False): """ When the model has finished producing its outputs, read all the transcriptions and sort the files by the quantity of their speech content or the quantity of their speech belonging to the noiseme_class. @@ -228,13 +250,13 @@ def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False) the path. sad: name of the sad tool to be used to analyze the snippets of sound. - perc: the percentage of speech to keep. + nb_chunks: the number of chunks that need to be kept (the ones containing the most speech). diar: the diarization model (if provided). mode: the type of speech that needs to be kept (has to be amongst ['CHI']). child_aware : (only used if mode == ACCA) Indicates, if we should filter the snippets that don't present any child activity. - Output: + Output: sorted_files: list(str), list of the files, sorted by the quantity of the speech content (as returned by the SAD tool) or the quantity of the speech content classified as @@ -260,7 +282,6 @@ def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False) # we extract the base name composed of wav_file_name + t_deg + t_dur base = extract_base_name(file, diar) - with open(os.path.join(temp_abs, file), 'r') as fin: speech_activity = fin.readlines() @@ -308,7 +329,10 @@ def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False) files_n_dur.append((base, tot_dur, chi_points)) # remove annotation when finished reading - os.remove(os.path.join(temp_abs, file)) + if keep_rttm: + os.move(os.path.join(temp_abs, file), ) + else: + os.remove(os.path.join(temp_abs, file)) if child_aware and diar_mode == 'ACCA': files_n_dur = [file for file in files_n_dur if file[2] > 3] @@ -319,10 +343,10 @@ def read_analyses(temp_abs, sad, perc, diar=None, mode='CHI', child_aware=False) files_n_dur = sorted(files_n_dur, key=itemgetter(1), reverse=True) - # return top 10%% of snippets - percent = max(1, int(math.ceil(perc * len(files_n_dur)))) + # Extract the nb_chunks snippets that contain the have the highest score + nb_chunks = min(len(files_n_dur), nb_chunks) - sorted_files = files_n_dur[:percent] + sorted_files = files_n_dur[:nb_chunks] return sorted_files @@ -353,7 +377,6 @@ def new_onsets_two_minutes(sorted_files): # new segment is centered around snippet, so get middle of snippet new_onset = length / 2 + float(onset) - new_onset_list.append(new_onset) return new_onset_list @@ -381,13 +404,64 @@ def new_onsets_five_minutes(sorted_files): offset = os.path.splitext(snippet)[0].split('_')[-1] # new segment starts 2 minute before the 2 minute chunk - new_onset = float(onset) - 120.0 + new_onset = max(0.0, float(onset) - 120.0) + new_onset_list.append(new_onset) return new_onset_list +def write_final_stats(output_rttm): + stats = collections.OrderedDict([("filename", None), + ("CHI_duration", 0.0), + ("MAL_duration", 0.0), + ("FEM_duration", 0.0), + ("ADU_ADU_turntaking", 0), + ("ADU_CHI_turntaking", 0)]) + original_name = '_'.join(os.path.basename(output_rttm[0]).split('_')[:-2]) + output_stats = os.path.join(os.path.dirname(output_rttm[0]), "high_volubility_stats_" + original_name + ".txt") + with open(output_stats, "w") as fout: + fout.write(",".join(stats.keys())) + fout.write("\n") + + for file in output_rttm: + stats["filename"] = os.path.basename(file).replace(".rttm", "") + with open(file, "r") as rttm: + # type of the last activity + previous_activity = None + onset_prev = 0.0 + dur_prev = 0.0 + for line in rttm: + anno_fields = line.split(' ') + dur = float(anno_fields[4]) + onset = float(anno_fields[3]) + curr_activity = anno_fields[7] + + if onset_prev + dur_prev == onset: + silence_dur = 0.0 + else: + silence_dur = onset - onset_prev - dur_prev + + stats[curr_activity+"_duration"] += dur + if detect_adults_conv(previous_activity, curr_activity, silence_dur): + stats["ADU_ADU_turntaking"] += 1 + if detect_parent_child_conv(previous_activity, curr_activity, silence_dur): + stats["ADU_CHI_turntaking"] += 1 + + previous_activity = curr_activity + onset_prev = onset + dur_prev = dur + fout.write(",".join(str(x) for x in stats.values())) + fout.write("\n") + + # Go back to 0 + stats = collections.OrderedDict([("filename", None), + ("CHI_duration", 0.0), + ("MAL_duration", 0.0), + ("FEM_duration", 0.0), + ("ADU_ADU_turntaking", 0), + ("ADU_CHI_turntaking", 0)]) def main(): """ Get duration of wav file @@ -426,14 +500,9 @@ def main(): '''these are again analysed by the SAD tool, the 10%% that ''' ''' contain the most speech are kept, and 300.0s chunks ''' ''' are finally extracted around these kept chunks.''') - parser.add_argument('--nb_chunks', default=1, type=float, - help='''(Optional) Percentage of snippets to keep at each stage. ''' - '''By default, we keep 10%% of snippets each time.\n''' - '''For a 15h long recording, we have 90x10s snippets, ''' - '''we keep the 10%% with the most speech content, that ''' - '''lead to 9x120s snippets, we again keep the 10%% with the ''' - '''most speech content, so in the end we have 1x300 seconds ''' - '''segment.''') + parser.add_argument('--nb_chunks', default=5, type=float, + help='''(Optional) Number of snippets to keep at the last stage. ''' + '''By default, we keep the top 5 snippets that have the most speech content.\n''') parser.add_argument('--temp', default='tmp', help='''(Optional) Path to a temp folder in which the small wav ''' '''segments will be stored. If it doesn't exist, it will be ''' @@ -473,8 +542,8 @@ def main(): # Define absolute path to wav file wav_abs = os.path.join(data_dir, args.daylong) - # get percentage - perc = args.percentage / 100.0 + # get number of chunks that need to be kept + nb_chunks = int(args.nb_chunks) # get duration duration = get_audio_length(wav_abs) @@ -489,11 +558,9 @@ def main(): run_Model(temp_rel, temp_abs, args.sad, args.diar) # sort by speech duration - sorted_files = read_analyses(temp_abs, args.sad, perc, args.diar, args.mode) - + sorted_files = read_analyses(temp_abs, args.sad, nb_chunks*3, args.diar, args.mode) # get new onsets for two minutes chunks new_onset_list = new_onsets_two_minutes(sorted_files) - # extract two minutes chunks extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[1], temp_abs) @@ -505,15 +572,22 @@ def main(): if args.mode == 'ACCA': child_aware = True - sorted_files = read_analyses(temp_abs, args.sad, perc, args.diar, args.mode, child_aware) - + sorted_files = read_analyses(temp_abs, args.sad, nb_chunks, args.diar, args.mode, child_aware) # get new onsets for five minutes chunks new_onset_list = new_onsets_five_minutes(sorted_files) - # extract final five minutes long chunks + extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[2], temp_abs) + + ## Run one last time the model to get the transcription + # analyze using SAD tool output_dir = os.path.dirname(wav_abs) - extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[2], output_dir) + output_rttm = run_Model(temp_rel, temp_abs, args.sad, args.diar, output_dir) + + #output_rttm = ["/vagrant/data/daylong/yunitator_english_0396_sub_1085.0_1385.0.rttm"] + write_final_stats(output_rttm) + + if __name__ == '__main__': - main() + main() \ No newline at end of file From 177ace2f71ec63ee16a25052ecd29f741cf73991 Mon Sep 17 00:00:00 2001 From: alecristia Date: Thu, 11 Apr 2019 20:16:02 +0200 Subject: [PATCH 242/299] correct frankenstein instructions --- docs/source/install.md | 19 ++-- docs/source/usage.md | 191 ++++++----------------------------------- 2 files changed, 36 insertions(+), 174 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 503abda..51e8209 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -4,6 +4,14 @@ DiViMe can be installed in any operating system and computer with at least 1 CPU (and occupying 2GB when active). You may need to make some adaptations for known issues. Specifically, *before following the instructions under "First Installation"*, you must follow the instructions in the relevant subsection of the Troubleshooting section, at the end of this page, in the following cases: +- your computer has only one core +- your computer has 20 GB or less of storage space +- your computer has 6 GB or less of RAM +- your computer is running ubuntu (e.g., 16.04) + + +## First Installation + 1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link and follow the prompted instructions 2. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. @@ -58,8 +66,8 @@ DiarTK passed the test. Testing Yunitator... Yunitator passed the test. -Testing the evaluation pipeline... -The evaluation pipeline passed the test. +Testing DScore... +Yunitator passed the test. Congratulations, everything is OK! @@ -67,14 +75,9 @@ Congratulations, everything is OK! ``` -Congratulations, everything is OK! - -- For noisemesSad, and diartk, you may get an error "failed the test because a dependency was missing. Please re-read the README for DiViMe installation, Step number 4 (HTK installation)." This means that your HTK installation was not successful. Please re-download the - - ## Updating DiViMe -If there is a new version of DiViMe, you will need to perform the following 3 steps from within the DiViME folder on your terminal: +If you want to install a new release of DiViMe, you will need to perform the following 3 steps from within the DiViME folder on your terminal: ``` diff --git a/docs/source/usage.md b/docs/source/usage.md index 28d5e88..35b80da 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -27,7 +27,7 @@ You can drop a whole folder into ```data```. You will provide the path to the sp If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. -If you have any annotations, put them also in the same "data" folder. Annotations can be in .eaf, .textgrid, or .rttm format, and *they should be named exactly as your wav files*. For more information on these formats, see the Format section. +If you have any annotations, put them also in the same "data" folder. Annotations must be in .rttm format, and *they should be named exactly as your wav files*. If you have annotations in .cha, .eaf, .textgrid, or .its, see the Format section for instructions on converting them into .rttm. IMPORTANT: If you already analyzed a file with a given tool, re-running the tool will result in the previous analysis being overwritten. @@ -133,29 +133,25 @@ You can read that command as follows: *noisemesSad*: Remember that this tool does "talker diarization": Given some speech, attribute it to a speaker. Therefore, this type of tool necessitates speech/voice activity detection. This third argument tells DiViMe what file contains information about which sections of the sound file contain speech. -You can only use one of the following options: textgrid, eaf, rttm, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. +You can only use one of the following options: rttm, opensmileSad, tocomboSad, noisemesSad. We explain each of these options next. -You can provide annotations done by a human or in some other way, and encoded as one of the following three file types: +You can provide annotations done by a human or in some other way, and encoded as rttms. If you have a different format, see the Format section. *What is crucial for this procedure to work is that your rttm's reflection your human-annotation are called exactly like your sound files.* Notice that all annotations that say "speech" in the eighth column count as such. -- textgrid: this means you want the system to use your textgrid annotations. Notice that all tiers count, so if you have some tiers that are non-speech, you should remove them from your textgrids before you start. Please note that the system will convert your textgrids into .rttm in the process. -- eaf: this means you want the system to use your eaf annotations. Notice that we only know how to properly process .eaf files that follow the [ACLEW Annotation Scheme](https://osf.io/b2jep/wiki/home/). Please note that the system will convert your eafs into .rttm in the process. -- rttm: this means you want the system to use your rttm annotations. Notice that all annotations that say "speech" in the eight column count as such. +Alternatively, you can use automatic annotations generated by DiViMe's speech/voice activity detection systems, encoded in rttm files. In this case, you would pass one of the following options: -Alternatively, you can provide use automatic annotations generated by DiViMe's speech/voice activity detection systems, encoded in rttm files. In this case, you would pass one of the following options: - -- this system before: this means you want the system to use the output of the noisemesSad system. If you have not run noisemesSad, the system will fail. +- noisemesSad: this means you want the system to use the output of the noisemesSad system. If you have not run noisemesSad, the system will fail. - opensmileSad: this means you want the system to use the output of the opensmile system. If you have not run this system before, the system will fail. - tocomboSad: this means you want the system to use the output of the tocomboSad system. If you have not ran this system before, the system will fail. If the third parameter is not provided, the system will give an error. -If all three parameters are provided, then the system will first find all the annotation files matching the third parameter (e.g., all the files *.TextGrid; or all the tocomboSad_*.rttm files), and then find the corresponding sound files. For example, imagine you have put into your ```data/mydata/``` folder the following files: +If all three parameters are provided, then the system will first find all the annotation files matching the third parameter (e.g., all the human-annotated files *.rttm; or all the tocomboSad_*.rttm files), and then find the corresponding sound files. For example, imagine you have put into your ```data/mydata/``` folder the following files: - participant23.wav - opensmileSad_participant23.rttm - participant24.wav -- participant24.TextGrid +- participant24.rttm If you run: @@ -165,105 +161,6 @@ If you run: then only participant23.wav will be analyzed. -If you run: - -`$ vagrant ssh -c "diartk.sh data/mydata/ textgrid"` - -then only participant24.wav will be analyzed. - -At the end of the process, there will be an added rttm file for each analyzed file. For instance, if you have just one sound file (participant23.wav) at the beginning and you run opensmileSad followed by diartk, then you will end up with the following three files: - -- participant23.wav: your original sound file -- opensmileSad_participant23.rttm: the output of opensmileSad, which states where there is speech -- diartk_opensmileSad_participant23.rttm: the output of opensmileSad followed by diartk, which states which speech sections belong to which speakers. - -If you look inside a diartk_*.rttm file, it will look as follows: - -``` -SPEAKER file17 1 4.2 0.4 talker0 -SPEAKER file17 1 4.6 1.2 talker0 -SPEAKER file17 1 5.8 1.1 talker1 -SPEAKER file17 1 6.9 1.2 talker0 -SPEAKER file17 1 8.1 0.7 talker1 -``` - -This means that diartk considered that one talker spoke starting at 4.2 seconds for .4 seconds; starting at 4.6 for 1.2 seconds; then someone else spoke starting at 5.8 seconds and for 1.1 seconds; etc. - -### How to run a Role assignment tool - -For these tools, type a command like this one: - -`$ vagrant ssh -c "yunitator.sh data/mydata/"` - -You can read that command as follows: - -*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. - -*yunitator.sh*: This first argument tells DiViMe which tool to run. The options are: yunitator. - -*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. - -It returns one rttm per sound file, with an estimation of where there are vocalizations by children, female adults, and male adults. - -### How to run a Vocalization classification tool - -vcm - -NO INFORMATION YET - -### How to run an Evaluation - -If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. - -#### Evaluating Speech/Voice activity detection - -Type a command like the one below: - -`$ vagrant ssh -c "evalSAD.sh data/ noisemesSad"` - -You can read that command as follows: - -*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. - -*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. - -*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. - -*noisemesSad*: The third argument indicates which tool's output to evaluate (in this case, noisemesSad). All of our Speech/Voice activity detection tools can be evaluated with this. - -For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). - -#### Evaluating Speech/Voice activity detection - -Type a command like the one below: - -`$ vagrant ssh -c "evalDiar.sh data/ diartk_noisemesSad"` - -You can read that command as follows: - -*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. - -*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. - -*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. - -* diartk_noisemesSad*: The third argument indicates which output to evaluate. - -**THIS NEEDS WORK** - -For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. If this does not exist, it will look for .eaf files (i.e., participant23.eaf). Finally, if those don't exist, it will check for .textgrid ones (i.e., participant23.TextGrid). - -## An alternative for Step 4: using recipes - -**THIS NEEDS WORK** - -## Further information on Step 5, putting DiViMe back to sleep - -Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: - -then only participant23.wav will be analyzed. - - If you run: `$ vagrant ssh -c "diartk.sh data/mydata/ rttm"` @@ -316,83 +213,45 @@ The vocalization classification tool returns one rttm per sound file, with an es See Format section for explanation on how to read the resulting rttm. -### How to evaluate models +### How to run an Evaluation If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. -Type a command like the one below : +#### Evaluating Speech/Voice activity detection -`$ vagrant ssh -c "eval.sh data/ tocomboSad accuracy"` +Type a command like the one below: + +`$ vagrant ssh -c "evalSAD.sh data/ noisemesSad"` You can read that command as follows: *vagrant ssh -c*: This tells DiViMe that it needs to run a tool. -*eval.sh*: This first argument tells DiViMe which tool to run. Here, we want to run an evaluation. - -*data/*: This second argument tells DiViMe where are the sound files to analyze. This directory must also contain the annotations generated by the model and the gold annotations. - -*noisemesSad*: The third argument indicates which tool's output to evaluate. - -*accuracy*: The fourth argument tells DiViMe which metric need to be used to assess the model's performances. Here, we want to use the well-known accuracy measure. - -The output should look like this : - -``` -accuracy report - detection accuracy true positive true negative false positive false negative - % -item -my_file1.rttm 48.73 30.49 27.16 44.47 16.18 -my_file2.rttm 57.00 12.32 55.13 40.36 10.53 -TOTAL 52.86 42.81 82.29 84.83 26.71 -``` - -It generates a table showing the scores obtained for each file. -Since it is usually not enough to look at the final metric (the detection accuracy here), the table also shows intermediate metrics, therefore allowing the user to have a better insight of model's performances. -Note that this table will be saved in the .csv format in the *data/* folder. - -Here, all the metrics that are implemented : - -
- -| Speech Activity Detection | Diarization | Identification | -|---|---|---| -| Accuracy | Completeness | Identification Error Rate | -| Detection Error Rate | Coverage | Precision | -| Precision | Diarization Error Rate | Recall | -| Recall | Homogeneity | | -| | Purity | | - -
All metrics that are implemented. A more extensive documentation is available here
-
+*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. -  - -Where the identification task is the same as the diarization task when the one-to-one mapping between the reference talkers and the hypothesis ones is known. -To assess a diarization model's performances in the identification mode, you need to type the following command : +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. -`$ vagrant ssh -c "eval.sh data/ diartk_tocomboSad completeness --identification"` +*noisemesSad*: The third argument indicates which tool's output to evaluate (in this case, noisemesSad). All of our Speech/Voice activity detection tools can be evaluated with this. -If the flag *-\-identification* is not passed, the script will run in the diarization mode. +For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. -Note that you can ask to compute several metrics at once by typing : +#### Evaluating Diarization or Talker type -`$ vagrant ssh -c "eval.sh data/ tocomboSad accuracy precision recall"` +Type a command like the one below: -It will generate a report for each metric. +`$ vagrant ssh -c "evalDiar.sh data/ diartk_noisemesSad"` -If you're not a math person, you can add the -\-visualization flag by typing : +You can read that command as follows: -`$ vagrant ssh -c "eval.sh data/ tocomboSad accuracy precision recall --visualization"` +*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. -It will extract the minute that contains the most speech for each file and align the reference and the hypothesis segments : +*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. -![
One minute alignement that has been obtained by adding the flag --visualization
](../images/example_visu.png) +*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. +*diartk_noisemesSad*: The third argument indicates which output to evaluate. Another example: yunitator. -Note that the process of calcuting the minute that contains the most speech can be time-consuming. -We therefore advise you to use this flag only when processing little data. +For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. ## An alternative for Step 4: using recipes From 61ad867aaaf65561fffcd9c628a0c4fd6ffd803c Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Fri, 12 Apr 2019 13:52:03 +0200 Subject: [PATCH 243/299] Try *.sh text eol=lf in gitignore to avoid bash script issues --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index e6f8acd..b8935e5 100755 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ vignettes/*.pdf # Temporary files created by R markdown *.utf8.md *.knit.md + +# To avoid issues with bash scripts when git cloning on windows +*.sh text eol=lf From 4c9d38654be3808687819c069fe6ea152812af66 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Tue, 16 Apr 2019 14:59:13 +0200 Subject: [PATCH 244/299] Update HTK instructions --- docs/source/install.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/install.md b/docs/source/install.md index 51e8209..cbef2db 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -25,7 +25,7 @@ DiViMe can be installed in any operating system and computer with at least 1 CPU - Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) - Register by following the instructions on the left (under "Getting HTK": Register) - Check that you have received your password via email; you will need it for the next step. - - Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. + - Find the link that reads "HTK source code" under Linux/Unix downloads (since the latter will be installed within the VM which runs under Unix). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. - Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). 6. Type `$ vagrant up` From 39b83c671301a07523fc7d0d94ad1f87a647fd33 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Tue, 16 Apr 2019 15:25:46 +0200 Subject: [PATCH 245/299] Update doc for new evaluation pipeline --- docs/source/install.md | 4 +-- docs/source/usage.md | 66 ++++++++++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index cbef2db..a1722dc 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -66,8 +66,8 @@ DiarTK passed the test. Testing Yunitator... Yunitator passed the test. -Testing DScore... -Yunitator passed the test. +Testing the evaluation pipeline... +The evaluation pipeline passed the test. Congratulations, everything is OK! diff --git a/docs/source/usage.md b/docs/source/usage.md index 35b80da..3c6760f 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -217,41 +217,75 @@ See Format section for explanation on how to read the resulting rttm. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. -#### Evaluating Speech/Voice activity detection - Type a command like the one below: -`$ vagrant ssh -c "evalSAD.sh data/ noisemesSad"` +`vagrant ssh -c "eval.sh data/ tocomboSad accuracy"`` You can read that command as follows: *vagrant ssh -c*: This tells DiViMe that it needs to run a tool. -*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. +*eval.sh*: This first argument tells DiViMe that we want to perform an evaluation. -*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. +*data/*: This second argument tells DiViMe where are the sound files that need to be evaluated. This directory must contain both the annotations generated by the model and the human-made ones. -*noisemesSad*: The third argument indicates which tool's output to evaluate (in this case, noisemesSad). All of our Speech/Voice activity detection tools can be evaluated with this. +*noisemesSad*: The third argument indicates which tool's output to evaluate. -For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. +*accuracy*: The fourth argument tells DiViMe which metric need to be used to assess the model's performances. Here, we want to use the well-known accuracy measure. -#### Evaluating Diarization or Talker type +The output should look like this : -Type a command like the one below: +``` +accuracy report + detection accuracy true positive true negative false positive false negative + % +item +my_file1.rttm 48.73 30.49 27.16 44.47 16.18 +my_file2.rttm 57.00 12.32 55.13 40.36 10.53 +TOTAL 52.86 42.81 82.29 84.83 26.71 +``` -`$ vagrant ssh -c "evalDiar.sh data/ diartk_noisemesSad"` +It generates a table showing the scores obtained for each file. +Since it is usually not enough to look at the final metric (the detection accuracy here), the table also shows intermediate metrics, therefore allowing the user to have a better insight of model's performances. +Note that this table will be saved in the .csv format in the *data/* folder. -You can read that command as follows: +Here, all the metrics that are implemented : -*vagrant ssh -c*: This tells DiViMe that it needs to run a tool. +
-*evalSAD.sh*: This first argument tells DiViMe which tool to run. The options are: evalSAD.sh. +| Speech Activity Detection | Diarization | Identification | +|---|---|---| +| Accuracy | Completeness | Identification Error Rate | +| Detection Error Rate | Coverage | Precision | +| Precision | Diarization Error Rate | Recall | +| Recall | Homogeneity | | +| | Purity | | -*data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. +
All metrics that are implemented. A more extensive documentation is available here
+
+ +Note that the identification task is the same as the diarization task when the one-to-one mapping between hypothesis classes and reference classes share the same labels. +To assess diarization model's performances in the identification mode, you need to type the following command : + +`vagrant ssh -c "eval.sh data/ diartk_tocomboSad completeness --identification"` + +If the flag *-\-identification* is not passed, the script will run in the diarization mode. + +Note that you can ask to compute several metrics at once by typing : + +`vagrant ssh -c "eval.sh data/ tocomboSad accuracy precision recall"` + +It will generated a report for each metric. + +If you're not a math person, you can add the -\-visualization flag by typing : + +`vagrant ssh -c "eval.sh data/ tocomboSad accuracy precision recall --visualization"` + +It will extract the minute that contains the most speech for each file and align the reference and the hypothesis segments : -*diartk_noisemesSad*: The third argument indicates which output to evaluate. Another example: yunitator. +![
One minute alignement that has been obtained by adding the flag --visualization
](../images/example_visu.png) -For the evaluation process, YOU MUST PROVIDE files that have the coding by humans. For each sound file that has been analyzed with that tool (e.g., in the example, for each file called noisemesSad*.rttm), the system will generate the name of the sound file (by removing "noisemesSad" and ".rttm". Then it will look for .rttm annotations; for instance, in our running example, it will look for a file called participant23.rttm. +Note that the process of calcuting the minute that contains the most speech can be time-consuming. ## An alternative for Step 4: using recipes From 556fbea1eb0f6935a64fb4b8cfaacd562fda0122 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Tue, 16 Apr 2019 18:01:45 -0400 Subject: [PATCH 246/299] Revert HTK instructions --- docs/source/install.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/install.md b/docs/source/install.md index a1722dc..69e5522 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -25,7 +25,7 @@ DiViMe can be installed in any operating system and computer with at least 1 CPU - Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) - Register by following the instructions on the left (under "Getting HTK": Register) - Check that you have received your password via email; you will need it for the next step. - - Find the link that reads "HTK source code" under Linux/Unix downloads (since the latter will be installed within the VM which runs under Unix). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. + - Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. - Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). 6. Type `$ vagrant up` From 8fa6e84de33d863d0944989b6ab2826ec3f1b3d3 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Tue, 16 Apr 2019 18:58:45 -0400 Subject: [PATCH 247/299] HTK for Linux must be installed, no matter on which OS the VM installed on --- docs/source/install.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/install.md b/docs/source/install.md index 69e5522..a1722dc 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -25,7 +25,7 @@ DiViMe can be installed in any operating system and computer with at least 1 CPU - Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) - Register by following the instructions on the left (under "Getting HTK": Register) - Check that you have received your password via email; you will need it for the next step. - - Find the link that reads "HTK source code" under your system (if you have a mac, it will be under "Linux/unix downloads"). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. + - Find the link that reads "HTK source code" under Linux/Unix downloads (since the latter will be installed within the VM which runs under Unix). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. - Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). 6. Type `$ vagrant up` From 6b5775ce77202c3d4e65b8b4eecc4e2c96eed115 Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Wed, 17 Apr 2019 16:45:32 +0200 Subject: [PATCH 248/299] Make evaluation pipeline safer --- utils/compute_metrics.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py index d83c585..581e716 100644 --- a/utils/compute_metrics.py +++ b/utils/compute_metrics.py @@ -67,7 +67,9 @@ def rttm_to_annotation(input_rttm, collapse_to_speech=False): if row[7] == "": raise ValueError("Speaker role is empty in %s" % os.path.basename(input_rttm)) anno[Segment(t_beg, t_beg + t_dur)] = spkr - return anno + return anno + else: + raise ValueError("%s not found. Please create it (even though it's empty) or remove the wav from the folder you want to evaluate." % os.path.basename(input_rttm)) def run_metrics(references_f, hypothesis_f, metrics, visualization=False): @@ -215,7 +217,6 @@ def main(): # Display a report for each metrics for name, m in metrics.items(): print("\n%s report" % name) - print(m) rep = m.report(display=True) colnames = list(rep.columns.get_level_values(0)) percent_or_count = rep.columns.get_level_values(1) From 82265d2ae7c3ccf1c02cfc8cdd8d9a646e70cb15 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Tue, 7 May 2019 23:11:02 -0400 Subject: [PATCH 249/299] initial choice of output formats for eaf2txt --- utils/eaf2txt.py | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/utils/eaf2txt.py b/utils/eaf2txt.py index 3f43e5d..4878b61 100755 --- a/utils/eaf2txt.py +++ b/utils/eaf2txt.py @@ -1,16 +1,21 @@ +#!/usr/bin/env python + """ -This script converts an eaf file into a txt file containing the following information : +This script converts an eaf file into a txt file +containing the following information : -onset offset transcription receiver speaker_tier + onset offset transcription receiver speaker_tier -It can be run either on a single eaf file, or on a whole folder containing eaf files. +It can be run either on a single eaf file, +or on a whole folder containing eaf files. Example of use : python tools/eaf2txt.py -i data/0396.eaf # One one file python tools/eaf2txt.py -i data/ # On a whole folder About the naming convention of the output : - For each file called input_file.eaf, the result will be stored in input_file.txt + For each file called input_file.eaf, + the result will be stored in input_file.txt """ import pympi as pmp @@ -21,7 +26,7 @@ reload(sys) sys.setdefaultencoding('utf8') -def eaf2txt(path_to_eaf, output_folder, cleanup=False): +def eaf2txt(path_to_eaf, output_folder, cleanup=False, format='okko'): """ Convert an eaf file to the txt format by extracting the onset, offset, ortho, and the speaker tier. Note that the ortho field has been made by a human and needs @@ -57,13 +62,26 @@ def eaf2txt(path_to_eaf, output_folder, cleanup=False): if cleanup: transcript = clean_up_annotation(transcript) - output_file.write("%d\t%d\t%s\t%s\t%s\n" % (onset, offset, str(receiver), str(transcript), str(speaker))) + if format == 'okko': + output_file.write("%d\t%d\t%s\t%s\t%s\n" % (onset, offset, str(receiver), str(transcript), str(speaker))) + elif 'LINGUISTIC_TYPE_REF' in parameters and parameters['LINGUISTIC_TYPE_REF'] == 'XDS': + output_file.write("%s\t%d\t%d\t%s\t%s\t%s\t%s\t%s\n" % (str(speaker), onset, offset, str(receiver), 'NA', 'NA', 'NA', str(transcript))) + elif 'LINGUISTIC_TYPE_REF' in parameters and parameters['LINGUISTIC_TYPE_REF'] == 'VCM': + l=len(str.split(str(transcript))) + lex='0' if l == 0 else 'W' + mwu='M' if l > 1 else '1' + output_file.write("%s\t%d\t%d\t%s\t%s\t%s\t%s\t%s\n" % (str(speaker), onset, offset, 'NA', str(receiver), lex, mwu, str(transcript))) + else: + pass + output_file.close() def main(): parser = argparse.ArgumentParser(description="convert .eaf into .rttm") parser.add_argument('-i', '--input', type=str, required=True, help="path to the input .eaf file or the folder containing eaf files.") + parser.add_argument('-f', '--format', type=str, required=False, default='okko', + help="format flag, 'okko' or 'marisa'.") args = parser.parse_args() # Removing extra beginning / that might break the code @@ -86,12 +104,12 @@ def main(): os.mkdir(output) if args.input[-4:] == '.eaf': # A single file has been provided by the user - eaf2txt(args.input, output) + eaf2txt(args.input, output, format=args.format) else: # A whole folder has been provided eaf_files = glob.iglob(os.path.join(args.input, '*.eaf')) for eaf_path in eaf_files: print("Processing %s" % eaf_path) - eaf2txt(eaf_path, output) + eaf2txt(eaf_path, output, format=args.format) if __name__ == '__main__': main() From bb2449c54c3663663542b888fa26c19b612b82d7 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 15 May 2019 19:41:03 -0400 Subject: [PATCH 250/299] added check for small memory situation --- launcher/yunitate.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index d251f69..333e25a 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -72,6 +72,8 @@ done # This setting was chosen arbitrarily and was successful for tests at 2GB-4GB. chunksize=$(free | awk '/^Mem:/{print $2}') let chunksize=$chunksize/100000*200 +[ $chunksize -gt 0 ] || echo You seem to have very little free memory. Things may be slow. +[ $chunksize -gt 0 ] || let chunksize=1000 python yunified.py yunitator $audio_dir $chunksize $MODE # MODE equal to old, english or universal From 63fa185bd31e039b5a18a2ffb996f09419e71106 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 15 May 2019 19:43:05 -0400 Subject: [PATCH 251/299] fixed logic error --- launcher/yunitate.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 333e25a..8314f9a 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -72,8 +72,8 @@ done # This setting was chosen arbitrarily and was successful for tests at 2GB-4GB. chunksize=$(free | awk '/^Mem:/{print $2}') let chunksize=$chunksize/100000*200 -[ $chunksize -gt 0 ] || echo You seem to have very little free memory. Things may be slow. -[ $chunksize -gt 0 ] || let chunksize=1000 +[ $chunksize -eq 0 ] || echo You seem to have very little free memory. Things may be slow. +[ $chunksize -eq 0 ] || let chunksize=1000 python yunified.py yunitator $audio_dir $chunksize $MODE # MODE equal to old, english or universal From a459b62bb10140be46112096def996401204a25d Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Sat, 18 May 2019 00:22:17 -0400 Subject: [PATCH 252/299] made temp folder in high_volubility.py automatic by default --- LICENSE | 0 README.md | 0 launcher/yunitate.sh | 7 ++++--- utils/high_volubility.py | 31 +++++++++++++++++++++---------- 4 files changed, 25 insertions(+), 13 deletions(-) mode change 100755 => 100644 LICENSE mode change 100755 => 100644 README.md diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 8314f9a..7622bd2 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -47,10 +47,10 @@ filename=$(basename "${audio_dir}") dirname=$(dirname "${audio_dir}") extension="${filename##*.}" basename="${filename%.*}" + # Check audio_dir to see if empty or if contains empty wav bash /home/vagrant/utils/check_folder.sh ${audio_dir} - # let's get our bearings: set CWD to the path of Yunitator cd $YUNITATDIR @@ -72,8 +72,9 @@ done # This setting was chosen arbitrarily and was successful for tests at 2GB-4GB. chunksize=$(free | awk '/^Mem:/{print $2}') let chunksize=$chunksize/100000*200 -[ $chunksize -eq 0 ] || echo You seem to have very little free memory. Things may be slow. -[ $chunksize -eq 0 ] || let chunksize=1000 +[ $chunksize -eq 0 ] && echo You seem to have very little free memory. Things may be slow: +[ $chunksize -eq 0 ] && free +[ $chunksize -eq 0 ] && let chunksize=1000 python yunified.py yunitator $audio_dir $chunksize $MODE # MODE equal to old, english or universal diff --git a/utils/high_volubility.py b/utils/high_volubility.py index b9ddc34..3471000 100755 --- a/utils/high_volubility.py +++ b/utils/high_volubility.py @@ -29,6 +29,8 @@ import argparse import subprocess import collections +import tempfile +import shutil from operator import itemgetter LAUCHER_FOLDER = "/home/vagrant/launcher" @@ -500,10 +502,10 @@ def main(): '''these are again analysed by the SAD tool, the 10%% that ''' ''' contain the most speech are kept, and 300.0s chunks ''' ''' are finally extracted around these kept chunks.''') - parser.add_argument('--nb_chunks', default=5, type=float, + parser.add_argument('--nb_chunks', default=5, type=int, help='''(Optional) Number of snippets to keep at the last stage. ''' '''By default, we keep the top 5 snippets that have the most speech content.\n''') - parser.add_argument('--temp', default='tmp', + parser.add_argument('--temp', default='(auto)', help='''(Optional) Path to a temp folder in which the small wav ''' '''segments will be stored. If it doesn't exist, it will be ''' '''created.''') @@ -529,14 +531,22 @@ def main(): print("Resetting step at 300.0 seconds (more suitable for CHI/PCCONV/ACCA mode).") args.step = 300.0 - # Define Data dir + # Sanity check and auto-generation of temp dir + if os.path.isabs(args.temp) or os.path.isabs(args.daylong): + sys.exit("Paths must be relative, not "+args.temp+" or "+args.daylong) + + # Define data dir data_dir = "/vagrant" - # check if temp dir exist and create it if not - temp_abs = os.path.join(data_dir, args.temp) - temp_rel = args.temp # to launch SAD tool we need the relative path to temp - - if not os.path.isdir(temp_abs): + # to launch SAD tool we need the relative path to temp + if args.temp == '(auto)': + temp_abs = tempfile.mkdtemp(dir=data_dir) + temp_rel = os.path.basename(temp_abs) + del_temp = True + else: + temp_abs = os.path.join(data_dir, args.temp) + temp_rel = args.temp + del_temp = False os.makedirs(temp_abs) # Define absolute path to wav file @@ -586,8 +596,9 @@ def main(): #output_rttm = ["/vagrant/data/daylong/yunitator_english_0396_sub_1085.0_1385.0.rttm"] write_final_stats(output_rttm) - + if del_temp: + shutil.rmtree(temp_abs) if __name__ == '__main__': - main() \ No newline at end of file + main() From b93ff32f1618d376a45ff5e2f8c317c42a1bfc86 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Tue, 21 May 2019 19:50:55 -0400 Subject: [PATCH 253/299] added output switch --- utils/high_volubility.py | 45 ++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/utils/high_volubility.py b/utils/high_volubility.py index 3471000..b187b35 100755 --- a/utils/high_volubility.py +++ b/utils/high_volubility.py @@ -33,7 +33,7 @@ import shutil from operator import itemgetter -LAUCHER_FOLDER = "/home/vagrant/launcher" +LAUNCHER_FOLDER = "/home/vagrant/launcher" def get_audio_length(wav): """ Return duration of Wave file. @@ -145,18 +145,18 @@ def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None): mode = diar.split("_")[1] available_flavors = ["old", "english", "universal"] if mode not in available_flavors: - raise ValueError("Yunitator's flavor not recognized. Should be in %s" % available_flavors) - cmd = [os.path.join(LAUCHER_FOLDER, 'yunitate.sh'), '{}'.format(temp_rel), '{}'.format(mode)] + sys.exit("Yunitator's flavor not recognized. Should be in %s" % available_flavors) + cmd = [os.path.join(LAUNCHER_FOLDER, 'yunitate.sh'), '{}'.format(temp_rel), '{}'.format(mode)] elif diar == 'diartk': - cmd = [os.path.join(LAUCHER_FOLDER, '{}.sh').format(diar), '{}'.format(temp_rel), '{}'.format(sad)] + cmd = [os.path.join(LAUNCHER_FOLDER, '{}.sh').format(diar), '{}'.format(temp_rel), '{}'.format(sad)] else: cmd = ['exit 1'] else: # SAD mode - cmd = [os.path.join(LAUCHER_FOLDER, '{}.sh').format(sad), '{}'.format(temp_rel)] + cmd = [os.path.join(LAUNCHER_FOLDER, '{}.sh').format(sad), '{}'.format(temp_rel)] subprocess.call(cmd) - #After the model has finished running, remove the wav files + # after the model has finished running, remove the wav files if output_dir is None: for fin in os.listdir(temp_abs): if fin.endswith('.wav'): @@ -164,7 +164,7 @@ def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None): else: output_files = [] for fin in os.listdir(temp_abs): - if not os.path.isfile(os.path.join(output_dir, fin)): + if not os.path.isfile(os.path.join(output_dir, fin)) and not fin.endswith('.wav'): shutil.move(os.path.join(temp_abs, fin), output_dir) if fin[-5:] == ".rttm": output_files.append(os.path.join(output_dir, fin)) @@ -340,8 +340,7 @@ def read_analyses(temp_abs, sad, nb_chunks, diar=None, mode='CHI', child_aware=F files_n_dur = [file for file in files_n_dur if file[2] > 3] if len(files_n_dur) == 0: - raise ValueError("No moments for the {} mode has been found.\n Try to decrease the step parameter or " + \ - "to increase the size of the chunks.") + sys.exit("No "+mode+" speech found, try to decrease the step parameter or to increase the size of the chunks.") files_n_dur = sorted(files_n_dur, key=itemgetter(1), reverse=True) @@ -509,6 +508,10 @@ def main(): help='''(Optional) Path to a temp folder in which the small wav ''' '''segments will be stored. If it doesn't exist, it will be ''' '''created.''') + parser.add_argument('--output', default=None, + help='''(Optional) Path to the output folder in which the results ''' + '''will be stored. If it doesn't exist, it will be ''' + '''created.''') parser.add_argument('--sad', default='noisemes_sad', help='''(Optional) name of the sad tool that will be used to ''' '''analyze the snippets of sound''') @@ -532,9 +535,11 @@ def main(): args.step = 300.0 # Sanity check and auto-generation of temp dir - if os.path.isabs(args.temp) or os.path.isabs(args.daylong): - sys.exit("Paths must be relative, not "+args.temp+" or "+args.daylong) - + if os.path.isabs(args.temp): + sys.exit("Temp path must be relative, not "+args.temp) + if os.path.isabs(args.daylong): + sys.exit("Daylong path must be relative, not "+args.daylong) + # Define data dir data_dir = "/vagrant" @@ -552,6 +557,13 @@ def main(): # Define absolute path to wav file wav_abs = os.path.join(data_dir, args.daylong) + if args.output is None: + output_dir = os.path.dirname(wav_abs) + elif os.path.isabs(args.output): + sys.exit("Output path must be relative, not "+args.output) + else: + output_dir = os.path.join(data_dir, args.output) + # get number of chunks that need to be kept nb_chunks = int(args.nb_chunks) @@ -565,7 +577,7 @@ def main(): extract_chunks(wav_abs, onset_list, args.chunk_sizes[0], temp_abs) # analyze using SAD tool - run_Model(temp_rel, temp_abs, args.sad, args.diar) + run_Model(temp_rel, temp_abs, args.sad, diar=args.diar) # sort by speech duration sorted_files = read_analyses(temp_abs, args.sad, nb_chunks*3, args.diar, args.mode) @@ -575,7 +587,7 @@ def main(): extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[1], temp_abs) # analyze using SAD tool - run_Model(temp_rel, temp_abs, args.sad, args.diar) + run_Model(temp_rel, temp_abs, args.sad, diar=args.diar) # sort by speech duration again child_aware = False @@ -590,8 +602,9 @@ def main(): ## Run one last time the model to get the transcription # analyze using SAD tool - output_dir = os.path.dirname(wav_abs) - output_rttm = run_Model(temp_rel, temp_abs, args.sad, args.diar, output_dir) + if not os.path.exists(output_dir): + os.makedirs(output_dir) + output_rttm = run_Model(temp_rel, temp_abs, args.sad, diar=args.diar, output_dir=output_dir) #output_rttm = ["/vagrant/data/daylong/yunitator_english_0396_sub_1085.0_1385.0.rttm"] write_final_stats(output_rttm) From e58b5147e97f0a52e960715598c149236761aba6 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Tue, 28 May 2019 12:16:28 -0400 Subject: [PATCH 254/299] Update high_volubility.py --- utils/high_volubility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/high_volubility.py b/utils/high_volubility.py index b187b35..eaa10cb 100755 --- a/utils/high_volubility.py +++ b/utils/high_volubility.py @@ -164,7 +164,7 @@ def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None): else: output_files = [] for fin in os.listdir(temp_abs): - if not os.path.isfile(os.path.join(output_dir, fin)) and not fin.endswith('.wav'): + if not os.path.isfile(os.path.join(output_dir, fin)): shutil.move(os.path.join(temp_abs, fin), output_dir) if fin[-5:] == ".rttm": output_files.append(os.path.join(output_dir, fin)) From 6854106253759eb4cd3e77388f62ba5a94e86eff Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 5 Jun 2019 00:27:56 -0400 Subject: [PATCH 255/299] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f3f8ac..c4d8506 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ -This repo contains the latest stable version of the ACLEW Diarization Virtual Machine (DiViMe). For the development version, visit https://github.com/srvk/DiViMe/. +This repo contains the ACLEW Diarization Virtual Machine (DiViMe), as described in: +Adrien Le Franc, Eric Riebling, Julien Karadayi, Yun Wang, Camila Scaff, Florian Metze, and Alejandrina Cristia. +[The ACLEW DiViMe: An easy-to-use diarization tool.](http://www.cs.cmu.edu/~fmetze/interACT/Publications_files/publications/aclew-divime-easy.pdf) +In Proc. INTERSPEECH, Hyderabad; India, September 2018. ISCA. Please see the online documentation at https://divime.readthedocs.io/ for instructions on installation and use. From dc93f2112d952913a6ed9243793be4e05c8a0968 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 5 Jun 2019 00:33:40 -0400 Subject: [PATCH 256/299] Update README.md --- launcher/README.md | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/launcher/README.md b/launcher/README.md index 0988f81..86d93f7 100755 --- a/launcher/README.md +++ b/launcher/README.md @@ -1,7 +1,5 @@ # Launcher -This repository contains scripts that launch tools in the ACLEW Diarization VM. - -## Overall summary +This repository contains scripts that launch tools in the ACLEW Diarization VM. The scripts in this folder are called when you "[use a tool on data](https://divime.readthedocs.io/en/latest/usage.html#further-information-on-step-4-using-tools-on-data)". ### SAD tools ``` @@ -9,17 +7,15 @@ noisemesSad.sh opensmileSad.sh tocomboSad.sh ``` + ### Talker Diarization tools ``` diartk.sh - ``` ### Role assignment tools - ``` yunitate.sh - ``` ### Scoring tools @@ -32,22 +28,3 @@ evalSAD.sh ``` test.sh ``` - -### python3 -``` -# activate divime environment to use python 3.6.5 -# put below in run script -source activate divime - -# list of libararies installed can be found with -# conda list -# to install new packages, edit conf/environment.yml file - -# to switch back to python 2, run -conda deactivate - -# And to use python3, make sure you use correct syntax -# in python files and/or checkout python3 branch from -# each tool -# see python3/ for examples -``` From c49e3d611824db161a774c4222813827e5e6f7c9 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 5 Jun 2019 00:36:22 -0400 Subject: [PATCH 257/299] Update README.md --- utils/README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/utils/README.md b/utils/README.md index af578e2..1735de1 100755 --- a/utils/README.md +++ b/utils/README.md @@ -1,4 +1,7 @@ # Utils -This repository contains utilities that are potentially useful to more than one tool in the ACLEW Diarization VM. It also contains some launchers that are in quarantine at present: -noisemes_full.sh -yuniSeg.sh + +This folder contains utilities that are potentially useful to more than one tool in the ACLEW Diarization VM. It also contains some launchers that are in quarantine at present: +- noisemes_full.sh +- yuniSeg.sh + +The end user should not need to deal with files in this folder, they are meant to be called by the "tools" that reside in the [DiViMe/launcher](https://github.com/srvk/DiViMe/tree/master/launcher) folder. From 21488e1fe8db7738de51124562f0a50c5456825c Mon Sep 17 00:00:00 2001 From: MarvinLvn Date: Wed, 5 Jun 2019 15:05:38 +0200 Subject: [PATCH 258/299] Add pyannote.core install + fix bug when evaluation asked with different path for gold and hypothesis --- conf/bootstrap.sh | 2 +- utils/compute_metrics.py | 6 ++--- utils/frame_cutter.py | 54 +++++++++++++++++----------------------- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 969dd48..ff3c7e7 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -173,7 +173,7 @@ python setup.py install ## Need to add anaconda to the PATH to be able to activate divime. export PATH=/home/vagrant/anaconda/bin:$PATH source activate divime -pip install pyannote.metrics +pip install pyannote.metrics pyannote.core conda deactivate #install launcher and utils diff --git a/utils/compute_metrics.py b/utils/compute_metrics.py index 581e716..05a8076 100644 --- a/utils/compute_metrics.py +++ b/utils/compute_metrics.py @@ -86,8 +86,6 @@ def run_metrics(references_f, hypothesis_f, metrics, visualization=False): # Set the uri as the basename for both reference and hypothesis ref.uri, hyp.uri = basename, basename # Let's accumulate the score for each metrics - # Let's accumulate the score for each metrics - for m in metrics.values(): res = m(ref, hyp) @@ -123,14 +121,16 @@ def get_couple_files(ref_path, hyp_path=None, prefix=None): prefix = prefix + "_" ref_path = os.path.join("/vagrant", ref_path) + if hyp_path is None: hyp_files = list(glob.iglob(os.path.join(ref_path, prefix+'*.rttm'))) ref_files = [os.path.join(os.path.dirname(f), os.path.basename(f).replace(prefix, '')) for f in hyp_files] else: + hyp_path = os.path.join("/vagrant", hyp_path) # Hyp files are stored in a different place, we check if a folder has been provided or if it just a single file if os.path.isdir(hyp_path): hyp_files = list(glob.iglob(os.path.join(hyp_path, prefix+'*.rttm'))) - ref_files = [f.replace(prefix, '').replace(hyp_files, ref_path) for f in hyp_files] + ref_files = [os.path.join(ref_path, os.path.basename(f).replace(prefix, '')) for f in hyp_files] elif os.path.isfile(hyp_path): hyp_files = [hyp_path] else: diff --git a/utils/frame_cutter.py b/utils/frame_cutter.py index 789a638..1f8eb97 100755 --- a/utils/frame_cutter.py +++ b/utils/frame_cutter.py @@ -7,7 +7,7 @@ from scipy.io import wavfile import math -def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): +def cutter(path_to_rttm, frame_length, output_file, prefix): """ Given a rttm file, create a new file whose represents the same rttm cutted in frames. If one frame has been classified as several classes in the original rttm, it concatenates classes. @@ -20,7 +20,6 @@ def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): frame_length : frame length. output_file : path to the output file. prefix : the prefix that needs to be remove (from rttm) to map the rttm to the wav file. - labels_map : to map the labels from original rttm (values) to the output rttm (keys). Write a rttm whose name is the same than the rttm's one suffixed by _cutted.rttm """ @@ -56,10 +55,10 @@ def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): sil_dur_s = onset_s - onset_prev_s - dur_prev_s onset_sil_s = onset_prev_s + dur_prev_s single_activity_cutter(basename, output, frame_length_s, - sil_dur_s, onset_sil_s, 'SIL', tot_dur_s, labels_map) + sil_dur_s, onset_sil_s, 'SIL', tot_dur_s) single_activity_cutter(basename, output, frame_length_s, - dur_s, onset_s, curr_activity, tot_dur_s, labels_map) + dur_s, onset_s, curr_activity, tot_dur_s) # Update previous fields dur_prev_s = dur_s @@ -76,10 +75,10 @@ def cutter(path_to_rttm, frame_length, output_file, prefix, labels_map): sil_dur_s = tot_dur_s - onset_s-dur_s onset_sil_s = onset_s + dur_s single_activity_cutter(basename, output, frame_length_s, - sil_dur_s, onset_sil_s, 'SIL', tot_dur_s, labels_map) + sil_dur_s, onset_sil_s, 'SIL', tot_dur_s) -def single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, curr_activity, tot_dur_s, labels_map): +def single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, curr_activity, tot_dur_s): """ Given an activity, its onset and its duration, cut it into frames of length frame_length_s. @@ -91,7 +90,6 @@ def single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, cur dur_s The duration of the current activity (in s). onset_s The onset of the current activity (in s). curr_activity The current activity. - labels_map : To map the labels from original rttm (values) to the output rttm (keys). """ @@ -106,22 +104,16 @@ def single_activity_cutter(basename, output, frame_length_s, dur_s, onset_s, cur onset_s = int(round(onset_s / frame_length_s)) * frame_length_s n_frames = int((dur_s+diff_s) / frame_length_s) # Get the output label (we want a full match or nothing) - activity = [k for k,v in labels_map.items() if re.match("("+v+")\Z", curr_activity) is not None] - if len(activity) != 1: - print("Can not map the input label to the output one : %s" % curr_activity) - sys.exit(1) - else: - activity = activity[0] for i in range(0, n_frames): output.write("SPEAKER %s 1 %s %s %s \n" % \ (basename, onset_s + frame_length_s * i, - str(frame_length_s), activity)) + str(frame_length_s), curr_activity)) if (not np.isclose(onset_s + frame_length_s * n_frames, onset_s+dur_s+diff_s, rtol=1e-05, atol=1e-08, equal_nan=False)) and (onset_s + frame_length_s * n_frames < tot_dur_s): output.write("SPEAKER %s 1 %s %s %s \n" % \ (basename, onset_s + frame_length_s * n_frames, - str(frame_length_s), activity)) + str(frame_length_s), curr_activity)) def aggregate_overlap(path_to_rttm, output_file): @@ -173,7 +165,7 @@ def aggregate_overlap(path_to_rttm, output_file): def main(): parser = argparse.ArgumentParser(description="convert a rttm file into another rttm cutted in frames.") parser.add_argument('-i', '--input', type=str, required=True, - help="path to the input .rttm file or the folder containing rttm files.") + help="path to the input .rttm file or the folder containing rttm and wav files.") parser.add_argument('-l', '--length', type=float, required=False, default=10.0, help="the frame length in ms (Default to 10 ms).") parser.add_argument('-p', '--prefix', type=str, default="", @@ -184,19 +176,19 @@ def main(): # "FEM": "FAN|FAF|FEM|F|MOT.?|FA.?", # "MAL": "MAL|M|MAN|MA.?", # "SIL": "SIL|S"} - labels_map = {"CHF":"CHF", - "CHI":"CHI", - "OCHI": "OCHI", - "CHN":"CHN", - "FAF":"FAF", - "FAN":"FAN", - "FEM":"FEM", - "MAF":"MAF", - "MAL":"MAL", - "MAN":"MAN", - "OLF":"OLF", - "OLN":"OLN", - "SIL":"SIL"} + # labels_map = {"CHF":"CHF", + # "CHI":"CHI", + # "OCHI": "OCHI", + # "CHN":"CHN", + # "FAF":"FAF", + # "FAN":"FAN", + # "FEM":"FEM", + # "MAF":"MAF", + # "MAL":"MAL", + # "MAN":"MAN", + # "OLF":"OLF", + # "OLN":"OLN", + # "SIL":"SIL"} # Initialize the output folder as the same folder than the input # if not provided by the user. if args.input[-5:] == '.rttm': @@ -213,7 +205,7 @@ def main(): if args.input[-5:] == '.rttm': # A single file has been provided by the user output = os.path.splitext(args.input)[0]+'_cutted.rttm' - cutter(args.input, args.length, output+'.tmp', args.prefix, labels_map) + cutter(args.input, args.length, output+'.tmp', args.prefix) aggregate_overlap(output+'.tmp', output) os.remove(output+'.tmp') else: # A whole folder has been provided @@ -221,7 +213,7 @@ def main(): for rttm_path in rttm_files: print("Processing %s" % rttm_path) output = os.path.splitext(rttm_path)[0] + '_cutted.rttm' - cutter(rttm_path, args.length, output + '.tmp', args.prefix, labels_map) + cutter(rttm_path, args.length, output + '.tmp', args.prefix) aggregate_overlap(output + '.tmp', output) os.remove(output + '.tmp') From 2574d57cf48496d23894573dd89688edef3c4aab Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Thu, 13 Jun 2019 07:20:19 -0400 Subject: [PATCH 259/299] debugging --- launcher/yunitate.sh | 1 + utils/high_volubility.py | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 7622bd2..dc75a32 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -76,6 +76,7 @@ let chunksize=$chunksize/100000*200 [ $chunksize -eq 0 ] && free [ $chunksize -eq 0 ] && let chunksize=1000 +echo python yunified.py yunitator $audio_dir $chunksize $MODE python yunified.py yunitator $audio_dir $chunksize $MODE # MODE equal to old, english or universal for f in `ls $YUNITEMP/*.rttm.sorted`; do diff --git a/utils/high_volubility.py b/utils/high_volubility.py index eaa10cb..951cabb 100755 --- a/utils/high_volubility.py +++ b/utils/high_volubility.py @@ -116,7 +116,7 @@ def extract_chunks(wav, onset_list, chunk_size, temp): subprocess.call(cmd) -def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None): +def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None, del_temp=True): """ When all the snippets of sound are extracted, and stored in the temp file, run them through a sad or diar tool, and keep the 10%% that have the most speech. @@ -147,6 +147,8 @@ def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None): if mode not in available_flavors: sys.exit("Yunitator's flavor not recognized. Should be in %s" % available_flavors) cmd = [os.path.join(LAUNCHER_FOLDER, 'yunitate.sh'), '{}'.format(temp_rel), '{}'.format(mode)] + if not del_temp: + cmd.append('--keep-temp') elif diar == 'diartk': cmd = [os.path.join(LAUNCHER_FOLDER, '{}.sh').format(diar), '{}'.format(temp_rel), '{}'.format(sad)] else: @@ -478,7 +480,7 @@ def main(): extracted chunks. --sad: (optional) name of the SAD tool to call to analyse the chunks. By default noiseme - --diar: (optional) name of the diarization tool to call to analyse + --diar: (optional) name of the diarization tool to call to analyse the chunks. No default option """ @@ -577,7 +579,7 @@ def main(): extract_chunks(wav_abs, onset_list, args.chunk_sizes[0], temp_abs) # analyze using SAD tool - run_Model(temp_rel, temp_abs, args.sad, diar=args.diar) + run_Model(temp_rel, temp_abs, args.sad, diar=args.diar, del_temp=del_temp) # sort by speech duration sorted_files = read_analyses(temp_abs, args.sad, nb_chunks*3, args.diar, args.mode) @@ -587,7 +589,7 @@ def main(): extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[1], temp_abs) # analyze using SAD tool - run_Model(temp_rel, temp_abs, args.sad, diar=args.diar) + run_Model(temp_rel, temp_abs, args.sad, diar=args.diar, del_temp=del_temp) # sort by speech duration again child_aware = False @@ -604,7 +606,7 @@ def main(): # analyze using SAD tool if not os.path.exists(output_dir): os.makedirs(output_dir) - output_rttm = run_Model(temp_rel, temp_abs, args.sad, diar=args.diar, output_dir=output_dir) + output_rttm = run_Model(temp_rel, temp_abs, args.sad, diar=args.diar, output_dir=output_dir, del_temp=del_temp) #output_rttm = ["/vagrant/data/daylong/yunitator_english_0396_sub_1085.0_1385.0.rttm"] write_final_stats(output_rttm) From e2a77282bc0176f935e8ba7ba9c253f0f06e7513 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Tue, 18 Jun 2019 07:35:07 -0400 Subject: [PATCH 260/299] fixed high_volubility.py to successfully process long files, specifically wrt #122 and #125. may still need improvements to cmd line parameters, expected behavior, or documentation/ code match --- launcher/tocomboSad.sh | 5 +- launcher/yunitate.sh | 6 ++ utils/high_volubility.py | 134 +++++++++++++++++++-------------------- 3 files changed, 74 insertions(+), 71 deletions(-) diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index 2a99729..51afb0a 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -14,8 +14,9 @@ trs_format=$2 ### Other variables specific to this script # create temp dir -workdir=${audio_dir}/temp -mkdir -p $workdir +#workdir=${audio_dir}/temp +#mkdir -p $workdir +workdir=`mktemp -d --tmpdir=${audio_dir}` TOCOMBOSADDIR=$REPOS/To-Combo-SAD MCR=/usr/local/MATLAB/MATLAB_Runtime/v93 diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index dc75a32..50891ae 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -59,11 +59,17 @@ mkdir -p $YUNITEMP # Iterate over files echo "Starting $0" +if true; then + # I think it is safe to do the feature extraction in parallel by default + ls ${audio_dir}/*.wav | xargs -P `nproc` -i ./extract-htk-vm2.sh '{}' $TEMPNAME +else for f in `ls ${audio_dir}/*.wav`; do basename=`basename $f .wav` # first features ./extract-htk-vm2.sh $f $TEMPNAME done +fi + # Choose chunksize based off memory. Currently this is equivalent to 200 # frames per 100MB of memory. diff --git a/utils/high_volubility.py b/utils/high_volubility.py index 951cabb..945e8de 100755 --- a/utils/high_volubility.py +++ b/utils/high_volubility.py @@ -53,21 +53,21 @@ def get_audio_length(wav): return duration -def select_onsets(duration, step): +def select_onsets(duration, step, min_chunk_size=-1.0, max_chunk_size=-1.0): """ Return list of onsets on which this script will extract the chunks of 10s Input: duration: float, duration of the daylong recording - Ouput: + Output: onsets: list[floats], list the onsets on which this script will extract the chunks of 10s to be run through the SAD tools """ - return numpy.arange(0.0, duration, step) + return list(numpy.arange((max_chunk_size-min_chunk_size)/2, duration, step)) -def extract_chunks(wav, onset_list, chunk_size, temp): +def extract_chunks(wav, onset_list, chunk_size, temp, duration=-1.0): """ Given a list of onset and a length in seconds, extract a snippet of audio at each onset of this length. The extraction will be done using SoX, called by subprocess. @@ -89,37 +89,51 @@ def extract_chunks(wav, onset_list, chunk_size, temp): length is the length of the chunk. """ - # for each onset, call SoX using subprocess to extract a chunk. - for on in onset_list: + print("extract_chunks("+wav+", "+str(onset_list)+", "+str(chunk_size)+", "+str(temp)+", "+str(duration)+")") - # get "id" basename of wav file - basename = os.path.splitext(os.path.basename(wav))[0] + # get "id" basename of wav file + basename = os.path.splitext(os.path.basename(wav))[0] + # for each onset, call SoX using subprocess to extract a chunk. + for on in onset_list: # create name of output off = on + chunk_size - str_on = (6 - len(str(on))) * '0' + str(on) - str_off = (6 - len(str(off))) * '0' + str(off) - - chunk_duration = float(str_off) - float(str_on) - if chunk_duration != chunk_size: - missed_duration = chunk_size - chunk_duration - if float(str_on) == 0.0: - str_off = str(float(str_off)+missed_duration) - else: - str_on = str(float(str_on)-missed_duration) + if on < 0.0: + on = 0.0 + if duration > 0 and off > duration: + off = duration + str_on = '{:.1f}'.format(on) + #(6 - len(str(on))) * '0' + str(on) + str_off = '{:.1f}'.format(off) + #(6 - len(str(off))) * '0' + str(off) + # {:08.1f} + + #chunk_duration = float(str_off) - float(str_on) + #if chunk_duration != chunk_size: + # missed_duration = chunk_size - chunk_duration + # if float(str_on) == 0.0: + # str_off = str(float(str_off)+missed_duration) + # else: + # str_on = str(float(str_on)-missed_duration) chunk_name = '_'.join([basename, str_on, str_off]) # call subprocess cmd = ['sox', wav, os.path.join(temp, '{}.wav'.format(chunk_name)), - 'trim', str(on), str(chunk_size)] - subprocess.call(cmd) + 'trim', '{:f}'.format(on), '{:f}'.format(off-on)] + try: + cpi = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + if len(cpi): + print(str(cmd), "->", str(cpi)) + except subprocess.CalledProcessError: + print("Error caused by: "+str(cmd)) + sys.exit(str(cpi)) def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None, del_temp=True): """ When all the snippets of sound are extracted, and stored in the temp file, run them through a sad or diar tool, and keep - the 10%% that have the most speech. + the 10% that have the most speech. By default, the function is on the SAD mode. That means that it will run a SAD model (by default noiseme). However, if the diar parameter is provided, this function will be on the diarization mode. @@ -140,6 +154,9 @@ def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None, del_temp=True Output: _: In temp, the SAD analyses will be written in RTTM format. """ + + print("run_Model("+temp_rel+", "+temp_abs+", "+sad+", diar="+str(diar)+", output_dir="+str(output_dir)+", del_temp="+str(del_temp)+")") + if diar is not None: # Diarization mode if diar.startswith('yunitator'): mode = diar.split("_")[1] @@ -156,7 +173,11 @@ def run_Model(temp_rel, temp_abs, sad, diar=None, output_dir=None, del_temp=True else: # SAD mode cmd = [os.path.join(LAUNCHER_FOLDER, '{}.sh').format(sad), '{}'.format(temp_rel)] - subprocess.call(cmd) + try: + cpi = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: + print("Error caused by: "+str(cmd)) + sys.exit(str(cpi)) # after the model has finished running, remove the wav files if output_dir is None: @@ -309,18 +330,22 @@ def read_analyses(temp_abs, sad, nb_chunks, diar=None, mode='CHI', child_aware=F else: silence_dur = onset-onset_prev-dur_prev - if not diar_mode: # SAD mode + if not diar_mode: + # SAD mode tot_dur += dur - elif diar_mode and mode == 'CHI' and curr_activity == 'CHI': # Child detection mode + elif diar_mode and mode == 'CHI' and curr_activity == 'CHI': + # Child detection mode tot_dur += 1 - elif diar_mode and mode == 'PCCONV': # Parent-child detection mode + elif diar_mode and mode == 'PCCONV': + # Parent-child detection mode if detect_parent_child_conv(previous_activity, curr_activity, silence_dur): # Here we consider more an objective function (number of turn-taking) that # we want to maximize. That comes from the fact that adults speak during a # longer time while children speak only for few seconds. And we don't want # to put too much weight on the adults speech. tot_dur += 1 - elif diar_mode and mode == 'ACCA': # Adults conversation child aware detection + elif diar_mode and mode == 'ACCA': + # Adults conversation child aware detection if detect_adults_conv(previous_activity, curr_activity, silence_dur): tot_dur += 1 elif curr_activity == 'CHI': @@ -353,7 +378,7 @@ def read_analyses(temp_abs, sad, nb_chunks, diar=None, mode='CHI', child_aware=F return sorted_files -def new_onsets_two_minutes(sorted_files): +def new_onsets(sorted_files, duration=0.0, chunk_size=120.0): """ Given a selection of file with lots of speech, extract new 2minutes long chunks of audio in the original wav, @@ -373,44 +398,14 @@ def new_onsets_two_minutes(sorted_files): # loop over selected files and retrieve their onsets from their name new_onset_list = [] for snippet, speech_dur, chi_points in sorted_files: - onset = os.path.splitext(snippet)[0].split('_')[-2] - offset = os.path.splitext(snippet)[0].split('_')[-1] - - length = float(offset) - float(onset) + onset = float(os.path.splitext(snippet)[0].split('_')[-2]) + offset = float(os.path.splitext(snippet)[0].split('_')[-1]) + length = offset - onset # new segment is centered around snippet, so get middle of snippet - new_onset = length / 2 + float(onset) - new_onset_list.append(new_onset) - - return new_onset_list - -def new_onsets_five_minutes(sorted_files): - """ - Given a selection of file with lots of speech, - extract new 5minutes long chunks of audio in the original wav, - by adding 2 minutes before and 1 minute after the 2minute chunks. - - Input: - sorted_files: list of the snippets that were selected - because they had lot of speech - temp_abs: absolute path to the temp folder that contains the - snippets - wav: path to the daylong recording - Ouput: - _: in the temp folder, new two minutes long chunks of - audio will be stored. - """ - # loop over selected files and retrieve their onsets from their name - new_onset_list = [] - for snippet, speech_dur, chi_points in sorted_files: - onset = os.path.splitext(snippet)[0].split('_')[-2] - offset = os.path.splitext(snippet)[0].split('_')[-1] - - # new segment starts 2 minute before the 2 minute chunk - new_onset = max(0.0, float(onset) - 120.0) - - - new_onset_list.append(new_onset) + new_onset = onset + length/2 - chunk_size/2 + if new_onset + chunk_size > 0 and new_onset < duration: + new_onset_list.append(new_onset) return new_onset_list @@ -573,10 +568,11 @@ def main(): duration = get_audio_length(wav_abs) # get list of onsets - onset_list = select_onsets(duration, args.step) + onset_list = select_onsets(duration, args.step, + min_chunk_size=args.chunk_sizes[0], max_chunk_size=args.chunk_sizes[2]) # call subprocess to extract the chunks - extract_chunks(wav_abs, onset_list, args.chunk_sizes[0], temp_abs) + extract_chunks(wav_abs, onset_list, args.chunk_sizes[0], temp_abs, duration=duration) # analyze using SAD tool run_Model(temp_rel, temp_abs, args.sad, diar=args.diar, del_temp=del_temp) @@ -584,9 +580,9 @@ def main(): # sort by speech duration sorted_files = read_analyses(temp_abs, args.sad, nb_chunks*3, args.diar, args.mode) # get new onsets for two minutes chunks - new_onset_list = new_onsets_two_minutes(sorted_files) + new_onset_list = new_onsets(sorted_files, duration=duration, chunk_size=args.chunk_sizes[1]) # extract two minutes chunks - extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[1], temp_abs) + extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[1], temp_abs, duration=duration) # analyze using SAD tool run_Model(temp_rel, temp_abs, args.sad, diar=args.diar, del_temp=del_temp) @@ -598,9 +594,9 @@ def main(): sorted_files = read_analyses(temp_abs, args.sad, nb_chunks, args.diar, args.mode, child_aware) # get new onsets for five minutes chunks - new_onset_list = new_onsets_five_minutes(sorted_files) + new_onset_list = new_onsets(sorted_files, duration=duration, chunk_size=args.chunk_sizes[2]) # extract final five minutes long chunks - extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[2], temp_abs) + extract_chunks(wav_abs, new_onset_list, args.chunk_sizes[2], temp_abs, duration=duration) ## Run one last time the model to get the transcription # analyze using SAD tool From b3f9ad3f09ce8f380a8447a7bbf555dc796fc1ca Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 19 Jun 2019 07:03:09 -0400 Subject: [PATCH 261/299] installation more quiet --- conf/bootstrap.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index ff3c7e7..e589125 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -39,7 +39,7 @@ fi if ! grep -q -i anaconda .bashrc; then echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc fi -su ${user} -c "/home/${user}/anaconda/bin/conda install numpy scipy mkl dill tabulate joblib sphinx" +su ${user} -c "/home/${user}/anaconda/bin/conda install -q numpy scipy mkl dill tabulate joblib sphinx" # clean up big installer in home folder rm -f Anaconda-2.3.0-Linux-x86_64.sh @@ -96,7 +96,7 @@ echo "Installing OpenSMILE" su ${user} -c "mkdir -p /home/${user}/repos/" cd /home/${user}/repos/ wget -q --no-check-certificate https://www.audeering.com/download/opensmile-2-3-0-tar-gz/?wpdmdl=4782 -O OpenSMILE-2.3.tar.gz -tar zxvf OpenSMILE-2.3.tar.gz +tar zxf OpenSMILE-2.3.tar.gz chmod +x opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract cp opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin rm OpenSMILE-2.3.tar.gz @@ -136,15 +136,15 @@ cd /home/${user}/repos/ # Get OpenSAT=noisemes and dependencies git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev -su ${user} -c "/home/${user}/anaconda/bin/pip install -v ipdb" +su ${user} -c "/home/${user}/anaconda/bin/pip install -q ipdb" cp /vagrant/conf/.theanorc /home/${user}/ -su ${user} -c "/home/${user}/anaconda/bin/conda install -y theano=0.8.2" +su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y theano=0.8.2" # Install Yunitator and dependencies git clone https://github.com/srvk/Yunitator -su ${user} -c "/home/${user}/anaconda/bin/conda install cudatoolkit" -su ${user} -c "/home/${user}/anaconda/bin/conda install pytorch-cpu -c pytorch" +su ${user} -c "/home/${user}/anaconda/bin/conda install -q cudatoolkit" +su ${user} -c "/home/${user}/anaconda/bin/conda install -q pytorch-cpu -c pytorch" # Install VCM git clone https://github.com/srvk/vcm @@ -159,8 +159,8 @@ git clone http://github.com/srvk/ib_diarization_toolkit # Install WCE and dependencies git clone https://github.com/aclew/WCE_VM -su ${user} -c "/home/${user}/anaconda/bin/pip install keras" -su ${user} -c "/home/${user}/anaconda/bin/pip install -U tensorflow" +su ${user} -c "/home/${user}/anaconda/bin/pip install -q keras" +su ${user} -c "/home/${user}/anaconda/bin/pip install -q -U tensorflow" # Phonemizer installation git clone https://github.com/bootphon/phonemizer @@ -173,7 +173,7 @@ python setup.py install ## Need to add anaconda to the PATH to be able to activate divime. export PATH=/home/vagrant/anaconda/bin:$PATH source activate divime -pip install pyannote.metrics pyannote.core +pip install -q pyannote.metrics pyannote.core conda deactivate #install launcher and utils From 5606fa1ceae6563a25f784a9a15b1eed41a21b50 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 19 Jun 2019 07:16:09 -0400 Subject: [PATCH 262/299] installation partially downloads in background --- conf/bootstrap.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index e589125..43cf7d4 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -21,6 +21,9 @@ apt-get install -y git make automake libtool autoconf patch subversion fuse \ # Kaldi and others want bash - otherwise the build process fails [ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh +# This really takes a long time, start it in the background +wget -q -P /tmp http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip & + # Install Anaconda and Theano echo "Downloading Anaconda-2.3.0..." cd /home/${user} @@ -74,7 +77,8 @@ if [ $? -ne 0 ]; then PYTHON3_INSTALLED=false; fi # install Matlab runtime environment echo "Download matlab installer" cd /tmp -wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip +wait +#wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip echo "Install matlab" unzip -q MCR_R2017b_glnxa64_installer.zip ./install -mode silent -agreeToLicense yes From ac647a70c3c55784685d76e040b7a4213b158cbf Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Thu, 27 Jun 2019 00:21:11 -0400 Subject: [PATCH 263/299] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c4d8506..c2ee12c 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,7 @@ In Proc. INTERSPEECH, Hyderabad; India, September 2018. ISCA. Please see the online documentation at https://divime.readthedocs.io/ for instructions on installation and use. - +Quickstart: +- Install vagrant +- vagrant plugin install vagrant-aws vagrant-sshfs vagrant-vbguest +- vagrant up (in the DiViMe folder) From cc212dae9166cc33d0c02443fc0792fd851529ae Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Tue, 2 Jul 2019 23:38:30 -0400 Subject: [PATCH 264/299] various bug fixes and improvements --- Vagrantfile | 6 +- conf/bootstrap.sh | 245 ++- example-logs/launcher-test.log | 63 + example-logs/vagrant-up.log | 3237 ++++++++++++++++++++++++++++++++ launcher/diartk.sh | 10 +- launcher/eval.sh | 4 +- launcher/test.sh | 19 +- launcher/tocomboSad.sh | 11 +- launcher/vcm.sh | 11 +- 9 files changed, 3493 insertions(+), 113 deletions(-) create mode 100644 example-logs/launcher-test.log create mode 100644 example-logs/vagrant-up.log diff --git a/Vagrantfile b/Vagrantfile index f9a7298..342ff62 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -9,7 +9,7 @@ Vagrant.configure("2") do |config| # . aws.sh; vagrant up --provider aws # Make sure you don't check in aws.sh (maybe make a copy with your "secret" data) # Before that, do - # vagrant plugin install vagrant-aws; vagrant plugin install vagrant-sshfs + # vagrant plugin install vagrant-aws vagrant-sshfs # if you have this plugin (https://github.com/dotless-de/vagrant-vbguest) installed # the following line disables it (for faster startup) @@ -32,7 +32,7 @@ Vagrant.configure("2") do |config| config.vm.network "private_network", ip: "192.168.56.101" vbox.cpus = 2 - vbox.memory = 6144 + vbox.memory = 2048 end config.vm.provider "docker" do |d, override| @@ -40,6 +40,8 @@ Vagrant.configure("2") do |config| d.image = 'tknerr/baseimage-ubuntu:14.04' d.remains_running = true d.has_ssh = true + # This needs to be set on a Mac - not sure if it causes problems on other architectures? + d.force_host_vm = true # (too late?) override.vm.synced_folder ".", "/vagrant", owner: "vagrant", group: "vagrant", :mount_options => ["dmode=777", "fmode=777"] end diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index 43cf7d4..d84d461 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -1,16 +1,28 @@ # Please note that the bootstrap.sh script runs as root and not the vagrant user -echo "Start bootstraping DiViMe" +echo "---- Start bootstrapping DiViMe @ `date` ----" + +# Some reporting +echo "-- System information --" +echo nproc is `nproc` +df -h +cat /proc/meminfo + +# These downloads take a long time, start them in the background +#echo "c3100392685b5a62c8509c0588ce9376 */vagrant/Anaconda-2.3.0-Linux-x86_64.sh" | \ +# md5sum -c --quiet || wget -qP /vagrant --no-check-certificate \ +# https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh & +echo "dd87c316e211891df8889c52d9167a5d */vagrant/Anaconda2-2019.03-Linux-x86_64.sh" | \ + md5sum -c --quiet || wget -qP /vagrant --no-check-certificate \ + https://repo.anaconda.com/archive/Anaconda2-2019.03-Linux-x86_64.sh & +echo "ef082e99726b14a2b433c59d002ffb3b */vagrant/MCR_R2017b_glnxa64_installer.zip" | \ + md5sum -c --quiet || wget -qP /vagrant --no-check-certificate \ + http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip & + +echo "-- Updating system --" apt-get update -y apt-get upgrade -y -if grep --quiet vagrant /etc/passwd -then - user="vagrant" -else - user="ubuntu" -fi - apt-get install -y git make automake libtool autoconf patch subversion fuse \ libatlas-base-dev libatlas-dev liblapack-dev sox libav-tools g++ \ zlib1g-dev libsox-fmt-all sshfs gcc-multilib libncurses5-dev unzip bc \ @@ -18,18 +30,54 @@ apt-get install -y git make automake libtool autoconf patch subversion fuse \ libc6-dev-i386 festival espeak python-setuptools gawk \ libboost-all-dev +apt-get autoremove -y && apt-get clean -y && apt-get autoclean -y + +if grep --quiet vagrant /etc/passwd +then + user="vagrant" +else + user="ubuntu" +fi +cd /home/${user} + # Kaldi and others want bash - otherwise the build process fails [ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh -# This really takes a long time, start it in the background -wget -q -P /tmp http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip & +echo "-- System statistics report --" +echo $user +uname -a +free +#dpkg -l + +echo "---- Done system updates @ `date` ----" + +# Install OpenSMILE +su ${user} -c "mkdir -p /home/${user}/repos/" +echo "Downloading and installing OpenSMILE" +su ${user} -c "wget -qO- --no-check-certificate https://www.audeering.com/download/opensmile-2-3-0-tar-gz/?wpdmdl=4782 | tar -xzf - -C repos" +cp repos/opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin && chmod +x /usr/local/bin/SMILExtract + +# check if opensmile if installed +if ! [ -x "$(command -v SMILExtract)" ]; then + echo "*******************************" + echo " OPENSMILE installation failed" + echo "*******************************" + OPENSMILE_INSTALLED=false; +fi # Install Anaconda and Theano -echo "Downloading Anaconda-2.3.0..." -cd /home/${user} -wget -q https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh -echo "Installing Anaconda-2.3.0..." - sudo -S -u vagrant -i /bin/bash -l -c "bash /home/${user}/Anaconda-2.3.0-Linux-x86_64.sh -b" +#echo "Downloading Anaconda-2.3.0..." +#wget -q --no-check-certificate -P /tmp https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh +echo "Waiting for Anaconda download to finish" +# Anaconda download should be the first background process +#echo "c3100392685b5a62c8509c0588ce9376 */vagrant/Anaconda-2.3.0-Linux-x86_64.sh" | \ +# md5sum -c --quiet || wait `jobs -p|head -n 1` +#echo "Installing Anaconda-2.3.0..." +#sudo -S -u ${user} -i /bin/bash -l -c "bash /vagrant/Anaconda-2.3.0-Linux-x86_64.sh -b" +echo "dd87c316e211891df8889c52d9167a5d */vagrant/Anaconda2-2019.03-Linux-x86_64.sh" | \ + md5sum -c --quiet || wait `jobs -p|head -n 1` +echo "Installing Anaconda..." +sudo -S -u ${user} -i /bin/bash -l -c "bash /vagrant/Anaconda2-2019.03-Linux-x86_64.sh -b -p /home/${user}/anaconda" # check if anaconda is installed correctly if ! [ -x "$(command -v /home/${user}/anaconda/bin/conda)" ]; then @@ -40,11 +88,13 @@ if ! [ -x "$(command -v /home/${user}/anaconda/bin/conda)" ]; then fi if ! grep -q -i anaconda .bashrc; then + echo -e "\n# For DiViMe and Anaconda:" >> /home/${user}/.bashrc echo "export PATH=/home/${user}/launcher:/home/${user}/utils:/home/${user}/anaconda/bin:\$PATH" >> /home/${user}/.bashrc fi -su ${user} -c "/home/${user}/anaconda/bin/conda install -q numpy scipy mkl dill tabulate joblib sphinx" -# clean up big installer in home folder -rm -f Anaconda-2.3.0-Linux-x86_64.sh + +#su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y numpy scipy mkl dill tabulate joblib sphinx" +# clean up big installer +#rm -f /vagrant/Anaconda-2.3.0-Linux-x86_64.sh # To use miniconda (~40MB) instead of anaconda (~350MB), uncomment below block # echo "Downloading Miniconda-4.5.11..." @@ -68,19 +118,21 @@ rm -f Anaconda-2.3.0-Linux-x86_64.sh # rm -f Miniconda2-4.5.11-Linux-x86_64.sh # python3 env -echo "Create python3 env" -cd /home/$user -cp /vagrant/conf/environment.yml /home/${user}/ -su ${user} -c "/home/${user}/anaconda/bin/conda env create -f environment.yml" +echo "Creating python3 env..." +#cp /vagrant/conf/environment.yml /home/${user}/ +su ${user} -c "/home/${user}/anaconda/bin/conda env create -q -f /vagrant/conf/environment.yml" if [ $? -ne 0 ]; then PYTHON3_INSTALLED=false; fi # install Matlab runtime environment -echo "Download matlab installer" -cd /tmp -wait +#echo "Download matlab installer" #wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip -echo "Install matlab" -unzip -q MCR_R2017b_glnxa64_installer.zip +echo "Waiting for Matlab download to finish" +# This should be our last background process +echo "ef082e99726b14a2b433c59d002ffb3b */vagrant/MCR_R2017b_glnxa64_installer.zip" | \ + md5sum -c --quiet || wait +echo "Installing Matlab..." +cd /tmp +unzip -q /vagrant/MCR_R2017b_glnxa64_installer.zip ./install -mode silent -agreeToLicense yes # check if matlab is installed correctly @@ -92,31 +144,14 @@ if [ $? -ne 0 ]; then fi # add Matlab stuff to path +echo -e "\n# For Matlab:" >> /home/${user}/.bashrc echo 'LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH"' >> /home/${user}/.bashrc -rm /tmp/MCR_R2017b_glnxa64_installer.zip - -# Install OpenSMILE -echo "Installing OpenSMILE" -su ${user} -c "mkdir -p /home/${user}/repos/" -cd /home/${user}/repos/ -wget -q --no-check-certificate https://www.audeering.com/download/opensmile-2-3-0-tar-gz/?wpdmdl=4782 -O OpenSMILE-2.3.tar.gz -tar zxf OpenSMILE-2.3.tar.gz -chmod +x opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract -cp opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin -rm OpenSMILE-2.3.tar.gz - -# check if opensmile if installed -if ! [ -x "$(command -v SMILExtract)" ]; then - echo "*******************************" - echo " OPENSMILE installation failed" - echo "*******************************" - OPENSMILE_INSTALLED=false; -fi - +#rm /vagrant/MCR_R2017b_glnxa64_installer.zip # optionally Install HTK (without it, some other tools will not work) # the idea is to make users independently download HTK installer since # we cannot redistribute +echo "Installing HTK..." cd /home/${user} if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then if [[ ! -d repos/htk ]]; then @@ -128,56 +163,64 @@ if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then make all make install else - echo "Visibly htk has been already installed..." + echo "Visibly HTK has been already installed..." fi else - echo "Can't find HTK-3.4.1.tar.gz. Check that you installed the right version." + HTK_INSTALLED=false; + echo "Can't find HTK-3.4.1.tar.gz. Assuming HTK not needed." fi +echo "-- Conda report --" +su ${user} -c "/home/${user}/anaconda/bin/conda list" + # POPULATE THE REPOSITORY SECTION +echo "---- Changing into /home/${user}/repos @ `date` ----" cd /home/${user}/repos/ # Get OpenSAT=noisemes and dependencies -git clone http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev +su ${user} -c "git clone -q http://github.com/srvk/OpenSAT --branch yunified" # --branch v1.0 # need Dev -su ${user} -c "/home/${user}/anaconda/bin/pip install -q ipdb" +su ${user} -c "/home/${user}/anaconda/bin/pip --disable-pip-version-check install -q ipdb" -cp /vagrant/conf/.theanorc /home/${user}/ -su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y theano=0.8.2" +su ${user} -c "cp /vagrant/conf/.theanorc /home/${user}/" +#su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y --no-update-deps theano=0.8.2" +su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y theano cudatoolkit pytorch-cpu -c pytorch" # Install Yunitator and dependencies -git clone https://github.com/srvk/Yunitator -su ${user} -c "/home/${user}/anaconda/bin/conda install -q cudatoolkit" -su ${user} -c "/home/${user}/anaconda/bin/conda install -q pytorch-cpu -c pytorch" +su ${user} -c "git clone -q https://github.com/srvk/Yunitator" +#su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y --no-update-deps cudatoolkit" +#su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y --no-update-deps pytorch-cpu -c pytorch" # Install VCM -git clone https://github.com/srvk/vcm +su ${user} -c "git clone -q https://github.com/srvk/vcm" -#Install to-combo sad and dependencies (matlab runtime environnement) -git clone https://github.com/srvk/To-Combo-SAD -(cd To-Combo-SAD && git checkout 2ce2998) +# Install to-combo sad and dependencies (matlab runtime environnement) +su ${user} -c "git clone -q https://github.com/srvk/To-Combo-SAD" +(cd To-Combo-SAD && su ${user} -c "git checkout 2ce2998") # Install DiarTK -git clone http://github.com/srvk/ib_diarization_toolkit -(cd ib_diarization_toolkit && git checkout b3e4deb) +su ${user} -c "git clone -q http://github.com/srvk/ib_diarization_toolkit" +(cd ib_diarization_toolkit && su ${user} -c "git checkout b3e4deb") # Install WCE and dependencies -git clone https://github.com/aclew/WCE_VM -su ${user} -c "/home/${user}/anaconda/bin/pip install -q keras" -su ${user} -c "/home/${user}/anaconda/bin/pip install -q -U tensorflow" - -# Phonemizer installation -git clone https://github.com/bootphon/phonemizer -cd phonemizer -git checkout 332b8dd -python setup.py build -python setup.py install +git clone -q https://github.com/aclew/WCE_VM +su ${user} -c "/home/${user}/anaconda/bin/pip --disable-pip-version-check install -q keras tensorflow==1.13.1" +#su ${user} -c "/home/${user}/anaconda/bin/pip --disable-pip-version-check install -q -U tensorflow" + +# Phonemizer installation +su ${user} -c "git clone -q https://github.com/bootphon/phonemizer" +( + cd phonemizer + su ${user} -c "git checkout 332b8dd" + python setup.py build + python setup.py install +) # Install pyannote (python 3) ## Need to add anaconda to the PATH to be able to activate divime. -export PATH=/home/vagrant/anaconda/bin:$PATH +export PATH=/home/${user}/anaconda/bin:$PATH source activate divime -pip install -q pyannote.metrics pyannote.core +pip --disable-pip-version-check install -q pyannote.metrics pyannote.core conda deactivate #install launcher and utils @@ -190,21 +233,34 @@ conda deactivate # install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) # and intervaltree (needed for rttm2scp.py) # and recommonmark (needed to make html in docs/) -su ${user} -c "/home/${user}/anaconda/bin/pip install pympi-ling tgt intervaltree recommonmark sphinx-markdown-tables" +su ${user} -c "/home/${user}/anaconda/bin/pip install --disable-pip-version-check pympi-ling tgt intervaltree recommonmark sphinx-markdown-tables sphinx_rtd_theme" -# Link /vagrant/launcher and /vagrant/utils to home folder where scripts expect them -ln -s /vagrant/launcher /home/${user}/ -ln -s /vagrant/utils /home/${user}/ +# Document the version of the tools that we have installed +echo "---- git logs follow ----" +cd /home/${user}/repos/ +for f in /vagrant *; +do + if [[ $f =~ opensmile* ]]; then continue; fi + echo -- git log ${f} -- + git --git-dir=${f}/.git log -1 +done +echo "---- git logs done ----" -# Some cleanup -apt-get autoremove -y +# Link /vagrant/launcher and /vagrant/utils to home folder where scripts expect them +su ${user} -c "ln -s /vagrant/launcher /home/${user}/" +su ${user} -c "ln -s /vagrant/utils /home/${user}/" # Silence error message from missing file -touch /home/${user}/.Xauthority +su ${user} -c "touch /home/${user}/.Xauthority" -# Provisioning runs as root; we want files to belong to '${user}' +# Provisioning runs as root; we want files to belong to '${user}' (may no longer be needed) chown -R ${user}:${user} /home/${user} +# Build the docs +echo "---- Building the docs... ----" +cd /vagrant/docs +make SPHINXBUILD=/home/${user}/anaconda/bin/sphinx-build html + # Installation status if ! $PYTHON3_INSTALLED; then echo "*********************************************" @@ -216,12 +272,21 @@ if ! $OPENSMILE_INSTALLED; then echo "Warning: OpenSMILE is not installed" echo "***********************************" fi -if ! $HTK_INSTALLED; then - echo "*****************************" - echo "Warning: HTK is not installed" - echo "*****************************" -fi +#if ! $HTK_INSTALLED; then +# echo "*****************************" +# echo "Warning: HTK is not installed" +# echo "*****************************" +#fi + +# These files can be 'cached' for faster turn-around +[ -f /vagrant/Anaconda2-2019.03-Linux-x86_64.sh ] && echo INFO: You can remove Anaconda2-2019.03-Linux-x86_64.sh, if you don\'t plan on re-provisioning DiViMe any time soon. +[ -f /vagrant/MCR_R2017b_glnxa64_installer.zip ] && echo INFO: You can remove MCR_R2017b_glnxa64_installer.zip, if you don\'t plan on re-provisioning DiViMe any time soon. + +echo "---- Done bootstrapping DiViMe @ `date` ----" + +# To Test: +# - vagrant ssh -c "launcher/test.sh" +# - vagrant ssh -c "yunitate.sh data/" (with a large wav file in data) +# - vagrant ssh -c "utils/high_volubility.py data/7085.wav --diar yunitator_universal --mode CHI --nb_chunks 50" +# ... -# Build the docs -cd /vagrant/docs -make SPHINXBUILD=/home/${user}/anaconda/bin/sphinx-build html diff --git a/example-logs/launcher-test.log b/example-logs/launcher-test.log new file mode 100644 index 0000000..ba298ec --- /dev/null +++ b/example-logs/launcher-test.log @@ -0,0 +1,63 @@ +FloriansMBP2019:DiViMe metze$ vagrant ssh -c "launcher/test.sh" +Starting tests +Checking for HTK... + HTK missing. You can probably ignore this warning, HTK is no longer needed. +Testing noisemes... +Noisemes passed the test. +Testing OpenSmile SAD... +OpenSmile SAD passed the test. +Testing ToCombo SAD... +TOCOMBO SAD passed the test. +Testing DIARTK... +DiarTK passed the test. +Testing Yunitator... + Yunitator failed - no output RTTM +Testing the evaluation pipeline... +The evaluation pipeline passed the test. +Testing VCM... +VCM passed the test. +Testing WCE... +WCE passed the test +Some tools did not pass the test, but you can still use others +###################################################################################### +To wrap up, we will print out the results of the analyses that we ran during the test. +Compare the following results, corresponding to your system, against the reference results printed out below. +If the numbers are similar, then your system is working similarly to the original one. +If you see bigger changes, then please paste this output onto an issue on https://github.com/srvk/DiViMe/issues/. +RESULTS: +LINES: 10 DURATION SUM: 296.23 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm +LINES: 36 DURATION SUM: 31 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm +LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm +LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm +LINES: 36 DURATION SUM: 65.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm +LINES: 83 DURATION SUM: 145.8 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_universal_BN32_010007_test.rttm +****** REFERENCE RESULTS BEGINS ******. +LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm +LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm +LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm +LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm +LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm +LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm +LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm +****** REFERENCE RESULTS ENDS ******. +Evaluation pipeline: + +Evaluating noisemesSad on /vagrant/data/VanDam-Daylong/BN32/test with respect to : accuracy + +Pairs that have been found : +BN32_010007_test.rttm / noisemesSad_BN32_010007_test.rttm + +accuracy report + detection accuracy true positive true negative false positive false negative + % +item +BN32_010007_test.rttm 11.24 30.80 3.11 0.20 267.57 +TOTAL 11.24 30.80 3.11 0.20 267.57 +accuracy report + detection accuracy true positive true negative false positive false + % +item +BN32_010007_test.rttm 11.24 30.80 3.11 0.20 267.57 +TOTAL 11.24 30.80 3.11 0.20 267.57 +Connection to 127.0.0.1 closed. +FloriansMBP2019:DiViMe metze$ diff --git a/example-logs/vagrant-up.log b/example-logs/vagrant-up.log new file mode 100644 index 0000000..cd522d5 --- /dev/null +++ b/example-logs/vagrant-up.log @@ -0,0 +1,3237 @@ +FloriansMBP2019:DiViMe metze$ vagrant up +Bringing machine 'default' up with 'virtualbox' provider... +==> default: Importing base box 'ubuntu/trusty64'... +==> default: Matching MAC address for NAT networking... +==> default: Checking if box 'ubuntu/trusty64' version '20190429.0.1' is up to date... +==> default: Setting the name of the VM: DiViMe_default_1562123904987_96609 +==> default: Clearing any previously set forwarded ports... +==> default: Clearing any previously set network interfaces... +==> default: Preparing network interfaces based on configuration... + default: Adapter 1: nat + default: Adapter 2: hostonly + default: Adapter 3: hostonly + default: Adapter 4: hostonly + default: Adapter 5: hostonly + default: Adapter 6: hostonly + default: Adapter 7: hostonly +==> default: Forwarding ports... + default: 22 (guest) => 2222 (host) (adapter 1) +==> default: Running 'pre-boot' VM customizations... +==> default: Booting VM... +==> default: Waiting for machine to boot. This may take a few minutes... + default: SSH address: 127.0.0.1:2222 + default: SSH username: vagrant + default: SSH auth method: private key + default: + default: Vagrant insecure key detected. Vagrant will automatically replace + default: this with a newly generated keypair for better security. + default: + default: Inserting generated public key within guest... + default: Removing insecure key from the guest if it's present... + default: Key inserted! Disconnecting and reconnecting using new SSH key... +==> default: Machine booted and ready! +[default] GuestAdditions versions on your host (6.0.8) and guest (4.3.40) do not match. + vboxguest); sleep 1; umount -a -t vboxsf; sleep 1; rmmod vboxsf; sleep 1; rmmod + * Stopping VirtualBox Additions + ...done. +root@vagrant-ubuntu-trusty-64:/home/vagrant# exit +exit +t-dkms virtualbox-guest-utils virtualbox-guest-x11et -y -q purge virtualbox-gues +Reading package lists... +Building dependency tree... +Reading state information... +The following packages were automatically installed and are no longer required: + acl at-spi2-core colord dconf-gsettings-backend dconf-service dkms fakeroot + fontconfig fontconfig-config fonts-dejavu-core gcc gcc-4.8 + hicolor-icon-theme libasan0 libasound2 libasound2-data libatk-bridge2.0-0 + libatk1.0-0 libatk1.0-data libatomic1 libatspi2.0-0 libavahi-client3 + libavahi-common-data libavahi-common3 libc-dev-bin libc6-dev + libcairo-gobject2 libcairo2 libcanberra-gtk3-0 libcanberra-gtk3-module + libcanberra0 libcolord1 libcolorhug1 libcups2 libdatrie1 libdconf1 + libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libexif12 libfakeroot + libfontconfig1 libfontenc1 libgcc-4.8-dev libgd3 libgdk-pixbuf2.0-0 + libgdk-pixbuf2.0-common libgl1-mesa-dri libgl1-mesa-glx libglapi-mesa + libgomp1 libgphoto2-6 libgphoto2-l10n libgphoto2-port10 libgraphite2-3 + libgtk-3-0 libgtk-3-bin libgtk-3-common libgudev-1.0-0 libgusb2 + libharfbuzz0b libice6 libieee1284-3 libitm1 libjasper1 libjbig0 + libjpeg-turbo8 libjpeg8 liblcms2-2 libllvm3.4 libltdl7 libnotify-bin + libnotify4 libogg0 libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 + libpciaccess0 libpixman-1-0 libquadmath0 libsane libsane-common libsm6 + libtdb1 libthai-data libthai0 libtiff5 libtsan0 libtxc-dxtn-s2tc0 libv4l-0 + libv4lconvert0 libvorbis0a libvorbisfile3 libvpx1 libwayland-client0 + libwayland-cursor0 libx11-xcb1 libxaw7 libxcb-dri2-0 libxcb-dri3-0 + libxcb-glx0 libxcb-present0 libxcb-render0 libxcb-shm0 libxcb-sync1 + libxcomposite1 libxcursor1 libxdamage1 libxfixes3 libxfont1 libxi6 + libxinerama1 libxkbcommon0 libxkbfile1 libxmu6 libxpm4 libxrandr2 + libxrender1 libxshmfence1 libxt6 libxtst6 libxxf86vm1 linux-libc-dev + manpages-dev notification-daemon sound-theme-freedesktop x11-common + x11-xkb-utils xfonts-base xfonts-encodings xfonts-utils xserver-common + xserver-xorg-core +Use 'apt-get autoremove' to remove them. +The following packages will be REMOVED: + virtualbox-guest-dkms* virtualbox-guest-utils* virtualbox-guest-x11* +0 upgraded, 0 newly installed, 3 to remove and 0 not upgraded. +After this operation, 12.2 MB disk space will be freed. +(Reading database ... 63174 files and directories currently installed.) +Removing virtualbox-guest-dkms (4.3.40-dfsg-0ubuntu14.04.1) ... + +-------- Uninstall Beginning -------- +Module: virtualbox-guest +Version: 4.3.40 +Kernel: 3.13.0-170-generic (x86_64) +------------------------------------- + +Status: Before uninstall, this module version was ACTIVE on this kernel. + +vboxguest.ko: + - Uninstallation + - Deleting from: /lib/modules/3.13.0-170-generic/updates/dkms/ + - Original module + - No original module was found for this module on this kernel. + - Use the dkms install command to reinstall any previous module version. + + +vboxsf.ko: + - Uninstallation + - Deleting from: /lib/modules/3.13.0-170-generic/updates/dkms/ + - Original module + - No original module was found for this module on this kernel. + - Use the dkms install command to reinstall any previous module version. + + +vboxvideo.ko: + - Uninstallation + - Deleting from: /lib/modules/3.13.0-170-generic/updates/dkms/ + - Original module + - No original module was found for this module on this kernel. + - Use the dkms install command to reinstall any previous module version. + +depmod.... + +DKMS: uninstall completed. + +------------------------------ +Deleting module version: 4.3.40 +completely from the DKMS tree. +------------------------------ +Done. +Removing virtualbox-guest-x11 (4.3.40-dfsg-0ubuntu14.04.1) ... +Purging configuration files for virtualbox-guest-x11 (4.3.40-dfsg-0ubuntu14.04.1) ... +Removing virtualbox-guest-utils (4.3.40-dfsg-0ubuntu14.04.1) ... +Purging configuration files for virtualbox-guest-utils (4.3.40-dfsg-0ubuntu14.04.1) ... +Processing triggers for man-db (2.6.7.1-1ubuntu1) ... +Processing triggers for libc-bin (2.19-0ubuntu6.15) ... +root@vagrant-ubuntu-trusty-64:/home/vagrant# exit +exit +name -r` dkmsubuntu-trusty-64:/home/vagrant# apt-get install -y linux-headers-`u +Reading package lists... +Building dependency tree... +Reading state information... +dkms is already the newest version. +dkms set to manually installed. +linux-headers-3.13.0-170-generic is already the newest version. +linux-headers-3.13.0-170-generic set to manually installed. +The following packages were automatically installed and are no longer required: + acl at-spi2-core colord dconf-gsettings-backend dconf-service fontconfig + fontconfig-config fonts-dejavu-core hicolor-icon-theme libasound2 + libasound2-data libatk-bridge2.0-0 libatk1.0-0 libatk1.0-data libatspi2.0-0 + libavahi-client3 libavahi-common-data libavahi-common3 libcairo-gobject2 + libcairo2 libcanberra-gtk3-0 libcanberra-gtk3-module libcanberra0 libcolord1 + libcolorhug1 libcups2 libdatrie1 libdconf1 libdrm-intel1 libdrm-nouveau2 + libdrm-radeon1 libexif12 libfontconfig1 libfontenc1 libgd3 + libgdk-pixbuf2.0-0 libgdk-pixbuf2.0-common libgl1-mesa-dri libgl1-mesa-glx + libglapi-mesa libgphoto2-6 libgphoto2-l10n libgphoto2-port10 libgraphite2-3 + libgtk-3-0 libgtk-3-bin libgtk-3-common libgudev-1.0-0 libgusb2 + libharfbuzz0b libice6 libieee1284-3 libjasper1 libjbig0 libjpeg-turbo8 + libjpeg8 liblcms2-2 libllvm3.4 libltdl7 libnotify-bin libnotify4 libogg0 + libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 libpciaccess0 + libpixman-1-0 libsane libsane-common libsm6 libtdb1 libthai-data libthai0 + libtiff5 libtxc-dxtn-s2tc0 libv4l-0 libv4lconvert0 libvorbis0a + libvorbisfile3 libvpx1 libwayland-client0 libwayland-cursor0 libx11-xcb1 + libxaw7 libxcb-dri2-0 libxcb-dri3-0 libxcb-glx0 libxcb-present0 + libxcb-render0 libxcb-shm0 libxcb-sync1 libxcomposite1 libxcursor1 + libxdamage1 libxfixes3 libxfont1 libxi6 libxinerama1 libxkbcommon0 + libxkbfile1 libxmu6 libxpm4 libxrandr2 libxrender1 libxshmfence1 libxt6 + libxtst6 libxxf86vm1 notification-daemon sound-theme-freedesktop x11-common + x11-xkb-utils xfonts-base xfonts-encodings xfonts-utils xserver-common + xserver-xorg-core +Use 'apt-get autoremove' to remove them. +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +root@vagrant-ubuntu-trusty-64:/home/vagrant# exit +exit +Copy iso file /Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso into the box /tmp/VBoxGuestAdditions.iso +Mounting Virtualbox Guest Additions ISO to: /mnt +o loop /mntt-ubuntu-trusty-64:/home/vagrant# mount /tmp/VBoxGuestAdditions.iso - +mount: block device /tmp/VBoxGuestAdditions.iso is write-protected, mounting read-only +root@vagrant-ubuntu-trusty-64:/home/vagrant# exit +exit +Installing Virtualbox Guest Additions 6.0.8 - guest version is 4.3.40 +-nox11agrant-ubuntu-trusty-64:/home/vagrant# yes | /mnt/VBoxLinuxAdditions.run - +Verifying archive integrity... All good. +Uncompressing VirtualBox 6.0.8 Guest Additions for Linux........ +VirtualBox Guest Additions installer +Copying additional installer modules ... +Installing additional modules ... +VirtualBox Guest Additions: Starting. +VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel +modules. This may take a while. +VirtualBox Guest Additions: To build modules for other installed kernels, run +VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup +VirtualBox Guest Additions: or +VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all +VirtualBox Guest Additions: Building the modules for kernel 3.13.0-170-generic. + Adding system startup for /etc/init.d/vboxadd ... + /etc/rc0.d/K90vboxadd -> ../init.d/vboxadd + /etc/rc1.d/K90vboxadd -> ../init.d/vboxadd + /etc/rc6.d/K90vboxadd -> ../init.d/vboxadd + /etc/rc2.d/S10vboxadd -> ../init.d/vboxadd + /etc/rc3.d/S10vboxadd -> ../init.d/vboxadd + /etc/rc4.d/S10vboxadd -> ../init.d/vboxadd + /etc/rc5.d/S10vboxadd -> ../init.d/vboxadd + Adding system startup for /etc/init.d/vboxadd-service ... + /etc/rc0.d/K65vboxadd-service -> ../init.d/vboxadd-service + /etc/rc1.d/K65vboxadd-service -> ../init.d/vboxadd-service + /etc/rc6.d/K65vboxadd-service -> ../init.d/vboxadd-service + /etc/rc2.d/S35vboxadd-service -> ../init.d/vboxadd-service + /etc/rc3.d/S35vboxadd-service -> ../init.d/vboxadd-service + /etc/rc4.d/S35vboxadd-service -> ../init.d/vboxadd-service + /etc/rc5.d/S35vboxadd-service -> ../init.d/vboxadd-service +Building the VirtualBox Guest Additions kernel modules. This may take a while. +To build modules for other installed kernels, run + /sbin/rcvboxadd quicksetup +or + /sbin/rcvboxadd quicksetup all +Running kernel modules will not be replaced until the system is restarted +vboxadd-service.sh: Starting VirtualBox Guest Addition service. +bash: [3153: 2 (255)] tcsetattr: Inappropriate ioctl for device +root@vagrant-ubuntu-trusty-64:/home/vagrant# exit +exit +root@vagrant-ubuntu-trusty-64:/home/vagrant# /usr/sbin/service vboxadd start +VirtualBox Guest Additions: Starting. +VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel +modules. This may take a while. +VirtualBox Guest Additions: To build modules for other installed kernels, run +VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup +VirtualBox Guest Additions: or +VirtualBox Guest Additions: /sbin/rcvboxadd quicksetup all +VirtualBox Guest Additions: Running kernel modules will not be replaced until +the system is restarted +root@vagrant-ubuntu-trusty-64:/home/vagrant# exit +exit +Unmounting Virtualbox Guest Additions ISO from: /mnt +root@vagrant-ubuntu-trusty-64:/home/vagrant# umount /mnt +root@vagrant-ubuntu-trusty-64:/home/vagrant# exit +exit +vagrant@vagrant-ubuntu-trusty-64:~$ test + - +f /tm +p/VBoxGuestAd +di +tions. +iso && rm / +m +p/VBoxGues +t +Addition +s.iso +vagrant@vagrant-ubuntu-trusty-64:~$ exit +exit +==> default: Checking for guest additions in VM... +==> default: Configuring and enabling network interfaces... +==> default: Mounting shared folders... + default: /vagrant => /Users/metze/Work/Kitchen/DiViMe +==> default: Running provisioner: bootstrap (shell)... + default: Running: /var/folders/0p/f4ssc1410_sc6_9wkzz2d9100000gq/T/vagrant-shell20190702-5601-7btnlq.sh + default: root@vagrant-ubuntu-trusty-64:/home/vagrant# chmod + default: + + default: x '/t + default: m + default: p/vagr + default: a + default: nt-sh + default: ell' + default: + default: && +mp/ default: /t + default: vag + default: rant-shel + default: l + default: ---- Start bootstrapping DiViMe @ Wed Jul 3 03:19:24 UTC 2019 ---- + default: -- System information -- + default: nproc is 2 + default: Filesystem Size Used Avail Use% Mounted on + default: udev 996M 12K 996M 1% /dev + default: tmpfs 201M 424K 200M 1% /run + default: /dev/sda1 40G 1.5G 37G 4% / + default: none 4.0K 0 4.0K 0% /sys/fs/cgroup + default: none 5.0M 24K 5.0M 1% /run/lock + default: none 1001M 0 1001M 0% /run/shm + default: none 100M 0 100M 0% /run/user + default: vagrant 1.9T 1.6T 325G 83% /vagrant + default: MemTotal: 2049736 kB + default: MemFree: 1525300 kB + default: Buffers: 18884 kB + default: Cached: 358164 kB + default: SwapCached: 0 kB + default: Active: 243624 kB + default: Inactive: 215320 kB + default: Active(anon): 82028 kB + default: Inactive(anon): 324 kB + default: Active(file): 161596 kB + default: Inactive(file): 214996 kB + default: Unevictable: 0 kB + default: Mlocked: 0 kB + default: SwapTotal: 0 kB + default: SwapFree: 0 kB + default: Dirty: 25272 kB + default: Writeback: 0 kB + default: AnonPages: 81920 kB + default: Mapped: 9348 kB + default: Shmem: 460 kB + default: Slab: 37324 kB + default: SReclaimable: 26916 kB + default: SUnreclaim: 10408 kB + default: KernelStack: 1088 kB + default: PageTables: 3672 kB + default: NFS_Unstable: 0 kB + default: Bounce: 0 kB + default: WritebackTmp: 0 kB + default: CommitLimit: 1024868 kB + default: Committed_AS: 151508 kB + default: VmallocTotal: 34359738367 kB + default: VmallocUsed: 11116 kB + default: VmallocChunk: 34359723004 kB + default: HardwareCorrupted: 0 kB + default: AnonHugePages: 0 kB + default: HugePages_Total: 0 + default: HugePages_Free: 0 + default: HugePages_Rsvd: 0 + default: HugePages_Surp: 0 + default: Hugepagesize: 2048 kB + default: DirectMap4k: 36800 kB + default: DirectMap2M: 2060288 kB + default: -- Updating system -- + default: Ign http://archive.ubuntu.com trusty InRelease + default: Get:1 http://security.ubuntu.com trusty-security InRelease [65.9 kB] + default: Get:2 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB] + default: Get:3 http://security.ubuntu.com trusty-security/main Sources [172 kB] + default: Hit http://archive.ubuntu.com trusty-backports InRelease + default: Hit http://archive.ubuntu.com trusty Release.gpg + default: Get:4 http://archive.ubuntu.com trusty-updates/main Sources [431 kB] + default: Get:5 http://security.ubuntu.com trusty-security/universe Sources [102 kB] + default: Get:6 http://security.ubuntu.com trusty-security/main amd64 Packages [835 kB] + default: Get:7 http://archive.ubuntu.com trusty-updates/restricted Sources [6,313 B] + default: Get:8 http://archive.ubuntu.com trusty-updates/universe Sources [231 kB] + default: Get:9 http://security.ubuntu.com trusty-security/universe amd64 Packages [294 kB] + default: Get:10 http://archive.ubuntu.com trusty-updates/multiverse Sources [7,535 B] + default: Get:11 http://security.ubuntu.com trusty-security/main Translation-en [448 kB] + default: Get:12 http://archive.ubuntu.com trusty-updates/main amd64 Packages [1,177 kB] + default: Get:13 http://security.ubuntu.com trusty-security/universe Translation-en [162 kB] + default: Get:14 http://archive.ubuntu.com trusty-updates/restricted amd64 Packages [17.2 kB] + default: Get:15 http://archive.ubuntu.com trusty-updates/universe amd64 Packages [526 kB] + default: Get:16 http://archive.ubuntu.com trusty-updates/multiverse amd64 Packages [14.6 kB] + default: Get:17 http://archive.ubuntu.com trusty-updates/main Translation-en [582 kB] + default: Get:18 http://archive.ubuntu.com trusty-updates/multiverse Translation-en [7,616 B] + default: Get:19 http://archive.ubuntu.com trusty-updates/restricted Translation-en [4,028 B] + default: Get:20 http://archive.ubuntu.com trusty-updates/universe Translation-en [281 kB] + default: Get:21 http://archive.ubuntu.com trusty-backports/main Sources [9,709 B] + default: Get:22 http://archive.ubuntu.com trusty-backports/restricted Sources [28 B] + default: Get:23 http://archive.ubuntu.com trusty-backports/universe Sources [35.4 kB] + default: Get:24 http://archive.ubuntu.com trusty-backports/multiverse Sources [1,896 B] + default: Hit http://archive.ubuntu.com trusty-backports/main amd64 Packages + default: Hit http://archive.ubuntu.com trusty-backports/restricted amd64 Packages + default: Hit http://archive.ubuntu.com trusty-backports/universe amd64 Packages + default: Hit http://archive.ubuntu.com trusty-backports/multiverse amd64 Packages + default: Hit http://archive.ubuntu.com trusty-backports/main Translation-en + default: Hit http://archive.ubuntu.com trusty-backports/multiverse Translation-en + default: Hit http://archive.ubuntu.com trusty-backports/restricted Translation-en + default: Hit http://archive.ubuntu.com trusty-backports/universe Translation-en + default: Hit http://archive.ubuntu.com trusty Release + default: Get:25 http://archive.ubuntu.com trusty/main Sources [1,064 kB] + default: Get:26 http://archive.ubuntu.com trusty/restricted Sources [5,433 B] + default: Get:27 http://archive.ubuntu.com trusty/universe Sources [6,399 kB] + default: Get:28 http://archive.ubuntu.com trusty/multiverse Sources [174 kB] + default: Hit http://archive.ubuntu.com trusty/main amd64 Packages + default: Hit http://archive.ubuntu.com trusty/restricted amd64 Packages + default: Hit http://archive.ubuntu.com trusty/universe amd64 Packages + default: Hit http://archive.ubuntu.com trusty/multiverse amd64 Packages + default: Hit http://archive.ubuntu.com trusty/main Translation-en + default: Hit http://archive.ubuntu.com trusty/multiverse Translation-en + default: Hit http://archive.ubuntu.com trusty/restricted Translation-en + default: Hit http://archive.ubuntu.com trusty/universe Translation-en + default: Ign http://archive.ubuntu.com trusty/main Translation-en_US + default: Ign http://archive.ubuntu.com trusty/multiverse Translation-en_US + default: Ign http://archive.ubuntu.com trusty/restricted Translation-en_US + default: Ign http://archive.ubuntu.com trusty/universe Translation-en_US + default: Fetched 13.1 MB in 6s (2,038 kB/s) + default: Reading package lists... + default: Reading package lists... + default: Building dependency tree... + default: Reading state information... + default: The following packages were automatically installed and are no longer required: + default: acl at-spi2-core colord dconf-gsettings-backend dconf-service fontconfig + default: fontconfig-config fonts-dejavu-core hicolor-icon-theme libasound2 + default: libasound2-data libatk-bridge2.0-0 libatk1.0-0 libatk1.0-data libatspi2.0-0 + default: libavahi-client3 libavahi-common-data libavahi-common3 libcairo-gobject2 + default: libcairo2 libcanberra-gtk3-0 libcanberra-gtk3-module libcanberra0 libcolord1 + default: libcolorhug1 libcups2 libdatrie1 libdconf1 libdrm-intel1 libdrm-nouveau2 + default: libdrm-radeon1 libexif12 libfontconfig1 libfontenc1 libgd3 + default: libgdk-pixbuf2.0-0 libgdk-pixbuf2.0-common libgl1-mesa-dri libgl1-mesa-glx + default: libglapi-mesa libgphoto2-6 libgphoto2-l10n libgphoto2-port10 libgraphite2-3 + default: libgtk-3-0 libgtk-3-bin libgtk-3-common libgudev-1.0-0 libgusb2 + default: libharfbuzz0b libice6 libieee1284-3 libjasper1 libjbig0 libjpeg-turbo8 + default: libjpeg8 liblcms2-2 libllvm3.4 libltdl7 libnotify-bin libnotify4 libogg0 + default: libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 libpciaccess0 + default: libpixman-1-0 libsane libsane-common libsm6 libtdb1 libthai-data libthai0 + default: libtiff5 libtxc-dxtn-s2tc0 libv4l-0 libv4lconvert0 libvorbis0a + default: libvorbisfile3 libvpx1 libwayland-client0 libwayland-cursor0 libx11-xcb1 + default: libxaw7 libxcb-dri2-0 libxcb-dri3-0 libxcb-glx0 libxcb-present0 + default: libxcb-render0 libxcb-shm0 libxcb-sync1 libxcomposite1 libxcursor1 + default: libxdamage1 libxfixes3 libxfont1 libxi6 libxinerama1 libxkbcommon0 + default: libxkbfile1 libxmu6 libxpm4 libxrandr2 libxrender1 libxshmfence1 libxt6 + default: libxtst6 libxxf86vm1 notification-daemon sound-theme-freedesktop x11-common + default: x11-xkb-utils xfonts-base xfonts-encodings xfonts-utils xserver-common + default: xserver-xorg-core + default: Use 'apt-get autoremove' to remove them. + default: 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. + default: Reading package lists... + default: Building dependency tree... + default: Reading state information... + default: bc is already the newest version. + default: gawk is already the newest version. + default: make is already the newest version. + default: make set to manually installed. + default: fuse is already the newest version. + default: libx11-xcb1 is already the newest version. + default: libx11-xcb1 set to manually installed. + default: patch is already the newest version. + default: The following packages were automatically installed and are no longer required: + default: acl at-spi2-core colord dconf-gsettings-backend dconf-service + default: libatk-bridge2.0-0 libatspi2.0-0 libcairo-gobject2 libcanberra-gtk3-0 + default: libcanberra-gtk3-module libcanberra0 libcolord1 libcolorhug1 libdconf1 + default: libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libexif12 libfontenc1 libgd3 + default: libgl1-mesa-dri libgl1-mesa-glx libglapi-mesa libgphoto2-6 libgphoto2-l10n + default: libgphoto2-port10 libgtk-3-0 libgtk-3-bin libgtk-3-common libgudev-1.0-0 + default: libgusb2 libieee1284-3 libllvm3.4 libnotify-bin libnotify4 libsane + default: libsane-common libtdb1 libtxc-dxtn-s2tc0 libv4l-0 libv4lconvert0 + default: libwayland-client0 libwayland-cursor0 libxaw7 libxcb-dri2-0 libxcb-dri3-0 + default: libxcb-glx0 libxcb-present0 libxcb-sync1 libxfont1 libxkbcommon0 libxkbfile1 + default: libxmu6 libxpm4 libxshmfence1 libxxf86vm1 notification-daemon + default: sound-theme-freedesktop x11-xkb-utils xfonts-base xfonts-encodings + default: xfonts-utils xserver-common xserver-xorg-core + default: Use 'apt-get autoremove' to remove them. + default: The following extra packages will be installed: + default: alsa-base alsa-utils autotools-dev ca-certificates-java espeak-data + default: festlex-cmu festlex-poslex festvox-kallpc16k fonts-dejavu-extra g++-4.8 + default: gcc-4.8-multilib git-man icedtea-6-jre-cacao icedtea-6-jre-jamvm + default: icu-devtools java-common lib32asan0 lib32atomic1 lib32gcc-4.8-dev lib32gcc1 + default: lib32gomp1 lib32itm1 lib32quadmath0 libao-common libao4 libapr1 libaprutil1 + default: libasyncns0 libatk-wrapper-java libatk-wrapper-java-jni libatlas3-base + default: libavcodec54 libavdevice53 libavfilter3 libavformat54 libavresample1 + default: libavutil52 libblas-dev libblas3 libboost-atomic-dev libboost-atomic1.54-dev + default: libboost-atomic1.54.0 libboost-chrono-dev libboost-chrono1.54-dev + default: libboost-chrono1.54.0 libboost-context-dev libboost-context1.54-dev + default: libboost-context1.54.0 libboost-coroutine-dev libboost-coroutine1.54-dev + default: libboost-date-time-dev libboost-date-time1.54-dev libboost-date-time1.54.0 + default: libboost-dev libboost-exception-dev libboost-exception1.54-dev + default: libboost-filesystem-dev libboost-filesystem1.54-dev + default: libboost-filesystem1.54.0 libboost-graph-dev libboost-graph-parallel-dev + default: libboost-graph-parallel1.54-dev libboost-graph-parallel1.54.0 + default: libboost-graph1.54-dev libboost-graph1.54.0 libboost-iostreams-dev + default: libboost-iostreams1.54-dev libboost-locale-dev libboost-locale1.54-dev + default: libboost-locale1.54.0 libboost-log-dev libboost-log1.54-dev + default: libboost-log1.54.0 libboost-math-dev libboost-math1.54-dev + default: libboost-math1.54.0 libboost-mpi-dev libboost-mpi-python-dev + default: libboost-mpi-python1.54-dev libboost-mpi-python1.54.0 libboost-mpi1.54-dev + default: libboost-mpi1.54.0 libboost-program-options-dev + default: libboost-program-options1.54-dev libboost-program-options1.54.0 + default: libboost-python-dev libboost-python1.54-dev libboost-python1.54.0 + default: libboost-random-dev libboost-random1.54-dev libboost-random1.54.0 + default: libboost-regex-dev libboost-regex1.54-dev libboost-regex1.54.0 + default: libboost-serialization-dev libboost-serialization1.54-dev + default: libboost-serialization1.54.0 libboost-signals-dev libboost-signals1.54-dev + default: libboost-signals1.54.0 libboost-system-dev libboost-system1.54-dev + default: libboost-system1.54.0 libboost-test-dev libboost-test1.54-dev + default: libboost-test1.54.0 libboost-thread-dev libboost-thread1.54-dev + default: libboost-thread1.54.0 libboost-timer-dev libboost-timer1.54-dev + default: libboost-timer1.54.0 libboost-tools-dev libboost-wave-dev + default: libboost-wave1.54-dev libboost-wave1.54.0 libboost1.54-dev + default: libboost1.54-tools-dev libc6-dev-x32 libc6-i386 libc6-x32 libcaca0 + default: libcdio-cdda1 libcdio-paranoia1 libcdio13 libcr0 libdc1394-22 liberror-perl + default: libespeak1 libestools2.1 libexpat1-dev libflac8 libgfortran3 libgif4 libgsm1 + default: libgtk2.0-0 libgtk2.0-bin libgtk2.0-common libhwloc-dev libhwloc-plugins + default: libhwloc5 libibverbs-dev libibverbs1 libice-dev libicu-dev libid3tag0 + default: libjack-jackd2-0 liblapack3 libltdl-dev libmad0 libmp3lame0 libnspr4 libnss3 + default: libnss3-nssdb libopencore-amrnb0 libopencore-amrwb0 libopenjpeg2 + default: libopenmpi-dev libopenmpi1.6 libopus0 liborc-0.4-0 libpci-dev libpcsclite1 + default: libportaudio2 libpthread-stubs0-dev libpulse0 libpython-dev libpython2.7-dev + default: libraw1394-11 libsamplerate0 libschroedinger-1.0-0 libsdl1.2debian + default: libserf-1-1 libsm-dev libsndfile1 libsonic0 libsox-fmt-alsa libsox-fmt-ao + default: libsox-fmt-base libsox-fmt-mp3 libsox-fmt-oss libsox-fmt-pulse libsox2 + default: libspeex1 libstdc++-4.8-dev libsvn1 libswscale2 libtheora0 libtinfo-dev + default: libtorque2 libtwolame0 libva1 libvorbisenc2 libwavpack1 libx11-dev + default: libx11-doc libx264-142 libx32asan0 libx32atomic1 libx32gcc-4.8-dev + default: libx32gcc1 libx32gomp1 libx32itm1 libx32quadmath0 libxau-dev libxcb1-dev + default: libxdmcp-dev libxml2-dev libxvidcore4 linux-sound-base m4 mpi-default-bin + default: mpi-default-dev ocl-icd-libopencl1 openjdk-6-jre-headless openjdk-6-jre-lib + default: openmpi-bin openmpi-common ttf-dejavu-extra tzdata-java x11proto-core-dev + default: x11proto-input-dev x11proto-kb-dev xorg-sgml-doctools xtrans-dev + default: Suggested packages: + default: apmd alsa-oss oss-compat autoconf2.13 autoconf-archive gnu-standards + default: autoconf-doc gettext pidgin-festival festival-freebsoft-utils g++-multilib + default: g++-4.8-multilib gcc-4.8-doc libstdc++6-4.8-dbg git-daemon-run + default: git-daemon-sysvinit git-doc git-el git-email git-gui gitk gitweb git-arch + default: git-bzr git-cvs git-mediawiki git-svn default-jre equivs libaudio2 libesd0 + default: libesd-alsa0 libblas-doc liblapack-doc frei0r-plugins libboost-doc graphviz + default: libboost1.54-doc python-pyste libboost-coroutine.54-dev libboost-log.54-dev + default: libmpfrc++-dev libntl-dev xsltproc doxygen docbook-xml docbook-xsl + default: default-jdk fop blcr-dkms librsvg2-common gvfs libhwloc-contrib-plugins + default: libice-doc icu-doc jackd2 libtool-doc ncurses-doc opus-tools pcscd + default: pulseaudio libraw1394-doc libsm-doc speex libstdc++-4.8-doc automaken + default: gfortran fortran95-compiler gcj-jdk libxcb-doc pkg-config libxt-doc + default: opencl-icd icedtea-plugin libnss-mdns sun-java6-fonts fonts-ipafont-gothic + default: fonts-ipafont-mincho ttf-wqy-microhei ttf-wqy-zenhei ttf-indic-fonts-core + default: ttf-telugu-fonts ttf-oriya-fonts ttf-kannada-fonts ttf-bengali-fonts + default: openmpi-checkpoint subversion-tools db5.3-util zip + default: The following NEW packages will be installed: + default: alsa-base alsa-utils autoconf automake autotools-dev ca-certificates-java + default: espeak espeak-data festival festlex-cmu festlex-poslex festvox-kallpc16k + default: fonts-dejavu-extra g++ g++-4.8 gcc-4.8-multilib gcc-multilib git git-man + default: icedtea-6-jre-cacao icedtea-6-jre-jamvm icedtea-netx icedtea-netx-common + default: icu-devtools java-common lib32asan0 lib32atomic1 lib32gcc-4.8-dev lib32gcc1 + default: lib32gomp1 lib32itm1 lib32quadmath0 libao-common libao4 libapr1 libaprutil1 + default: libasyncns0 libatk-wrapper-java libatk-wrapper-java-jni libatlas-base-dev + default: libatlas-dev libatlas3-base libav-tools libavcodec54 libavdevice53 + default: libavfilter3 libavformat54 libavresample1 libavutil52 libblas-dev libblas3 + default: libboost-all-dev libboost-atomic-dev libboost-atomic1.54-dev + default: libboost-atomic1.54.0 libboost-chrono-dev libboost-chrono1.54-dev + default: libboost-chrono1.54.0 libboost-context-dev libboost-context1.54-dev + default: libboost-context1.54.0 libboost-coroutine-dev libboost-coroutine1.54-dev + default: libboost-date-time-dev libboost-date-time1.54-dev libboost-date-time1.54.0 + default: libboost-dev libboost-exception-dev libboost-exception1.54-dev + default: libboost-filesystem-dev libboost-filesystem1.54-dev + default: libboost-filesystem1.54.0 libboost-graph-dev libboost-graph-parallel-dev + default: libboost-graph-parallel1.54-dev libboost-graph-parallel1.54.0 + default: libboost-graph1.54-dev libboost-graph1.54.0 libboost-iostreams-dev + default: libboost-iostreams1.54-dev libboost-locale-dev libboost-locale1.54-dev + default: libboost-locale1.54.0 libboost-log-dev libboost-log1.54-dev + default: libboost-log1.54.0 libboost-math-dev libboost-math1.54-dev + default: libboost-math1.54.0 libboost-mpi-dev libboost-mpi-python-dev + default: libboost-mpi-python1.54-dev libboost-mpi-python1.54.0 libboost-mpi1.54-dev + default: libboost-mpi1.54.0 libboost-program-options-dev + default: libboost-program-options1.54-dev libboost-program-options1.54.0 + default: libboost-python-dev libboost-python1.54-dev libboost-python1.54.0 + default: libboost-random-dev libboost-random1.54-dev libboost-random1.54.0 + default: libboost-regex-dev libboost-regex1.54-dev libboost-regex1.54.0 + default: libboost-serialization-dev libboost-serialization1.54-dev + default: libboost-serialization1.54.0 libboost-signals-dev libboost-signals1.54-dev + default: libboost-signals1.54.0 libboost-system-dev libboost-system1.54-dev + default: libboost-system1.54.0 libboost-test-dev libboost-test1.54-dev + default: libboost-test1.54.0 libboost-thread-dev libboost-thread1.54-dev + default: libboost-thread1.54.0 libboost-timer-dev libboost-timer1.54-dev + default: libboost-timer1.54.0 libboost-tools-dev libboost-wave-dev + default: libboost-wave1.54-dev libboost-wave1.54.0 libboost1.54-dev + default: libboost1.54-tools-dev libc6-dev-i386 libc6-dev-x32 libc6-i386 libc6-x32 + default: libcaca0 libcdio-cdda1 libcdio-paranoia1 libcdio13 libcr0 libdc1394-22 + default: liberror-perl libespeak1 libestools2.1 libexpat1-dev libflac8 libgfortran3 + default: libgif4 libgsm1 libgtk2.0-0 libgtk2.0-bin libgtk2.0-common libhwloc-dev + default: libhwloc-plugins libhwloc5 libibverbs-dev libibverbs1 libice-dev libicu-dev + default: libid3tag0 libjack-jackd2-0 liblapack-dev liblapack3 libltdl-dev libmad0 + default: libmp3lame0 libncurses5-dev libnspr4 libnss3 libnss3-nssdb + default: libopencore-amrnb0 libopencore-amrwb0 libopenjpeg2 libopenmpi-dev + default: libopenmpi1.6 libopus0 liborc-0.4-0 libpci-dev libpcsclite1 libportaudio2 + default: libpthread-stubs0-dev libpulse0 libpython-dev libpython2.7-dev libraw1394-11 + default: libsamplerate0 libschroedinger-1.0-0 libsdl1.2debian libserf-1-1 libsm-dev + default: libsndfile1 libsonic0 libsox-fmt-all libsox-fmt-alsa libsox-fmt-ao + default: libsox-fmt-base libsox-fmt-mp3 libsox-fmt-oss libsox-fmt-pulse libsox2 + default: libspeex1 libstdc++-4.8-dev libsvn1 libswscale2 libtheora0 libtinfo-dev + default: libtool libtorque2 libtwolame0 libva1 libvorbisenc2 libwavpack1 libx11-dev + default: libx11-doc libx264-142 libx32asan0 libx32atomic1 libx32gcc-4.8-dev + default: libx32gcc1 libx32gomp1 libx32itm1 libx32quadmath0 libxau-dev libxcb1-dev + default: libxdmcp-dev libxml2-dev libxt-dev libxvidcore4 linux-sound-base m4 + default: mpi-default-bin mpi-default-dev ocl-icd-libopencl1 openjdk-6-jre + default: openjdk-6-jre-headless openjdk-6-jre-lib openmpi-bin openmpi-common + default: python-setuptools sox sshfs subversion ttf-dejavu-extra tzdata-java unzip + default: x11proto-core-dev x11proto-input-dev x11proto-kb-dev xorg-sgml-doctools + default: xtrans-dev zlib1g-dev + default: 0 upgraded, 251 newly installed, 0 to remove and 0 not upgraded. + default: Need to get 162 MB of archives. + default: After this operation, 600 MB of additional disk space will be used. + default: Get:1 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libc6-i386 amd64 2.19-0ubuntu6.15 [2,208 kB] + default: Get:2 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libc6-dev-i386 amd64 2.19-0ubuntu6.15 [1,153 kB] + default: Get:3 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libc6-x32 amd64 2.19-0ubuntu6.15 [2,431 kB] + default: Get:4 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libc6-dev-x32 amd64 2.19-0ubuntu6.15 [1,414 kB] + default: Get:5 http://archive.ubuntu.com/ubuntu/ trusty-updates/main lib32gcc1 amd64 1:4.9.3-0ubuntu4 [47.8 kB] + default: Get:6 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libx32gcc1 amd64 1:4.9.3-0ubuntu4 [38.6 kB] + default: Get:7 http://archive.ubuntu.com/ubuntu/ trusty-updates/main lib32gomp1 amd64 4.8.4-2ubuntu1~14.04.4 [25.0 kB] + default: Get:8 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libx32gomp1 amd64 4.8.4-2ubuntu1~14.04.4 [22.5 kB] + default: Get:9 http://archive.ubuntu.com/ubuntu/ trusty-updates/main lib32itm1 amd64 4.8.4-2ubuntu1~14.04.4 [28.5 kB] + default: Get:10 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libx32itm1 amd64 4.8.4-2ubuntu1~14.04.4 [28.4 kB] + default: Get:11 http://archive.ubuntu.com/ubuntu/ trusty-updates/main lib32atomic1 amd64 4.8.4-2ubuntu1~14.04.4 [8,250 B] + default: Get:12 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libx32atomic1 amd64 4.8.4-2ubuntu1~14.04.4 [8,604 B] + default: Get:13 http://archive.ubuntu.com/ubuntu/ trusty-updates/main lib32asan0 amd64 4.8.4-2ubuntu1~14.04.4 [64.2 kB] + default: Get:14 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libx32asan0 amd64 4.8.4-2ubuntu1~14.04.4 [63.1 kB] + default: Get:15 http://archive.ubuntu.com/ubuntu/ trusty-updates/main lib32quadmath0 amd64 4.8.4-2ubuntu1~14.04.4 [187 kB] + default: Get:16 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libx32quadmath0 amd64 4.8.4-2ubuntu1~14.04.4 [128 kB] + default: Get:17 http://archive.ubuntu.com/ubuntu/ trusty-updates/main lib32gcc-4.8-dev amd64 4.8.4-2ubuntu1~14.04.4 [1,685 kB] + default: Get:18 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libx32gcc-4.8-dev amd64 4.8.4-2ubuntu1~14.04.4 [1,558 kB] + default: Get:19 http://archive.ubuntu.com/ubuntu/ trusty-updates/main gcc-4.8-multilib amd64 4.8.4-2ubuntu1~14.04.4 [982 B] + default: Get:20 http://archive.ubuntu.com/ubuntu/ trusty/main gcc-multilib amd64 4:4.8.2-1ubuntu6 [1,024 B] + default: Get:21 http://archive.ubuntu.com/ubuntu/ trusty/main libao-common all 1.1.0-2ubuntu2 [6,278 B] + default: Get:22 http://archive.ubuntu.com/ubuntu/ trusty/main libao4 amd64 1.1.0-2ubuntu2 [31.5 kB] + default: Get:23 http://archive.ubuntu.com/ubuntu/ trusty/main libapr1 amd64 1.5.0-1 [85.1 kB] + default: Get:24 http://archive.ubuntu.com/ubuntu/ trusty/main libaprutil1 amd64 1.5.3-1 [76.4 kB] + default: Get:25 http://archive.ubuntu.com/ubuntu/ trusty/main libasyncns0 amd64 0.8-4ubuntu2 [11.9 kB] + default: Get:26 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libgtk2.0-common all 2.24.23-0ubuntu1.4 [121 kB] + default: Get:27 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libgtk2.0-0 amd64 2.24.23-0ubuntu1.4 [1,739 kB] + default: Get:28 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe openjdk-6-jre-lib all 6b41-1.13.13-0ubuntu0.14.04.1 [6,007 kB] + default: Get:29 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libnspr4 amd64 2:4.13.1-0ubuntu0.14.04.1 [110 kB] + default: Get:30 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libnss3-nssdb all 2:3.28.4-0ubuntu0.14.04.5 [10.6 kB] + default: Get:31 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libnss3 amd64 2:3.28.4-0ubuntu0.14.04.5 [1,124 kB] + default: Get:32 http://archive.ubuntu.com/ubuntu/ trusty/main ca-certificates-java all 20130815ubuntu1 [13.4 kB] + default: Get:33 http://archive.ubuntu.com/ubuntu/ trusty-updates/main tzdata-java all 2019a-0ubuntu0.14.04 [70.0 kB] + default: Get:34 http://archive.ubuntu.com/ubuntu/ trusty/main java-common all 0.51 [130 kB] + default: Get:35 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libpcsclite1 amd64 1.8.10-1ubuntu1.1 [21.1 kB] + default: Get:36 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe openjdk-6-jre-headless amd64 6b41-1.13.13-0ubuntu0.14.04.1 [31.2 MB] + default: Get:37 http://archive.ubuntu.com/ubuntu/ trusty/main libgif4 amd64 4.1.6-11 [28.6 kB] + default: Get:38 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libflac8 amd64 1.3.0-2ubuntu0.14.04.1 [80.2 kB] + default: Get:39 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libvorbisenc2 amd64 1.3.2-1.3ubuntu1.2 [84.6 kB] + default: Get:40 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libsndfile1 amd64 1.0.25-7ubuntu2.2 [136 kB] + default: Get:41 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libpulse0 amd64 1:4.0-0ubuntu11.1 [225 kB] + default: Get:42 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe openjdk-6-jre amd64 6b41-1.13.13-0ubuntu0.14.04.1 [192 kB] + default: Get:43 http://archive.ubuntu.com/ubuntu/ trusty/main libatk-wrapper-java all 0.30.4-4 [30.2 kB] + default: Get:44 http://archive.ubuntu.com/ubuntu/ trusty/main libatk-wrapper-java-jni amd64 0.30.4-4 [25.2 kB] + default: Get:45 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libavutil52 amd64 6:9.20-0ubuntu0.14.04.1 [66.9 kB] + default: Get:46 http://archive.ubuntu.com/ubuntu/ trusty/universe libgsm1 amd64 1.0.13-4 [27.1 kB] + default: Get:47 http://archive.ubuntu.com/ubuntu/ trusty/universe libmp3lame0 amd64 3.99.5+repack1-3ubuntu1 [158 kB] + default: Get:48 http://archive.ubuntu.com/ubuntu/ trusty/universe libopenjpeg2 amd64 1.3+dfsg-4.7ubuntu1 [64.3 kB] + default: Get:49 http://archive.ubuntu.com/ubuntu/ trusty/main libopus0 amd64 1.1-0ubuntu1 [153 kB] + default: Get:50 http://archive.ubuntu.com/ubuntu/ trusty/main liborc-0.4-0 amd64 1:0.4.18-1ubuntu1 [136 kB] + default: Get:51 http://archive.ubuntu.com/ubuntu/ trusty/universe libschroedinger-1.0-0 amd64 1.0.11-2ubuntu1 [268 kB] + default: Get:52 http://archive.ubuntu.com/ubuntu/ trusty/main libspeex1 amd64 1.2~rc1.1-1ubuntu1 [50.7 kB] + default: Get:53 http://archive.ubuntu.com/ubuntu/ trusty/main libtheora0 amd64 1.1.1+dfsg.1-3.2 [163 kB] + default: Get:54 http://archive.ubuntu.com/ubuntu/ trusty/universe libva1 amd64 1.3.0-2 [38.6 kB] + default: Get:55 http://archive.ubuntu.com/ubuntu/ trusty/universe libx264-142 amd64 2:0.142.2389+git956c8d8-2 [575 kB] + default: Get:56 http://archive.ubuntu.com/ubuntu/ trusty/universe libxvidcore4 amd64 2:1.3.2-9ubuntu1 [298 kB] + default: Get:57 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libavcodec54 amd64 6:9.20-0ubuntu0.14.04.1 [2,350 kB] + default: Get:58 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libavformat54 amd64 6:9.20-0ubuntu0.14.04.1 [481 kB] + default: Get:59 http://archive.ubuntu.com/ubuntu/ trusty/main libcdio13 amd64 0.83-4.1ubuntu1 [53.6 kB] + default: Get:60 http://archive.ubuntu.com/ubuntu/ trusty/main libcdio-cdda1 amd64 0.83-4.1ubuntu1 [15.5 kB] + default: Get:61 http://archive.ubuntu.com/ubuntu/ trusty/main libcdio-paranoia1 amd64 0.83-4.1ubuntu1 [15.2 kB] + default: Get:62 http://archive.ubuntu.com/ubuntu/ trusty/main libraw1394-11 amd64 2.1.0-1ubuntu1 [29.9 kB] + default: Get:63 http://archive.ubuntu.com/ubuntu/ trusty/universe libdc1394-22 amd64 2.2.1-2ubuntu2 [75.0 kB] + default: Get:64 http://archive.ubuntu.com/ubuntu/ trusty/main libsamplerate0 amd64 0.1.8-7 [938 kB] + default: Get:65 http://archive.ubuntu.com/ubuntu/ trusty/main libjack-jackd2-0 amd64 1.9.9.5+20130622git7de15e7a-1ubuntu1 [182 kB] + default: Get:66 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libavdevice53 amd64 6:9.20-0ubuntu0.14.04.1 [32.3 kB] + default: Get:67 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libavresample1 amd64 6:9.20-0ubuntu0.14.04.1 [39.2 kB] + default: Get:68 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libswscale2 amd64 6:9.20-0ubuntu0.14.04.1 [81.7 kB] + default: Get:69 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libavfilter3 amd64 6:9.20-0ubuntu0.14.04.1 [93.6 kB] + default: Get:70 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libcaca0 amd64 0.99.beta18-1ubuntu5.1 [202 kB] + default: Get:71 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libsdl1.2debian amd64 1.2.15-8ubuntu1.1 [162 kB] + default: Get:72 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libav-tools amd64 6:9.20-0ubuntu0.14.04.1 [3,310 kB] + default: Get:73 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-atomic1.54.0 amd64 1.54.0-4ubuntu3.1 [8,076 B] + default: Get:74 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-system1.54.0 amd64 1.54.0-4ubuntu3.1 [10.1 kB] + default: Get:75 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-chrono1.54.0 amd64 1.54.0-4ubuntu3.1 [12.5 kB] + default: Get:76 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-context1.54.0 amd64 1.54.0-4ubuntu3.1 [8,028 B] + default: Get:77 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-date-time1.54.0 amd64 1.54.0-4ubuntu3.1 [20.8 kB] + default: Get:78 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-filesystem1.54.0 amd64 1.54.0-4ubuntu3.1 [34.2 kB] + default: Get:79 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-serialization1.54.0 amd64 1.54.0-4ubuntu3.1 [126 kB] + default: Get:80 http://archive.ubuntu.com/ubuntu/ trusty/universe libcr0 amd64 0.8.5-2.1 [18.6 kB] + default: Get:81 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libhwloc5 amd64 1.8-1ubuntu1.14.04.1 [78.0 kB] + default: Get:82 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libibverbs1 amd64 1.1.7-1ubuntu1.1 [23.6 kB] + default: Get:83 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libtorque2 amd64 2.4.16+dfsg-1.3ubuntu1.1 [76.6 kB] + default: Get:84 http://archive.ubuntu.com/ubuntu/ trusty/universe libopenmpi1.6 amd64 1.6.5-8 [1,396 kB] + default: Get:85 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-mpi1.54.0 amd64 1.54.0-4ubuntu3.1 [45.6 kB] + default: Get:86 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-graph-parallel1.54.0 amd64 1.54.0-4ubuntu3.1 [71.3 kB] + default: Get:87 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-regex1.54.0 amd64 1.54.0-4ubuntu3.1 [261 kB] + default: Get:88 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-graph1.54.0 amd64 1.54.0-4ubuntu3.1 [94.7 kB] + default: Get:89 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-thread1.54.0 amd64 1.54.0-4ubuntu3.1 [26.5 kB] + default: Get:90 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-locale1.54.0 amd64 1.54.0-4ubuntu3.1 [212 kB] + default: Get:91 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-math1.54.0 amd64 1.54.0-4ubuntu3.1 [252 kB] + default: Get:92 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-python1.54.0 amd64 1.54.0-4ubuntu3.1 [122 kB] + default: Get:93 http://archive.ubuntu.com/ubuntu/ trusty/universe openmpi-common all 1.6.5-8 [101 kB] + default: Get:94 http://archive.ubuntu.com/ubuntu/ trusty/universe openmpi-bin amd64 1.6.5-8 [84.5 kB] + default: Get:95 http://archive.ubuntu.com/ubuntu/ trusty/universe mpi-default-bin amd64 1.0.2ubuntu1 [3,252 B] + default: Get:96 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-mpi-python1.54.0 amd64 1.54.0-4ubuntu3.1 [215 kB] + default: Get:97 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-program-options1.54.0 amd64 1.54.0-4ubuntu3.1 [115 kB] + default: Get:98 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-random1.54.0 amd64 1.54.0-4ubuntu3.1 [9,834 B] + default: Get:99 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-signals1.54.0 amd64 1.54.0-4ubuntu3.1 [29.8 kB] + default: Get:100 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-test1.54.0 amd64 1.54.0-4ubuntu3.1 [178 kB] + default: Get:101 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-timer1.54.0 amd64 1.54.0-4ubuntu3.1 [9,926 B] + default: Get:102 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-wave1.54.0 amd64 1.54.0-4ubuntu3.1 [161 kB] + default: Get:103 http://archive.ubuntu.com/ubuntu/ trusty/main libportaudio2 amd64 19+svn20140130-1 [62.9 kB] + default: Get:104 http://archive.ubuntu.com/ubuntu/ trusty/main libsonic0 amd64 0.1.18-0ubuntu1 [11.5 kB] + default: Get:105 http://archive.ubuntu.com/ubuntu/ trusty/main espeak-data amd64 1.47.11-1ubuntu1 [853 kB] + default: Get:106 http://archive.ubuntu.com/ubuntu/ trusty/main libespeak1 amd64 1.47.11-1ubuntu1 [138 kB] + default: Get:107 http://archive.ubuntu.com/ubuntu/ trusty/universe libestools2.1 amd64 1:2.1~release-6 [1,292 kB] + default: Get:108 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libgfortran3 amd64 4.8.4-2ubuntu1~14.04.4 [248 kB] + default: Get:109 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libmad0 amd64 0.15.1b-9ubuntu14.04.1 [62.0 kB] + default: Get:110 http://archive.ubuntu.com/ubuntu/ trusty/universe libopencore-amrnb0 amd64 0.1.3-2ubuntu1 [90.4 kB] + default: Get:111 http://archive.ubuntu.com/ubuntu/ trusty/universe libopencore-amrwb0 amd64 0.1.3-2ubuntu1 [45.3 kB] + default: Get:112 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libexpat1-dev amd64 2.1.0-4ubuntu1.4 [115 kB] + default: Get:113 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libpython2.7-dev amd64 2.7.6-8ubuntu0.5 [22.0 MB] + default: Get:114 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libserf-1-1 amd64 1.3.3-1ubuntu0.1 [42.2 kB] + default: Get:115 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libsox2 amd64 14.4.1-3ubuntu1.1 [221 kB] + default: Get:116 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libsvn1 amd64 1.8.8-1ubuntu3.3 [918 kB] + default: Get:117 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libwavpack1 amd64 4.70.0-1ubuntu0.2 [74.7 kB] + default: Get:118 http://archive.ubuntu.com/ubuntu/ trusty/universe ocl-icd-libopencl1 amd64 2.1.3-4 [28.1 kB] + default: Get:119 http://archive.ubuntu.com/ubuntu/ trusty/main linux-sound-base all 1.0.25+dfsg-0ubuntu4 [14.5 kB] + default: Get:120 http://archive.ubuntu.com/ubuntu/ trusty/main alsa-base all 1.0.25+dfsg-0ubuntu4 [151 kB] + default: Get:121 http://archive.ubuntu.com/ubuntu/ trusty/main alsa-utils amd64 1.0.27.2-1ubuntu2 [933 kB] + default: Get:122 http://archive.ubuntu.com/ubuntu/ trusty/main m4 amd64 1.4.17-2ubuntu1 [195 kB] + default: Get:123 http://archive.ubuntu.com/ubuntu/ trusty/main autoconf all 2.69-6 [322 kB] + default: Get:124 http://archive.ubuntu.com/ubuntu/ trusty/main autotools-dev all 20130810.1 [44.3 kB] + default: Get:125 http://archive.ubuntu.com/ubuntu/ trusty/main automake all 1:1.14.1-2ubuntu1 [510 kB] + default: Get:126 http://archive.ubuntu.com/ubuntu/ trusty/main espeak amd64 1.47.11-1ubuntu1 [60.0 kB] + default: Get:127 http://archive.ubuntu.com/ubuntu/ trusty/universe festival amd64 1:2.1~release-6ubuntu1 [1,016 kB] + default: Get:128 http://archive.ubuntu.com/ubuntu/ trusty/universe festlex-cmu all 1.4.0-6 [881 kB] + default: Get:129 http://archive.ubuntu.com/ubuntu/ trusty/universe festlex-poslex all 1.4.0-5 [235 kB] + default: Get:130 http://archive.ubuntu.com/ubuntu/ trusty/main fonts-dejavu-extra all 2.34-1ubuntu1 [1,736 kB] + default: Get:131 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libstdc++-4.8-dev amd64 4.8.4-2ubuntu1~14.04.4 [1,051 kB] + default: Get:132 http://archive.ubuntu.com/ubuntu/ trusty-updates/main g++-4.8 amd64 4.8.4-2ubuntu1~14.04.4 [18.0 MB] + default: Get:133 http://archive.ubuntu.com/ubuntu/ trusty/main g++ amd64 4:4.8.2-1ubuntu6 [1,490 B] + default: Get:134 http://archive.ubuntu.com/ubuntu/ trusty/main liberror-perl all 0.17-1.1 [21.1 kB] + default: Get:135 http://archive.ubuntu.com/ubuntu/ trusty-updates/main git-man all 1:1.9.1-1ubuntu0.10 [700 kB] + default: Get:136 http://archive.ubuntu.com/ubuntu/ trusty-updates/main git amd64 1:1.9.1-1ubuntu0.10 [2,737 kB] + default: Get:137 http://archive.ubuntu.com/ubuntu/ trusty-updates/main icu-devtools amd64 52.1-3ubuntu0.8 [163 kB] + default: Get:138 http://archive.ubuntu.com/ubuntu/ trusty/universe libatlas3-base amd64 3.10.1-4 [2,677 kB] + default: Get:139 http://archive.ubuntu.com/ubuntu/ trusty/main libblas3 amd64 1.2.20110419-7 [215 kB] + default: Get:140 http://archive.ubuntu.com/ubuntu/ trusty/main libblas-dev amd64 1.2.20110419-7 [240 kB] + default: Get:141 http://archive.ubuntu.com/ubuntu/ trusty/universe libatlas-dev all 3.10.1-4 [22.7 kB] + default: Get:142 http://archive.ubuntu.com/ubuntu/ trusty/universe libatlas-base-dev amd64 3.10.1-4 [3,348 kB] + default: Get:143 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost1.54-dev amd64 1.54.0-4ubuntu3.1 [5,682 kB] + default: Get:144 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-dev amd64 1.54.0.1ubuntu1 [3,076 B] + default: Get:145 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost1.54-tools-dev amd64 1.54.0-4ubuntu3.1 [1,048 kB] + default: Get:146 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-tools-dev amd64 1.54.0.1ubuntu1 [2,992 B] + default: Get:147 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-atomic1.54-dev amd64 1.54.0-4ubuntu3.1 [4,914 B] + default: Get:148 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-atomic-dev amd64 1.54.0.1ubuntu1 [3,128 B] + default: Get:149 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-chrono1.54-dev amd64 1.54.0-4ubuntu3.1 [14.2 kB] + default: Get:150 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-chrono-dev amd64 1.54.0.1ubuntu1 [3,450 B] + default: Get:151 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-context1.54-dev amd64 1.54.0-4ubuntu3.1 [4,760 B] + default: Get:152 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-context-dev amd64 1.54.0.1ubuntu1 [3,010 B] + default: Get:153 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-coroutine1.54-dev amd64 1.54.0-4ubuntu3.1 [6,860 B] + default: Get:154 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-coroutine-dev amd64 1.54.0.1ubuntu1 [3,084 B] + default: Get:155 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-serialization1.54-dev amd64 1.54.0-4ubuntu3.1 [151 kB] + default: Get:156 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-date-time1.54-dev amd64 1.54.0-4ubuntu3.1 [25.2 kB] + default: Get:157 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-date-time-dev amd64 1.54.0.1ubuntu1 [2,826 B] + default: Get:158 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-exception1.54-dev amd64 1.54.0-4ubuntu3.1 [4,392 B] + default: Get:159 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-exception-dev amd64 1.54.0.1ubuntu1 [2,812 B] + default: Get:160 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-system1.54-dev amd64 1.54.0-4ubuntu3.1 [8,428 B] + default: Get:161 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-filesystem1.54-dev amd64 1.54.0-4ubuntu3.1 [41.7 kB] + default: Get:162 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-filesystem-dev amd64 1.54.0.1ubuntu1 [2,854 B] + default: Get:163 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-test1.54-dev amd64 1.54.0-4ubuntu3.1 [213 kB] + default: Get:164 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-graph1.54-dev amd64 1.54.0-4ubuntu3.1 [98.3 kB] + default: Get:165 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-graph-dev amd64 1.54.0.1ubuntu1 [2,912 B] + default: Get:166 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-graph-parallel1.54-dev amd64 1.54.0-4ubuntu3.1 [72.5 kB] + default: Get:167 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-graph-parallel-dev amd64 1.54.0.1ubuntu1 [2,948 B] + default: Get:168 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libicu-dev amd64 52.1-3ubuntu0.8 [7,615 kB] + default: Get:169 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-regex1.54-dev amd64 1.54.0-4ubuntu3.1 [302 kB] + default: Get:170 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-iostreams1.54-dev amd64 1.54.0-4ubuntu3.1 [32.7 kB] + default: Get:171 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-iostreams-dev amd64 1.54.0.1ubuntu1 [2,816 B] + default: Get:172 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-locale1.54-dev amd64 1.54.0-4ubuntu3.1 [277 kB] + default: Get:173 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-locale-dev amd64 1.54.0.1ubuntu1 [3,150 B] + default: Get:174 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-log1.54.0 amd64 1.54.0-4ubuntu3.1 [529 kB] + default: Get:175 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-thread1.54-dev amd64 1.54.0-4ubuntu3.1 [26.0 kB] + default: Get:176 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-log1.54-dev amd64 1.54.0-4ubuntu3.1 [621 kB] + default: Get:177 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-log-dev amd64 1.54.0.1ubuntu1 [3,012 B] + default: Get:178 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-math1.54-dev amd64 1.54.0-4ubuntu3.1 [621 kB] + default: Get:179 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-math-dev amd64 1.54.0.1ubuntu1 [3,018 B] + default: Get:180 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libibverbs-dev amd64 1.1.7-1ubuntu1.1 [70.0 kB] + default: Get:181 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libxml2-dev amd64 2.9.1+dfsg1-3ubuntu4.13 [630 kB] + default: Get:182 http://archive.ubuntu.com/ubuntu/ trusty-updates/main zlib1g-dev amd64 1:1.2.8.dfsg-1ubuntu1.1 [166 kB] + default: Get:183 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libpci-dev amd64 1:3.2.1-1ubuntu5.1 [43.9 kB] + default: Get:184 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libhwloc-dev amd64 1.8-1ubuntu1.14.04.1 [129 kB] + default: Get:185 http://archive.ubuntu.com/ubuntu/ trusty/universe libopenmpi-dev amd64 1.6.5-8 [379 kB] + default: Get:186 http://archive.ubuntu.com/ubuntu/ trusty/universe mpi-default-dev amd64 1.0.2ubuntu1 [3,822 B] + default: Get:187 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-mpi1.54-dev amd64 1.54.0-4ubuntu3.1 [118 kB] + default: Get:188 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-mpi-dev amd64 1.54.0.1ubuntu1 [2,904 B] + default: Get:189 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-mpi-python1.54-dev amd64 1.54.0-4ubuntu3.1 [23.5 kB] + default: Get:190 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-mpi-python-dev amd64 1.54.0.1ubuntu1 [2,940 B] + default: Get:191 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-program-options1.54-dev amd64 1.54.0-4ubuntu3.1 [133 kB] + default: Get:192 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-program-options-dev amd64 1.54.0.1ubuntu1 [2,840 B] + default: Get:193 http://archive.ubuntu.com/ubuntu/ trusty/main libpython-dev amd64 2.7.5-5ubuntu3 [7,078 B] + default: Get:194 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libboost-python1.54-dev amd64 1.54.0-4ubuntu3.1 [119 kB] + default: Get:195 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-python-dev amd64 1.54.0.1ubuntu1 [3,204 B] + default: Get:196 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-random1.54-dev amd64 1.54.0-4ubuntu3.1 [6,366 B] + default: Get:197 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-random-dev amd64 1.54.0.1ubuntu1 [2,812 B] + default: Get:198 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-regex-dev amd64 1.54.0.1ubuntu1 [3,084 B] + default: Get:199 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-serialization-dev amd64 1.54.0.1ubuntu1 [3,050 B] + default: Get:200 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-signals1.54-dev amd64 1.54.0-4ubuntu3.1 [31.0 kB] + default: Get:201 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-signals-dev amd64 1.54.0.1ubuntu1 [2,884 B] + default: Get:202 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-system-dev amd64 1.54.0.1ubuntu1 [2,956 B] + default: Get:203 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-test-dev amd64 1.54.0.1ubuntu1 [2,858 B] + default: Get:204 http://archive.ubuntu.com/ubuntu/ trusty/main libboost-thread-dev amd64 1.54.0.1ubuntu1 [2,848 B] + default: Get:205 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-timer1.54-dev amd64 1.54.0-4ubuntu3.1 [9,554 B] + default: Get:206 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-timer-dev amd64 1.54.0.1ubuntu1 [2,940 B] + default: Get:207 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libboost-wave1.54-dev amd64 1.54.0-4ubuntu3.1 [210 kB] + default: Get:208 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-wave-dev amd64 1.54.0.1ubuntu1 [2,852 B] + default: Get:209 http://archive.ubuntu.com/ubuntu/ trusty/universe libboost-all-dev amd64 1.54.0.1ubuntu1 [2,096 B] + default: Get:210 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libgtk2.0-bin amd64 2.24.23-0ubuntu1.4 [9,774 B] + default: Get:211 http://archive.ubuntu.com/ubuntu/ trusty/main xorg-sgml-doctools all 1:1.11-1 [12.9 kB] + default: Get:212 http://archive.ubuntu.com/ubuntu/ trusty-updates/main x11proto-core-dev all 7.0.26-1~ubuntu2 [700 kB] + default: Get:213 http://archive.ubuntu.com/ubuntu/ trusty/main libice-dev amd64 2:1.0.8-2 [57.6 kB] + default: Get:214 http://archive.ubuntu.com/ubuntu/ trusty/main libid3tag0 amd64 0.15.1b-10ubuntu1 [28.9 kB] + default: Get:215 http://archive.ubuntu.com/ubuntu/ trusty/main liblapack3 amd64 3.5.0-2ubuntu1 [1,730 kB] + default: Get:216 http://archive.ubuntu.com/ubuntu/ trusty/main liblapack-dev amd64 3.5.0-2ubuntu1 [1,740 kB] + default: Get:217 http://archive.ubuntu.com/ubuntu/ trusty/main libltdl-dev amd64 2.4.2-1.7ubuntu1 [157 kB] + default: Get:218 http://archive.ubuntu.com/ubuntu/ trusty/main libtinfo-dev amd64 5.9+20140118-1ubuntu1 [76.3 kB] + default: Get:219 http://archive.ubuntu.com/ubuntu/ trusty/main libncurses5-dev amd64 5.9+20140118-1ubuntu1 [170 kB] + default: Get:220 http://archive.ubuntu.com/ubuntu/ trusty/main libpthread-stubs0-dev amd64 0.3-4 [4,068 B] + default: Get:221 http://archive.ubuntu.com/ubuntu/ trusty/main libsm-dev amd64 2:1.2.1-2 [19.9 kB] + default: Get:222 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libsox-fmt-alsa amd64 14.4.1-3ubuntu1.1 [7,116 B] + default: Get:223 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libsox-fmt-ao amd64 14.4.1-3ubuntu1.1 [4,108 B] + default: Get:224 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libsox-fmt-base amd64 14.4.1-3ubuntu1.1 [28.5 kB] + default: Get:225 http://archive.ubuntu.com/ubuntu/ trusty/universe libtwolame0 amd64 0.3.13-1ubuntu1 [48.8 kB] + default: Get:226 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libsox-fmt-mp3 amd64 14.4.1-3ubuntu1.1 [12.2 kB] + default: Get:227 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libsox-fmt-oss amd64 14.4.1-3ubuntu1.1 [4,572 B] + default: Get:228 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libsox-fmt-pulse amd64 14.4.1-3ubuntu1.1 [4,040 B] + default: Get:229 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libsox-fmt-all amd64 14.4.1-3ubuntu1.1 [1,712 B] + default: Get:230 http://archive.ubuntu.com/ubuntu/ trusty/main libtool amd64 2.4.2-1.7ubuntu1 [188 kB] + default: Get:231 http://archive.ubuntu.com/ubuntu/ trusty/main libxau-dev amd64 1:1.0.8-1 [11.1 kB] + default: Get:232 http://archive.ubuntu.com/ubuntu/ trusty/main libxdmcp-dev amd64 1:1.1.1-1 [26.9 kB] + default: Get:233 http://archive.ubuntu.com/ubuntu/ trusty/main x11proto-input-dev all 2.3-1 [139 kB] + default: Get:234 http://archive.ubuntu.com/ubuntu/ trusty/main x11proto-kb-dev all 1.0.6-2 [269 kB] + default: Get:235 http://archive.ubuntu.com/ubuntu/ trusty-updates/main xtrans-dev all 1.3.5-1~ubuntu14.04.2 [70.7 kB] + default: Get:236 http://archive.ubuntu.com/ubuntu/ trusty/main libxcb1-dev amd64 1.10-2ubuntu1 [76.6 kB] + default: Get:237 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libx11-dev amd64 2:1.6.2-1ubuntu2.1 [632 kB] + default: Get:238 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libx11-doc all 2:1.6.2-1ubuntu2.1 [1,447 kB] + default: Get:239 http://archive.ubuntu.com/ubuntu/ trusty/main libxt-dev amd64 1:1.1.4-1 [455 kB] + default: Get:240 http://archive.ubuntu.com/ubuntu/ trusty-updates/main python-setuptools all 3.3-1ubuntu2 [230 kB] + default: Get:241 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe sox amd64 14.4.1-3ubuntu1.1 [97.1 kB] + default: Get:242 http://archive.ubuntu.com/ubuntu/ trusty/main sshfs amd64 2.5-1ubuntu1 [41.7 kB] + default: Get:243 http://archive.ubuntu.com/ubuntu/ trusty-updates/main subversion amd64 1.8.8-1ubuntu3.3 [281 kB] + default: Get:244 http://archive.ubuntu.com/ubuntu/ trusty/main ttf-dejavu-extra all 2.34-1ubuntu1 [3,104 B] + default: Get:245 http://archive.ubuntu.com/ubuntu/ trusty-updates/main unzip amd64 6.0-9ubuntu1.5 [157 kB] + default: Get:246 http://archive.ubuntu.com/ubuntu/ trusty/universe festvox-kallpc16k all 1.4.0-5 [4,094 kB] + default: Get:247 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe icedtea-6-jre-cacao amd64 6b41-1.13.13-0ubuntu0.14.04.1 [334 kB] + default: Get:248 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe icedtea-6-jre-jamvm amd64 6b41-1.13.13-0ubuntu0.14.04.1 [400 kB] + default: Get:249 http://archive.ubuntu.com/ubuntu/ trusty-updates/main icedtea-netx-common all 1.5.3-0ubuntu0.14.04.1 [1,121 kB] + default: Get:250 http://archive.ubuntu.com/ubuntu/ trusty-updates/main icedtea-netx amd64 1.5.3-0ubuntu0.14.04.1 [20.4 kB] + default: Get:251 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libhwloc-plugins amd64 1.8-1ubuntu1.14.04.1 [12.0 kB] + default: dpkg-preconfigure: unable to re-open stdin: No such file or directory + default: Fetched 162 MB in 32s (4,985 kB/s) + default: Selecting previously unselected package libc6-i386. + default: (Reading database ... 62899 files and directories currently installed.) + default: Preparing to unpack .../libc6-i386_2.19-0ubuntu6.15_amd64.deb ... + default: Unpacking libc6-i386 (2.19-0ubuntu6.15) ... + default: Selecting previously unselected package libc6-dev-i386. + default: Preparing to unpack .../libc6-dev-i386_2.19-0ubuntu6.15_amd64.deb ... + default: Unpacking libc6-dev-i386 (2.19-0ubuntu6.15) ... + default: Selecting previously unselected package libc6-x32. + default: Preparing to unpack .../libc6-x32_2.19-0ubuntu6.15_amd64.deb ... + default: Unpacking libc6-x32 (2.19-0ubuntu6.15) ... + default: Selecting previously unselected package libc6-dev-x32. + default: Preparing to unpack .../libc6-dev-x32_2.19-0ubuntu6.15_amd64.deb ... + default: Unpacking libc6-dev-x32 (2.19-0ubuntu6.15) ... + default: Selecting previously unselected package lib32gcc1. + default: Preparing to unpack .../lib32gcc1_1%3a4.9.3-0ubuntu4_amd64.deb ... + default: Unpacking lib32gcc1 (1:4.9.3-0ubuntu4) ... + default: Selecting previously unselected package libx32gcc1. + default: Preparing to unpack .../libx32gcc1_1%3a4.9.3-0ubuntu4_amd64.deb ... + default: Unpacking libx32gcc1 (1:4.9.3-0ubuntu4) ... + default: Selecting previously unselected package lib32gomp1. + default: Preparing to unpack .../lib32gomp1_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking lib32gomp1 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package libx32gomp1. + default: Preparing to unpack .../libx32gomp1_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking libx32gomp1 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package lib32itm1. + default: Preparing to unpack .../lib32itm1_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking lib32itm1 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package libx32itm1. + default: Preparing to unpack .../libx32itm1_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking libx32itm1 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package lib32atomic1. + default: Preparing to unpack .../lib32atomic1_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking lib32atomic1 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package libx32atomic1. + default: Preparing to unpack .../libx32atomic1_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking libx32atomic1 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package lib32asan0. + default: Preparing to unpack .../lib32asan0_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking lib32asan0 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package libx32asan0. + default: Preparing to unpack .../libx32asan0_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking libx32asan0 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package lib32quadmath0. + default: Preparing to unpack .../lib32quadmath0_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking lib32quadmath0 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package libx32quadmath0. + default: Preparing to unpack .../libx32quadmath0_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking libx32quadmath0 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package lib32gcc-4.8-dev. + default: Preparing to unpack .../lib32gcc-4.8-dev_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking lib32gcc-4.8-dev (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package libx32gcc-4.8-dev. + default: Preparing to unpack .../libx32gcc-4.8-dev_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking libx32gcc-4.8-dev (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package gcc-4.8-multilib. + default: Preparing to unpack .../gcc-4.8-multilib_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking gcc-4.8-multilib (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package gcc-multilib. + default: Preparing to unpack .../gcc-multilib_4%3a4.8.2-1ubuntu6_amd64.deb ... + default: Unpacking gcc-multilib (4:4.8.2-1ubuntu6) ... + default: Selecting previously unselected package libao-common. + default: Preparing to unpack .../libao-common_1.1.0-2ubuntu2_all.deb ... + default: Unpacking libao-common (1.1.0-2ubuntu2) ... + default: Selecting previously unselected package libao4:amd64. + default: Preparing to unpack .../libao4_1.1.0-2ubuntu2_amd64.deb ... + default: Unpacking libao4:amd64 (1.1.0-2ubuntu2) ... + default: Selecting previously unselected package libapr1:amd64. + default: Preparing to unpack .../libapr1_1.5.0-1_amd64.deb ... + default: Unpacking libapr1:amd64 (1.5.0-1) ... + default: Selecting previously unselected package libaprutil1:amd64. + default: Preparing to unpack .../libaprutil1_1.5.3-1_amd64.deb ... + default: Unpacking libaprutil1:amd64 (1.5.3-1) ... + default: Selecting previously unselected package libasyncns0:amd64. + default: Preparing to unpack .../libasyncns0_0.8-4ubuntu2_amd64.deb ... + default: Unpacking libasyncns0:amd64 (0.8-4ubuntu2) ... + default: Selecting previously unselected package libgtk2.0-common. + default: Preparing to unpack .../libgtk2.0-common_2.24.23-0ubuntu1.4_all.deb ... + default: Unpacking libgtk2.0-common (2.24.23-0ubuntu1.4) ... + default: Selecting previously unselected package libgtk2.0-0:amd64. + default: Preparing to unpack .../libgtk2.0-0_2.24.23-0ubuntu1.4_amd64.deb ... + default: Unpacking libgtk2.0-0:amd64 (2.24.23-0ubuntu1.4) ... + default: Selecting previously unselected package openjdk-6-jre-lib. + default: Preparing to unpack .../openjdk-6-jre-lib_6b41-1.13.13-0ubuntu0.14.04.1_all.deb ... + default: Unpacking openjdk-6-jre-lib (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libnspr4:amd64. + default: Preparing to unpack .../libnspr4_2%3a4.13.1-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libnspr4:amd64 (2:4.13.1-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libnss3-nssdb. + default: Preparing to unpack .../libnss3-nssdb_2%3a3.28.4-0ubuntu0.14.04.5_all.deb ... + default: Unpacking libnss3-nssdb (2:3.28.4-0ubuntu0.14.04.5) ... + default: Selecting previously unselected package libnss3:amd64. + default: Preparing to unpack .../libnss3_2%3a3.28.4-0ubuntu0.14.04.5_amd64.deb ... + default: Unpacking libnss3:amd64 (2:3.28.4-0ubuntu0.14.04.5) ... + default: Selecting previously unselected package ca-certificates-java. + default: Preparing to unpack .../ca-certificates-java_20130815ubuntu1_all.deb ... + default: Unpacking ca-certificates-java (20130815ubuntu1) ... + default: Selecting previously unselected package tzdata-java. + default: Preparing to unpack .../tzdata-java_2019a-0ubuntu0.14.04_all.deb ... + default: Unpacking tzdata-java (2019a-0ubuntu0.14.04) ... + default: Selecting previously unselected package java-common. + default: Preparing to unpack .../java-common_0.51_all.deb ... + default: Unpacking java-common (0.51) ... + default: Selecting previously unselected package libpcsclite1:amd64. + default: Preparing to unpack .../libpcsclite1_1.8.10-1ubuntu1.1_amd64.deb ... + default: Unpacking libpcsclite1:amd64 (1.8.10-1ubuntu1.1) ... + default: Selecting previously unselected package openjdk-6-jre-headless:amd64. + default: Preparing to unpack .../openjdk-6-jre-headless_6b41-1.13.13-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking openjdk-6-jre-headless:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libgif4:amd64. + default: Preparing to unpack .../libgif4_4.1.6-11_amd64.deb ... + default: Unpacking libgif4:amd64 (4.1.6-11) ... + default: Selecting previously unselected package libflac8:amd64. + default: Preparing to unpack .../libflac8_1.3.0-2ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libflac8:amd64 (1.3.0-2ubuntu0.14.04.1) ... + default: Selecting previously unselected package libvorbisenc2:amd64. + default: Preparing to unpack .../libvorbisenc2_1.3.2-1.3ubuntu1.2_amd64.deb ... + default: Unpacking libvorbisenc2:amd64 (1.3.2-1.3ubuntu1.2) ... + default: Selecting previously unselected package libsndfile1:amd64. + default: Preparing to unpack .../libsndfile1_1.0.25-7ubuntu2.2_amd64.deb ... + default: Unpacking libsndfile1:amd64 (1.0.25-7ubuntu2.2) ... + default: Selecting previously unselected package libpulse0:amd64. + default: Preparing to unpack .../libpulse0_1%3a4.0-0ubuntu11.1_amd64.deb ... + default: Unpacking libpulse0:amd64 (1:4.0-0ubuntu11.1) ... + default: Selecting previously unselected package openjdk-6-jre:amd64. + default: Preparing to unpack .../openjdk-6-jre_6b41-1.13.13-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking openjdk-6-jre:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libatk-wrapper-java. + default: Preparing to unpack .../libatk-wrapper-java_0.30.4-4_all.deb ... + default: Unpacking libatk-wrapper-java (0.30.4-4) ... + default: Selecting previously unselected package libatk-wrapper-java-jni:amd64. + default: Preparing to unpack .../libatk-wrapper-java-jni_0.30.4-4_amd64.deb ... + default: Unpacking libatk-wrapper-java-jni:amd64 (0.30.4-4) ... + default: Selecting previously unselected package libavutil52:amd64. + default: Preparing to unpack .../libavutil52_6%3a9.20-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libavutil52:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libgsm1:amd64. + default: Preparing to unpack .../libgsm1_1.0.13-4_amd64.deb ... + default: Unpacking libgsm1:amd64 (1.0.13-4) ... + default: Selecting previously unselected package libmp3lame0:amd64. + default: Preparing to unpack .../libmp3lame0_3.99.5+repack1-3ubuntu1_amd64.deb ... + default: Unpacking libmp3lame0:amd64 (3.99.5+repack1-3ubuntu1) ... + default: Selecting previously unselected package libopenjpeg2:amd64. + default: Preparing to unpack .../libopenjpeg2_1.3+dfsg-4.7ubuntu1_amd64.deb ... + default: Unpacking libopenjpeg2:amd64 (1.3+dfsg-4.7ubuntu1) ... + default: Selecting previously unselected package libopus0. + default: Preparing to unpack .../libopus0_1.1-0ubuntu1_amd64.deb ... + default: Unpacking libopus0 (1.1-0ubuntu1) ... + default: Selecting previously unselected package liborc-0.4-0:amd64. + default: Preparing to unpack .../liborc-0.4-0_1%3a0.4.18-1ubuntu1_amd64.deb ... + default: Unpacking liborc-0.4-0:amd64 (1:0.4.18-1ubuntu1) ... + default: Selecting previously unselected package libschroedinger-1.0-0:amd64. + default: Preparing to unpack .../libschroedinger-1.0-0_1.0.11-2ubuntu1_amd64.deb ... + default: Unpacking libschroedinger-1.0-0:amd64 (1.0.11-2ubuntu1) ... + default: Selecting previously unselected package libspeex1:amd64. + default: Preparing to unpack .../libspeex1_1.2~rc1.1-1ubuntu1_amd64.deb ... + default: Unpacking libspeex1:amd64 (1.2~rc1.1-1ubuntu1) ... + default: Selecting previously unselected package libtheora0:amd64. + default: Preparing to unpack .../libtheora0_1.1.1+dfsg.1-3.2_amd64.deb ... + default: Unpacking libtheora0:amd64 (1.1.1+dfsg.1-3.2) ... + default: Selecting previously unselected package libva1:amd64. + default: Preparing to unpack .../libva1_1.3.0-2_amd64.deb ... + default: Unpacking libva1:amd64 (1.3.0-2) ... + default: Selecting previously unselected package libx264-142:amd64. + default: Preparing to unpack .../libx264-142_2%3a0.142.2389+git956c8d8-2_amd64.deb ... + default: Unpacking libx264-142:amd64 (2:0.142.2389+git956c8d8-2) ... + default: Selecting previously unselected package libxvidcore4:amd64. + default: Preparing to unpack .../libxvidcore4_2%3a1.3.2-9ubuntu1_amd64.deb ... + default: Unpacking libxvidcore4:amd64 (2:1.3.2-9ubuntu1) ... + default: Selecting previously unselected package libavcodec54:amd64. + default: Preparing to unpack .../libavcodec54_6%3a9.20-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libavcodec54:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libavformat54:amd64. + default: Preparing to unpack .../libavformat54_6%3a9.20-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libavformat54:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libcdio13. + default: Preparing to unpack .../libcdio13_0.83-4.1ubuntu1_amd64.deb ... + default: Unpacking libcdio13 (0.83-4.1ubuntu1) ... + default: Selecting previously unselected package libcdio-cdda1. + default: Preparing to unpack .../libcdio-cdda1_0.83-4.1ubuntu1_amd64.deb ... + default: Unpacking libcdio-cdda1 (0.83-4.1ubuntu1) ... + default: Selecting previously unselected package libcdio-paranoia1. + default: Preparing to unpack .../libcdio-paranoia1_0.83-4.1ubuntu1_amd64.deb ... + default: Unpacking libcdio-paranoia1 (0.83-4.1ubuntu1) ... + default: Selecting previously unselected package libraw1394-11:amd64. + default: Preparing to unpack .../libraw1394-11_2.1.0-1ubuntu1_amd64.deb ... + default: Unpacking libraw1394-11:amd64 (2.1.0-1ubuntu1) ... + default: Selecting previously unselected package libdc1394-22:amd64. + default: Preparing to unpack .../libdc1394-22_2.2.1-2ubuntu2_amd64.deb ... + default: Unpacking libdc1394-22:amd64 (2.2.1-2ubuntu2) ... + default: Selecting previously unselected package libsamplerate0:amd64. + default: Preparing to unpack .../libsamplerate0_0.1.8-7_amd64.deb ... + default: Unpacking libsamplerate0:amd64 (0.1.8-7) ... + default: Selecting previously unselected package libjack-jackd2-0:amd64. + default: Preparing to unpack .../libjack-jackd2-0_1.9.9.5+20130622git7de15e7a-1ubuntu1_amd64.deb ... + default: Unpacking libjack-jackd2-0:amd64 (1.9.9.5+20130622git7de15e7a-1ubuntu1) ... + default: Selecting previously unselected package libavdevice53:amd64. + default: Preparing to unpack .../libavdevice53_6%3a9.20-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libavdevice53:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libavresample1:amd64. + default: Preparing to unpack .../libavresample1_6%3a9.20-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libavresample1:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libswscale2:amd64. + default: Preparing to unpack .../libswscale2_6%3a9.20-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libswscale2:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libavfilter3:amd64. + default: Preparing to unpack .../libavfilter3_6%3a9.20-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libavfilter3:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libcaca0:amd64. + default: Preparing to unpack .../libcaca0_0.99.beta18-1ubuntu5.1_amd64.deb ... + default: Unpacking libcaca0:amd64 (0.99.beta18-1ubuntu5.1) ... + default: Selecting previously unselected package libsdl1.2debian:amd64. + default: Preparing to unpack .../libsdl1.2debian_1.2.15-8ubuntu1.1_amd64.deb ... + default: Unpacking libsdl1.2debian:amd64 (1.2.15-8ubuntu1.1) ... + default: Selecting previously unselected package libav-tools. + default: Preparing to unpack .../libav-tools_6%3a9.20-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking libav-tools (6:9.20-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libboost-atomic1.54.0:amd64. + default: Preparing to unpack .../libboost-atomic1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-atomic1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-system1.54.0:amd64. + default: Preparing to unpack .../libboost-system1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-system1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-chrono1.54.0:amd64. + default: Preparing to unpack .../libboost-chrono1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-chrono1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-context1.54.0:amd64. + default: Preparing to unpack .../libboost-context1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-context1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-date-time1.54.0:amd64. + default: Preparing to unpack .../libboost-date-time1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-date-time1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-filesystem1.54.0:amd64. + default: Preparing to unpack .../libboost-filesystem1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-filesystem1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-serialization1.54.0:amd64. + default: Preparing to unpack .../libboost-serialization1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-serialization1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libcr0. + default: Preparing to unpack .../libcr0_0.8.5-2.1_amd64.deb ... + default: Unpacking libcr0 (0.8.5-2.1) ... + default: Selecting previously unselected package libhwloc5:amd64. + default: Preparing to unpack .../libhwloc5_1.8-1ubuntu1.14.04.1_amd64.deb ... + default: Unpacking libhwloc5:amd64 (1.8-1ubuntu1.14.04.1) ... + default: Selecting previously unselected package libibverbs1. + default: Preparing to unpack .../libibverbs1_1.1.7-1ubuntu1.1_amd64.deb ... + default: Unpacking libibverbs1 (1.1.7-1ubuntu1.1) ... + default: Selecting previously unselected package libtorque2. + default: Preparing to unpack .../libtorque2_2.4.16+dfsg-1.3ubuntu1.1_amd64.deb ... + default: Unpacking libtorque2 (2.4.16+dfsg-1.3ubuntu1.1) ... + default: Selecting previously unselected package libopenmpi1.6. + default: Preparing to unpack .../libopenmpi1.6_1.6.5-8_amd64.deb ... + default: Unpacking libopenmpi1.6 (1.6.5-8) ... + default: Selecting previously unselected package libboost-mpi1.54.0. + default: Preparing to unpack .../libboost-mpi1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-mpi1.54.0 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-graph-parallel1.54.0. + default: Preparing to unpack .../libboost-graph-parallel1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-graph-parallel1.54.0 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-regex1.54.0:amd64. + default: Preparing to unpack .../libboost-regex1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-regex1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-graph1.54.0:amd64. + default: Preparing to unpack .../libboost-graph1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-graph1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-thread1.54.0:amd64. + default: Preparing to unpack .../libboost-thread1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-thread1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-locale1.54.0:amd64. + default: Preparing to unpack .../libboost-locale1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-locale1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-math1.54.0:amd64. + default: Preparing to unpack .../libboost-math1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-math1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-python1.54.0:amd64. + default: Preparing to unpack .../libboost-python1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-python1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package openmpi-common. + default: Preparing to unpack .../openmpi-common_1.6.5-8_all.deb ... + default: Unpacking openmpi-common (1.6.5-8) ... + default: Selecting previously unselected package openmpi-bin. + default: Preparing to unpack .../openmpi-bin_1.6.5-8_amd64.deb ... + default: Unpacking openmpi-bin (1.6.5-8) ... + default: Selecting previously unselected package mpi-default-bin. + default: Preparing to unpack .../mpi-default-bin_1.0.2ubuntu1_amd64.deb ... + default: Unpacking mpi-default-bin (1.0.2ubuntu1) ... + default: Selecting previously unselected package libboost-mpi-python1.54.0. + default: Preparing to unpack .../libboost-mpi-python1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-mpi-python1.54.0 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-program-options1.54.0:amd64. + default: Preparing to unpack .../libboost-program-options1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-program-options1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-random1.54.0:amd64. + default: Preparing to unpack .../libboost-random1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-random1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-signals1.54.0:amd64. + default: Preparing to unpack .../libboost-signals1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-signals1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-test1.54.0:amd64. + default: Preparing to unpack .../libboost-test1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-test1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-timer1.54.0:amd64. + default: Preparing to unpack .../libboost-timer1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-timer1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-wave1.54.0:amd64. + default: Preparing to unpack .../libboost-wave1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-wave1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libportaudio2:amd64. + default: Preparing to unpack .../libportaudio2_19+svn20140130-1_amd64.deb ... + default: Unpacking libportaudio2:amd64 (19+svn20140130-1) ... + default: Selecting previously unselected package libsonic0:amd64. + default: Preparing to unpack .../libsonic0_0.1.18-0ubuntu1_amd64.deb ... + default: Unpacking libsonic0:amd64 (0.1.18-0ubuntu1) ... + default: Selecting previously unselected package espeak-data:amd64. + default: Preparing to unpack .../espeak-data_1.47.11-1ubuntu1_amd64.deb ... + default: Unpacking espeak-data:amd64 (1.47.11-1ubuntu1) ... + default: Selecting previously unselected package libespeak1:amd64. + default: Preparing to unpack .../libespeak1_1.47.11-1ubuntu1_amd64.deb ... + default: Unpacking libespeak1:amd64 (1.47.11-1ubuntu1) ... + default: Selecting previously unselected package libestools2.1:amd64. + default: Preparing to unpack .../libestools2.1_1%3a2.1~release-6_amd64.deb ... + default: Unpacking libestools2.1:amd64 (1:2.1~release-6) ... + default: Selecting previously unselected package libgfortran3:amd64. + default: Preparing to unpack .../libgfortran3_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking libgfortran3:amd64 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package libmad0:amd64. + default: Preparing to unpack .../libmad0_0.15.1b-9ubuntu14.04.1_amd64.deb ... + default: Unpacking libmad0:amd64 (0.15.1b-9ubuntu14.04.1) ... + default: Selecting previously unselected package libopencore-amrnb0:amd64. + default: Preparing to unpack .../libopencore-amrnb0_0.1.3-2ubuntu1_amd64.deb ... + default: Unpacking libopencore-amrnb0:amd64 (0.1.3-2ubuntu1) ... + default: Selecting previously unselected package libopencore-amrwb0:amd64. + default: Preparing to unpack .../libopencore-amrwb0_0.1.3-2ubuntu1_amd64.deb ... + default: Unpacking libopencore-amrwb0:amd64 (0.1.3-2ubuntu1) ... + default: Selecting previously unselected package libexpat1-dev:amd64. + default: Preparing to unpack .../libexpat1-dev_2.1.0-4ubuntu1.4_amd64.deb ... + default: Unpacking libexpat1-dev:amd64 (2.1.0-4ubuntu1.4) ... + default: Selecting previously unselected package libpython2.7-dev:amd64. + default: Preparing to unpack .../libpython2.7-dev_2.7.6-8ubuntu0.5_amd64.deb ... + default: Unpacking libpython2.7-dev:amd64 (2.7.6-8ubuntu0.5) ... + default: Selecting previously unselected package libserf-1-1:amd64. + default: Preparing to unpack .../libserf-1-1_1.3.3-1ubuntu0.1_amd64.deb ... + default: Unpacking libserf-1-1:amd64 (1.3.3-1ubuntu0.1) ... + default: Selecting previously unselected package libsox2:amd64. + default: Preparing to unpack .../libsox2_14.4.1-3ubuntu1.1_amd64.deb ... + default: Unpacking libsox2:amd64 (14.4.1-3ubuntu1.1) ... + default: Selecting previously unselected package libsvn1:amd64. + default: Preparing to unpack .../libsvn1_1.8.8-1ubuntu3.3_amd64.deb ... + default: Unpacking libsvn1:amd64 (1.8.8-1ubuntu3.3) ... + default: Selecting previously unselected package libwavpack1:amd64. + default: Preparing to unpack .../libwavpack1_4.70.0-1ubuntu0.2_amd64.deb ... + default: Unpacking libwavpack1:amd64 (4.70.0-1ubuntu0.2) ... + default: Selecting previously unselected package ocl-icd-libopencl1:amd64. + default: Preparing to unpack .../ocl-icd-libopencl1_2.1.3-4_amd64.deb ... + default: Unpacking ocl-icd-libopencl1:amd64 (2.1.3-4) ... + default: Selecting previously unselected package linux-sound-base. + default: Preparing to unpack .../linux-sound-base_1.0.25+dfsg-0ubuntu4_all.deb ... + default: Unpacking linux-sound-base (1.0.25+dfsg-0ubuntu4) ... + default: Selecting previously unselected package alsa-base. + default: Preparing to unpack .../alsa-base_1.0.25+dfsg-0ubuntu4_all.deb ... + default: Unpacking alsa-base (1.0.25+dfsg-0ubuntu4) ... + default: Selecting previously unselected package alsa-utils. + default: Preparing to unpack .../alsa-utils_1.0.27.2-1ubuntu2_amd64.deb ... + default: Unpacking alsa-utils (1.0.27.2-1ubuntu2) ... + default: Selecting previously unselected package m4. + default: Preparing to unpack .../m4_1.4.17-2ubuntu1_amd64.deb ... + default: Unpacking m4 (1.4.17-2ubuntu1) ... + default: Selecting previously unselected package autoconf. + default: Preparing to unpack .../autoconf_2.69-6_all.deb ... + default: Unpacking autoconf (2.69-6) ... + default: Selecting previously unselected package autotools-dev. + default: Preparing to unpack .../autotools-dev_20130810.1_all.deb ... + default: Unpacking autotools-dev (20130810.1) ... + default: Selecting previously unselected package automake. + default: Preparing to unpack .../automake_1%3a1.14.1-2ubuntu1_all.deb ... + default: Unpacking automake (1:1.14.1-2ubuntu1) ... + default: Selecting previously unselected package espeak. + default: Preparing to unpack .../espeak_1.47.11-1ubuntu1_amd64.deb ... + default: Unpacking espeak (1.47.11-1ubuntu1) ... + default: Selecting previously unselected package festival. + default: Preparing to unpack .../festival_1%3a2.1~release-6ubuntu1_amd64.deb ... + default: Unpacking festival (1:2.1~release-6ubuntu1) ... + default: Selecting previously unselected package festlex-cmu. + default: Preparing to unpack .../festlex-cmu_1.4.0-6_all.deb ... + default: Unpacking festlex-cmu (1.4.0-6) ... + default: Selecting previously unselected package festlex-poslex. + default: Preparing to unpack .../festlex-poslex_1.4.0-5_all.deb ... + default: Unpacking festlex-poslex (1.4.0-5) ... + default: Selecting previously unselected package fonts-dejavu-extra. + default: Preparing to unpack .../fonts-dejavu-extra_2.34-1ubuntu1_all.deb ... + default: Unpacking fonts-dejavu-extra (2.34-1ubuntu1) ... + default: Selecting previously unselected package libstdc++-4.8-dev:amd64. + default: Preparing to unpack .../libstdc++-4.8-dev_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking libstdc++-4.8-dev:amd64 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package g++-4.8. + default: Preparing to unpack .../g++-4.8_4.8.4-2ubuntu1~14.04.4_amd64.deb ... + default: Unpacking g++-4.8 (4.8.4-2ubuntu1~14.04.4) ... + default: Selecting previously unselected package g++. + default: Preparing to unpack .../g++_4%3a4.8.2-1ubuntu6_amd64.deb ... + default: Unpacking g++ (4:4.8.2-1ubuntu6) ... + default: Selecting previously unselected package liberror-perl. + default: Preparing to unpack .../liberror-perl_0.17-1.1_all.deb ... + default: Unpacking liberror-perl (0.17-1.1) ... + default: Selecting previously unselected package git-man. + default: Preparing to unpack .../git-man_1%3a1.9.1-1ubuntu0.10_all.deb ... + default: Unpacking git-man (1:1.9.1-1ubuntu0.10) ... + default: Selecting previously unselected package git. + default: Preparing to unpack .../git_1%3a1.9.1-1ubuntu0.10_amd64.deb ... + default: Unpacking git (1:1.9.1-1ubuntu0.10) ... + default: Selecting previously unselected package icu-devtools. + default: Preparing to unpack .../icu-devtools_52.1-3ubuntu0.8_amd64.deb ... + default: Unpacking icu-devtools (52.1-3ubuntu0.8) ... + default: Selecting previously unselected package libatlas3-base. + default: Preparing to unpack .../libatlas3-base_3.10.1-4_amd64.deb ... + default: Unpacking libatlas3-base (3.10.1-4) ... + default: Selecting previously unselected package libblas3. + default: Preparing to unpack .../libblas3_1.2.20110419-7_amd64.deb ... + default: Unpacking libblas3 (1.2.20110419-7) ... + default: Selecting previously unselected package libblas-dev. + default: Preparing to unpack .../libblas-dev_1.2.20110419-7_amd64.deb ... + default: Unpacking libblas-dev (1.2.20110419-7) ... + default: Selecting previously unselected package libatlas-dev. + default: Preparing to unpack .../libatlas-dev_3.10.1-4_all.deb ... + default: Unpacking libatlas-dev (3.10.1-4) ... + default: Selecting previously unselected package libatlas-base-dev. + default: Preparing to unpack .../libatlas-base-dev_3.10.1-4_amd64.deb ... + default: Unpacking libatlas-base-dev (3.10.1-4) ... + default: Selecting previously unselected package libboost1.54-dev. + default: Preparing to unpack .../libboost1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost1.54-dev (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-dev. + default: Preparing to unpack .../libboost-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-dev (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost1.54-tools-dev. + default: Preparing to unpack .../libboost1.54-tools-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost1.54-tools-dev (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-tools-dev. + default: Preparing to unpack .../libboost-tools-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-tools-dev (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-atomic1.54-dev:amd64. + default: Preparing to unpack .../libboost-atomic1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-atomic1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-atomic-dev:amd64. + default: Preparing to unpack .../libboost-atomic-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-atomic-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-chrono1.54-dev:amd64. + default: Preparing to unpack .../libboost-chrono1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-chrono1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-chrono-dev:amd64. + default: Preparing to unpack .../libboost-chrono-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-chrono-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-context1.54-dev:amd64. + default: Preparing to unpack .../libboost-context1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-context1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-context-dev:amd64. + default: Preparing to unpack .../libboost-context-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-context-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-coroutine1.54-dev. + default: Preparing to unpack .../libboost-coroutine1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-coroutine1.54-dev (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-coroutine-dev. + default: Preparing to unpack .../libboost-coroutine-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-coroutine-dev (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-serialization1.54-dev:amd64. + default: Preparing to unpack .../libboost-serialization1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-serialization1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-date-time1.54-dev:amd64. + default: Preparing to unpack .../libboost-date-time1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-date-time1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-date-time-dev:amd64. + default: Preparing to unpack .../libboost-date-time-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-date-time-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-exception1.54-dev:amd64. + default: Preparing to unpack .../libboost-exception1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-exception1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-exception-dev:amd64. + default: Preparing to unpack .../libboost-exception-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-exception-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-system1.54-dev:amd64. + default: Preparing to unpack .../libboost-system1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-system1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-filesystem1.54-dev:amd64. + default: Preparing to unpack .../libboost-filesystem1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-filesystem1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-filesystem-dev:amd64. + default: Preparing to unpack .../libboost-filesystem-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-filesystem-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-test1.54-dev:amd64. + default: Preparing to unpack .../libboost-test1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-test1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-graph1.54-dev:amd64. + default: Preparing to unpack .../libboost-graph1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-graph1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-graph-dev:amd64. + default: Preparing to unpack .../libboost-graph-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-graph-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-graph-parallel1.54-dev. + default: Preparing to unpack .../libboost-graph-parallel1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-graph-parallel1.54-dev (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-graph-parallel-dev. + default: Preparing to unpack .../libboost-graph-parallel-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-graph-parallel-dev (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libicu-dev:amd64. + default: Preparing to unpack .../libicu-dev_52.1-3ubuntu0.8_amd64.deb ... + default: Unpacking libicu-dev:amd64 (52.1-3ubuntu0.8) ... + default: Selecting previously unselected package libboost-regex1.54-dev:amd64. + default: Preparing to unpack .../libboost-regex1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-regex1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-iostreams1.54-dev:amd64. + default: Preparing to unpack .../libboost-iostreams1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-iostreams1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-iostreams-dev:amd64. + default: Preparing to unpack .../libboost-iostreams-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-iostreams-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-locale1.54-dev:amd64. + default: Preparing to unpack .../libboost-locale1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-locale1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-locale-dev:amd64. + default: Preparing to unpack .../libboost-locale-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-locale-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-log1.54.0. + default: Preparing to unpack .../libboost-log1.54.0_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-log1.54.0 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-thread1.54-dev:amd64. + default: Preparing to unpack .../libboost-thread1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-thread1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-log1.54-dev. + default: Preparing to unpack .../libboost-log1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-log1.54-dev (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-log-dev. + default: Preparing to unpack .../libboost-log-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-log-dev (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-math1.54-dev:amd64. + default: Preparing to unpack .../libboost-math1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-math1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-math-dev:amd64. + default: Preparing to unpack .../libboost-math-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-math-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libibverbs-dev. + default: Preparing to unpack .../libibverbs-dev_1.1.7-1ubuntu1.1_amd64.deb ... + default: Unpacking libibverbs-dev (1.1.7-1ubuntu1.1) ... + default: Selecting previously unselected package libxml2-dev:amd64. + default: Preparing to unpack .../libxml2-dev_2.9.1+dfsg1-3ubuntu4.13_amd64.deb ... + default: Unpacking libxml2-dev:amd64 (2.9.1+dfsg1-3ubuntu4.13) ... + default: Selecting previously unselected package zlib1g-dev:amd64. + default: Preparing to unpack .../zlib1g-dev_1%3a1.2.8.dfsg-1ubuntu1.1_amd64.deb ... + default: Unpacking zlib1g-dev:amd64 (1:1.2.8.dfsg-1ubuntu1.1) ... + default: Selecting previously unselected package libpci-dev. + default: Preparing to unpack .../libpci-dev_1%3a3.2.1-1ubuntu5.1_amd64.deb ... + default: Unpacking libpci-dev (1:3.2.1-1ubuntu5.1) ... + default: Selecting previously unselected package libhwloc-dev:amd64. + default: Preparing to unpack .../libhwloc-dev_1.8-1ubuntu1.14.04.1_amd64.deb ... + default: Unpacking libhwloc-dev:amd64 (1.8-1ubuntu1.14.04.1) ... + default: Selecting previously unselected package libopenmpi-dev. + default: Preparing to unpack .../libopenmpi-dev_1.6.5-8_amd64.deb ... + default: Unpacking libopenmpi-dev (1.6.5-8) ... + default: Selecting previously unselected package mpi-default-dev. + default: Preparing to unpack .../mpi-default-dev_1.0.2ubuntu1_amd64.deb ... + default: Unpacking mpi-default-dev (1.0.2ubuntu1) ... + default: Selecting previously unselected package libboost-mpi1.54-dev. + default: Preparing to unpack .../libboost-mpi1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-mpi1.54-dev (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-mpi-dev. + default: Preparing to unpack .../libboost-mpi-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-mpi-dev (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-mpi-python1.54-dev. + default: Preparing to unpack .../libboost-mpi-python1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-mpi-python1.54-dev (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-mpi-python-dev. + default: Preparing to unpack .../libboost-mpi-python-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-mpi-python-dev (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-program-options1.54-dev:amd64. + default: Preparing to unpack .../libboost-program-options1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-program-options1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-program-options-dev:amd64. + default: Preparing to unpack .../libboost-program-options-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-program-options-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libpython-dev:amd64. + default: Preparing to unpack .../libpython-dev_2.7.5-5ubuntu3_amd64.deb ... + default: Unpacking libpython-dev:amd64 (2.7.5-5ubuntu3) ... + default: Selecting previously unselected package libboost-python1.54-dev:amd64. + default: Preparing to unpack .../libboost-python1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-python1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-python-dev. + default: Preparing to unpack .../libboost-python-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-python-dev (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-random1.54-dev:amd64. + default: Preparing to unpack .../libboost-random1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-random1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-random-dev:amd64. + default: Preparing to unpack .../libboost-random-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-random-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-regex-dev:amd64. + default: Preparing to unpack .../libboost-regex-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-regex-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-serialization-dev:amd64. + default: Preparing to unpack .../libboost-serialization-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-serialization-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-signals1.54-dev:amd64. + default: Preparing to unpack .../libboost-signals1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-signals1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-signals-dev:amd64. + default: Preparing to unpack .../libboost-signals-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-signals-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-system-dev:amd64. + default: Preparing to unpack .../libboost-system-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-system-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-test-dev:amd64. + default: Preparing to unpack .../libboost-test-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-test-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-thread-dev:amd64. + default: Preparing to unpack .../libboost-thread-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-thread-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-timer1.54-dev:amd64. + default: Preparing to unpack .../libboost-timer1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-timer1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-timer-dev:amd64. + default: Preparing to unpack .../libboost-timer-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-timer-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-wave1.54-dev:amd64. + default: Preparing to unpack .../libboost-wave1.54-dev_1.54.0-4ubuntu3.1_amd64.deb ... + default: Unpacking libboost-wave1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Selecting previously unselected package libboost-wave-dev:amd64. + default: Preparing to unpack .../libboost-wave-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-wave-dev:amd64 (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libboost-all-dev. + default: Preparing to unpack .../libboost-all-dev_1.54.0.1ubuntu1_amd64.deb ... + default: Unpacking libboost-all-dev (1.54.0.1ubuntu1) ... + default: Selecting previously unselected package libgtk2.0-bin. + default: Preparing to unpack .../libgtk2.0-bin_2.24.23-0ubuntu1.4_amd64.deb ... + default: Unpacking libgtk2.0-bin (2.24.23-0ubuntu1.4) ... + default: Selecting previously unselected package xorg-sgml-doctools. + default: Preparing to unpack .../xorg-sgml-doctools_1%3a1.11-1_all.deb ... + default: Unpacking xorg-sgml-doctools (1:1.11-1) ... + default: Selecting previously unselected package x11proto-core-dev. + default: Preparing to unpack .../x11proto-core-dev_7.0.26-1~ubuntu2_all.deb ... + default: Unpacking x11proto-core-dev (7.0.26-1~ubuntu2) ... + default: Selecting previously unselected package libice-dev:amd64. + default: Preparing to unpack .../libice-dev_2%3a1.0.8-2_amd64.deb ... + default: Unpacking libice-dev:amd64 (2:1.0.8-2) ... + default: Selecting previously unselected package libid3tag0. + default: Preparing to unpack .../libid3tag0_0.15.1b-10ubuntu1_amd64.deb ... + default: Unpacking libid3tag0 (0.15.1b-10ubuntu1) ... + default: Selecting previously unselected package liblapack3. + default: Preparing to unpack .../liblapack3_3.5.0-2ubuntu1_amd64.deb ... + default: Unpacking liblapack3 (3.5.0-2ubuntu1) ... + default: Selecting previously unselected package liblapack-dev. + default: Preparing to unpack .../liblapack-dev_3.5.0-2ubuntu1_amd64.deb ... + default: Unpacking liblapack-dev (3.5.0-2ubuntu1) ... + default: Selecting previously unselected package libltdl-dev:amd64. + default: Preparing to unpack .../libltdl-dev_2.4.2-1.7ubuntu1_amd64.deb ... + default: Unpacking libltdl-dev:amd64 (2.4.2-1.7ubuntu1) ... + default: Selecting previously unselected package libtinfo-dev:amd64. + default: Preparing to unpack .../libtinfo-dev_5.9+20140118-1ubuntu1_amd64.deb ... + default: Unpacking libtinfo-dev:amd64 (5.9+20140118-1ubuntu1) ... + default: Selecting previously unselected package libncurses5-dev:amd64. + default: Preparing to unpack .../libncurses5-dev_5.9+20140118-1ubuntu1_amd64.deb ... + default: Unpacking libncurses5-dev:amd64 (5.9+20140118-1ubuntu1) ... + default: Selecting previously unselected package libpthread-stubs0-dev:amd64. + default: Preparing to unpack .../libpthread-stubs0-dev_0.3-4_amd64.deb ... + default: Unpacking libpthread-stubs0-dev:amd64 (0.3-4) ... + default: Selecting previously unselected package libsm-dev:amd64. + default: Preparing to unpack .../libsm-dev_2%3a1.2.1-2_amd64.deb ... + default: Unpacking libsm-dev:amd64 (2:1.2.1-2) ... + default: Selecting previously unselected package libsox-fmt-alsa:amd64. + default: Preparing to unpack .../libsox-fmt-alsa_14.4.1-3ubuntu1.1_amd64.deb ... + default: Unpacking libsox-fmt-alsa:amd64 (14.4.1-3ubuntu1.1) ... + default: Selecting previously unselected package libsox-fmt-ao:amd64. + default: Preparing to unpack .../libsox-fmt-ao_14.4.1-3ubuntu1.1_amd64.deb ... + default: Unpacking libsox-fmt-ao:amd64 (14.4.1-3ubuntu1.1) ... + default: Selecting previously unselected package libsox-fmt-base:amd64. + default: Preparing to unpack .../libsox-fmt-base_14.4.1-3ubuntu1.1_amd64.deb ... + default: Unpacking libsox-fmt-base:amd64 (14.4.1-3ubuntu1.1) ... + default: Selecting previously unselected package libtwolame0. + default: Preparing to unpack .../libtwolame0_0.3.13-1ubuntu1_amd64.deb ... + default: Unpacking libtwolame0 (0.3.13-1ubuntu1) ... + default: Selecting previously unselected package libsox-fmt-mp3:amd64. + default: Preparing to unpack .../libsox-fmt-mp3_14.4.1-3ubuntu1.1_amd64.deb ... + default: Unpacking libsox-fmt-mp3:amd64 (14.4.1-3ubuntu1.1) ... + default: Selecting previously unselected package libsox-fmt-oss:amd64. + default: Preparing to unpack .../libsox-fmt-oss_14.4.1-3ubuntu1.1_amd64.deb ... + default: Unpacking libsox-fmt-oss:amd64 (14.4.1-3ubuntu1.1) ... + default: Selecting previously unselected package libsox-fmt-pulse:amd64. + default: Preparing to unpack .../libsox-fmt-pulse_14.4.1-3ubuntu1.1_amd64.deb ... + default: Unpacking libsox-fmt-pulse:amd64 (14.4.1-3ubuntu1.1) ... + default: Selecting previously unselected package libsox-fmt-all:amd64. + default: Preparing to unpack .../libsox-fmt-all_14.4.1-3ubuntu1.1_amd64.deb ... + default: Unpacking libsox-fmt-all:amd64 (14.4.1-3ubuntu1.1) ... + default: Selecting previously unselected package libtool. + default: Preparing to unpack .../libtool_2.4.2-1.7ubuntu1_amd64.deb ... + default: Unpacking libtool (2.4.2-1.7ubuntu1) ... + default: Selecting previously unselected package libxau-dev:amd64. + default: Preparing to unpack .../libxau-dev_1%3a1.0.8-1_amd64.deb ... + default: Unpacking libxau-dev:amd64 (1:1.0.8-1) ... + default: Selecting previously unselected package libxdmcp-dev:amd64. + default: Preparing to unpack .../libxdmcp-dev_1%3a1.1.1-1_amd64.deb ... + default: Unpacking libxdmcp-dev:amd64 (1:1.1.1-1) ... + default: Selecting previously unselected package x11proto-input-dev. + default: Preparing to unpack .../x11proto-input-dev_2.3-1_all.deb ... + default: Unpacking x11proto-input-dev (2.3-1) ... + default: Selecting previously unselected package x11proto-kb-dev. + default: Preparing to unpack .../x11proto-kb-dev_1.0.6-2_all.deb ... + default: Unpacking x11proto-kb-dev (1.0.6-2) ... + default: Selecting previously unselected package xtrans-dev. + default: Preparing to unpack .../xtrans-dev_1.3.5-1~ubuntu14.04.2_all.deb ... + default: Unpacking xtrans-dev (1.3.5-1~ubuntu14.04.2) ... + default: Selecting previously unselected package libxcb1-dev:amd64. + default: Preparing to unpack .../libxcb1-dev_1.10-2ubuntu1_amd64.deb ... + default: Unpacking libxcb1-dev:amd64 (1.10-2ubuntu1) ... + default: Selecting previously unselected package libx11-dev:amd64. + default: Preparing to unpack .../libx11-dev_2%3a1.6.2-1ubuntu2.1_amd64.deb ... + default: Unpacking libx11-dev:amd64 (2:1.6.2-1ubuntu2.1) ... + default: Selecting previously unselected package libx11-doc. + default: Preparing to unpack .../libx11-doc_2%3a1.6.2-1ubuntu2.1_all.deb ... + default: Unpacking libx11-doc (2:1.6.2-1ubuntu2.1) ... + default: Selecting previously unselected package libxt-dev:amd64. + default: Preparing to unpack .../libxt-dev_1%3a1.1.4-1_amd64.deb ... + default: Unpacking libxt-dev:amd64 (1:1.1.4-1) ... + default: Selecting previously unselected package python-setuptools. + default: Preparing to unpack .../python-setuptools_3.3-1ubuntu2_all.deb ... + default: Unpacking python-setuptools (3.3-1ubuntu2) ... + default: Selecting previously unselected package sox. + default: Preparing to unpack .../sox_14.4.1-3ubuntu1.1_amd64.deb ... + default: Unpacking sox (14.4.1-3ubuntu1.1) ... + default: Selecting previously unselected package sshfs. + default: Preparing to unpack .../sshfs_2.5-1ubuntu1_amd64.deb ... + default: Unpacking sshfs (2.5-1ubuntu1) ... + default: Selecting previously unselected package subversion. + default: Preparing to unpack .../subversion_1.8.8-1ubuntu3.3_amd64.deb ... + default: Unpacking subversion (1.8.8-1ubuntu3.3) ... + default: Selecting previously unselected package ttf-dejavu-extra. + default: Preparing to unpack .../ttf-dejavu-extra_2.34-1ubuntu1_all.deb ... + default: Unpacking ttf-dejavu-extra (2.34-1ubuntu1) ... + default: Selecting previously unselected package unzip. + default: Preparing to unpack .../unzip_6.0-9ubuntu1.5_amd64.deb ... + default: Unpacking unzip (6.0-9ubuntu1.5) ... + default: Selecting previously unselected package festvox-kallpc16k. + default: Preparing to unpack .../festvox-kallpc16k_1.4.0-5_all.deb ... + default: Unpacking festvox-kallpc16k (1.4.0-5) ... + default: Selecting previously unselected package icedtea-6-jre-cacao:amd64. + default: Preparing to unpack .../icedtea-6-jre-cacao_6b41-1.13.13-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking icedtea-6-jre-cacao:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package icedtea-6-jre-jamvm:amd64. + default: Preparing to unpack .../icedtea-6-jre-jamvm_6b41-1.13.13-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking icedtea-6-jre-jamvm:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package icedtea-netx-common. + default: Preparing to unpack .../icedtea-netx-common_1.5.3-0ubuntu0.14.04.1_all.deb ... + default: Unpacking icedtea-netx-common (1.5.3-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package icedtea-netx:amd64. + default: Preparing to unpack .../icedtea-netx_1.5.3-0ubuntu0.14.04.1_amd64.deb ... + default: Unpacking icedtea-netx:amd64 (1.5.3-0ubuntu0.14.04.1) ... + default: Selecting previously unselected package libhwloc-plugins. + default: Preparing to unpack .../libhwloc-plugins_1.8-1ubuntu1.14.04.1_amd64.deb ... + default: Unpacking libhwloc-plugins (1.8-1ubuntu1.14.04.1) ... + default: Processing triggers for man-db (2.6.7.1-1ubuntu1) ... + default: Processing triggers for ca-certificates (20170717~14.04.2) ... + default: Updating certificates in /etc/ssl/certs... + default: 0 added, 0 removed; done. + default: Running hooks in /etc/ca-certificates/update.d.... + default: done. + default: Processing triggers for mime-support (3.54ubuntu1.1) ... + default: Processing triggers for hicolor-icon-theme (0.13-1) ... + default: Processing triggers for ureadahead (0.100.0-16) ... + default: Processing triggers for install-info (5.2.0.dfsg.1-2) ... + default: Processing triggers for sgml-base (1.26+nmu4ubuntu1) ... + default: Processing triggers for fontconfig (2.11.0-0ubuntu4.2) ... + default: Setting up libc6-i386 (2.19-0ubuntu6.15) ... + default: Setting up libc6-dev-i386 (2.19-0ubuntu6.15) ... + default: Setting up libc6-x32 (2.19-0ubuntu6.15) ... + default: Setting up libc6-dev-x32 (2.19-0ubuntu6.15) ... + default: Setting up lib32gcc1 (1:4.9.3-0ubuntu4) ... + default: Setting up libx32gcc1 (1:4.9.3-0ubuntu4) ... + default: Setting up lib32gomp1 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up libx32gomp1 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up lib32itm1 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up libx32itm1 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up lib32atomic1 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up libx32atomic1 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up lib32asan0 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up libx32asan0 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up lib32quadmath0 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up libx32quadmath0 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up lib32gcc-4.8-dev (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up libx32gcc-4.8-dev (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up gcc-4.8-multilib (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up gcc-multilib (4:4.8.2-1ubuntu6) ... + default: Setting up libao-common (1.1.0-2ubuntu2) ... + default: Setting up libao4:amd64 (1.1.0-2ubuntu2) ... + default: Setting up libapr1:amd64 (1.5.0-1) ... + default: Setting up libaprutil1:amd64 (1.5.3-1) ... + default: Setting up libasyncns0:amd64 (0.8-4ubuntu2) ... + default: Setting up libgtk2.0-common (2.24.23-0ubuntu1.4) ... + default: Setting up libgtk2.0-0:amd64 (2.24.23-0ubuntu1.4) ... + default: Setting up libnspr4:amd64 (2:4.13.1-0ubuntu0.14.04.1) ... + default: Setting up tzdata-java (2019a-0ubuntu0.14.04) ... + default: Setting up java-common (0.51) ... + default: Setting up libpcsclite1:amd64 (1.8.10-1ubuntu1.1) ... + default: Setting up libgif4:amd64 (4.1.6-11) ... + default: Setting up libflac8:amd64 (1.3.0-2ubuntu0.14.04.1) ... + default: Setting up libvorbisenc2:amd64 (1.3.2-1.3ubuntu1.2) ... + default: Setting up libsndfile1:amd64 (1.0.25-7ubuntu2.2) ... + default: Setting up libpulse0:amd64 (1:4.0-0ubuntu11.1) ... + default: Setting up libavutil52:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Setting up libgsm1:amd64 (1.0.13-4) ... + default: Setting up libmp3lame0:amd64 (3.99.5+repack1-3ubuntu1) ... + default: Setting up libopenjpeg2:amd64 (1.3+dfsg-4.7ubuntu1) ... + default: Setting up libopus0 (1.1-0ubuntu1) ... + default: Setting up liborc-0.4-0:amd64 (1:0.4.18-1ubuntu1) ... + default: Setting up libschroedinger-1.0-0:amd64 (1.0.11-2ubuntu1) ... + default: Setting up libspeex1:amd64 (1.2~rc1.1-1ubuntu1) ... + default: Setting up libtheora0:amd64 (1.1.1+dfsg.1-3.2) ... + default: Setting up libva1:amd64 (1.3.0-2) ... + default: Setting up libx264-142:amd64 (2:0.142.2389+git956c8d8-2) ... + default: Setting up libxvidcore4:amd64 (2:1.3.2-9ubuntu1) ... + default: Setting up libavcodec54:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Setting up libavformat54:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Setting up libcdio13 (0.83-4.1ubuntu1) ... + default: Setting up libcdio-cdda1 (0.83-4.1ubuntu1) ... + default: Setting up libcdio-paranoia1 (0.83-4.1ubuntu1) ... + default: Setting up libraw1394-11:amd64 (2.1.0-1ubuntu1) ... + default: Setting up libdc1394-22:amd64 (2.2.1-2ubuntu2) ... + default: Setting up libsamplerate0:amd64 (0.1.8-7) ... + default: Setting up libjack-jackd2-0:amd64 (1.9.9.5+20130622git7de15e7a-1ubuntu1) ... + default: Setting up libavdevice53:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Setting up libavresample1:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Setting up libswscale2:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Setting up libavfilter3:amd64 (6:9.20-0ubuntu0.14.04.1) ... + default: Setting up libcaca0:amd64 (0.99.beta18-1ubuntu5.1) ... + default: Setting up libsdl1.2debian:amd64 (1.2.15-8ubuntu1.1) ... + default: Setting up libav-tools (6:9.20-0ubuntu0.14.04.1) ... + default: Setting up libboost-atomic1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-system1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-chrono1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-context1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-date-time1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-filesystem1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-serialization1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libcr0 (0.8.5-2.1) ... + default: Setting up libhwloc5:amd64 (1.8-1ubuntu1.14.04.1) ... + default: Setting up libibverbs1 (1.1.7-1ubuntu1.1) ... + default: Setting up libtorque2 (2.4.16+dfsg-1.3ubuntu1.1) ... + default: Setting up libopenmpi1.6 (1.6.5-8) ... + default: Setting up libboost-mpi1.54.0 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-graph-parallel1.54.0 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-regex1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-graph1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-thread1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-locale1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-math1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-python1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up openmpi-common (1.6.5-8) ... + default: Setting up openmpi-bin (1.6.5-8) ... + default: update-alternatives: + default: using /usr/bin/mpirun.openmpi to provide /usr/bin/mpirun (mpirun) in auto mode + default: Setting up mpi-default-bin (1.0.2ubuntu1) ... + default: Setting up libboost-mpi-python1.54.0 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-program-options1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-random1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-signals1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-test1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-timer1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-wave1.54.0:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libportaudio2:amd64 (19+svn20140130-1) ... + default: Setting up libsonic0:amd64 (0.1.18-0ubuntu1) ... + default: Setting up espeak-data:amd64 (1.47.11-1ubuntu1) ... + default: Setting up libespeak1:amd64 (1.47.11-1ubuntu1) ... + default: Setting up libestools2.1:amd64 (1:2.1~release-6) ... + default: Setting up libgfortran3:amd64 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up libmad0:amd64 (0.15.1b-9ubuntu14.04.1) ... + default: Setting up libopencore-amrnb0:amd64 (0.1.3-2ubuntu1) ... + default: Setting up libopencore-amrwb0:amd64 (0.1.3-2ubuntu1) ... + default: Setting up libexpat1-dev:amd64 (2.1.0-4ubuntu1.4) ... + default: Setting up libpython2.7-dev:amd64 (2.7.6-8ubuntu0.5) ... + default: Setting up libserf-1-1:amd64 (1.3.3-1ubuntu0.1) ... + default: Setting up libsox2:amd64 (14.4.1-3ubuntu1.1) ... + default: Setting up libsvn1:amd64 (1.8.8-1ubuntu3.3) ... + default: Setting up libwavpack1:amd64 (4.70.0-1ubuntu0.2) ... + default: Setting up ocl-icd-libopencl1:amd64 (2.1.3-4) ... + default: Setting up linux-sound-base (1.0.25+dfsg-0ubuntu4) ... + default: Setting up alsa-base (1.0.25+dfsg-0ubuntu4) ... + default: Setting up alsa-utils (1.0.27.2-1ubuntu2) ... + default: Setting up m4 (1.4.17-2ubuntu1) ... + default: Setting up autoconf (2.69-6) ... + default: Setting up autotools-dev (20130810.1) ... + default: Setting up automake (1:1.14.1-2ubuntu1) ... + default: update-alternatives: + default: using /usr/bin/automake-1.14 to provide /usr/bin/automake (automake) in auto mode + default: Setting up espeak (1.47.11-1ubuntu1) ... + default: Setting up fonts-dejavu-extra (2.34-1ubuntu1) ... + default: Setting up libstdc++-4.8-dev:amd64 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up g++-4.8 (4.8.4-2ubuntu1~14.04.4) ... + default: Setting up g++ (4:4.8.2-1ubuntu6) ... + default: update-alternatives: + default: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto mode + default: Setting up liberror-perl (0.17-1.1) ... + default: Setting up git-man (1:1.9.1-1ubuntu0.10) ... + default: Setting up git (1:1.9.1-1ubuntu0.10) ... + default: Setting up icu-devtools (52.1-3ubuntu0.8) ... + default: Setting up libatlas3-base (3.10.1-4) ... + default: update-alternatives: + default: using /usr/lib/atlas-base/atlas/libblas.so.3 to provide /usr/lib/libblas.so.3 (libblas.so.3) in auto mode + default: update-alternatives: + default: using /usr/lib/atlas-base/atlas/liblapack.so.3 to provide /usr/lib/liblapack.so.3 (liblapack.so.3) in auto mode + default: Setting up libblas3 (1.2.20110419-7) ... + default: Setting up libblas-dev (1.2.20110419-7) ... + default: update-alternatives: + default: using /usr/lib/libblas/libblas.so to provide /usr/lib/libblas.so (libblas.so) in auto mode + default: Setting up libatlas-dev (3.10.1-4) ... + default: Setting up libatlas-base-dev (3.10.1-4) ... + default: update-alternatives: + default: using /usr/lib/atlas-base/atlas/libblas.so to provide /usr/lib/libblas.so (libblas.so) in auto mode + default: update-alternatives: + default: using /usr/lib/atlas-base/atlas/liblapack.so to provide /usr/lib/liblapack.so (liblapack.so) in auto mode + default: Setting up libboost1.54-dev (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-dev (1.54.0.1ubuntu1) ... + default: Setting up libboost1.54-tools-dev (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-tools-dev (1.54.0.1ubuntu1) ... + default: Setting up libboost-atomic1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-atomic-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-chrono1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-chrono-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-context1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-context-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-coroutine1.54-dev (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-coroutine-dev (1.54.0.1ubuntu1) ... + default: Setting up libboost-serialization1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-date-time1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-date-time-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-exception1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-exception-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-system1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-filesystem1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-filesystem-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-test1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-graph1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-graph-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-graph-parallel1.54-dev (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-graph-parallel-dev (1.54.0.1ubuntu1) ... + default: Setting up libicu-dev:amd64 (52.1-3ubuntu0.8) ... + default: Setting up libboost-regex1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-iostreams1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-iostreams-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-locale1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-locale-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-log1.54.0 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-thread1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-log1.54-dev (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-log-dev (1.54.0.1ubuntu1) ... + default: Setting up libboost-math1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-math-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libibverbs-dev (1.1.7-1ubuntu1.1) ... + default: Setting up libxml2-dev:amd64 (2.9.1+dfsg1-3ubuntu4.13) ... + default: Setting up zlib1g-dev:amd64 (1:1.2.8.dfsg-1ubuntu1.1) ... + default: Setting up libpci-dev (1:3.2.1-1ubuntu5.1) ... + default: Setting up libhwloc-dev:amd64 (1.8-1ubuntu1.14.04.1) ... + default: Setting up libopenmpi-dev (1.6.5-8) ... + default: update-alternatives: + default: using /usr/lib/openmpi/include to provide /usr/include/mpi (mpi) in auto mode + default: Setting up mpi-default-dev (1.0.2ubuntu1) ... + default: Setting up libboost-mpi1.54-dev (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-mpi-dev (1.54.0.1ubuntu1) ... + default: Setting up libboost-mpi-python1.54-dev (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-mpi-python-dev (1.54.0.1ubuntu1) ... + default: Setting up libboost-program-options1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-program-options-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libpython-dev:amd64 (2.7.5-5ubuntu3) ... + default: Setting up libboost-python1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-python-dev (1.54.0.1ubuntu1) ... + default: Setting up libboost-random1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-random-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-regex-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-serialization-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-signals1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-signals-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-system-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-test-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-thread-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-timer1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-timer-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-wave1.54-dev:amd64 (1.54.0-4ubuntu3.1) ... + default: Setting up libboost-wave-dev:amd64 (1.54.0.1ubuntu1) ... + default: Setting up libboost-all-dev (1.54.0.1ubuntu1) ... + default: Setting up libgtk2.0-bin (2.24.23-0ubuntu1.4) ... + default: Setting up xorg-sgml-doctools (1:1.11-1) ... + default: Setting up x11proto-core-dev (7.0.26-1~ubuntu2) ... + default: Setting up libice-dev:amd64 (2:1.0.8-2) ... + default: Setting up libid3tag0 (0.15.1b-10ubuntu1) ... + default: Setting up liblapack3 (3.5.0-2ubuntu1) ... + default: update-alternatives: + default: using /usr/lib/lapack/liblapack.so.3 to provide /usr/lib/liblapack.so.3 (liblapack.so.3) in auto mode + default: Setting up liblapack-dev (3.5.0-2ubuntu1) ... + default: update-alternatives: + default: using /usr/lib/lapack/liblapack.so to provide /usr/lib/liblapack.so (liblapack.so) in auto mode + default: Setting up libltdl-dev:amd64 (2.4.2-1.7ubuntu1) ... + default: Setting up libtinfo-dev:amd64 (5.9+20140118-1ubuntu1) ... + default: Setting up libncurses5-dev:amd64 (5.9+20140118-1ubuntu1) ... + default: Setting up libpthread-stubs0-dev:amd64 (0.3-4) ... + default: Setting up libsm-dev:amd64 (2:1.2.1-2) ... + default: Setting up libsox-fmt-alsa:amd64 (14.4.1-3ubuntu1.1) ... + default: Setting up libsox-fmt-ao:amd64 (14.4.1-3ubuntu1.1) ... + default: Setting up libsox-fmt-base:amd64 (14.4.1-3ubuntu1.1) ... + default: Setting up libtwolame0 (0.3.13-1ubuntu1) ... + default: Setting up libsox-fmt-mp3:amd64 (14.4.1-3ubuntu1.1) ... + default: Setting up libsox-fmt-oss:amd64 (14.4.1-3ubuntu1.1) ... + default: Setting up libsox-fmt-pulse:amd64 (14.4.1-3ubuntu1.1) ... + default: Setting up libsox-fmt-all:amd64 (14.4.1-3ubuntu1.1) ... + default: Setting up libtool (2.4.2-1.7ubuntu1) ... + default: Setting up libxau-dev:amd64 (1:1.0.8-1) ... + default: Setting up libxdmcp-dev:amd64 (1:1.1.1-1) ... + default: Setting up x11proto-input-dev (2.3-1) ... + default: Setting up x11proto-kb-dev (1.0.6-2) ... + default: Setting up xtrans-dev (1.3.5-1~ubuntu14.04.2) ... + default: Setting up libxcb1-dev:amd64 (1.10-2ubuntu1) ... + default: Setting up libx11-dev:amd64 (2:1.6.2-1ubuntu2.1) ... + default: Setting up libx11-doc (2:1.6.2-1ubuntu2.1) ... + default: Setting up libxt-dev:amd64 (1:1.1.4-1) ... + default: Setting up python-setuptools (3.3-1ubuntu2) ... + default: Setting up sox (14.4.1-3ubuntu1.1) ... + default: Setting up sshfs (2.5-1ubuntu1) ... + default: Setting up subversion (1.8.8-1ubuntu3.3) ... + default: Setting up ttf-dejavu-extra (2.34-1ubuntu1) ... + default: Setting up unzip (6.0-9ubuntu1.5) ... + default: Setting up icedtea-netx-common (1.5.3-0ubuntu0.14.04.1) ... + default: Setting up libhwloc-plugins (1.8-1ubuntu1.14.04.1) ... + default: Processing triggers for ureadahead (0.100.0-16) ... + default: Setting up festival (1:2.1~release-6ubuntu1) ... + default: Processing triggers for sgml-base (1.26+nmu4ubuntu1) ... + default: Setting up festlex-cmu (1.4.0-6) ... + default: Setting up festlex-poslex (1.4.0-5) ... + default: Setting up festvox-kallpc16k (1.4.0-5) ... + default: Setting up libnss3-nssdb (2:3.28.4-0ubuntu0.14.04.5) ... + default: Setting up openjdk-6-jre-lib (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: Setting up libatk-wrapper-java (0.30.4-4) ... + default: Setting up libnss3:amd64 (2:3.28.4-0ubuntu0.14.04.5) ... + default: Setting up openjdk-6-jre-headless:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java to provide /usr/bin/java (java) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/keytool to provide /usr/bin/keytool (keytool) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/pack200 to provide /usr/bin/pack200 (pack200) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/rmid to provide /usr/bin/rmid (rmid) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/rmiregistry to provide /usr/bin/rmiregistry (rmiregistry) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/unpack200 to provide /usr/bin/unpack200 (unpack200) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/orbd to provide /usr/bin/orbd (orbd) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/servertool to provide /usr/bin/servertool (servertool) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/tnameserv to provide /usr/bin/tnameserv (tnameserv) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/jexec to provide /usr/bin/jexec (jexec) in auto mode + default: Setting up ca-certificates-java (20130815ubuntu1) ... + default: Adding debian:Hellenic_Academic_and_Research_Institutions_RootCA_2011.pem + default: Adding debian:GeoTrust_Primary_Certification_Authority_-_G2.pem + default: Adding debian:Certum_Root_CA.pem + default: Adding debian:NetLock_Arany_=Class_Gold=_Főtanúsítvány.pem + default: Adding debian:DST_ACES_CA_X6.pem + default: Adding debian:CNNIC_ROOT.pem + default: Adding debian:GlobalSign_Root_CA_-_R2.pem + default: Adding debian:PSCProcert.pem + default: Adding debian:QuoVadis_Root_CA_2_G3.pem + default: Adding debian:VeriSign_Class_3_Public_Primary_Certification_Authority_-_G4.pem + default: Adding debian:Buypass_Class_2_Root_CA.pem + default: Adding debian:Amazon_Root_CA_2.pem + default: Adding debian:T-TeleSec_GlobalRoot_Class_3.pem + default: Adding debian:Cybertrust_Global_Root.pem + default: Adding debian:XRamp_Global_CA_Root.pem + default: Adding debian:Certinomis_-_Autorité_Racine.pem + default: Adding debian:OISTE_WISeKey_Global_Root_GA_CA.pem + default: Adding debian:AffirmTrust_Commercial.pem + default: Adding debian:DigiCert_Assured_ID_Root_G2.pem + default: Adding debian:Izenpe.com.pem + default: Adding debian:Starfield_Root_Certificate_Authority_-_G2.pem + default: Adding debian:T-TeleSec_GlobalRoot_Class_2.pem + default: Adding debian:Global_Chambersign_Root_-_2008.pem + default: Adding debian:GeoTrust_Global_CA_2.pem + default: Adding debian:Comodo_Secure_Services_root.pem + default: Adding debian:Certum_Trusted_Network_CA.pem + default: Adding debian:DST_Root_CA_X3.pem + default: Adding debian:TWCA_Root_Certification_Authority.pem + default: Adding debian:IdenTrust_Public_Sector_Root_CA_1.pem + default: Adding debian:Network_Solutions_Certificate_Authority.pem + default: Adding debian:SecureSign_RootCA11.pem + default: Adding debian:OpenTrust_Root_CA_G3.pem + default: Adding debian:GeoTrust_Universal_CA_2.pem + default: Adding debian:D-TRUST_Root_Class_3_CA_2_2009.pem + default: Adding debian:Visa_eCommerce_Root.pem + default: Adding debian:Security_Communication_Root_CA.pem + default: Adding debian:Entrust.net_Premium_2048_Secure_Server_CA.pem + default: Adding debian:GeoTrust_Global_CA.pem + default: Adding debian:Starfield_Class_2_CA.pem + default: Adding debian:TÜRKTRUST_Elektronik_Sertifika_Hizmet_Sağlayıcısı_H5.pem + default: Adding debian:Hellenic_Academic_and_Research_Institutions_RootCA_2015.pem + default: Adding debian:Microsec_e-Szigno_Root_CA_2009.pem + default: Adding debian:TeliaSonera_Root_CA_v1.pem + default: Adding debian:D-TRUST_Root_Class_3_CA_2_EV_2009.pem + default: Adding debian:QuoVadis_Root_CA_3.pem + default: Adding debian:Atos_TrustedRoot_2011.pem + default: Adding debian:Staat_der_Nederlanden_Root_CA_-_G3.pem + default: Adding debian:VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.pem + default: Adding debian:Amazon_Root_CA_1.pem + default: Adding debian:TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.pem + default: Adding debian:Certum_Trusted_Network_CA_2.pem + default: Adding debian:GeoTrust_Primary_Certification_Authority.pem + default: Adding debian:VeriSign_Universal_Root_Certification_Authority.pem + default: Adding debian:Certplus_Root_CA_G1.pem + default: Adding debian:Camerfirma_Chambers_of_Commerce_Root.pem + default: Adding debian:Entrust_Root_Certification_Authority_-_EC1.pem + default: Adding debian:ePKI_Root_Certification_Authority.pem + default: Adding debian:COMODO_Certification_Authority.pem + default: Adding debian:DigiCert_Trusted_Root_G4.pem + default: Adding debian:CA_Disig_Root_R2.pem + default: Adding debian:TWCA_Global_Root_CA.pem + default: Adding debian:E-Tugra_Certification_Authority.pem + default: Adding debian:IdenTrust_Commercial_Root_CA_1.pem + default: Adding debian:Go_Daddy_Class_2_CA.pem + default: Adding debian:EE_Certification_Centre_Root_CA.pem + default: Adding debian:SwissSign_Silver_CA_-_G2.pem + default: Adding debian:GeoTrust_Universal_CA.pem + default: Adding debian:UTN_USERFirst_Hardware_Root_CA.pem + default: Adding debian:GlobalSign_Root_CA_-_R3.pem + default: Adding debian:AffirmTrust_Premium_ECC.pem + default: Adding debian:DigiCert_Global_Root_G3.pem + default: Adding debian:SwissSign_Gold_CA_-_G2.pem + default: Adding debian:Certigna.pem + default: Adding debian:Certinomis_-_Root_CA.pem + default: Adding debian:DigiCert_High_Assurance_EV_Root_CA.pem + default: Adding debian:DigiCert_Assured_ID_Root_G3.pem + default: Adding debian:Comodo_AAA_Services_root.pem + default: Adding debian:Certplus_Root_CA_G2.pem + default: Adding debian:TÜBİTAK_UEKAE_Kök_Sertifika_Hizmet_Sağlayıcısı_-_Sürüm_3.pem + default: Adding debian:Secure_Global_CA.pem + default: Adding debian:Actalis_Authentication_Root_CA.pem + default: Adding debian:AddTrust_External_Root.pem + default: Adding debian:QuoVadis_Root_CA_1_G3.pem + default: Adding debian:DigiCert_Assured_ID_Root_CA.pem + default: Adding debian:Camerfirma_Global_Chambersign_Root.pem + default: Adding debian:Security_Communication_EV_RootCA1.pem + default: Adding debian:Entrust_Root_Certification_Authority.pem + default: Adding debian:DigiCert_Global_Root_G2.pem + default: Adding debian:Staat_der_Nederlanden_Root_CA_-_G2.pem + default: Adding debian:ACEDICOM_Root.pem + default: Adding debian:Go_Daddy_Root_Certificate_Authority_-_G2.pem + default: Adding debian:QuoVadis_Root_CA_3_G3.pem + default: Adding debian:CA_Disig_Root_R1.pem + default: Adding debian:Certplus_Class_2_Primary_CA.pem + default: Adding debian:GlobalSign_ECC_Root_CA_-_R4.pem + default: Adding debian:EC-ACC.pem + default: Adding debian:LuxTrust_Global_Root_2.pem + default: Adding debian:SZAFIR_ROOT_CA2.pem + default: Adding debian:Starfield_Services_Root_Certificate_Authority_-_G2.pem + default: Adding debian:CFCA_EV_ROOT.pem + default: Adding debian:certSIGN_ROOT_CA.pem + default: Adding debian:Staat_der_Nederlanden_EV_Root_CA.pem + default: Adding debian:Sonera_Class_2_Root_CA.pem + default: Adding debian:Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.pem + default: Adding debian:Buypass_Class_3_Root_CA.pem + default: Adding debian:Baltimore_CyberTrust_Root.pem + default: Adding debian:Amazon_Root_CA_4.pem + default: Adding debian:SecureTrust_CA.pem + default: Adding debian:OISTE_WISeKey_Global_Root_GB_CA.pem + default: Adding debian:USERTrust_ECC_Certification_Authority.pem + default: Adding debian:Swisscom_Root_CA_1.pem + default: Adding debian:QuoVadis_Root_CA.pem + default: Adding debian:thawte_Primary_Root_CA_-_G2.pem + default: Adding debian:Swisscom_Root_CA_2.pem + default: Adding debian:Comodo_Trusted_Services_root.pem + default: Adding debian:AddTrust_Qualified_Certificates_Root.pem + default: Adding debian:COMODO_ECC_Certification_Authority.pem + default: Adding debian:Taiwan_GRCA.pem + default: Adding debian:ISRG_Root_X1.pem + default: Adding debian:OpenTrust_Root_CA_G2.pem + default: Adding debian:GlobalSign_ECC_Root_CA_-_R5.pem + default: Adding debian:Hongkong_Post_Root_CA_1.pem + default: Adding debian:Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.pem + default: Adding debian:AddTrust_Low-Value_Services_Root.pem + default: Adding debian:DigiCert_Global_Root_CA.pem + default: Adding debian:GeoTrust_Primary_Certification_Authority_-_G3.pem + default: Adding debian:Deutsche_Telekom_Root_CA_2.pem + default: Adding debian:GlobalSign_Root_CA.pem + default: Adding debian:QuoVadis_Root_CA_2.pem + default: Adding debian:China_Internet_Network_Information_Center_EV_Certificates_Root.pem + default: Adding debian:ACCVRAIZ1.pem + default: Adding debian:AffirmTrust_Premium.pem + default: Adding debian:Trustis_FPS_Root_CA.pem + default: Adding debian:Chambers_of_Commerce_Root_-_2008.pem + default: Adding debian:OpenTrust_Root_CA_G1.pem + default: Adding debian:Swisscom_Root_EV_CA_2.pem + default: Adding debian:Entrust_Root_Certification_Authority_-_G2.pem + default: Adding debian:USERTrust_RSA_Certification_Authority.pem + default: Adding debian:AffirmTrust_Networking.pem + default: Adding debian:thawte_Primary_Root_CA.pem + default: Adding debian:COMODO_RSA_Certification_Authority.pem + default: Adding debian:AddTrust_Public_Services_Root.pem + default: Adding debian:Security_Communication_RootCA2.pem + default: Adding debian:thawte_Primary_Root_CA_-_G3.pem + default: Adding debian:Amazon_Root_CA_3.pem + default: Adding debian:AC_RAIZ_FNMT-RCM.pem + default: Adding debian:TURKTRUST_Certificate_Services_Provider_Root_2007.pem + default: Adding debian:Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.pem + default: done. + default: Setting up libatk-wrapper-java-jni:amd64 (0.30.4-4) ... + default: Setting up openjdk-6-jre:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: update-alternatives: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/policytool to provide /usr/bin/policytool (policytool) in auto mode + default: Setting up icedtea-6-jre-cacao:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: Setting up icedtea-6-jre-jamvm:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... + default: Setting up icedtea-netx:amd64 (1.5.3-0ubuntu0.14.04.1) ... + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/javaws to provide /usr/bin/javaws (javaws) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/itweb-settings to provide /usr/bin/itweb-settings (itweb-settings) in auto mode + default: update-alternatives: warning: + default: not replacing /usr/share/man/man1/itweb-settings.1.gz with a link + default: update-alternatives: + default: using /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/javaws to provide /usr/bin/javaws (javaws) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/itweb-settings to provide /usr/bin/itweb-settings (itweb-settings) in auto mode + default: update-alternatives: warning: + default: not replacing /usr/share/man/man1/itweb-settings.1.gz with a link + default: Processing triggers for libc-bin (2.19-0ubuntu6.15) ... + default: Processing triggers for ca-certificates (20170717~14.04.2) ... + default: Updating certificates in /etc/ssl/certs... + default: 0 added, 0 removed; done. + default: Running hooks in /etc/ca-certificates/update.d.... + default: done. + default: done. + default: Reading package lists... + default: Building dependency tree... + default: Reading state information... + default: The following packages will be REMOVED: + default: acl at-spi2-core colord dconf-gsettings-backend dconf-service + default: libatk-bridge2.0-0 libatspi2.0-0 libcairo-gobject2 libcanberra-gtk3-0 + default: libcanberra-gtk3-module libcanberra0 libcolord1 libcolorhug1 libdconf1 + default: libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libexif12 libfontenc1 libgd3 + default: libgl1-mesa-dri libgl1-mesa-glx libglapi-mesa libgphoto2-6 libgphoto2-l10n + default: libgphoto2-port10 libgtk-3-0 libgtk-3-bin libgtk-3-common libgudev-1.0-0 + default: libgusb2 libieee1284-3 libllvm3.4 libnotify-bin libnotify4 libsane + default: libsane-common libtdb1 libtxc-dxtn-s2tc0 libv4l-0 libv4lconvert0 + default: libwayland-client0 libwayland-cursor0 libxaw7 libxcb-dri2-0 libxcb-dri3-0 + default: libxcb-glx0 libxcb-present0 libxcb-sync1 libxfont1 libxkbcommon0 libxkbfile1 + default: libxmu6 libxpm4 libxshmfence1 libxxf86vm1 notification-daemon + default: sound-theme-freedesktop x11-xkb-utils xfonts-base xfonts-encodings + default: xfonts-utils xserver-common xserver-xorg-core + default: 0 upgraded, 0 newly installed, 64 to remove and 0 not upgraded. + default: After this operation, 109 MB disk space will be freed. + default: (Reading database ... 82676 files and directories currently installed.) + default: Removing colord (1.0.6-1) ... + default: Removing libsane:amd64 (1.0.23-3ubuntu3.1) ... + default: Removing acl (2.2.52-1) ... + default: Removing at-spi2-core (2.10.2.is.2.10.1-0ubuntu1) ... + default: Removing libgtk-3-bin (3.10.8-0ubuntu1.6) ... + default: Removing 'diversion of /usr/sbin/update-icon-caches to /usr/sbin/update-icon-caches.gtk2 by libgtk-3-bin' + default: Removing 'diversion of /usr/share/man/man8/update-icon-caches.8.gz to /usr/share/man/man8/update-icon-caches.gtk2.8.gz by libgtk-3-bin' + default: Removing notification-daemon (0.7.6-1) ... + default: Removing libcanberra-gtk3-module:amd64 (0.30-0ubuntu3) ... + default: Removing libcanberra-gtk3-0:amd64 (0.30-0ubuntu3) ... + default: Removing libcanberra0:amd64 (0.30-0ubuntu3) ... + default: Removing libcolorhug1:amd64 (1.0.6-1) ... + default: Removing libgl1-mesa-dri:amd64 (10.1.3-0ubuntu0.6) ... + default: Removing libdrm-intel1:amd64 (2.4.67-1ubuntu0.14.04.2) ... + default: Removing libdrm-nouveau2:amd64 (2.4.67-1ubuntu0.14.04.2) ... + default: Removing libdrm-radeon1:amd64 (2.4.67-1ubuntu0.14.04.2) ... + default: Removing libgphoto2-6:amd64 (2.5.3.1-1ubuntu2.2) ... + default: Removing libexif12:amd64 (0.6.21-1ubuntu1) ... + default: Removing xserver-xorg-core (2:1.15.1-0ubuntu2.11) ... + default: Removing xfonts-base (1:1.0.3) ... + default: Removing xfonts-utils (1:7.7+1) ... + default: Removing libxfont1:amd64 (1:1.4.7-1ubuntu0.4) ... + default: Removing libfontenc1:amd64 (1:1.1.2-1) ... + default: Removing libgd3:amd64 (2.1.0-3ubuntu0.11) ... + default: Removing libgl1-mesa-glx:amd64 (10.1.3-0ubuntu0.6) ... + default: Removing libglapi-mesa:amd64 (10.1.3-0ubuntu0.6) ... + default: Removing libgphoto2-l10n (2.5.3.1-1ubuntu2.2) ... + default: Removing libgphoto2-port10:amd64 (2.5.3.1-1ubuntu2.2) ... + default: Removing libgusb2:amd64 (0.1.6-5) ... + default: Removing libgudev-1.0-0:amd64 (1:204-5ubuntu20.31) ... + default: Removing libieee1284-3:amd64 (0.2.11-12) ... + default: Removing libllvm3.4:amd64 (1:3.4-1ubuntu3) ... + default: Removing libnotify-bin (0.7.6-1ubuntu3) ... + default: Removing libnotify4:amd64 (0.7.6-1ubuntu3) ... + default: Removing libsane-common (1.0.23-3ubuntu3.1) ... + default: Removing libtdb1:amd64 (1.3.8-0ubuntu0.14.04.1) ... + default: Removing libtxc-dxtn-s2tc0:amd64 (0~git20131104-1.1) ... + default: Removing libv4l-0:amd64 (1.0.1-1) ... + default: Removing libv4lconvert0:amd64 (1.0.1-1) ... + default: Removing xserver-common (2:1.15.1-0ubuntu2.11) ... + default: Removing x11-xkb-utils (7.7+1) ... + default: Removing libxaw7:amd64 (2:1.0.12-1) ... + default: Removing libxcb-dri2-0:amd64 (1.10-2ubuntu1) ... + default: Removing libxcb-dri3-0:amd64 (1.10-2ubuntu1) ... + default: Removing libxcb-glx0:amd64 (1.10-2ubuntu1) ... + default: Removing libxcb-present0:amd64 (1.10-2ubuntu1) ... + default: Removing libxcb-sync1:amd64 (1.10-2ubuntu1) ... + default: Removing libxkbfile1:amd64 (1:1.0.8-1) ... + default: Removing libxmu6:amd64 (2:1.1.1-1) ... + default: Removing libxpm4:amd64 (1:3.5.10-1ubuntu0.1) ... + default: Removing libxshmfence1:amd64 (1.1-2) ... + default: Removing libxxf86vm1:amd64 (1:1.1.3-1) ... + default: Removing sound-theme-freedesktop (0.8-1) ... + default: Removing xfonts-encodings (1:1.0.4-1ubuntu1) ... + default: Removing libgtk-3-0:amd64 (3.10.8-0ubuntu1.6) ... + default: Removing libgtk-3-common (3.10.8-0ubuntu1.6) ... + default: Removing dconf-gsettings-backend:amd64 (0.20.0-1) ... + default: Removing dconf-service (0.20.0-1) ... + default: Removing libatk-bridge2.0-0:amd64 (2.10.2-2ubuntu1) ... + default: Removing libatspi2.0-0:amd64 (2.10.2.is.2.10.1-0ubuntu1) ... + default: Removing libcairo-gobject2:amd64 (1.13.0~20140204-0ubuntu1.1) ... + default: Removing libcolord1:amd64 (1.0.6-1) ... + default: Removing libdconf1:amd64 (0.20.0-1) ... + default: Removing libwayland-cursor0:amd64 (1.4.0-1ubuntu1.1) ... + default: Removing libwayland-client0:amd64 (1.4.0-1ubuntu1.1) ... + default: Removing libxkbcommon0:amd64 (0.4.1-0ubuntu1.1) ... + default: Processing triggers for libglib2.0-0:amd64 (2.40.2-0ubuntu1.1) ... + default: No schema files found: removed existing output file. + default: Processing triggers for man-db (2.6.7.1-1ubuntu1) ... + default: Processing triggers for libc-bin (2.19-0ubuntu6.15) ... + default: Processing triggers for mime-support (3.54ubuntu1.1) ... + default: Processing triggers for udev (204-5ubuntu20.31) ... + default: Processing triggers for fontconfig (2.11.0-0ubuntu4.2) ... + default: Reading package lists... + default: Building dependency tree... + default: Reading state information... + default: -- System statistics report -- + default: vagrant + default: Linux vagrant-ubuntu-trusty-64 3.13.0-170-generic #220-Ubuntu SMP Thu May 9 12:40:49 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux + default: total used free shared buffers cached + default: Mem: 2049736 1307964 741772 444 61148 1043652 + default: -/+ buffers/cache: 203164 1846572 + default: Swap: 0 0 0 + default: ---- Done system updates @ Wed Jul 3 03:20:42 UTC 2019 ---- + default: Downloading and installing OpenSMILE + default: Waiting for Anaconda download to finish + default: Installing Anaconda... + default: PREFIX=/home/vagrant/anaconda + default: installing: python-2.7.16-h9bab390_0 ... + default: Python 2.7.16 :: Anaconda, Inc. + default: installing: conda-env-2.6.0-1 ... + default: installing: blas-1.0-mkl ... + default: installing: ca-certificates-2019.1.23-0 ... + default: installing: intel-openmp-2019.3-199 ... + default: installing: libgcc-ng-8.2.0-hdf63c60_1 ... + default: installing: libgfortran-ng-7.3.0-hdf63c60_0 ... + default: installing: libstdcxx-ng-8.2.0-hdf63c60_1 ... + default: installing: bzip2-1.0.6-h14c3975_5 ... + default: installing: expat-2.2.6-he6710b0_0 ... + default: installing: fribidi-1.0.5-h7b6447c_0 ... + default: installing: gmp-6.1.2-h6c8ec71_1 ... + default: installing: graphite2-1.3.13-h23475e2_0 ... + default: installing: icu-58.2-h9c2bf20_1 ... + default: installing: jbig-2.1-hdba287a_0 ... + default: installing: jpeg-9b-h024ee3a_2 ... + default: installing: libffi-3.2.1-hd88cf55_4 ... + default: installing: liblief-0.9.0-h7725739_2 ... + default: installing: libsodium-1.0.16-h1bed415_0 ... + default: installing: libtool-2.4.6-h7b6447c_5 ... + default: installing: libuuid-1.0.3-h1bed415_2 ... + default: installing: libxcb-1.13-h1bed415_1 ... + default: installing: lz4-c-1.8.1.2-h14c3975_0 ... + default: installing: lzo-2.10-h49e0be7_2 ... + default: installing: mkl-2019.3-199 ... + default: installing: ncurses-6.1-he6710b0_1 ... + default: installing: openssl-1.1.1b-h7b6447c_1 ... + default: installing: patchelf-0.9-he6710b0_3 ... + default: installing: pcre-8.43-he6710b0_0 ... + default: installing: pixman-0.38.0-h7b6447c_0 ... + default: installing: snappy-1.1.7-hbae5bb6_3 ... + default: installing: xz-5.2.4-h14c3975_4 ... + default: installing: yaml-0.1.7-had09818_2 ... + default: installing: zlib-1.2.11-h7b6447c_3 ... + default: installing: blosc-1.15.0-hd408876_0 ... + default: installing: glib-2.56.2-hd408876_0 ... + default: installing: hdf5-1.10.4-hb1b8bf9_0 ... + default: installing: libedit-3.1.20181209-hc058e9b_0 ... + default: installing: libpng-1.6.36-hbc83047_0 ... + default: installing: libssh2-1.8.0-h1ba5d50_4 ... + default: installing: libxml2-2.9.9-he19cac6_0 ... + default: installing: mpfr-4.0.1-hdf1c602_3 ... + default: installing: pandoc-2.2.3.2-0 ... + default: installing: readline-7.0-h7b6447c_5 ... + default: installing: tk-8.6.8-hbc83047_0 ... + default: installing: zeromq-4.3.1-he6710b0_3 ... + default: installing: zstd-1.3.7-h0b5b093_0 ... + default: installing: dbus-1.13.6-h746ee38_0 ... + default: installing: freetype-2.9.1-h8a8886c_1 ... + default: installing: gstreamer-1.14.0-hb453b48_1 ... + default: installing: krb5-1.16.1-h173b8e3_7 ... + default: installing: libarchive-3.3.3-h5d8350f_5 ... + default: installing: libtiff-4.0.10-h2733197_2 ... + default: installing: libxslt-1.1.33-h7d1a2b0_0 ... + default: installing: mpc-1.1.0-h10f8cd9_1 ... + default: installing: sqlite-3.27.2-h7b6447c_0 ... + default: installing: unixodbc-2.3.7-h14c3975_0 ... + default: installing: fontconfig-2.13.0-h9420a91_0 ... + default: installing: gst-plugins-base-1.14.0-hbbd80ab_1 ... + default: installing: libcurl-7.64.0-h20c2e04_2 ... + default: installing: alabaster-0.7.12-py27_0 ... + default: installing: asn1crypto-0.24.0-py27_0 ... + default: installing: atomicwrites-1.3.0-py27_1 ... + default: installing: attrs-19.1.0-py27_1 ... + default: installing: backports-1.0-py27_1 ... + default: installing: backports_abc-0.5-py27h7b3c97b_0 ... + default: installing: bitarray-0.8.3-py27h14c3975_0 ... + default: installing: boto-2.49.0-py27_0 ... + default: installing: cairo-1.14.12-h8948797_3 ... + default: installing: cdecimal-2.3-py27h14c3975_3 ... + default: installing: certifi-2019.3.9-py27_0 ... + default: installing: chardet-3.0.4-py27_1 ... + default: installing: click-7.0-py27_0 ... + default: installing: cloudpickle-0.8.0-py27_0 ... + default: installing: colorama-0.4.1-py27_0 ... + default: installing: contextlib2-0.5.5-py27hbf4c468_0 ... + default: installing: curl-7.64.0-hbc83047_2 ... + default: installing: dask-core-1.1.4-py27_1 ... + default: installing: decorator-4.4.0-py27_1 ... + default: installing: defusedxml-0.5.0-py27_1 ... + default: installing: docutils-0.14-py27hae222c1_0 ... + default: installing: enum34-1.1.6-py27_1 ... + default: installing: et_xmlfile-1.0.1-py27h75840f5_0 ... + default: installing: fastcache-1.0.2-py27h14c3975_2 ... + default: installing: filelock-3.0.10-py27_0 ... + default: installing: funcsigs-1.0.2-py27h83f16ab_0 ... + default: installing: functools32-3.2.3.2-py27_1 ... + default: installing: future-0.17.1-py27_0 ... + default: installing: futures-3.2.0-py27_0 ... + default: installing: glob2-0.6-py27_1 ... + default: installing: gmpy2-2.0.8-py27h10f8cd9_2 ... + default: installing: greenlet-0.4.15-py27h7b6447c_0 ... + default: installing: grin-1.2.1-py27_4 ... + default: installing: heapdict-1.0.0-py27_2 ... + default: installing: idna-2.8-py27_0 ... + default: installing: imagesize-1.1.0-py27_0 ... + default: installing: ipaddress-1.0.22-py27_0 ... + default: installing: ipython_genutils-0.2.0-py27h89fb69b_0 ... + default: installing: itsdangerous-1.1.0-py27_0 ... + default: installing: jdcal-1.4-py27_0 ... + default: installing: kiwisolver-1.0.1-py27hf484d3e_0 ... + default: installing: lazy-object-proxy-1.3.1-py27h14c3975_2 ... + default: installing: linecache2-1.0.0-py27_0 ... + default: installing: locket-0.2.0-py27h73929a2_1 ... + default: installing: lxml-4.3.2-py27hefd8a0e_0 ... + default: installing: markupsafe-1.1.1-py27h7b6447c_0 ... + default: installing: mccabe-0.6.1-py27_1 ... + default: installing: mistune-0.8.4-py27h7b6447c_0 ... + default: installing: mkl-service-1.1.2-py27he904b0f_5 ... + default: installing: mpmath-1.1.0-py27_0 ... + default: installing: msgpack-python-0.6.1-py27hfd86e86_1 ... + default: installing: numpy-base-1.16.2-py27hde5b4d6_0 ... + default: installing: olefile-0.46-py27_0 ... + default: installing: pandocfilters-1.4.2-py27_1 ... + default: installing: parso-0.3.4-py27_0 ... + default: installing: pep8-1.7.1-py27_0 ... + default: installing: pkginfo-1.5.0.1-py27_0 ... + default: installing: pluggy-0.9.0-py27_0 ... + default: installing: ply-3.11-py27_0 ... + default: installing: prometheus_client-0.6.0-py27_0 ... + default: installing: psutil-5.6.1-py27h7b6447c_0 ... + default: installing: ptyprocess-0.6.0-py27_0 ... + default: installing: py-1.8.0-py27_0 ... + default: installing: py-lief-0.9.0-py27h7725739_2 ... + default: installing: pycodestyle-2.5.0-py27_0 ... + default: installing: pycosat-0.6.3-py27h14c3975_0 ... + default: installing: pycparser-2.19-py27_0 ... + default: installing: pycrypto-2.6.1-py27h14c3975_9 ... + default: installing: pycurl-7.43.0.2-py27h1ba5d50_0 ... + default: installing: pyflakes-2.1.1-py27_0 ... + default: installing: pyodbc-4.0.26-py27he6710b0_0 ... + default: installing: pyparsing-2.3.1-py27_0 ... + default: installing: pysocks-1.6.8-py27_0 ... + default: installing: python-libarchive-c-2.8-py27_6 ... + default: installing: pytz-2018.9-py27_0 ... + default: installing: pyyaml-5.1-py27h7b6447c_0 ... + default: installing: pyzmq-18.0.0-py27he6710b0_0 ... + default: installing: qt-5.9.7-h5867ecd_1 ... + default: installing: qtpy-1.7.0-py27_1 ... + default: installing: rope-0.12.0-py27_0 ... + default: installing: ruamel_yaml-0.15.46-py27h14c3975_0 ... + default: installing: scandir-1.10.0-py27h7b6447c_0 ... + default: installing: send2trash-1.5.0-py27_0 ... + default: installing: simplegeneric-0.8.1-py27_2 ... + default: installing: sip-4.19.8-py27hf484d3e_0 ... + default: installing: six-1.12.0-py27_0 ... + default: installing: snowballstemmer-1.2.1-py27h44e2768_0 ... + default: installing: sortedcontainers-2.1.0-py27_0 ... + default: installing: sphinxcontrib-1.0-py27_1 ... + default: installing: sqlalchemy-1.3.1-py27h7b6447c_0 ... + default: installing: subprocess32-3.5.3-py27h7b6447c_0 ... + default: installing: tblib-1.3.2-py27h51fe5ba_0 ... + default: installing: testpath-0.4.2-py27_0 ... + default: installing: toolz-0.9.0-py27_0 ... + default: installing: tqdm-4.31.1-py27_1 ... + default: installing: typing-3.6.6-py27_0 ... + default: installing: unicodecsv-0.14.1-py27h5062da9_0 ... + default: installing: wcwidth-0.1.7-py27h9e3e1ab_0 ... + default: installing: webencodings-0.5.1-py27_1 ... + default: installing: werkzeug-0.14.1-py27_0 ... + default: installing: wrapt-1.11.1-py27h7b6447c_0 ... + default: installing: wurlitzer-1.0.2-py27_0 ... + default: installing: xlrd-1.2.0-py27_0 ... + default: installing: xlsxwriter-1.1.5-py27_0 ... + default: installing: xlwt-1.3.0-py27h3d85d97_0 ... + default: installing: zipp-0.3.3-py27_1 ... + default: installing: babel-2.6.0-py27_0 ... + default: installing: backports.os-0.1.1-py27_0 ... + default: installing: backports.shutil_get_terminal_size-1.0.0-py27_2 ... + default: installing: cffi-1.12.2-py27h2e261b9_1 ... + default: installing: configparser-3.7.3-py27_1 ... + default: installing: cycler-0.10.0-py27hc7354d3_0 ... + default: installing: cytoolz-0.9.0.1-py27h14c3975_1 ... + default: installing: harfbuzz-1.8.8-hffaf4a1_0 ... + default: installing: html5lib-1.0.1-py27_0 ... + default: installing: jedi-0.13.3-py27_0 ... + default: installing: llvmlite-0.28.0-py27hd408876_0 ... + default: installing: mkl_random-1.0.2-py27hd81dba3_0 ... + default: installing: more-itertools-5.0.0-py27_0 ... + default: installing: multipledispatch-0.6.0-py27_0 ... + default: installing: nltk-3.4-py27_1 ... + default: installing: openpyxl-2.6.1-py27_1 ... + default: installing: packaging-19.0-py27_0 ... + default: installing: partd-0.3.10-py27_1 ... + default: installing: pathlib2-2.3.3-py27_0 ... + default: installing: pexpect-4.6.0-py27_0 ... + default: installing: pillow-5.4.1-py27h34e0f95_0 ... + default: installing: pycairo-1.18.0-py27h2a1e443_0 ... + default: installing: pyqt-5.9.2-py27h05f1152_2 ... + default: installing: pyrsistent-0.14.11-py27h7b6447c_0 ... + default: installing: python-dateutil-2.8.0-py27_0 ... + default: installing: qtawesome-0.5.7-py27_1 ... + default: installing: setuptools-40.8.0-py27_0 ... + default: installing: singledispatch-3.4.0.3-py27h9bcb476_0 ... + default: installing: sortedcollections-1.1.2-py27_0 ... + default: installing: sphinxcontrib-websupport-1.1.0-py27_1 ... + default: installing: ssl_match_hostname-3.7.0.1-py27_0 ... + default: installing: sympy-1.3-py27_0 ... + default: installing: traceback2-1.4.0-py27_0 ... + default: installing: traitlets-4.3.2-py27hd6ce930_0 ... + default: installing: zict-0.1.4-py27_0 ... + default: installing: backports.functools_lru_cache-1.5-py27_1 ... + default: installing: bleach-3.1.0-py27_0 ... + default: installing: clyent-1.2.2-py27_1 ... + default: installing: cryptography-2.6.1-py27h1ba5d50_0 ... + default: installing: cython-0.29.6-py27he6710b0_0 ... + default: installing: entrypoints-0.3-py27_0 ... + default: installing: get_terminal_size-1.0.0-haa9412d_0 ... + default: installing: gevent-1.4.0-py27h7b6447c_0 ... + default: installing: importlib_metadata-0.8-py27_0 ... + default: installing: jinja2-2.10-py27_0 ... + default: installing: jsonschema-3.0.1-py27_0 ... + default: installing: jupyter_core-4.4.0-py27_0 ... + default: installing: navigator-updater-0.2.1-py27_0 ... + default: installing: networkx-2.2-py27_1 ... + default: installing: nose-1.3.7-py27_2 ... + default: installing: pango-1.42.4-h049681c_0 ... + default: installing: pickleshare-0.7.5-py27_0 ... + default: installing: pygments-2.3.1-py27_0 ... + default: installing: pytest-4.3.1-py27_0 ... + default: installing: tornado-5.1.1-py27h7b6447c_0 ... + default: installing: unittest2-1.1.0-py27_0 ... + default: installing: wheel-0.33.1-py27_0 ... + default: installing: astroid-1.6.5-py27_0 ... + default: installing: conda-verify-3.1.1-py27_0 ... + default: installing: distributed-1.26.0-py27_1 ... + default: installing: flask-1.0.2-py27_1 ... + default: installing: isort-4.3.16-py27_0 ... + default: installing: jupyter_client-5.2.4-py27_0 ... + default: installing: nbformat-4.4.0-py27hed7f2b2_0 ... + default: installing: path.py-11.5.0-py27_0 ... + default: installing: pip-19.0.3-py27_0 ... + default: installing: prompt_toolkit-1.0.15-py27h1b593e1_0 ... + default: installing: pyopenssl-19.0.0-py27_0 ... + default: installing: soupsieve-1.8-py27_0 ... + default: installing: terminado-0.8.1-py27_1 ... + default: installing: beautifulsoup4-4.7.1-py27_1 ... + default: installing: ipython-5.8.0-py27_0 ... + default: installing: nbconvert-5.4.1-py27_3 ... + default: installing: pylint-1.9.2-py27_0 ... + default: installing: urllib3-1.24.1-py27_0 ... + default: installing: ipykernel-4.10.0-py27_0 ... + default: installing: requests-2.21.0-py27_0 ... + default: installing: anaconda-client-1.7.2-py27_0 ... + default: installing: conda-4.6.11-py27_0 ... + default: installing: jupyter_console-5.2.0-py27_1 ... + default: installing: notebook-5.7.8-py27_0 ... + default: installing: qtconsole-4.4.3-py27_0 ... + default: installing: sphinx-1.8.5-py27_0 ... + default: installing: spyder-kernels-0.4.2-py27_0 ... + default: installing: anaconda-navigator-1.9.7-py27_0 ... + default: installing: anaconda-project-0.8.2-py27_0 ... + default: installing: conda-build-3.17.8-py27_0 ... + default: installing: jupyterlab_launcher-0.11.2-py27h28b3542_0 ... + default: installing: numpydoc-0.8.0-py27_0 ... + default: installing: widgetsnbextension-3.4.2-py27_0 ... + default: installing: ipywidgets-7.4.2-py27_0 ... + default: installing: jupyterlab-0.33.11-py27_0 ... + default: installing: spyder-3.3.3-py27_0 ... + default: installing: _ipyw_jlab_nb_ext_conf-0.1.0-py27_0 ... + default: installing: jupyter-1.0.0-py27_7 ... + default: installing: astropy-2.0.9-py27hdd07704_0 ... + default: installing: bokeh-1.0.4-py27_0 ... + default: installing: bottleneck-1.2.1-py27h035aef0_1 ... + default: installing: h5py-2.9.0-py27h7918eee_0 ... + default: installing: imageio-2.5.0-py27_0 ... + default: installing: matplotlib-2.2.3-py27hb69df0a_0 ... + default: installing: mkl_fft-1.0.10-py27ha843d7b_0 ... + default: installing: numpy-1.16.2-py27h7e9f1db_0 ... + default: installing: numba-0.43.1-py27h962f231_0 ... + default: installing: numexpr-2.6.9-py27h9e4a6bb_0 ... + default: installing: pandas-0.24.2-py27he6710b0_0 ... + default: installing: pywavelets-1.0.2-py27hdd07704_0 ... + default: installing: scipy-1.2.1-py27h7c811a0_0 ... + default: installing: bkcharts-0.2-py27h241ae91_0 ... + default: installing: dask-1.1.4-py27_1 ... + default: installing: patsy-0.5.1-py27_0 ... + default: installing: pytables-3.5.1-py27h71ec239_0 ... + default: installing: scikit-image-0.14.2-py27he6710b0_0 ... + default: installing: scikit-learn-0.20.3-py27hd81dba3_0 ... + default: installing: statsmodels-0.9.0-py27h035aef0_0 ... + default: installing: seaborn-0.9.0-py27_0 ... + default: installing: anaconda-2019.03-py27_0 ... + default: installation finished. + default: Creating python3 env... + default: WARNING: The conda.compat module is deprecated and will be removed in a future release. + default: WARNING: The conda.compat module is deprecated and will be removed in a future release. + default: Warning: you have pip-installed dependencies in your environment file, but you do not list pip itself as one of your conda dependencies. Conda may not use the correct pip to install your packages, and they may end up in the wrong place. Please add an explicit pip dependency. I'm adding one for you, but still nagging you. + default: Collecting package metadata: + default: ...working... + default: done + default: Solving environment: + default: ...working... + default: done + default: Preparing transaction: ...working... + default: done + default: Verifying transaction: + default: ...working... + default: done + default: Executing transaction: ...working... + default: done + default: Ran pip subprocess with arguments: + default: [u'/home/vagrant/anaconda/envs/divime/bin/python', '-m', 'pip', 'install', '-r', '/tmp/tmpDeepCN.requirements.txt'] + default: Pip subprocess output: + default: Collecting theano (from -r /tmp/tmpDeepCN.requirements.txt (line 1)) + default: Downloading https://files.pythonhosted.org/packages/7d/c4/6341148ad458b6cd8361b774d7ee6895c38eab88f05331f22304c484ed5d/Theano-1.0.4.tar.gz (2.8MB) + default: Collecting intervaltree (from -r /tmp/tmpDeepCN.requirements.txt (line 2)) + default: Downloading https://files.pythonhosted.org/packages/e8/f9/76237755b2020cd74549e98667210b2dd54d3fb17c6f4a62631e61d31225/intervaltree-3.0.2.tar.gz + default: Collecting pympi-ling (from -r /tmp/tmpDeepCN.requirements.txt (line 3)) + default: Downloading https://files.pythonhosted.org/packages/92/c7/90b4821910509e9c888d93386e6fe00efaf7dd5ae37fc607391d6838df40/pympi-ling-1.69.tar.gz + default: Collecting tgt (from -r /tmp/tmpDeepCN.requirements.txt (line 4)) + default: Downloading https://files.pythonhosted.org/packages/51/9a/25d82ed43c926e0234c8705e374323d7f9bfe0b311019fe3b1e2e445fbb6/tgt-1.4.4.tar.gz + default: Collecting ipdb (from -r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/6d/43/c3c2e866a8803e196d6209595020a4a6db1a3c5d07c01455669497ae23d0/ipdb-0.12.tar.gz + default: Requirement already satisfied: numpy>=1.9.1 in /home/vagrant/anaconda/envs/divime/lib/python3.6/site-packages (from theano->-r /tmp/tmpDeepCN.requirements.txt (line 1)) (1.16.4) + default: Requirement already satisfied: scipy>=0.14 in /home/vagrant/anaconda/envs/divime/lib/python3.6/site-packages (from theano->-r /tmp/tmpDeepCN.requirements.txt (line 1)) (1.2.1) + default: Requirement already satisfied: six>=1.9.0 in /home/vagrant/anaconda/envs/divime/lib/python3.6/site-packages (from theano->-r /tmp/tmpDeepCN.requirements.txt (line 1)) (1.12.0) + default: Collecting sortedcontainers<3.0,>=2.0 (from intervaltree->-r /tmp/tmpDeepCN.requirements.txt (line 2)) + default: Downloading https://files.pythonhosted.org/packages/13/f3/cf85f7c3a2dbd1a515d51e1f1676d971abe41bba6f4ab5443240d9a78e5b/sortedcontainers-2.1.0-py2.py3-none-any.whl + default: Requirement already satisfied: setuptools in /home/vagrant/anaconda/envs/divime/lib/python3.6/site-packages (from ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) (41.0.1) + default: Collecting ipython>=5.1.0 (from ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/9f/be/e7fcd8545f17902fb96ee62cdbb141f1054e579406fdc7f1da7504c1420b/ipython-7.6.0-py3-none-any.whl (774kB) + default: Collecting prompt-toolkit<2.1.0,>=2.0.0 (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/f7/a7/9b1dd14ef45345f186ef69d175bdd2491c40ab1dfa4b2b3e4352df719ed7/prompt_toolkit-2.0.9-py3-none-any.whl (337kB) + default: Collecting traitlets>=4.2 (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/93/d6/abcb22de61d78e2fc3959c964628a5771e47e7cc60d53e9342e21ed6cc9a/traitlets-4.3.2-py2.py3-none-any.whl (74kB) + default: Collecting pickleshare (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/9a/41/220f49aaea88bc6fa6cba8d05ecf24676326156c23b991e80b3f2fc24c77/pickleshare-0.7.5-py2.py3-none-any.whl + default: Collecting backcall (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/84/71/c8ca4f5bb1e08401b916c68003acf0a0655df935d74d93bf3f3364b310e0/backcall-0.1.0.tar.gz + default: Collecting pygments (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/5c/73/1dfa428150e3ccb0fa3e68db406e5be48698f2a979ccbcec795f28f44048/Pygments-2.4.2-py2.py3-none-any.whl (883kB) + default: Collecting pexpect; sys_platform != "win32" (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/0e/3e/377007e3f36ec42f1b84ec322ee12141a9e10d808312e5738f52f80a232c/pexpect-4.7.0-py2.py3-none-any.whl (58kB) + default: Collecting decorator (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN. + default: requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/5f/88/0075e461560a1e750a0dcbf77f1d9de775028c37a19a346a6c565a257399/decorator-4.4.0-py2.py3-none-any.whl + default: Collecting jedi>=0.10 (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/68/42/6309f3871b2f8361764ac5b2fe6719f9c6e6561d9307d8cecda319cf5843/jedi-0.14.0-py2.py3-none-any.whl (1.0MB) + default: Collecting wcwidth (from prompt-toolkit<2.1.0,>=2.0.0->ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/7e/9f/526a6947247599b084ee5232e4f9190a38f398d7300d866af3ab571a5bfe/wcwidth-0.1.7-py2.py3-none-any.whl + default: Collecting ipython-genutils (from traitlets>=4.2->ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/fa/bc/9bd3b5c2b4774d5f33b2d544f1460be9df7df2fe42f352135381c347c69a/ipython_genutils-0.2.0-py2.py3-none-any.whl + default: Collecting ptyprocess>=0.5 (from pexpect; sys_platform != "win32"->ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/d1/29/605c2cc68a9992d18dada28206eeada56ea4bd07a239669da41674648b6f/ptyprocess-0.6.0-py2.py3-none-any.whl + default: Collecting parso>=0.3.0 (from jedi>=0.10->ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) + default: Downloading https://files.pythonhosted.org/packages/68/59/482f5a00fe3da7f0aaeedf61c2a25c445b68c9124437195f6e8b2beddbc0/parso-0.5.0-py2.py3-none-any.whl (94kB) + default: Building wheels for collected packages: theano, intervaltree, pympi-ling, tgt, ipdb, backcall + default: Building wheel for theano (setup.py): started + default: Building wheel for theano (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/88/fb/be/483910ff7e9f703f30a10605ad7605f3316493875c86637014 + default: Building wheel for intervaltree (setup.py): started + default: Building wheel for intervaltree (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/08/99/c0/5a5942f5b9567c59c14aac76f95a70bf11dccc71240b91ebf5 + default: Building wheel for pympi-ling (setup.py): started + default: Building wheel for pympi-ling (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/34/c2/ab/1107ef0b833e770faf53b41179884b4bfa6f5bd641dc74e8f4 + default: Building wheel for tgt (setup.py): started + default: Building wheel for tgt (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/d0/01/c2/7b18446d6ce6b1ced14c50044844180f89a51b960d0799802d + default: Building wheel for ipdb (setup.py): started + default: Building wheel for ipdb (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/59/24/91/695211bd228d40fb22dff0ce3f05ba41ab724ab771736233f3 + default: Building wheel for backcall (setup.py): started + default: Building wheel for backcall (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/98/b0/dd/29e28ff615af3dda4c67cab719dd51357597eabff926976b45 + default: Successfully built theano intervaltree pympi-ling tgt ipdb backcall + default: Installing collected packages: theano, sortedcontainers, intervaltree, pympi-ling, tgt, wcwidth, prompt-toolkit, ipython-genutils, decorator, traitlets, pickleshare, backcall, pygments, ptyprocess, pexpect, parso, jedi, ipython, ipdb + default: Successfully installed backcall-0.1.0 decorator-4.4.0 intervaltree-3.0.2 ipdb-0.12 ipython-7.6.0 ipython-genutils-0.2.0 jedi-0.14.0 parso-0.5.0 pexpect-4.7.0 pickleshare-0.7.5 prompt-toolkit-2.0.9 ptyprocess-0.6.0 pygments-2.4.2 pympi-ling-1.69 sortedcontainers-2.1.0 tgt-1.4.4 theano-1.0.4 traitlets-4.3.2 wcwidth-0.1.7 + default: + default: # + default: # To activate this environment, use: + default: # > conda activate divime + default: # + default: # To deactivate an active environment, use: + default: # > conda deactivate + default: # + default: Waiting for Matlab download to finish + default: Installing Matlab... + default: Preparing installation files ... + default: Installing ... + default: (Jul 03, 2019 03:27:02) ################################################################## + default: (Jul 03, 2019 03:27:02) # + default: (Jul 03, 2019 03:27:02) # Today's Date: + default: (Jul 03, 2019 03:27:02) Wed Jul 03 03:27:02 UTC 2019 + default: (Jul 03, 2019 03:27:02) + default: (Jul 03, 2019 03:27:02) System Info + default: (Jul 03, 2019 03:27:02) OS: Linux 3.13.0-170-generic + default: (Jul 03, 2019 03:27:02) Arch: amd64 + default: (Jul 03, 2019 03:27:02) Data Model: 64 + default: (Jul 03, 2019 03:27:02) Language: en + default: (Jul 03, 2019 03:27:02) Java Vendor: Oracle Corporation + default: (Jul 03, 2019 03:27:02) Java Home: /tmp/mathworks_22207/sys/java/jre/glnxa64/jre + default: (Jul 03, 2019 03:27:02) Java Version: 1.8.0_121 + default: (Jul 03, 2019 03:27:02) Java VM Name: Java HotSpot(TM) 64-Bit Server VM + default: (Jul 03, 2019 03:27:02) Java Class Path: /tmp/mathworks_22207/java/config/installagent/pathlist.jar + default: (Jul 03, 2019 03:27:02) User Name: root + default: (Jul 03, 2019 03:27:02) Current Directory: /tmp/mathworks_22207 + default: (Jul 03, 2019 03:27:02) Input arguments: + default: (Jul 03, 2019 03:27:02) root /tmp + default: (Jul 03, 2019 03:27:02) libdir /tmp/mathworks_22207 + default: (Jul 03, 2019 03:27:02) mode silent + default: (Jul 03, 2019 03:27:02) agreeToLicense yes + default: (Jul 03, 2019 03:27:02) standalone true + default: (Jul 03, 2019 03:27:02) connectionMode OFFLINE_ONLY + default: (Jul 03, 2019 03:27:03) Starting local product/component search in download directory + default: (Jul 03, 2019 03:27:03) Assembling product list... + default: (Jul 03, 2019 03:27:03) Searching for archives... + default: (Jul 03, 2019 03:27:03) Reading /tmp/archives + default: (Jul 03, 2019 03:27:03) 1569 files found in /tmp/archives + default: (Jul 03, 2019 03:27:03) Reading /tmp + default: (Jul 03, 2019 03:27:03) 16 files found in /tmp + default: (Jul 03, 2019 03:27:03) Archive search complete. 1585 total files found. + default: (Jul 03, 2019 03:27:04) Completed local product/component search + default: (Jul 03, 2019 03:27:04) Starting local product/component search in download directory + default: (Jul 03, 2019 03:27:04) Searching for archives... + default: (Jul 03, 2019 03:27:04) /usr/local/MATLAB/MATLAB_Runtime/v93/archives doesn't exist ... skipping. + default: (Jul 03, 2019 03:27:04) Archive search complete. 0 total files found. + default: (Jul 03, 2019 03:27:04) Completed local product/component search + default: (Jul 03, 2019 03:27:04) Installing Product: MATLAB Runtime - Builder JA 9.3 + default: (Jul 03, 2019 03:27:06) Installing Product: MATLAB Runtime - Core 9.3 + default: (Jul 03, 2019 03:27:24) Installing Product: MATLAB Runtime - GPU 9.3 + default: (Jul 03, 2019 03:27:33) Installing Product: MATLAB Runtime - Hadoop And Spark 9.3 + default: (Jul 03, 2019 03:27:33) Installing Product: MATLAB Runtime - NET And XL 9.3 + default: (Jul 03, 2019 03:27:33) Installing Product: MATLAB Runtime - Numerics 9.3 + default: (Jul 03, 2019 03:27:41) Notes: + default: On the target computer, append the following to your LD_LIBRARY_PATH environment variable: + default: + default: /usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64: + default: + default: If MATLAB Runtime is to be used with MATLAB Production Server, you do not need to modify the above environment variable. + default: (Jul 03, 2019 03:27:41) Exiting with status 0 + default: (Jul 03, 2019 03:27:41) End - Successful. + default: Finished + default: Installing HTK... + default: Can't find HTK-3.4.1.tar.gz. Assuming HTK not needed. + default: -- Conda report -- + default: WARNING: The conda.compat module is deprecated and will be removed in a future release. + default: # packages in environment at /home/vagrant/anaconda: + default: # + default: # Name Version Build Channel + default: _ipyw_jlab_nb_ext_conf 0.1.0 py27_0 + default: alabaster 0.7.12 py27_0 + default: anaconda 2019.03 py27_0 + default: anaconda-client 1.7.2 py27_0 + default: anaconda-navigator 1.9.7 py27_0 + default: anaconda-project 0.8.2 py27_0 + default: asn1crypto 0.24.0 py27_0 + default: astroid 1.6.5 py27_0 + default: astropy 2.0.9 py27hdd07704_0 + default: atomicwrites 1.3.0 py27_1 + default: attrs 19.1.0 py27_1 + default: babel 2.6.0 py27_0 + default: backports 1.0 py27_1 + default: backports.functools_lru_cache 1.5 py27_1 + default: backports.os 0.1.1 py27_0 + default: backports.shutil_get_terminal_size 1.0.0 py27_2 + default: backports_abc 0.5 py27h7b3c97b_0 + default: beautifulsoup4 4.7.1 py27_1 + default: bitarray 0.8.3 py27h14c3975_0 + default: bkcharts 0.2 py27h241ae91_0 + default: blas 1.0 mkl + default: bleach 3.1.0 py27_0 + default: blosc 1.15.0 hd408876_0 + default: bokeh 1.0.4 py27_0 + default: boto 2.49.0 py27_0 + default: bottleneck 1.2.1 py27h035aef0_1 + default: bzip2 1.0.6 h14c3975_5 + default: ca-certificates 2019.1.23 0 + default: cairo 1.14.12 h8948797_3 + default: cdecimal 2.3 py27h14c3975_3 + default: certifi 2019.3.9 py27_0 + default: cffi 1.12.2 py27h2e261b9_1 + default: chardet 3.0.4 py27_1 + default: click 7.0 py27_0 + default: cloudpickle 0.8.0 py27_0 + default: clyent 1.2.2 py27_1 + default: colorama 0.4.1 py27_0 + default: conda 4.6.11 py27_0 + default: conda-build 3.17.8 py27_0 + default: conda-env 2.6.0 1 + default: conda-verify 3.1.1 py27_0 + default: configparser 3.7.3 py27_1 + default: contextlib2 0.5.5 py27hbf4c468_0 + default: cryptography 2.6.1 py27h1ba5d50_0 + default: curl 7.64.0 hbc83047_2 + default: cycler 0.10.0 py27hc7354d3_0 + default: cython 0.29.6 py27he6710b0_0 + default: cytoolz 0.9.0.1 py27h14c3975_1 + default: dask 1.1.4 py27_1 + default: dask-core 1.1.4 py27_1 + default: dbus 1.13.6 h746ee38_0 + default: decorator 4.4.0 py27_1 + default: defusedxml 0.5.0 py27_1 + default: distributed 1.26.0 py27_1 + default: docutils 0.14 py27hae222c1_0 + default: entrypoints 0.3 py27_0 + default: enum34 1.1.6 py27_1 + default: et_xmlfile 1.0.1 py27h75840f5_0 + default: expat 2.2.6 he6710b0_0 + default: fastcache 1.0.2 py27h14c3975_2 + default: filelock 3.0.10 py27_0 + default: flask 1.0.2 py27_1 + default: fontconfig 2.13.0 h9420a91_0 + default: freetype 2.9.1 h8a8886c_1 + default: fribidi 1.0.5 h7b6447c_0 + default: funcsigs 1.0.2 py27h83f16ab_0 + default: functools32 3.2.3.2 py27_1 + default: future 0.17.1 py27_0 + default: futures 3.2.0 py27_0 + default: get_terminal_size 1.0.0 haa9412d_0 + default: gevent 1.4.0 py27h7b6447c_0 + default: glib 2.56.2 hd408876_0 + default: glob2 0.6 py27_1 + default: gmp 6.1.2 h6c8ec71_1 + default: gmpy2 2.0.8 py27h10f8cd9_2 + default: graphite2 1.3.13 h23475e2_0 + default: greenlet 0.4.15 py27h7b6447c_0 + default: grin 1.2.1 py27_4 + default: gst-plugins-base 1.14.0 hbbd80ab_1 + default: gstreamer 1.14.0 hb453b48_1 + default: h5py 2.9.0 py27h7918eee_0 + default: harfbuzz 1.8.8 hffaf4a1_0 + default: hdf5 1.10.4 hb1b8bf9_0 + default: heapdict 1.0.0 py27_2 + default: html5lib 1.0.1 py27_0 + default: icu 58.2 h9c2bf20_1 + default: idna 2.8 py27_0 + default: imageio 2.5.0 py27_0 + default: imagesize 1.1.0 py27_0 + default: importlib_metadata 0.8 py27_0 + default: intel-openmp 2019.3 199 + default: ipaddress 1.0.22 py27_0 + default: ipykernel 4.10.0 py27_0 + default: ipython 5.8.0 py27_0 + default: ipython_genutils 0.2.0 py27h89fb69b_0 + default: ipywidgets 7.4.2 py27_0 + default: isort 4.3.16 py27_0 + default: itsdangerous 1.1.0 py27_0 + default: jbig 2.1 hdba287a_0 + default: jdcal 1.4 py27_0 + default: jedi 0.13.3 py27_0 + default: jinja2 2.10 py27_0 + default: jpeg 9b h024ee3a_2 + default: jsonschema 3.0.1 py27_0 + default: jupyter 1.0.0 py27_7 + default: jupyter_client 5.2.4 py27_0 + default: jupyter_console 5.2.0 py27_1 + default: jupyter_core 4.4.0 py27_0 + default: jupyterlab 0.33.11 py27_0 + default: jupyterlab_launcher 0.11.2 py27h28b3542_0 + default: kiwisolver 1.0.1 py27hf484d3e_0 + default: krb5 1.16.1 h173b8e3_7 + default: lazy-object-proxy 1.3.1 py27h14c3975_2 + default: libarchive 3.3.3 h5d8350f_5 + default: libcurl 7.64.0 h20c2e04_2 + default: libedit 3.1.20181209 hc058e9b_0 + default: libffi 3.2.1 hd88cf55_4 + default: libgcc-ng 8.2.0 hdf63c60_1 + default: libgfortran-ng 7.3.0 hdf63c60_0 + default: liblief 0.9.0 h7725739_2 + default: libpng 1.6.36 hbc83047_0 + default: libsodium 1.0.16 h1bed415_0 + default: libssh2 1.8.0 h1ba5d50_4 + default: libstdcxx-ng 8.2.0 hdf63c60_1 + default: libtiff 4.0.10 h2733197_2 + default: libtool 2.4.6 h7b6447c_5 + default: libuuid 1.0.3 h1bed415_2 + default: libxcb 1.13 h1bed415_1 + default: libxml2 2.9.9 he19cac6_0 + default: libxslt 1.1.33 h7d1a2b0_0 + default: linecache2 1.0.0 py27_0 + default: llvmlite 0.28.0 py27hd408876_0 + default: locket 0.2.0 py27h73929a2_1 + default: lxml 4.3.2 py27hefd8a0e_0 + default: lz4-c 1.8.1.2 h14c3975_0 + default: lzo 2.10 h49e0be7_2 + default: markupsafe 1.1.1 py27h7b6447c_0 + default: matplotlib 2.2.3 py27hb69df0a_0 + default: mccabe 0.6.1 py27_1 + default: mistune 0.8.4 py27h7b6447c_0 + default: mkl 2019.3 199 + default: mkl-service 1.1.2 py27he904b0f_5 + default: mkl_fft 1.0.10 py27ha843d7b_0 + default: mkl_random 1.0.2 py27hd81dba3_0 + default: more-itertools 5.0.0 py27_0 + default: mpc 1.1.0 h10f8cd9_1 + default: mpfr 4.0.1 hdf1c602_3 + default: mpmath 1.1.0 py27_0 + default: msgpack-python 0.6.1 py27hfd86e86_1 + default: multipledispatch 0.6.0 py27_0 + default: navigator-updater 0.2.1 py27_0 + default: nbconvert 5.4.1 py27_3 + default: nbformat 4.4.0 py27hed7f2b2_0 + default: ncurses 6.1 he6710b0_1 + default: networkx 2.2 py27_1 + default: nltk 3.4 py27_1 + default: nose 1.3.7 py27_2 + default: notebook 5.7.8 py27_0 + default: numba 0.43.1 py27h962f231_0 + default: numexpr 2.6.9 py27h9e4a6bb_0 + default: numpy 1.16.2 py27h7e9f1db_0 + default: numpy-base 1.16.2 py27hde5b4d6_0 + default: numpydoc 0.8.0 py27_0 + default: olefile 0.46 py27_0 + default: openpyxl 2.6.1 py27_1 + default: openssl 1.1.1b h7b6447c_1 + default: packaging 19.0 py27_0 + default: pandas 0.24.2 py27he6710b0_0 + default: pandoc 2.2.3.2 0 + default: pandocfilters 1.4.2 py27_1 + default: pango 1.42.4 h049681c_0 + default: parso 0.3.4 py27_0 + default: partd 0.3.10 py27_1 + default: patchelf 0.9 he6710b0_3 + default: path.py 11.5.0 py27_0 + default: pathlib2 2.3.3 py27_0 + default: patsy 0.5.1 py27_0 + default: pcre 8.43 he6710b0_0 + default: pep8 1.7.1 py27_0 + default: pexpect 4.6.0 py27_0 + default: pickleshare 0.7.5 py27_0 + default: pillow 5.4.1 py27h34e0f95_0 + default: pip 19.0.3 py27_0 + default: pixman 0.38.0 h7b6447c_0 + default: pkginfo 1.5.0.1 py27_0 + default: pluggy 0.9.0 py27_0 + default: ply 3.11 py27_0 + default: prometheus_client 0.6.0 py27_0 + default: prompt_toolkit 1.0.15 py27h1b593e1_0 + default: psutil 5.6.1 py27h7b6447c_0 + default: ptyprocess 0.6.0 py27_0 + default: py 1.8.0 py27_0 + default: py-lief 0.9.0 py27h7725739_2 + default: pycairo 1.18.0 py27h2a1e443_0 + default: pycodestyle 2.5.0 py27_0 + default: pycosat 0.6.3 py27h14c3975_0 + default: pycparser 2.19 py27_0 + default: pycrypto 2.6.1 py27h14c3975_9 + default: pycurl 7.43.0.2 py27h1ba5d50_0 + default: pyflakes 2.1.1 py27_0 + default: pygments 2.3.1 py27_0 + default: pylint 1.9.2 py27_0 + default: pyodbc 4.0.26 py27he6710b0_0 + default: pyopenssl 19.0.0 py27_0 + default: pyparsing 2.3.1 py27_0 + default: pyqt 5.9.2 py27h05f1152_2 + default: pyrsistent 0.14.11 py27h7b6447c_0 + default: pysocks 1.6.8 py27_0 + default: pytables 3.5.1 py27h71ec239_0 + default: pytest 4.3.1 py27_0 + default: python 2.7.16 h9bab390_0 + default: python-dateutil 2.8.0 py27_0 + default: python-libarchive-c 2.8 py27_6 + default: pytz 2018.9 py27_0 + default: pywavelets 1.0.2 py27hdd07704_0 + default: pyyaml 5.1 py27h7b6447c_0 + default: pyzmq 18.0.0 py27he6710b0_0 + default: qt 5.9.7 h5867ecd_1 + default: qtawesome 0.5.7 py27_1 + default: qtconsole 4.4.3 py27_0 + default: qtpy 1.7.0 py27_1 + default: readline 7.0 h7b6447c_5 + default: requests 2.21.0 py27_0 + default: rope 0.12.0 py27_0 + default: ruamel_yaml 0.15.46 py27h14c3975_0 + default: scandir 1.10.0 py27h7b6447c_0 + default: scikit-image 0.14.2 py27he6710b0_0 + default: scikit-learn 0.20.3 py27hd81dba3_0 + default: scipy 1.2.1 py27h7c811a0_0 + default: seaborn 0.9.0 py27_0 + default: send2trash 1.5.0 py27_0 + default: setuptools 40.8.0 py27_0 + default: simplegeneric 0.8.1 py27_2 + default: singledispatch 3.4.0.3 py27h9bcb476_0 + default: sip 4.19.8 py27hf484d3e_0 + default: six 1.12.0 py27_0 + default: snappy 1.1.7 hbae5bb6_3 + default: snowballstemmer 1.2.1 py27h44e2768_0 + default: sortedcollections 1.1.2 py27_0 + default: sortedcontainers 2.1.0 py27_0 + default: soupsieve 1.8 py27_0 + default: sphinx 1.8.5 py27_0 + default: sphinxcontrib 1.0 py27_1 + default: sphinxcontrib-websupport 1.1.0 py27_1 + default: spyder 3.3.3 py27_0 + default: spyder-kernels 0.4.2 py27_0 + default: sqlalchemy 1.3.1 py27h7b6447c_0 + default: sqlite 3.27.2 h7b6447c_0 + default: ssl_match_hostname 3.7.0.1 py27_0 + default: statsmodels 0.9.0 py27h035aef0_0 + default: subprocess32 3.5.3 py27h7b6447c_0 + default: sympy 1.3 py27_0 + default: tblib 1.3.2 py27h51fe5ba_0 + default: terminado 0.8.1 py27_1 + default: testpath 0.4.2 py27_0 + default: tk 8.6.8 hbc83047_0 + default: toolz 0.9.0 py27_0 + default: tornado 5.1.1 py27h7b6447c_0 + default: tqdm 4.31.1 py27_1 + default: traceback2 1.4.0 py27_0 + default: traitlets 4.3.2 py27hd6ce930_0 + default: typing 3.6.6 py27_0 + default: unicodecsv 0.14.1 py27h5062da9_0 + default: unittest2 1.1.0 py27_0 + default: unixodbc 2.3.7 h14c3975_0 + default: urllib3 1.24.1 py27_0 + default: wcwidth 0.1.7 py27h9e3e1ab_0 + default: webencodings 0.5.1 py27_1 + default: werkzeug 0.14.1 py27_0 + default: wheel 0.33.1 py27_0 + default: widgetsnbextension 3.4.2 + default: py27_0 + default: wrapt 1.11.1 py27h7b6447c_0 + default: wurlitzer 1.0.2 py27_0 + default: xlrd 1.2.0 py27_0 + default: xlsxwriter 1.1.5 py27_0 + default: xlwt 1.3.0 py27h3d85d97_0 + default: xz 5.2.4 h14c3975_4 + default: yaml 0.1.7 had09818_2 + default: zeromq 4.3.1 he6710b0_3 + default: zict 0.1.4 py27_0 + default: zipp 0.3.3 py27_1 + default: zlib 1.2.11 h7b6447c_3 + default: zstd 1.3.7 h0b5b093_0 + default: ---- Changing into /home/vagrant/repos @ Wed Jul 3 03:27:43 UTC 2019 ---- + default: DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. + default: WARNING: The conda.compat module is deprecated and will be removed in a future release. + default: Collecting package metadata: + default: ...working... + default: done + default: Solving environment: + default: ...working... + default: done + default: + default: ## Package Plan ## + default: + default: environment location: /home/vagrant/anaconda + default: + default: added / updated specs: + default: - cudatoolkit + default: - pytorch-cpu + default: - theano + default: + default: + default: The following packages will be downloaded: + default: + default: package | build + default: ---------------------------|----------------- + default: binutils_impl_linux-64-2.31.1| h6176602_1 16.5 MB + default: binutils_linux-64-2.31.1 | h6176602_7 9 KB + default: conda-4.7.5 | py27_0 3.0 MB + default: conda-package-handling-1.3.10| py27_0 259 KB + default: gcc_impl_linux-64-7.3.0 | habb00fd_1 73.2 MB + default: gcc_linux-64-7.3.0 | h553295d_7 10 KB + default: gxx_impl_linux-64-7.3.0 | hdf63c60_1 18.7 MB + default: gxx_linux-64-7.3.0 | h553295d_7 10 KB + default: libgpuarray-0.7.6 | h14c3975_0 264 KB + default: mako-1.0.10 | py_0 61 KB + default: ninja-1.9.0 | py27hfd86e86_0 1.6 MB + default: pygpu-0.7.6 | py27h035aef0_0 685 KB + default: pytorch-cpu-1.1.0 | py2.7_cpu_0 53.5 MB pytorch + default: theano-1.0.3 | py27hfd86e86_0 3.6 MB + default: ------------------------------------------------------------ + default: Total: 171.4 MB + default: + default: The following NEW packages will be INSTALLED: + default: + default: _libgcc_mutex pkgs/main/linux-64::_libgcc_mutex-0.1-main + default: binutils_impl_lin~ pkgs/main/linux-64::binutils_impl_linux-64-2.31.1-h6176602_1 + default: binutils_linux-64 pkgs/main/linux-64::binutils_linux-64-2.31.1-h6176602_7 + default: conda-package-han~ pkgs/main/linux-64::conda-package-handling-1.3.10-py27_0 + default: cudatoolkit pkgs/main/linux-64::cudatoolkit-10.1.168-0 + default: gcc_impl_linux-64 pkgs/main/linux-64::gcc_impl_linux-64-7.3.0-habb00fd_1 + default: gcc_linux-64 pkgs/main/linux-64::gcc_linux-64-7.3.0-h553295d_7 + default: gxx_impl_linux-64 pkgs/main/linux-64::gxx_impl_linux-64-7.3.0-hdf63c60_1 + default: gxx_linux-64 pkgs/main/linux-64::gxx_linux-64-7.3.0-h553295d_7 + default: libgpuarray pkgs/main/linux-64::libgpuarray-0.7.6-h14c3975_0 + default: mako pkgs/main/noarch::mako-1.0.10-py_0 + default: ninja pkgs/main/linux-64::ninja-1.9.0-py27hfd86e86_0 + default: pygpu pkgs/main/linux-64::pygpu-0.7.6-py27h035aef0_0 + default: pytorch-cpu pytorch/linux-64::pytorch-cpu-1.1.0-py2.7_cpu_0 + default: theano pkgs/main/linux-64::theano-1.0.3-py27hfd86e86_0 + default: + default: The following packages will be UPDATED: + default: + default: conda 4.6.11-py27_0 --> 4.7.5-py27_0 + default: + default: + default: Preparing transaction: + default: ...working... + default: done + default: Verifying transaction: + default: ...working... + default: done + default: Executing transaction: + default: ...working... + default: done + default: Note: checking out '2ce2998'. + default: + default: You are in 'detached HEAD' state. You can look around, make experimental + default: changes and commit them, and you can discard any commits you make in this + default: state without impacting any branches by performing another checkout. + default: + default: If you want to create a new branch to retain commits you create, you may + default: do so (now or later) by using -b with the checkout command again. Example: + default: + default: git checkout -b new_branch_name + default: HEAD is now at 2ce2998... Change tabulation to space rttm + default: Note: checking out 'b3e4deb'. + default: + default: You are in 'detached HEAD' state. You can look around, make experimental + default: changes and commit them, and you can discard any commits you make in this + default: state without impacting any branches by performing another checkout. + default: + default: If you want to create a new branch to retain commits you create, you may + default: do so (now or later) by using -b with the checkout command again. Example: + default: + default: git checkout -b new_branch_name + default: HEAD is now at b3e4deb... don't exit early; process every RTTM line + default: DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. + default: Note: checking out '332b8dd'. + default: + default: You are in 'detached HEAD' state. You can look around, make experimental + default: changes and commit them, and you can discard any commits you make in this + default: state without impacting any branches by performing another checkout. + default: + default: If you want to create a new branch to retain commits you create, you may + default: do so (now or later) by using -b with the checkout command again. Example: + default: + default: git checkout -b new_branch_name + default: HEAD is now at 332b8dd... fixed #14 + default: running build + default: running build_py + default: creating build + default: creating build/lib.linux-x86_64-2.7 + default: creating build/lib.linux-x86_64-2.7/phonemizer + default: copying phonemizer/main.py -> build/lib.linux-x86_64-2.7/phonemizer + default: copying phonemizer/espeak.py -> build/lib.linux-x86_64-2.7/phonemizer + default: copying phonemizer/festival.py -> build/lib.linux-x86_64-2.7/phonemizer + default: copying phonemizer/separator.py -> build/lib.linux-x86_64-2.7/phonemizer + default: copying phonemizer/lispy.py -> build/lib.linux-x86_64-2.7/phonemizer + default: copying phonemizer/__init__.py -> build/lib.linux-x86_64-2.7/phonemizer + default: copying phonemizer/phonemize.py -> build/lib.linux-x86_64-2.7/phonemizer + default: creating build/lib.linux-x86_64-2.7/phonemizer/share + default: copying phonemizer/share/phonemize.scm -> build/lib.linux-x86_64-2.7/phonemizer/share + default: running install + default: running bdist_egg + default: running egg_info + default: creating phonemizer.egg-info + default: writing requirements to phonemizer.egg-info/requires.txt + default: writing phonemizer.egg-info/PKG-INFO + default: writing top-level names to phonemizer.egg-info/top_level.txt + default: writing dependency_links to phonemizer.egg-info/dependency_links.txt + default: writing entry points to phonemizer.egg-info/entry_points.txt + default: writing manifest file 'phonemizer.egg-info/SOURCES.txt' + default: reading manifest file 'phonemizer.egg-info/SOURCES.txt' + default: writing manifest file 'phonemizer.egg-info/SOURCES.txt' + default: installing library code to build/bdist.linux-x86_64/egg + default: running install_lib + default: running build_py + default: creating build/bdist.linux-x86_64 + default: creating build/bdist.linux-x86_64/egg + default: creating build/bdist.linux-x86_64/egg/phonemizer + default: copying build/lib.linux-x86_64-2.7/phonemizer/main.py -> build/bdist.linux-x86_64/egg/phonemizer + default: copying build/lib.linux-x86_64-2.7/phonemizer/espeak.py -> build/bdist.linux-x86_64/egg/phonemizer + default: copying build/lib.linux-x86_64-2.7/phonemizer/festival.py -> build/bdist.linux-x86_64/egg/phonemizer + default: copying build/lib.linux-x86_64-2.7/phonemizer/separator.py -> build/bdist.linux-x86_64/egg/phonemizer + default: creating build/bdist.linux-x86_64/egg/phonemizer/share + default: copying build/lib.linux-x86_64-2.7/phonemizer/share/phonemize.scm -> build/bdist.linux-x86_64/egg/phonemizer/share + default: copying build/lib.linux-x86_64-2.7/phonemizer/lispy.py -> build/bdist.linux-x86_64/egg/phonemizer + default: copying build/lib.linux-x86_64-2.7/phonemizer/__init__.py -> build/bdist.linux-x86_64/egg/phonemizer + default: copying build/lib.linux-x86_64-2.7/phonemizer/phonemize.py -> build/bdist.linux-x86_64/egg/phonemizer + default: byte-compiling build/bdist.linux-x86_64/egg/phonemizer/main.py to main.pyc + default: byte-compiling build/bdist.linux-x86_64/egg/phonemizer/espeak.py to espeak.pyc + default: byte-compiling build/bdist.linux-x86_64/egg/phonemizer/festival.py to festival.pyc + default: byte-compiling build/bdist.linux-x86_64/egg/phonemizer/separator.py to separator.pyc + default: byte-compiling build/bdist.linux-x86_64/egg/phonemizer/lispy.py to lispy.pyc + default: byte-compiling build/bdist.linux-x86_64/egg/phonemizer/__init__.py to __init__.pyc + default: byte-compiling build/bdist.linux-x86_64/egg/phonemizer/phonemize.py to phonemize.pyc + default: creating build/bdist.linux-x86_64/egg/EGG-INFO + default: copying phonemizer.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO + default: copying phonemizer.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO + default: copying phonemizer.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO + default: copying phonemizer.egg-info/entry_points.txt -> build/bdist.linux-x86_64/egg/EGG-INFO + default: copying phonemizer.egg-info/requires.txt -> build/bdist.linux-x86_64/egg/EGG-INFO + default: copying phonemizer.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO + default: copying phonemizer.egg-info/zip-safe -> build/bdist.linux-x86_64/egg/EGG-INFO + default: creating dist + default: creating 'dist/phonemizer-0.3.2-py2.7.egg' and adding 'build/bdist.linux-x86_64/egg' to it + default: removing 'build/bdist.linux-x86_64/egg' (and everything under it) + default: Processing phonemizer-0.3.2-py2.7.egg + default: Copying phonemizer-0.3.2-py2.7.egg to /usr/local/lib/python2.7/dist-packages + default: Adding phonemizer 0.3.2 to easy-install.pth file + default: Installing phonemize script to /usr/local/bin + default: + default: Installed /usr/local/lib/python2.7/dist-packages/phonemizer-0.3.2-py2.7.egg + default: Processing dependencies for phonemizer==0.3.2 + default: Searching for joblib + default: Reading https://pypi.python.org/simple/joblib/ + default: Best match: joblib 0.13.2 + default: Downloading https://files.pythonhosted.org/packages/2c/7f/c1da4e341d81840c2fa46d583cbc92bb02e5274fe601e9cbc72bcb78b2d7/joblib-0.13.2.tar.gz#sha256=315d6b19643ec4afd4c41c671f9f2d65ea9d787da093487a81ead7b0bac94524 + default: Processing joblib-0.13.2.tar.gz + default: Writing /tmp/easy_install-TTrxOO/joblib-0.13.2/setup.cfg + default: Running joblib-0.13.2/setup.py -q bdist_egg --dist-dir /tmp/easy_install-TTrxOO/joblib-0.13.2/egg-dist-tmp-LNl2JK + default: warning: no files found matching '*.rst' under directory 'joblib' + default: warning: no previously-included files matching '*~' found anywhere in distribution + default: warning: no previously-included files matching '*.swp' found anywhere in distribution + default: zip_safe flag not set; analyzing archive contents... + default: joblib.format_stack: module references __file__ + default: joblib.format_stack: module MAY be using inspect.getinnerframes + default: joblib.format_stack: module MAY be using inspect.getouterframes + default: joblib.func_inspect: module MAY be using inspect.getsourcefile + default: joblib.test.test_func_inspect: module references __file__ + default: joblib.test.test_numpy_pickle: module references __file__ + default: joblib.test.test_parallel: module references __file__ + default: joblib.externals.cloudpickle.cloudpickle: module references __file__ + default: joblib.externals.loky.backend.spawn: module references __file__ + default: Adding joblib 0.13.2 to easy-install.pth file + default: + default: Installed /usr/local/lib/python2.7/dist-packages/joblib-0.13.2-py2.7.egg + default: Finished processing dependencies for phonemizer==0.3.2 + default: DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. + default: Collecting pympi-ling + default: Using cached https://files.pythonhosted.org/packages/92/c7/90b4821910509e9c888d93386e6fe00efaf7dd5ae37fc607391d6838df40/pympi-ling-1.69.tar.gz + default: Collecting tgt + default: Using cached https://files.pythonhosted.org/packages/51/9a/25d82ed43c926e0234c8705e374323d7f9bfe0b311019fe3b1e2e445fbb6/tgt-1.4.4.tar.gz + default: Collecting intervaltree + default: Using cached https://files.pythonhosted.org/packages/e8/f9/76237755b2020cd74549e98667210b2dd54d3fb17c6f4a62631e61d31225/intervaltree-3.0.2.tar.gz + default: Collecting recommonmark + default: Downloading https://files.pythonhosted.org/packages/9b/3d/92ea48401622510e57b4bdaa74dc9db2fb9e9e892324b48f9c02d716a93a/recommonmark-0.5.0-py2.py3-none-any.whl + default: Collecting sphinx-markdown-tables + default: Downloading https://files.pythonhosted.org/packages/3d/d0/4f6e12f06f87bcae7a97997fc50862222ee78f859edece0da0ad75d8ada4/sphinx-markdown-tables-0.0.9.tar.gz + default: Collecting sphinx_rtd_theme + default: Downloading https://files.pythonhosted.org/packages/60/b4/4df37087a1d36755e3a3bfd2a30263f358d2dea21938240fa02313d45f51/sphinx_rtd_theme-0.4.3-py2.py3-none-any.whl (6.4MB) + default: Requirement already satisfied: sortedcontainers<3.0,>=2.0 in /home/vagrant/anaconda/lib/python2.7/site-packages (from intervaltree) (2.1.0) + default: Requirement already satisfied: docutils>=0.11 in /home/vagrant/anaconda/lib/python2.7/site-packages (from recommonmark) (0.14) + default: Requirement already satisfied: sphinx>=1.3.1 in /home/vagrant/anaconda/lib/python2.7/site-packages (from recommonmark) (1.8.5) + default: Collecting commonmark>=0.7.3 (from recommonmark) + default: Downloading https://files.pythonhosted.org/packages/a7/65/2ea45a38e8c6a0a13453c5cadcc9b725049425c8628dbe7da87b30944573/commonmark-0.9.0-py2.py3-none-any.whl (51kB) + default: Collecting markdown==2.6.11 (from sphinx-markdown-tables) + default: Downloading https://files.pythonhosted.org/packages/6d/7d/488b90f470b96531a3f5788cf12a93332f543dbab13c423a5e7ce96a0493/Markdown-2.6.11-py2.py3-none-any.whl (78kB) + default: Requirement already satisfied: six>=1.5 in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (1.12.0) + default: Requirement already satisfied: Jinja2>=2.3 in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (2.10) + default: Requirement already satisfied: Pygments>=2.0 in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (2.3.1) + default: Requirement already satisfied: snowballstemmer>=1.1 in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (1.2.1) + default: Requirement already satisfied: babel!=2.0,>=1.3 in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (2.6.0) + default: Requirement already satisfied: alabaster<0.8,>=0.7 in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (0.7.12) + default: Requirement already satisfied: imagesize in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (1.1.0) + default: Requirement already satisfied: requests>=2.0.0 in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (2.21.0) + default: Requirement already satisfied: setuptools in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (40.8.0) + default: Requirement already satisfied: packaging in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (19.0) + default: Requirement already satisfied: sphinxcontrib-websupport in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (1.1.0) + default: Requirement already satisfied: typing in /home/vagrant/anaconda/lib/python2.7/site-packages (from sphinx>=1.3.1->recommonmark) (3.6.6) + default: Requirement already satisfied: future in /home/vagrant/anaconda/lib/python2.7/site-packages (from commonmark>=0.7.3->recommonmark) (0.17.1) + default: Requirement already satisfied: MarkupSafe>=0.23 in /home/vagrant/anaconda/lib/python2.7/site-packages (from Jinja2>=2.3->sphinx>=1.3.1->recommonmark) (1.1.1) + default: Requirement already satisfied: pytz>=0a in /home/vagrant/anaconda/lib/python2.7/site-packages (from babel!=2.0,>=1.3->sphinx>=1.3.1->recommonmark) (2018.9) + default: Requirement already satisfied: urllib3<1.25,>=1.21.1 in /home/vagrant/anaconda/lib/python2.7/site-packages (from requests>=2.0.0->sphinx>=1.3.1->recommonmark) (1.24.1) + default: Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /home/vagrant/anaconda/lib/python2.7/site-packages (from requests>=2.0.0->sphinx>=1.3.1->recommonmark) (3.0.4) + default: Requirement already satisfied: idna<2.9,>=2.5 in /home/vagrant/anaconda/lib/python2.7/site-packages (from requests>=2.0.0->sphinx>=1.3.1->recommonmark) (2.8) + default: Requirement already satisfied: certifi>=2017.4.17 in /home/vagrant/anaconda/lib/python2.7/site-packages (from requests>=2.0.0->sphinx>=1.3.1->recommonmark) (2019.3.9) + default: Requirement already satisfied: pyparsing>=2.0.2 in /home/vagrant/anaconda/lib/python2.7/site-packages (from packaging->sphinx>=1.3.1->recommonmark) (2.3.1) + default: Building wheels for collected packages: pympi-ling, tgt, intervaltree, sphinx-markdown-tables + default: Building wheel for pympi-ling (setup.py): started + default: Building wheel for pympi-ling (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/34/c2/ab/1107ef0b833e770faf53b41179884b4bfa6f5bd641dc74e8f4 + default: Building wheel for tgt (setup.py): started + default: Building wheel for tgt (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/d0/01/c2/7b18446d6ce6b1ced14c50044844180f89a51b960d0799802d + default: Building wheel for intervaltree (setup.py): started + default: Building wheel for intervaltree (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/08/99/c0/5a5942f5b9567c59c14aac76f95a70bf11dccc71240b91ebf5 + default: Building wheel for sphinx-markdown-tables (setup.py): started + default: Building wheel for sphinx-markdown-tables (setup.py): finished with status 'done' + default: Stored in directory: /home/vagrant/.cache/pip/wheels/df/ae/13/2e436636f69f99f623599b532c2c11bdd4331c5030e246700f + default: Successfully built pympi-ling tgt intervaltree sphinx-markdown-tables + default: Installing collected packages: pympi-ling, tgt, intervaltree, commonmark, recommonmark, markdown, sphinx-markdown-tables, sphinx-rtd-theme + default: Found existing installation: Markdown 3.1.1 + default: Uninstalling Markdown-3.1.1: + default: Successfully uninstalled Markdown-3.1.1 + default: Successfully installed commonmark-0.9.0 intervaltree-3.0.2 markdown-2.6.11 pympi-ling-1.69 recommonmark-0.5.0 sphinx-markdown-tables-0.0.9 sphinx-rtd-theme-0.4.3 tgt-1.4.4 + default: ---- git logs follow ---- + default: -- git log /vagrant -- + default: commit 5606fa1ceae6563a25f784a9a15b1eed41a21b50 + default: Author: Florian Metze + default: Date: Wed Jun 19 07:16:09 2019 -0400 + default: + default: installation partially downloads in background + default: -- git log ib_diarization_toolkit -- + default: commit b3e4deb2465b36270cec0c934bd3f7be2f88e3fa + default: Author: riebling + default: Date: Thu Aug 16 11:28:15 2018 -0400 + default: + default: don't exit early; process every RTTM line + default: + default: assume we process every line in RTTM, don't look for standard symbols in certain columns + default: -- git log OpenSAT -- + default: commit e47575acecdde5651e585b167722c3b98f510d27 + default: Author: jaden-w + default: Date: Tue Nov 27 12:45:05 2018 -0500 + default: + default: Modify RNN.py for python3 (and encoding issues) + default: -- git log phonemizer -- + default: commit 332b8dd8bb399e16fce025c4eaa95d9e21da45bf + default: Author: Mathieu Bernard + default: Date: Mon Oct 22 13:08:12 2018 +0200 + default: + default: fixed #14 + default: -- git log To-Combo-SAD -- + default: commit 2ce29984ef621439fd7b58a337e59df88139307c + default: Author: Marvin Lavechin + default: Date: Tue Oct 23 14:21:37 2018 +0200 + default: + default: Change tabulation to space rttm + default: -- git log vcm -- + default: commit 8d00df0db4014c3c275a504bd85d376fe7185fab + default: Author: Florian Metze + default: Date: Wed Jul 3 03:15:38 2019 +0000 + default: + default: added yunitator mode + default: -- git log WCE_VM -- + default: commit ccef86bc3d23c24ace8a8c10d77de07fe274b65c + default: Author: orasanen + default: Date: Thu Jan 17 10:27:35 2019 +0200 + default: + default: added WCE out-of-the-box model + default: -- git log Yunitator -- + default: commit 5f062e444351ca29c10bcb449b9afc8a1a34900b + default: Author: Florian Metze + default: Date: Fri Jun 21 20:11:31 2019 +0000 + default: + default: better to specify the shell for extract-htk-vm2.sh + default: ---- git logs done ---- + default: ---- Building the docs... ---- + default: Running Sphinx v1.8.5 + default: loading pickled environment... + default: done + default: building [mo]: targets for 0 po files that are out of date + default: building [html]: targets for 12 source files that are out of date + default: updating environment: + default: 0 added, 0 changed, 0 removed + default: looking for now-outdated files... + default: none found + default: preparing documents... + default: done + default: writing output... [ 8%] WCEtool + default: writing output... [ 16%] extra-tools + default: writing output... [ 25%] formats + default: writing output... [ 33%] further-info + default: writing output... [ 41%] index + default: writing output... [ 50%] initial_questions + default: writing output... [ 58%] install + default: writing output... [ 66%] instructions_for_contributors + default: writing output... [ 75%] references + default: writing output... [ 83%] tool_doc + default: writing output... [ 91%] troubleshoot + default: writing output... [100%] usage + default: /vagrant/docs/source/formats.md:9: WARNING: None:any reference target not found: praat.org + default: /vagrant/docs/source/formats.md:9: WARNING: None:any reference target not found: www.lena.org + default: /vagrant/docs/source/install.md:42: WARNING: None:any reference target not found: homebank.talkbank.org + default: generating indices... + default: genindex + default: writing additional pages... + default: search + default: copying images... [100%] ../images/example_visu.png + default: copying static files... + default: WARNING: html_static_path entry u'/vagrant/docs/source/_static' does not exist + default: done + default: copying extra files... + default: done + default: dumping search index in English (code: en) ... + default: done + default: dumping object inventory... + default: done + default: build succeeded, 4 warnings. + default: The HTML pages are in build/html. + default: INFO: You can remove Anaconda2-2019.03-Linux-x86_64.sh, if you don't plan on re-provisioning DiViMe any time soon. + default: INFO: You can remove MCR_R2017b_glnxa64_installer.zip, if you don't plan on re-provisioning DiViMe any time soon. + default: ---- Done bootstrapping DiViMe @ Wed Jul 3 03:30:01 UTC 2019 ---- + default: root@vagrant-ubuntu-trusty-64:/home/vagrant# + default: e + default: x + default: i + default: t + default: exit +FloriansMBP2019:DiViMe metze$ diff --git a/launcher/diartk.sh b/launcher/diartk.sh index 165b7fe..dbd798b 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -106,8 +106,14 @@ for fin in `ls ${audio_dir}/*.wav`; do # don't process files with empty transcription if [ -s $scpfile ]; then # first generate HTK features - HCopy -T 2 -C htkconfig $fin $featfile - + #HCopy -T 2 -C htkconfig $fin $featfile + >&2 echo WARNING for $featfile: replacing HCopy htconfig with SMILExtract MFCC12_E_D_A is untested + LD_LIBRARY_PATH=/usr/local/lib \ + SMILExtract \ + -C ~/repos/opensmile-2.3.0/config/MFCC12_E_D_A.conf \ + -I $fin -O $featfile \ + -logfile $workdir/opensmile-diartk.log + # next run DiarTK scripts/run.diarizeme.sh $featfile $scpfile $workdir $basename diff --git a/launcher/eval.sh b/launcher/eval.sh index 75d9d71..351aa19 100755 --- a/launcher/eval.sh +++ b/launcher/eval.sh @@ -82,10 +82,10 @@ LAUNCHER=$BASEDIR/launcher source activate divime case $MODEL in "tocomboSad"|"opensmileSad"|"noisemesSad") - python $UTILS/compute_metrics.py --reference $DATA --prefix $MODEL --task detection --metrics ${METRICS[*]} ${FLAGS[*]} + python $UTILS/compute_metrics.py --reference $DATA/.. --hypothesis $DATA --prefix $MODEL --task detection --metrics ${METRICS[*]} ${FLAGS[*]} ;; "yunitator_old"|"yunitator_english"|"yunitator_universal"|"lena"|"diartk_noisemesSad"|"diartk_tocomboSad"|"diartk_opensmileSad"|"diartk_goldSad") - python $UTILS/compute_metrics.py --reference $DATA --prefix $MODEL --task diarization --metrics ${METRICS[*]} ${FLAGS[*]} + python $UTILS/compute_metrics.py --reference $DATA/.. --hypothesis $DATA --prefix $MODEL --task diarization --metrics ${METRICS[*]} ${FLAGS[*]} ;; *) display_usage diff --git a/launcher/test.sh b/launcher/test.sh index a1bf9ed..672eebb 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -76,8 +76,9 @@ echo "Checking for HTK..." if [ -s /usr/local/bin/HCopy ]; then echo "HTK is installed." else - echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml ?" - echo " If so, then you may need to re-install it. Run: vagrant ssh -c \"utils/install_htk.sh\" " + #echo " HTK missing; did you first download HTK-3.4.1 from http://htk.eng.cam.ac.uk/download.shtml ?" + #echo " If so, then you may need to re-install it. Run: vagrant ssh -c \"utils/install_htk.sh\" " + echo " HTK missing. You can probably ignore this warning, HTK is no longer needed." fi rm -rf $TESTDIR; mkdir -p $TESTDIR @@ -148,9 +149,8 @@ rm $TESTDIR/$BASETEST.rttm echo "Testing Yunitator..." # let 'er rip -$LAUNCHERS/yunitate.sh $DATADIR/test $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -echo "TEST DIR" -echo $TESTDIR/yunitator-test.log +yun="universal" +$LAUNCHERS/yunitate.sh $DATADIR/test $yun $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/yunitator_old_$BASETEST.rttm ]; then echo "Yunitator passed the test." else @@ -161,9 +161,10 @@ fi # Test the evaluation echo "Testing the evaluation pipeline..." source activate divime -rm $TESTDIR/accuracy_noisemesSad_report.csv +rm -f $TESTDIR/accuracy_noisemesSad_report.csv $LAUNCHERS/eval.sh $TESTDIR noisemesSad accuracy > $TESTDIR/eval-test.log || { echo " The evaluation pipeline failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/accuracy_noisemesSad_report.csv ]; then +# $TESTDIR/.. assumes that eval.sh puts the reference one directory up from the hypotheses +if [ -s $TESTDIR/../accuracy_noisemesSad_report.csv ]; then echo "The evaluation pipeline passed the test." else echo " The evaluation pipeline failed the test - output does not match expected" @@ -174,7 +175,7 @@ conda deactivate # Testing VCM echo "Testing VCM..." -$LAUNCHERS/vcm.sh $DATADIR/test $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} +$LAUNCHERS/vcm.sh $DATADIR/test $yun $KEEPTEMP > $TESTDIR/vcm-test.log 2>&1 || { echo " VCM failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/vcm_$BASETEST.rttm ]; then echo "VCM passed the test." else @@ -228,4 +229,4 @@ echo " detection accuracy true positive true negative false echo " % " echo "item " echo "BN32_010007_test.rttm 11.24 30.80 3.11 0.20 267.57" -echo "TOTAL 11.24 30.80 3.11 0.20 267.57" \ No newline at end of file +echo "TOTAL 11.24 30.80 3.11 0.20 267.57" diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index 51afb0a..2a91f49 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -70,16 +70,17 @@ export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64 ./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt #convert to rttms -for f in ${audio_dir}/*.ToCombo.txt; do +for f in `ls ${audio_dir}/*.ToCombo.txt ${workdir}/*.ToCombo.txt`; do + echo converting to rttm $f bn=`basename $f .wav.ToCombo.txt` python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > ${workdir}/tocomboSad_$bn.rttm done # same in the temp folder which has the .wav that were not monochannel -for f in ${workdir}/*.ToCombo.txt; do - bn=`basename $f .wav.ToCombo.txt` - python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > ${workdir}/tocomboSad_$bn.rttm -done +#for f in ${workdir}/*.ToCombo.txt; do +# bn=`basename $f .wav.ToCombo.txt` +# python $TOCOMBOSADDIR/tocombo2rttm.py $f $bn > ${workdir}/tocomboSad_$bn.rttm +#done # get the rttm mv ${workdir}/*.rttm ${audio_dir} diff --git a/launcher/vcm.sh b/launcher/vcm.sh index 18c22db..ede5435 100755 --- a/launcher/vcm.sh +++ b/launcher/vcm.sh @@ -11,14 +11,19 @@ BASEDIR=`dirname $SCRIPT` VCMDIR=/home/vagrant/repos/vcm UTIL=/home/vagrant/utils -if [ $# -ne 1 ]; then - echo "Usage: $0 " +if [ $# -gt 2 ]; then + echo "Usage: $0 [yun_mode]" echo "where dirname is the name of the folder" echo "containing the wav files" exit 1 fi audio_dir=/vagrant/$1 +if [ $# -gt 1 ]; then + yun=$2 +else + yun="universal" +fi filename=$(basename "${audio_dir}") dirname=$(dirname "${audio_dir}") extension="${filename##*.}" @@ -40,7 +45,7 @@ cd $VCMDIR echo "Starting" for f in `ls ${audio_dir}/*.wav`; do echo $f - ./runVCM.sh $f + ./runVCM.sh $f $yun done echo "$0 finished running" From 8a11d2634791f527123ca40bcc48b22156d8ee89 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 3 Jul 2019 00:02:36 -0400 Subject: [PATCH 265/299] Update initial_questions.md --- docs/source/initial_questions.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/source/initial_questions.md b/docs/source/initial_questions.md index 544e226..f3e98fd 100755 --- a/docs/source/initial_questions.md +++ b/docs/source/initial_questions.md @@ -34,4 +34,7 @@ Adrien Le Franc, Eric Riebling, Julien Karadayi, Yun Wang, Camila Scaff, Florian [The ACLEW DiViMe: An easy-to-use diarization tool](https://www.isca-speech.org/archive/Interspeech_2018/pdfs/2324.pdf). In Proc. INTERSPEECH, Hyderabad; India, September 2018. The idea of using virtual machines to package speech tools comes from this work: -Florian Metze, Eric Fosler-Lussier, and Rebecca Bates. The speech recognition virtual kitchen. In Proc. INTERSPEECH, Lyon; France, August 2013. [https://github.org/srvk](https://github.org/srvk). \ No newline at end of file + +Florian Metze, Eric Fosler-Lussier, and Rebecca Bates. The speech recognition virtual kitchen. In Proc. INTERSPEECH, Lyon; France, August 2013. [https://github.org/srvk](https://github.org/srvk). + +Depending on the particular tool that you are using, you should potentially cite additional papers that describe the underlying software or methods - please check. From bdb217dc0c00ccc229c6ab06060da4ba32cee43e Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 3 Jul 2019 00:31:24 -0400 Subject: [PATCH 266/299] Update install.md --- docs/source/install.md | 113 +++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 60 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index a1722dc..1544670 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -2,25 +2,25 @@ ## Requirements -DiViMe can be installed in any operating system and computer with at least 1 CPU (and occupying 2GB when active). You may need to make some adaptations for known issues. Specifically, *before following the instructions under "First Installation"*, you must follow the instructions in the relevant subsection of the Troubleshooting section, at the end of this page, in the following cases: +DiViMe can be installed in any operating system and computer with at least 2 CPUs, 8GB of RAM, and 25GB of available disc space. You may need more of everything to actually use the tools, specifically when running on large files. *Before following the instructions under "First Installation"*, you must follow the instructions in the relevant subsection of the Troubleshooting section, at the end of this page, in the following cases: -- your computer has only one core -- your computer has 20 GB or less of storage space +- your computer has only one core (or you don't know) +- your computer has 25 GB or less of disc space - your computer has 6 GB or less of RAM -- your computer is running ubuntu (e.g., 16.04) +- your computer is running Ubuntu (e.g., 16.04) ## First Installation -1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link and follow the prompted instructions +1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link for your operating system and follow the prompted instructions 2. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. -3. Clone the present repository: To do this, you must use a terminal. If you don't know what this means, we recommend that you first follow the [Software Carpentry Shell Tutorial](https://swcarpentry.github.io/shell-novice/) (up to 00:45, namely "Introducing the shell", and "Navigating files and directories"). Next, navigate to the directory in which you want the VM to be hosted and type in: `$ git clone https://github.com/srvk/DiViMe` +3. Clone the present repository: To do this, you must use a terminal. If you don't know what this means, we recommend that you first follow the [Software Carpentry Shell Tutorial](https://swcarpentry.github.io/shell-novice/) (up to 00:45, namely "Introducing the shell", and "Navigating files and directories"). Next, navigate to the directory in which you want the VM to be hosted and type in: `$ git clone https://github.com/srvk/DiViMe` - or use another way or tool to "clone" a [Git](https://git-scm.com) repository 4. Change into this folder: `$ cd DiViMe` -5. Install HTK. HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. +5. *OBSOLETE as of 2019 (no need to do this any more):* Install HTK. HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. - Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) - Register by following the instructions on the left (under "Getting HTK": Register) @@ -30,13 +30,24 @@ DiViMe can be installed in any operating system and computer with at least 1 CPU 6. Type `$ vagrant up` -The first time you do this, it will take at least 20 minutes to install all the packages that are needed to build the virtual machine. -Once the virtual machine will be installed, it will stay stuck at "installation finished" for few minutes. However, the tools are not yet installed at this step. -You will need to wait for the tools to be installed, and to take back the control of the terminal to run the tools. +The first time you do this, it will take at least 15 minutes to install all the packages that are needed to build the virtual machine. You are done when you see something like this: -The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/srvk/DiViMe/issues), describing your situation. +``` +FloriansMBP2019:DiViMe metze$ tail -n 8 example-logs/vagrant-up.log + default: build succeeded, 4 warnings. + default: The HTML pages are in build/html. + default: INFO: You can remove Anaconda2-2019.03-Linux-x86_64.sh, if you don't plan on re-provisioning DiViMe any time soon. + default: INFO: You can remove MCR_R2017b_glnxa64_installer.zip, if you don't plan on re-provisioning DiViMe any time soon. + default: ---- Done bootstrapping DiViMe @ Wed Jul 3 03:30:01 UTC 2019 ---- + default: root@vagrant-ubuntu-trusty-64:/home/vagrant# + default: exit +``` + +The instructions above make the simplest assumptions as to your environment. If you have Amazon Web Services, an Ubuntu system, or you do not have admin rights in your computer, you might need to read the [instructions to the eesen-transcriber](https://github.com/srvk/eesen-transcriber/blob/master/INSTALL.md) for fancier options. Or you can just open an issue [here](https://github.com/srvk/DiViMe/issues), describing your situation. -We are working on [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker), but this option is not yet functional. +We are working on [Installing With Docker](https://github.com/srvk/DiViMe/wiki/InstallingWithDocker), but this option is not yet fully functional. + +Please note that there is a large amount of documentation on Vagrant and Virtualbox online, explaining on how to fix assorted errors. It is often a good idea to simply "google" errors that these tools throw; you may find a solution to your specific problem quickly, because the problem may not lie with DiViMe, but the VM, before DiViMe gets involved. ## Checking your installation @@ -44,42 +55,29 @@ The very first time you use DiViMe, it is a good idea to run a quick start test, 1. Open a terminal 2. Navigate inside the DiViMe folder -3. Do `$ vagrant up` +3. Do `$ vagrant up` (if you haven't done it already) 4. Do `$ vagrant ssh -c "launcher/test.sh"` -This should produce the output: +This should produce the following output: ``` - -Testing Speech Activity Detection Using Noisemes... +FloriansMBP2019:DiViMe metze$ vagrant ssh -c "launcher/test.sh" +Starting tests +Checking for HTK... + HTK missing. You can probably ignore this warning, HTK is no longer needed. +Testing noisemes... Noisemes passed the test. - Testing OpenSmile SAD... OpenSmile SAD passed the test. - -Testing Threshold Optimized Combo SAD... -Threshold Optimized Combo SAD passed the test. - -Testing DiarTK... -DiarTK passed the test. - -Testing Yunitator... -Yunitator passed the test. - -Testing the evaluation pipeline... -The evaluation pipeline passed the test. - - +[...] Congratulations, everything is OK! - +[...] ``` - ## Updating DiViMe If you want to install a new release of DiViMe, you will need to perform the following 3 steps from within the DiViME folder on your terminal: - ``` $ vagrant destroy $ git pull @@ -88,55 +86,50 @@ $ vagrant up ## Uninstallation -If you want to get rid of the files completely, you should perform the following 3 steps from within the DiViME folder on your terminal: +If you want to get rid of the files completely, you should perform the following 3 steps from within the DiViME folder on your terminal (assuming you are on Unix): ``` $ vagrant destroy $ cd .. -$ rm -r -f divime +$ rm -rf DiViMe ``` ## Troubleshooting ### If your computer only has one core -Before doing `vagrant up`, open the file called Vagrantfile in a text editor. Change the following line: - +Before doing `vagrant up`, open the file called `DiViMe/Vagrantfile` in a text editor. Change the following line: +``` > vbox.cpus = 2 - +``` into: - +``` > vbox.cpus = 1 +``` +Then proceed with the installation. Also, if you have more than one CPU, and you do not want DiViMe to take over your entire computer, you can set it to any value >= 2, and you should be fine. DiViMe uses multiple processors, but we have not yet fully optimized for many cores. -Then proceed with the Installation. - -### If your computer has 20 GB or less of storage space +### If your computer has 25 GB or less of storage space -If your computer has less than 20 GB of storage space, then *you cannot build a fully working DiViMe* (without crippling your computer). In this case, clean up your files to free up space. +If your computer has less than 25 GB of storage space, then *you cannot build a fully working DiViMe*. In this case, clean up your files to free up space. ### If your computer has 6 GB or less of RAM -If your computer has less than 4 GB of RAM, then *you cannot build a fully working DiViMe* (without crippling your computer). - -For computers with 4-6 GB of RAM, you need to change the space allocated to the virtual machine. Before doing `vagrant up`, open the file called Vagrantfile in a text editor. Change the following line: - -> vbox.memory = 3072 - +If your computer has less than about 8 GB of RAM, then you may or may not be able to build and use DiViMe. You probably need to change the space allocated to the virtual machine. Before doing `vagrant up`, open the file called `DiViMe/Vagrantfile` in a text editor. Change the following line: +``` +> vbox.memory = 4096 +``` into: - +``` > vbox.memory = 2048 +``` +Then proceed with the Installation. Also, if you have more RAM, and you experience issues during installation (or use), you may benefit from increasing this value, which should normally not exceed half of your total installed RAM (as a rule of thumb). -Then proceed with the Installation. +### If your computer is running Ubuntu (16.04) -### If your computer is running ubuntu (16.04) +There is a known incompatibility between VirtualBox and the 4.13 Linux kernel on Ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installationSimple), or install the latest version of VirtualBox, which should fix the problem. -There is a known incompatibility between VirtualBox and the 4.13 Linux kernel on ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installationSimple), or install the latest version of virtualbox, which should fix the problem. +Again, there is often a lot of information available online, because Vagrant and VirtualBox are widely used tools. ### If something else fails -Please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output there, so we can better provide you with a solution. - - -## References - -VanDam, M., De Palma, P., Strong, W. E. (2015, May). Fundamental frequency of speech directed to children who have hearing loss. Poster presented at the 169th Meeting of the Acoustical Society of America, Pittsburgh, PA. +Please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output of the failing run there, so we can better provide you with a solution. Also, please provide detailed information on your host system (which OS, RAM, CPU, HDD), which changes you made to the Vagrantfile, and also provide access to the data the system chokes on (if any). From e309a5eb37bd8ff20c0c4551eb4a1c3fb7702b1f Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 3 Jul 2019 00:41:35 -0400 Subject: [PATCH 267/299] Update install.md --- docs/source/install.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 1544670..fc36bad 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -14,19 +14,15 @@ DiViMe can be installed in any operating system and computer with at least 2 CPU 1. Install [Vagrant](https://www.vagrantup.com/): Click on the download link for your operating system and follow the prompted instructions -2. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one. +2. Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads): When we last checked, the links for download for all operating systems were under the header "VirtualBox 5.2.18 platform packages", so look for a title like that one (picking the latest version, most likely). 3. Clone the present repository: To do this, you must use a terminal. If you don't know what this means, we recommend that you first follow the [Software Carpentry Shell Tutorial](https://swcarpentry.github.io/shell-novice/) (up to 00:45, namely "Introducing the shell", and "Navigating files and directories"). Next, navigate to the directory in which you want the VM to be hosted and type in: `$ git clone https://github.com/srvk/DiViMe` - or use another way or tool to "clone" a [Git](https://git-scm.com) repository 4. Change into this folder: `$ cd DiViMe` -5. *OBSOLETE as of 2019 (no need to do this any more):* Install HTK. HTK is used by some of these tools (until we find and implement an open-source replacement). We are not allowed to distribute HTK, so unfortunately you have to get it yourself. +5. Install several Vagrant plugins: `$ vagrant plugin install vagrant-aws vagrant-sshfs vagrant-vbguest` - - Go to the [HTK download page](http://htk.eng.cam.ac.uk/download.shtml) - - Register by following the instructions on the left (under "Getting HTK": Register) - - Check that you have received your password via email; you will need it for the next step. - - Find the link that reads "HTK source code" under Linux/Unix downloads (since the latter will be installed within the VM which runs under Unix). Notice that you will need your username and password (from the previous step). You must download the version 3.4.1. - - Move the HTK-3.4.1.tar.gz file into the root folder of this repository (alongside Vagrantfile). +Depending on how you want to use DiViMe, and which provider you will be using, you may or may not need to install the above plugins (or you may need to install additional plugins), but this quickly turns into an advanced topic, because not all plugins will work equally well on all host platforms ... 6. Type `$ vagrant up` @@ -74,6 +70,10 @@ Congratulations, everything is OK! [...] ``` +## When you are done with DiViMe, Teardown + +After working with DiViMe, you can shut down the virtual machine, which will free up CPU and RAM resources on your computer (but not disc space). To do this, type `$ vagrant halt` or `$ vagrant suspend`. To continue working with the VM at a later point, simply issue another `$ vagrant up` command. + ## Updating DiViMe If you want to install a new release of DiViMe, you will need to perform the following 3 steps from within the DiViME folder on your terminal: @@ -133,3 +133,7 @@ Again, there is often a lot of information available online, because Vagrant and ### If something else fails Please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output of the failing run there, so we can better provide you with a solution. Also, please provide detailed information on your host system (which OS, RAM, CPU, HDD), which changes you made to the Vagrantfile, and also provide access to the data the system chokes on (if any). + +### References + +VanDam, M., De Palma, P., Strong, W. E. (2015, May). Fundamental frequency of speech directed to children who have hearing loss. Poster presented at the 169th Meeting of the Acoustical Society of America, Pittsburgh, PA. From f29734be4a5199814fe8a330baebdb30a1a70e2d Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 3 Jul 2019 01:09:26 -0400 Subject: [PATCH 268/299] Update usage.md --- docs/source/usage.md | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index 3c6760f..e8a411e 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -2,13 +2,12 @@ ## Overview -This is an overview of the full tool presentation found in the next stage, recapping the main steps: +This is an overview of the full tool presentation found in the next sextion, recapping the main steps: 1. Put your data in the ```data``` shared directory. 2. Do `$ vagrant up` to "wake the machine up" - -Next we provide instructions for all tools. More detailed information about each tool can be found in separate readme's. +Next we provide instructions for all tools. More detailed information about each tool can be found in separate ReadMe files. Assuming the installation of the virtual machine is complete and some of the tests have passed, you can now use at least some of the tools in the virtual machine. We explain more about each step below, but in a nutshell, the steps to use DiViMe are always the same: @@ -21,13 +20,13 @@ Assuming the installation of the virtual machine is complete and some of the tes ## Further information on Step 1, putting your data into the ```data/``` directory -Put the sound files that you want analyzed (and annotations, if you have any) inside the shared ```data``` folder. It is probably safer to make a copy of your files (rather than moving them), in case you later decide to delete the whole folder. +Put the sound files that you want analyzed (and annotations, if you have any) inside the shared ```data``` folder. It is probably safer to make a copy of your files (rather than moving them), in case you later decide to delete the whole folder. Also, for greater security, DiViMe (as a VM) can only see data within the ```DiViMe``` folder, so soft links to files outside of that fodler will not work. You can drop a whole folder into ```data```. You will provide the path to the specific folder to be analyzed when running the tools (as per instructions below). All `.wav` files in that folder will be analyzed. If your files aren't .wav some of the tools may not work. Please consider converting them into wav with some other program, such as [ffmpeg](https://www.ffmpeg.org/). It is probably safer to make a copy (rather than moving your files into the data folder), in case you later decide to delete the whole folder. -If you have any annotations, put them also in the same "data" folder. Annotations must be in .rttm format, and *they should be named exactly as your wav files*. If you have annotations in .cha, .eaf, .textgrid, or .its, see the Format section for instructions on converting them into .rttm. +If you have any annotations, put them also in the same ```data``` folder. Annotations must be in .rttm format, and *they should be named exactly as your wav files*. If you have annotations in .cha, .eaf, .textgrid, or .its, see the Format section for instructions on converting them into .rttm. IMPORTANT: If you already analyzed a file with a given tool, re-running the tool will result in the previous analysis being overwritten. @@ -37,7 +36,6 @@ To interact with the virtual machine, you must use a terminal. If you don't know Next, navigate in the terminal window to the DiViMe directory that was created when you did `git clone https://github.com/srvk/DiViMe` when installing DiViMe. - ## Further information on Step 3, Waking the machine up Remember that you will be using a mini-computer within your computer. Typically, the machine will be down - i.e., it will not be running. This is good, because when it is running, it will use memory and other resources from your computer (which we call "the host", because it is hosting the other computer). With this step, you launch the virtual machine: @@ -60,15 +58,14 @@ If all tools passed the test, then you'll be able to automatically add the follo 5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, diartk, yunitator -### Overview of "pipelines" +### The concept of "pipelines" -DiViMe is a platform for tools to analyze naturalistic, unannotated audiorecordings. We consider this process to involve three kinds of processes: +DiViMe is a platform for tools to analyze naturalistic, unannotated audio recordings. We consider this process to involve three kinds of processes: - speech activity detection and voice activity detection = “detecting vocalizations”, - diarization = “deciding to whom the vocalizations belong”, and - “additional annotations” - Some tools actually combine two of these stages (e.g. a tool may do both speech activity detection and role attribution in one fell swoop). This [flowchart](https://docs.google.com/presentation/d/1vh2rTFdVZDZKh4WQ-UEzzPvHpr4-k-Q6Lf-5fvotRXw/edit#slide=id.g44f4e7b6a3_0_9) may help. We call a *pipeline* a sequence of those processes; i.e., it involves using one tool after another. For example, you may do *speech activity detection* + *talker diarization* + *vocal type classification* @@ -93,10 +90,8 @@ You can read that command as follows: *data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. - For each input wav file, there will be one rttm file created in the same directory, with the name of the tool added at the beginning. For example, imagine you have put a single file called participant23.wav into ```data/```, and you decided to run two SADs: - ``` $ vagrant ssh -c "opensmileSad.sh data/" $ vagrant ssh -c "noisemesSad.sh data/" @@ -137,7 +132,6 @@ You can only use one of the following options: rttm, opensmileSad, tocomboSad, n You can provide annotations done by a human or in some other way, and encoded as rttms. If you have a different format, see the Format section. *What is crucial for this procedure to work is that your rttm's reflection your human-annotation are called exactly like your sound files.* Notice that all annotations that say "speech" in the eighth column count as such. - Alternatively, you can use automatic annotations generated by DiViMe's speech/voice activity detection systems, encoded in rttm files. In this case, you would pass one of the following options: - noisemesSad: this means you want the system to use the output of the noisemesSad system. If you have not run noisemesSad, the system will fail. @@ -153,7 +147,6 @@ If all three parameters are provided, then the system will first find all the an - participant24.wav - participant24.rttm - If you run: `$ vagrant ssh -c "diartk.sh data/mydata/ opensmileSad"` @@ -169,9 +162,9 @@ then only participant24.wav will be analyzed. At the end of the process, there will be an added rttm file for each analyzed file. For instance, if you have just one sound file (participant23.wav) at the beginning and you run opensmileSad followed by diartk, then you will end up with the following three files: -- participant23.wav: your original sound file -- opensmileSad_participant23.rttm: the output of opensmileSad, which states where there is speech -- diartk_opensmileSad_participant23.rttm: the output of opensmileSad followed by diartk, which states which speech sections belong to which speakers. +- `participant23.wav`: your original sound file +- `opensmileSad_participant23.rttm`: the output of opensmileSad, which states where there is speech +- `diartk_opensmileSad_participant23.rttm`: the output of opensmileSad followed by diartk, which states which speech sections belong to which speakers. See Format section for explanation on how to read the resulting rttm. @@ -289,11 +282,10 @@ Note that the process of calcuting the minute that contains the most speech can ## An alternative for Step 4: using recipes -**THIS NEEDS WORK** +It is possible to combine multiple steps into one program, which can then execute an entire complex analysis all by itself. Feel free to experiment. If you have good examples, **feel free to share**. ## Further information on Step 5, putting DiViMe back to sleep Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: `$ vagrant halt` - From d60cdd77cf43aa15492a55dd65bc02f6045e7615 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Mon, 15 Jul 2019 07:55:51 -0400 Subject: [PATCH 269/299] added a gitattributes file in response to #117 --- .gitattribute | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattribute diff --git a/.gitattribute b/.gitattribute new file mode 100644 index 0000000..dfdb8b7 --- /dev/null +++ b/.gitattribute @@ -0,0 +1 @@ +*.sh text eol=lf From ee1328ed97c8d93790ee1b6e76e33018ab18f4c8 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 15 Jul 2019 17:02:53 -0400 Subject: [PATCH 270/299] fixed typo --- docs/source/tool_doc.md | 4 ++-- docs/source/usage.md | 15 ++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/source/tool_doc.md b/docs/source/tool_doc.md index adcfd25..e91a733 100755 --- a/docs/source/tool_doc.md +++ b/docs/source/tool_doc.md @@ -217,12 +217,12 @@ This section contains documentation from other tools. -## Yunitator +## Yunitate ### General intro -Given that there is no reference for this tool, we provide a more extensive introduction based on a presentation Florian Metze gave on 2018-08-13 in an ACLEW Meeting. +There is no reference for this tool, we provide a more extensive introduction based on a presentation Florian Metze gave on 2018-08-13 in an ACLEW Meeting. The data used for training were: diff --git a/docs/source/usage.md b/docs/source/usage.md index e8a411e..a787c30 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -52,11 +52,11 @@ If all tools passed the test, then you'll be able to automatically add the follo 2) Talker diarization (_who is talking?_) The tools available for this task are the following: diartk -3) Role diarization (_what kind of person is talking?_) The tools available for this task are the following: yunitator +3) Role diarization (_what kind of person is talking?_) The tools available for this task are the following: yunitate 4) Vocal type classification (_what kind of vocalization is this one?_) The tools available for this task are the following: vcm -5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, diartk, yunitator +5) Evaluation (_how good is the automatic annotation?_) There is an evaluation available for the following tools: noisemesSad, tocomboSad, opensmileSad, diartk, yunitate ### The concept of "pipelines" @@ -172,13 +172,13 @@ See Format section for explanation on how to read the resulting rttm. For these tools, type a command like this one: -`$ vagrant ssh -c "yunitator.sh data/mydata/"` +`$ vagrant ssh -c "yunitate.sh data/mydata/"` You can read that command as follows: *vagrant ssh -c*: This tells DiViMe that it needs to run a tool. -*yunitator.sh*: This first argument tells DiViMe which tool to run. The options are: yunitator. +*yunitate.sh*: This first argument tells DiViMe which tool to run. The options are: yunitate. *data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. @@ -199,7 +199,7 @@ You can read that command as follows: *data/mydata/*: This second argument tells DiViMe where are the sound files to analyze. Note that the directory containing the input files should be located in the ```data/``` directory (or it can be ```data/``` itself). The directory does not need to be called `mydata` - you can choose any name. -**The vocalization classification tool depends on the output of the talker type tool yunitator. Therefore, the directory where you put your clips to analyze must contain files called yunitator_*.rttm (e.g., yunitator_participant23.wav).** +**The vocalization classification tool depends on the output of the talker type tool yunitate. Therefore, the directory where you put your clips to analyze must contain files called yunitate_*.rttm (e.g., yunitate_participant23.wav).** The vocalization classification tool returns one rttm per sound file, with an estimation for each CHI vocalzsation to be a canonical syllable (CNS), non-canonical syllable (NCS), crying (CRY), and others (OTH, normally refer to laughing). @@ -210,6 +210,11 @@ See Format section for explanation on how to read the resulting rttm. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. +You may first need to generate .rttm files for the evaluation. We provide some undocumented tools for this in `utils`, which you can use at your own risk. The only case that is currently supported and documented here is when you have an ELAN file following the ACLEW annotation scheme at least in the following ways: + +- you have a tier called " +- you have intervals that are + Type a command like the one below: `vagrant ssh -c "eval.sh data/ tocomboSad accuracy"`` From da1b474bb6ea3d353e0126a17a006af9220846d0 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 15 Jul 2019 17:27:23 -0400 Subject: [PATCH 271/299] addressing #135 in progress --- docs/source/usage.md | 64 +++++++++++++++++---------------- utils/eafAAS2enriched_folder.sh | 10 ++++++ utils/eafAAS2rttm_folder.sh | 3 -- 3 files changed, 43 insertions(+), 34 deletions(-) create mode 100755 utils/eafAAS2enriched_folder.sh diff --git a/docs/source/usage.md b/docs/source/usage.md index a787c30..10857e9 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -210,11 +210,15 @@ See Format section for explanation on how to read the resulting rttm. If you have some annotations that you have made, you probably want to know how well our tools did - how close they were to your hard-earned human annotations. -You may first need to generate .rttm files for the evaluation. We provide some undocumented tools for this in `utils`, which you can use at your own risk. The only case that is currently supported and documented here is when you have an ELAN file following the ACLEW annotation scheme at least in the following ways: +You may first need to generate .rttm files for the evaluation. We provide some undocumented tools for this in `utils`, which you can use at your own risk. The only case that is currently supported and documented here is when you have an ELAN file following the ACLEW annotation scheme exhaustively (i.e., the whole file has been annotated by humans) at least in terms of how participants are called. To generate rttms for evaluation, -- you have a tier called " -- you have intervals that are +`vagrant ssh -c "eafAAS2rttm_folder.sh data/"` +You should see appear files that are called exactly like your .eaf's but that have an rttm format. See Format section for explanation on how to read the resulting rttm. + +**IMPORTANT** The rttm's containing this human annotation should be named exactly the same as your sound files!!! + + Type a command like the one below: `vagrant ssh -c "eval.sh data/ tocomboSad accuracy"`` @@ -247,33 +251,31 @@ It generates a table showing the scores obtained for each file. Since it is usually not enough to look at the final metric (the detection accuracy here), the table also shows intermediate metrics, therefore allowing the user to have a better insight of model's performances. Note that this table will be saved in the .csv format in the *data/* folder. -Here, all the metrics that are implemented : - -
- -| Speech Activity Detection | Diarization | Identification | -|---|---|---| -| Accuracy | Completeness | Identification Error Rate | -| Detection Error Rate | Coverage | Precision | -| Precision | Diarization Error Rate | Recall | -| Recall | Homogeneity | | -| | Purity | | - -
All metrics that are implemented. A more extensive documentation is available here
-
- -Note that the identification task is the same as the diarization task when the one-to-one mapping between hypothesis classes and reference classes share the same labels. -To assess diarization model's performances in the identification mode, you need to type the following command : - -`vagrant ssh -c "eval.sh data/ diartk_tocomboSad completeness --identification"` - -If the flag *-\-identification* is not passed, the script will run in the diarization mode. - -Note that you can ask to compute several metrics at once by typing : - -`vagrant ssh -c "eval.sh data/ tocomboSad accuracy precision recall"` - -It will generated a report for each metric. +We use the program pyannote-metrics to compute these metrics. Therefore, please see the [pyannote-metrics docs](http://pyannote.github.io/pyannote-metrics/reference.html) for explanations. + +%
+% +%| Speech Activity Detection | Diarization | Identification | +%|---|---|---| +%| Accuracy | Completeness | Identification Error Rate | +%| Detection Error Rate | Coverage | Precision | +%| Precision | Diarization Error Rate | Recall | +%| Recall | Homogeneity | | +%| | Purity | | +% +% +% +%Note that the identification task is the same as the diarization task when the one-to-one mapping between hypothesis classes and reference classes share the same labels. To assess a role diarization model in identification mode, you need to type the following command : +% +%`vagrant ssh -c "eval.sh data/ diartk_tocomboSad completeness --identification"` +% +%If the flag *-\-identification* is not passed, the script will run in the diarization mode. +% +%Note that you can ask to compute several metrics at once by typing : +% +%`vagrant ssh -c "eval.sh data/ tocomboSad accuracy precision recall"` +% +%It will generated a report for each metric. If you're not a math person, you can add the -\-visualization flag by typing : @@ -283,7 +285,7 @@ It will extract the minute that contains the most speech for each file and align ![
One minute alignement that has been obtained by adding the flag --visualization
](../images/example_visu.png) -Note that the process of calcuting the minute that contains the most speech can be time-consuming. +Note that the process of calculating the minute that contains the most speech can be time-consuming. ## An alternative for Step 4: using recipes diff --git a/utils/eafAAS2enriched_folder.sh b/utils/eafAAS2enriched_folder.sh new file mode 100755 index 0000000..d6e0b94 --- /dev/null +++ b/utils/eafAAS2enriched_folder.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# +# Shell script to convert all .eaf files following the ACLEW Annotation Scheme inside a folder to .rttm format +# +for j in ${1}/*.eaf + do elan2rttm.py $j #generate the basic rttms +done + +#extra processing for WCE +eaf2enriched_txt.sh ${1}/ $2 diff --git a/utils/eafAAS2rttm_folder.sh b/utils/eafAAS2rttm_folder.sh index d6e0b94..f8b8d1d 100755 --- a/utils/eafAAS2rttm_folder.sh +++ b/utils/eafAAS2rttm_folder.sh @@ -5,6 +5,3 @@ for j in ${1}/*.eaf do elan2rttm.py $j #generate the basic rttms done - -#extra processing for WCE -eaf2enriched_txt.sh ${1}/ $2 From 34c65e8dc912c4b972defceafb490a393afd7e5f Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 15 Jul 2019 17:41:32 -0400 Subject: [PATCH 272/299] addressing #135 in progress --- utils/eafAAS2rttm_folder.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/utils/eafAAS2rttm_folder.sh b/utils/eafAAS2rttm_folder.sh index f8b8d1d..3ad879f 100755 --- a/utils/eafAAS2rttm_folder.sh +++ b/utils/eafAAS2rttm_folder.sh @@ -2,6 +2,8 @@ # # Shell script to convert all .eaf files following the ACLEW Annotation Scheme inside a folder to .rttm format # -for j in ${1}/*.eaf - do elan2rttm.py $j #generate the basic rttms -done +for j in ${1}/*.eaf; do + r=`echo $j | sed "s/.eaf/rttm/"` + elan2rttm.py -i $j -o $r +#generate the basic rttms +done \ No newline at end of file From 4cba37b175b129d0314b61ed7582d6221a5eb708 Mon Sep 17 00:00:00 2001 From: alecristia Date: Mon, 15 Jul 2019 17:42:43 -0400 Subject: [PATCH 273/299] addressing #135 in progress --- utils/elan2rttm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/elan2rttm.py b/utils/elan2rttm.py index d832279..a4d355d 100755 --- a/utils/elan2rttm.py +++ b/utils/elan2rttm.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python """ written in python3.5 From 600f3d128dc8f06df577f73c0901fedf2b60a966 Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 18 Jul 2019 10:06:15 +0300 Subject: [PATCH 274/299] Run WCE for segments defined in .rttm files Added possibility to run WCE for segments defined in .rttm files, located in the same folder with the original .wav files. --- launcher/WCE_from_SAD_outputs.sh | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 launcher/WCE_from_SAD_outputs.sh diff --git a/launcher/WCE_from_SAD_outputs.sh b/launcher/WCE_from_SAD_outputs.sh new file mode 100644 index 0000000..76fee92 --- /dev/null +++ b/launcher/WCE_from_SAD_outputs.sh @@ -0,0 +1,26 @@ +if [ $# -lt 1 ]; then + echo "Usage: sh WCE_from_SAD_outputs.sh " + echo "where dirname is a folder containing audio .wav files and the corresponding .rttm files" + echo "created using ." + echo "Output .rttm files with WCE counts will be produced to " + exit 1 +fi + + +SCRIPT_DIR=$(dirname "$0") +DATA_FOLDER=$1 + +#if [ -n "$2" ]; then +if [ "$#" -ne 2 ]; then +SADNAME="opensmile" +else +SADNAME=$2 +fi + +rm ${DATA_FOLDER}/wav_tmp/*.wav + +python /home/vagrant/repos/WCE_VM/aux_VM/rttm_to_wavs.py ${DATA_FOLDER} ${SADNAME} + +sh /home/vagrant/launcher/estimateWCE.sh ${DATA_FOLDER}/wav_tmp/ ${DATA_FOLDER}/wav_tmp/WCE_output.txt + +python /home/vagrant/repos/WCE_VM/aux_VM/WCE_to_rttm.py ${DATA_FOLDER}/wav_tmp/WCE_output.txt ${DATA_FOLDER} From 621759f1ba3aa4144a98cdf6cac4c57d5937bfa0 Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 18 Jul 2019 10:19:23 +0300 Subject: [PATCH 275/299] Suppress verbose WCE call outputs --- launcher/WCE_from_SAD_outputs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/WCE_from_SAD_outputs.sh b/launcher/WCE_from_SAD_outputs.sh index 76fee92..d7da19f 100644 --- a/launcher/WCE_from_SAD_outputs.sh +++ b/launcher/WCE_from_SAD_outputs.sh @@ -21,6 +21,6 @@ rm ${DATA_FOLDER}/wav_tmp/*.wav python /home/vagrant/repos/WCE_VM/aux_VM/rttm_to_wavs.py ${DATA_FOLDER} ${SADNAME} -sh /home/vagrant/launcher/estimateWCE.sh ${DATA_FOLDER}/wav_tmp/ ${DATA_FOLDER}/wav_tmp/WCE_output.txt +sh /home/vagrant/launcher/estimateWCE.sh ${DATA_FOLDER}/wav_tmp/ ${DATA_FOLDER}/wav_tmp/WCE_output.txt > /dev/null 2>&1 python /home/vagrant/repos/WCE_VM/aux_VM/WCE_to_rttm.py ${DATA_FOLDER}/wav_tmp/WCE_output.txt ${DATA_FOLDER} From 2b5c4b4bc10e7532b1cd508cf56b90b2bb9e3f62 Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 18 Jul 2019 10:46:25 +0300 Subject: [PATCH 276/299] updated documentation --- docs/source/WCEtool.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/source/WCEtool.md b/docs/source/WCEtool.md index 1401e7b..767880a 100644 --- a/docs/source/WCEtool.md +++ b/docs/source/WCEtool.md @@ -10,7 +10,7 @@ The purpose of the WCE tool is to provide an estimate of the number of words in There are two basic ways to use the current tool: 1) An out-of-the-box version that can be used directly on any speech data , and -2) An adapted version, where the WCE system is first adapted to data provided by the user, and then performs more accurately on similar data. +2) An adapted version, where the WCE system is first adapted to data provided by the user, and then performs more accurately on similar data. NOTE: This version is going to be obsolote, as the DiViMe will move on to using language-independent syllable count estimation instead of word ount estimation. In practice, out-of-the-box variant provides only syllable count estimates for the input data, while the adaptation mode can be used to re-train the system to provide meaningful word count estimates in any language or other data domain. These two operation modes are detailed further below. @@ -34,16 +34,22 @@ vagrant ssh -c "~/launcher/estimateWCE.sh data/my_audiofolder/ data/WCE_output.t which will run WCE on all .wav files in data/my_audiofolder/ and output results to data/WCE_output.txt. -## Instructions for adapting the WCE to new language +## Instructions for running out-of-the-box WCE for SAD-based utterance segments -NOTE: DOCUMENTATION INCOMPLETE +If you have .rttm files corresponding to your .wav files that define speech segments in each recording (see SAD tool documentation on DiViMe), you can place your .wav files and corresponding .rttm files into on the VM (e.g., /vagrant/data/mydatafolder/), and then run: + +vagrant ssh -c "~/launcher/WCE_from_SAD_outputs.sh " -NOTE: This requires audio files and .eaf annotation files in ACLEW DAS annotation format. +e.g., +vagrant ssh -c "~/launcher/WCE_from_SAD_outputs.sh /vagrant/data/mydatafolder/ opensmileSad -## Changing configuration +Output syllable counts will be wirtten as .rttm files of format WCE__.rttm and located in . + +NOTE: The .rttm files must be named as _.rttm, where is the original .wav file name located in the same . -NOTE: DOCUMENTATION INCOMPLETE + +## Instructions for language-adapted use: OBSOLETE. WILL BE UPDATED IN A NEW VERSION OF THE SYSTEM. ## Main references for this tool: From cc60d8762db80cb30df4cbc3ea28f19934ca2c58 Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 18 Jul 2019 11:30:30 +0300 Subject: [PATCH 277/299] improved documentation --- launcher/WCE_from_SAD_outputs.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/launcher/WCE_from_SAD_outputs.sh b/launcher/WCE_from_SAD_outputs.sh index d7da19f..7f4a316 100644 --- a/launcher/WCE_from_SAD_outputs.sh +++ b/launcher/WCE_from_SAD_outputs.sh @@ -1,3 +1,7 @@ +# Runs WCE for .wav files using the corresponding speech activity detection (SAD) +# segments defined in .rttm files named as _.rttm , all located +# in the same directory . + if [ $# -lt 1 ]; then echo "Usage: sh WCE_from_SAD_outputs.sh " echo "where dirname is a folder containing audio .wav files and the corresponding .rttm files" @@ -10,17 +14,20 @@ fi SCRIPT_DIR=$(dirname "$0") DATA_FOLDER=$1 -#if [ -n "$2" ]; then if [ "$#" -ne 2 ]; then -SADNAME="opensmile" +SADNAME="tocomboSad" else SADNAME=$2 fi +if [ -d "${DATA_FOLDER}/wav_tmp/" ]; then rm ${DATA_FOLDER}/wav_tmp/*.wav +fi python /home/vagrant/repos/WCE_VM/aux_VM/rttm_to_wavs.py ${DATA_FOLDER} ${SADNAME} +echo "Running WCE..." sh /home/vagrant/launcher/estimateWCE.sh ${DATA_FOLDER}/wav_tmp/ ${DATA_FOLDER}/wav_tmp/WCE_output.txt > /dev/null 2>&1 python /home/vagrant/repos/WCE_VM/aux_VM/WCE_to_rttm.py ${DATA_FOLDER}/wav_tmp/WCE_output.txt ${DATA_FOLDER} +echo "WCE estimation complete." From 3ee4b811ff63b81f81e28ae0acee74687587d72a Mon Sep 17 00:00:00 2001 From: orasanen Date: Thu, 18 Jul 2019 11:36:44 +0300 Subject: [PATCH 278/299] updated documentation --- launcher/WCE_from_SAD_outputs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/WCE_from_SAD_outputs.sh b/launcher/WCE_from_SAD_outputs.sh index 7f4a316..b5c75ce 100644 --- a/launcher/WCE_from_SAD_outputs.sh +++ b/launcher/WCE_from_SAD_outputs.sh @@ -30,4 +30,4 @@ echo "Running WCE..." sh /home/vagrant/launcher/estimateWCE.sh ${DATA_FOLDER}/wav_tmp/ ${DATA_FOLDER}/wav_tmp/WCE_output.txt > /dev/null 2>&1 python /home/vagrant/repos/WCE_VM/aux_VM/WCE_to_rttm.py ${DATA_FOLDER}/wav_tmp/WCE_output.txt ${DATA_FOLDER} -echo "WCE estimation complete." +echo "WCE complete." From 33f30f693895e81fccc29110f2743e9cdeeefe03 Mon Sep 17 00:00:00 2001 From: alecristia Date: Tue, 23 Jul 2019 07:08:35 -0400 Subject: [PATCH 279/299] first attempt at recipe #88 --- utils/analyze.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 utils/analyze.sh diff --git a/utils/analyze.sh b/utils/analyze.sh new file mode 100644 index 0000000..42500c9 --- /dev/null +++ b/utils/analyze.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# pipeline producing a 3-class diarization (all children, female adult, male adult), a word count estimator for all speaker types, and a vocal class for children speakers +# Okko Räsänen & A. Cristia + +SCRIPT_DIR=$(dirname "$0") + +if [ "$#" -ne 1 ]; then +DATA_FOLDER="data/to_analysis/" +else +DATA_FOLDER=$1 +fi + +sh ~/launcher/yunitate.sh ${DATA_FOLDER} english +sh ~/launcher/vcm.sh ${DATA_FOLDER} english +sh WCE_from_SAD_outputs.sh /vagrant/${DATA_FOLDER} yunitator_english + +if [ -d "/vagrant/${DATA_FOLDER}/detailed_outputs/" ]; then +rm /vagrant/${DATA_FOLDER}/detailed_outputs/*.rttm +else +mkdir /vagrant/${DATA_FOLDER}/detailed_outputs/ +fi + +mv /vagrant/${DATA_FOLDER}/*.rttm /vagrant/${DATA_FOLDER}/detailed_outputs/ + +if [ -d "/vagrant/${DATA_FOLDER}/wav_tmp/" ]; then +rm -rf /vagrant/${DATA_FOLDER}/wav_tmp/ +fi + +ls /vagrant/${DATA_FOLDER}/detailed_outputs/yunitator*.rttm | sed "s/.*english_//g" > files.txt + +cat /vagrant/${DATA_FOLDER}/files.txt | while read -r line ; do + #get first five cols & speaker col + awk '{print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $8}' < /vagrant/${DATA_FOLDER}/detailed_outputs/yunitator_english_$line > base.temp + + #add WCE info + awk '{print $8}' < /vagrant/${DATA_FOLDER}/detailed_outputs/WCE_yunitator_english_$line > /vagrant/${DATA_FOLDER}/wce.temp + paste /vagrant/${DATA_FOLDER}/base.temp /vagrant/${DATA_FOLDER}/wce.temp > /vagrant/${DATA_FOLDER}/base2.temp + + #sort by speaker column to add the + sort -k6 /vagrant/${DATA_FOLDER}/base2.temp > /vagrant/${DATA_FOLDER}/base3.temp + + #pull out chi info & complete with empties + awk '{print "{vcm@ " $8 "}"}' < /vagrant/${DATA_FOLDER}/detailed_outputs/vcm_$line > /vagrant/${DATA_FOLDER}/vcm.temp + + #todo implement adding of ADS for adult lines + nchi=`wc -l vcm.temp | awk '{print $1}'` + nall=`wc -l base3.temp | awk '{print $1}'` + if [ "$nall" -gt "$nchi" ] ; then + i=$nchi + while [ "$i" -lt "$nall" ] ; do + echo "{xds@ 0}" >> /vagrant/${DATA_FOLDER}/vcm.temp + i=$((i + 1)) + done + fi + paste /vagrant/${DATA_FOLDER}/base3.temp /vagrant/${DATA_FOLDER}/vcm.temp > b/vagrant/${DATA_FOLDER}/ase4.temp + sort -k4 -n /vagrant/${DATA_FOLDER}/base4.temp | sed "s/.rttm//" | sed "s/NCS/N/" | sed "s/CNS/C/" | awk -F"\t" '{print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $7 "\t" $8 "\t" "" "\t" $6}' > /vagrant/${DATA_FOLDER}/final_$line + rm /vagrant/${DATA_FOLDER}/*.temp +done \ No newline at end of file From 89b3fc2b7d42310f3147953b7efa2888011c6629 Mon Sep 17 00:00:00 2001 From: orasanen Date: Tue, 23 Jul 2019 08:06:40 -0400 Subject: [PATCH 280/299] fixed a handful of path errors --- utils/analyze.sh | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/utils/analyze.sh b/utils/analyze.sh index 42500c9..b1de1b5 100644 --- a/utils/analyze.sh +++ b/utils/analyze.sh @@ -10,9 +10,13 @@ else DATA_FOLDER=$1 fi -sh ~/launcher/yunitate.sh ${DATA_FOLDER} english -sh ~/launcher/vcm.sh ${DATA_FOLDER} english -sh WCE_from_SAD_outputs.sh /vagrant/${DATA_FOLDER} yunitator_english +if [ ! -d "/vagrant/${DATA_FOLDER}/logs/" ]; then + mkdir /vagrant/${DATA_FOLDER}/logs/ +fi + +sh ~/launcher/yunitate.sh ${DATA_FOLDER} english > /vagrant/${DATA_FOLDER}/logs/yunitate.log +sh ~/launcher/vcm.sh ${DATA_FOLDER} english > /vagrant/${DATA_FOLDER}/logs/vcm.log +sh WCE_from_SAD_outputs.sh /vagrant/${DATA_FOLDER} yunitator_english > /vagrant/${DATA_FOLDER}/logs/WCE.log if [ -d "/vagrant/${DATA_FOLDER}/detailed_outputs/" ]; then rm /vagrant/${DATA_FOLDER}/detailed_outputs/*.rttm @@ -26,11 +30,11 @@ if [ -d "/vagrant/${DATA_FOLDER}/wav_tmp/" ]; then rm -rf /vagrant/${DATA_FOLDER}/wav_tmp/ fi -ls /vagrant/${DATA_FOLDER}/detailed_outputs/yunitator*.rttm | sed "s/.*english_//g" > files.txt +ls /vagrant/${DATA_FOLDER}/detailed_outputs/yunitator*.rttm | sed "s/.*english_//g" > /vagrant/${DATA_FOLDER}/files.txt cat /vagrant/${DATA_FOLDER}/files.txt | while read -r line ; do #get first five cols & speaker col - awk '{print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $8}' < /vagrant/${DATA_FOLDER}/detailed_outputs/yunitator_english_$line > base.temp + awk '{print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $8}' < /vagrant/${DATA_FOLDER}/detailed_outputs/yunitator_english_$line > /vagrant/${DATA_FOLDER}/base.temp #add WCE info awk '{print $8}' < /vagrant/${DATA_FOLDER}/detailed_outputs/WCE_yunitator_english_$line > /vagrant/${DATA_FOLDER}/wce.temp @@ -39,12 +43,12 @@ cat /vagrant/${DATA_FOLDER}/files.txt | while read -r line ; do #sort by speaker column to add the sort -k6 /vagrant/${DATA_FOLDER}/base2.temp > /vagrant/${DATA_FOLDER}/base3.temp - #pull out chi info & complete with empties + #pull out chi info & complete with empties awk '{print "{vcm@ " $8 "}"}' < /vagrant/${DATA_FOLDER}/detailed_outputs/vcm_$line > /vagrant/${DATA_FOLDER}/vcm.temp #todo implement adding of ADS for adult lines - nchi=`wc -l vcm.temp | awk '{print $1}'` - nall=`wc -l base3.temp | awk '{print $1}'` + nchi=`wc -l /vagrant/${DATA_FOLDER}/vcm.temp | awk '{print $1}'` + nall=`wc -l /vagrant/${DATA_FOLDER}/base3.temp | awk '{print $1}'` if [ "$nall" -gt "$nchi" ] ; then i=$nchi while [ "$i" -lt "$nall" ] ; do @@ -52,7 +56,7 @@ cat /vagrant/${DATA_FOLDER}/files.txt | while read -r line ; do i=$((i + 1)) done fi - paste /vagrant/${DATA_FOLDER}/base3.temp /vagrant/${DATA_FOLDER}/vcm.temp > b/vagrant/${DATA_FOLDER}/ase4.temp + paste /vagrant/${DATA_FOLDER}/base3.temp /vagrant/${DATA_FOLDER}/vcm.temp > /vagrant/${DATA_FOLDER}/base4.temp sort -k4 -n /vagrant/${DATA_FOLDER}/base4.temp | sed "s/.rttm//" | sed "s/NCS/N/" | sed "s/CNS/C/" | awk -F"\t" '{print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $7 "\t" $8 "\t" "" "\t" $6}' > /vagrant/${DATA_FOLDER}/final_$line rm /vagrant/${DATA_FOLDER}/*.temp -done \ No newline at end of file +done From 35d433e3de3cb8dbbb36696805e233f17d21a4d8 Mon Sep 17 00:00:00 2001 From: orasanen Date: Tue, 23 Jul 2019 08:53:13 -0400 Subject: [PATCH 281/299] Update usage.md --- docs/source/usage.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/source/usage.md b/docs/source/usage.md index 10857e9..7a66e2e 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -17,6 +17,13 @@ Assuming the installation of the virtual machine is complete and some of the tes 4. Use tools on data, typically by doing `vagrant ssh -c "script.sh [arguments]"`. You can also run a recipe. 5. Finally, remember to put DiViMe back to sleep with `$ vagrant halt` +## An example use case: analyzing .wav files using the full pipeline of current tools + +1. Put the data you want to process in ```data/mydata/``` under the DiViMe main directory. Create a folder if it does not exist. +2. Make sure DiViMe is running (`vagrant up`) +3. Run `vagrant ssh -c "analyze.sh data/mydata/"` +4. Check ```data/mydata/``` for ELAN-readable .rttm files that contain full tool outputs (currently: speech detection & role diarization, vocal maturity classification, and syllable count estimation"). + ## Further information on Step 1, putting your data into the ```data/``` directory From 60455dbd69b70934e26eab4ced8ed03ad66713a0 Mon Sep 17 00:00:00 2001 From: orasanen Date: Tue, 23 Jul 2019 08:56:22 -0400 Subject: [PATCH 282/299] fixed a bunch of path errors --- utils/analyze.sh | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/utils/analyze.sh b/utils/analyze.sh index b1de1b5..4ce7ee4 100644 --- a/utils/analyze.sh +++ b/utils/analyze.sh @@ -10,13 +10,9 @@ else DATA_FOLDER=$1 fi -if [ ! -d "/vagrant/${DATA_FOLDER}/logs/" ]; then - mkdir /vagrant/${DATA_FOLDER}/logs/ -fi - -sh ~/launcher/yunitate.sh ${DATA_FOLDER} english > /vagrant/${DATA_FOLDER}/logs/yunitate.log -sh ~/launcher/vcm.sh ${DATA_FOLDER} english > /vagrant/${DATA_FOLDER}/logs/vcm.log -sh WCE_from_SAD_outputs.sh /vagrant/${DATA_FOLDER} yunitator_english > /vagrant/${DATA_FOLDER}/logs/WCE.log +sh ~/launcher/yunitate.sh ${DATA_FOLDER} english +sh ~/launcher/vcm.sh ${DATA_FOLDER} english +sh WCE_from_SAD_outputs.sh /vagrant/${DATA_FOLDER} yunitator_english if [ -d "/vagrant/${DATA_FOLDER}/detailed_outputs/" ]; then rm /vagrant/${DATA_FOLDER}/detailed_outputs/*.rttm From 244e80c9f0cfb3efd379fcd8e43b1e6c29343b44 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Tue, 23 Jul 2019 09:13:37 -0400 Subject: [PATCH 283/299] Update install.md --- docs/source/install.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/source/install.md b/docs/source/install.md index fc36bad..4976ac0 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -70,10 +70,24 @@ Congratulations, everything is OK! [...] ``` +## Using it + +You can now run commands and experiment on multiple data files, using as many `$ vagrant ssh -c "[...]"` calls as you like. It *should* also be safe to have multiple ssh connections to the VM and run many experiments in parallel, if the tool that you are using supports it. There *may* be some that are not "thread-safe". + ## When you are done with DiViMe, Teardown After working with DiViMe, you can shut down the virtual machine, which will free up CPU and RAM resources on your computer (but not disc space). To do this, type `$ vagrant halt` or `$ vagrant suspend`. To continue working with the VM at a later point, simply issue another `$ vagrant up` command. +When you do `$ vagrant up` again (without previously shutting down the VM), its output will probably end in: + +``` + default: /vagrant => /Users/metze/Work/Kitchen/DiViMe +==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision` +==> default: flag to force provisioning. Provisioners marked to run always will still run. +``` + +This is safe to ignore, and you can continue with `$vagrant ssh -c "[...]"` as needed. + ## Updating DiViMe If you want to install a new release of DiViMe, you will need to perform the following 3 steps from within the DiViME folder on your terminal: From d41afef79ae8503e5b9b301a1acaa27d3c50ce36 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Tue, 23 Jul 2019 09:15:01 -0400 Subject: [PATCH 284/299] Update install.md --- docs/source/install.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/install.md b/docs/source/install.md index 4976ac0..56beebb 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -86,7 +86,7 @@ When you do `$ vagrant up` again (without previously shutting down the VM), its ==> default: flag to force provisioning. Provisioners marked to run always will still run. ``` -This is safe to ignore, and you can continue with `$vagrant ssh -c "[...]"` as needed. +This is safe to ignore, and you can continue with `$vagrant ssh -c "[...]"` as needed. Note that the VM is not set up to actually support a proper separate provisioning step, so `$ vagrant provision` probably will not work reliably. ## Updating DiViMe From 7f0079e0c2a1f3cd9fffe0de136fb846705d7f21 Mon Sep 17 00:00:00 2001 From: orasanen Date: Tue, 23 Jul 2019 09:21:17 -0400 Subject: [PATCH 285/299] added error logs --- utils/analyze.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/utils/analyze.sh b/utils/analyze.sh index 4ce7ee4..b1de1b5 100644 --- a/utils/analyze.sh +++ b/utils/analyze.sh @@ -10,9 +10,13 @@ else DATA_FOLDER=$1 fi -sh ~/launcher/yunitate.sh ${DATA_FOLDER} english -sh ~/launcher/vcm.sh ${DATA_FOLDER} english -sh WCE_from_SAD_outputs.sh /vagrant/${DATA_FOLDER} yunitator_english +if [ ! -d "/vagrant/${DATA_FOLDER}/logs/" ]; then + mkdir /vagrant/${DATA_FOLDER}/logs/ +fi + +sh ~/launcher/yunitate.sh ${DATA_FOLDER} english > /vagrant/${DATA_FOLDER}/logs/yunitate.log +sh ~/launcher/vcm.sh ${DATA_FOLDER} english > /vagrant/${DATA_FOLDER}/logs/vcm.log +sh WCE_from_SAD_outputs.sh /vagrant/${DATA_FOLDER} yunitator_english > /vagrant/${DATA_FOLDER}/logs/WCE.log if [ -d "/vagrant/${DATA_FOLDER}/detailed_outputs/" ]; then rm /vagrant/${DATA_FOLDER}/detailed_outputs/*.rttm From 28875f671c29b3240185e7c108d6547dd75d8df3 Mon Sep 17 00:00:00 2001 From: orasanen Date: Tue, 23 Jul 2019 09:30:08 -0400 Subject: [PATCH 286/299] Update usage.md --- docs/source/usage.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/source/usage.md b/docs/source/usage.md index 7a66e2e..d00ed6b 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -303,3 +303,13 @@ It is possible to combine multiple steps into one program, which can then execut Last but not least, you should **remember to halt the virtual machine**. If you don't, it will continue running in the background, taking up useful resources! To do so, simply navigate to the DiViMe folder on your terminal and type in: `$ vagrant halt` + +## Updating DiViMe + +1. Go to DiViMe main directory, and run +2. `vagrant halt` +3. `vagrant destroy` +4. `git pull` +5. `vagrant up` + +Note that this procedure will install newest version of DiViMe from scracth, and may take up to several hours depending on your network connection and computer. Note that vagrant destroy will *not* destroy your own files under data/. From 7a0538288bfa06daecc03b0e600a238692cf8e19 Mon Sep 17 00:00:00 2001 From: orasanen Date: Tue, 23 Jul 2019 09:31:51 -0400 Subject: [PATCH 287/299] Update usage.md --- docs/source/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usage.md b/docs/source/usage.md index d00ed6b..2074e10 100755 --- a/docs/source/usage.md +++ b/docs/source/usage.md @@ -312,4 +312,4 @@ Last but not least, you should **remember to halt the virtual machine**. If you 4. `git pull` 5. `vagrant up` -Note that this procedure will install newest version of DiViMe from scracth, and may take up to several hours depending on your network connection and computer. Note that vagrant destroy will *not* destroy your own files under data/. +Note that this procedure will install newest version of DiViMe from scracth, and may take up to several hours depending on your network connection and computer. Note that vagrant destroy will *not* destroy your own files under ```data/```. From 1074c1d5ae58acfc8bc632d760f5599c60e9bce9 Mon Sep 17 00:00:00 2001 From: alecristia Date: Tue, 23 Jul 2019 10:27:41 -0400 Subject: [PATCH 288/299] update recipe #88 --- utils/analyze.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/analyze.sh b/utils/analyze.sh index b1de1b5..65d0afd 100644 --- a/utils/analyze.sh +++ b/utils/analyze.sh @@ -57,6 +57,6 @@ cat /vagrant/${DATA_FOLDER}/files.txt | while read -r line ; do done fi paste /vagrant/${DATA_FOLDER}/base3.temp /vagrant/${DATA_FOLDER}/vcm.temp > /vagrant/${DATA_FOLDER}/base4.temp - sort -k4 -n /vagrant/${DATA_FOLDER}/base4.temp | sed "s/.rttm//" | sed "s/NCS/N/" | sed "s/CNS/C/" | awk -F"\t" '{print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $7 "\t" $8 "\t" "" "\t" $6}' > /vagrant/${DATA_FOLDER}/final_$line + sort -k4 -n /vagrant/${DATA_FOLDER}/base4.temp | sed "s/.rttm//" | sed "s/NCS/N/" | sed "s/CNS/C/" | awk -F"\t" '{print $1 "," $2 "," $3 "," $4 "," $5 "," $7 "," $8 "," "" "," $6}' > /vagrant/${DATA_FOLDER}/final_${line}.txt rm /vagrant/${DATA_FOLDER}/*.temp done From 755e118244fc92d3e1554331c2e835b90c2e663f Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Tue, 23 Jul 2019 11:23:24 -0400 Subject: [PATCH 289/299] Create vagrant-up-again.log --- example-logs/vagrant-up-again.log | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 example-logs/vagrant-up-again.log diff --git a/example-logs/vagrant-up-again.log b/example-logs/vagrant-up-again.log new file mode 100644 index 0000000..55d4003 --- /dev/null +++ b/example-logs/vagrant-up-again.log @@ -0,0 +1,33 @@ +Florians-MacBook-Pro-2019:DiViMe metze$ vagrant up +==> vagrant: A new version of Vagrant is available: 2.2.5 (installed version: 2.2.4)! +==> vagrant: To upgrade visit: https://www.vagrantup.com/downloads.html + +Bringing machine 'default' up with 'virtualbox' provider... +==> default: Checking if box 'ubuntu/trusty64' version '20190429.0.1' is up to date... +==> default: Clearing any previously set forwarded ports... +==> default: Clearing any previously set network interfaces... +==> default: Preparing network interfaces based on configuration... + default: Adapter 1: nat + default: Adapter 2: hostonly + default: Adapter 3: hostonly + default: Adapter 4: hostonly + default: Adapter 5: hostonly + default: Adapter 6: hostonly + default: Adapter 7: hostonly +==> default: Forwarding ports... + default: 22 (guest) => 2222 (host) (adapter 1) +==> default: Running 'pre-boot' VM customizations... +==> default: Booting VM... +==> default: Waiting for machine to boot. This may take a few minutes... + default: SSH address: 127.0.0.1:2222 + default: SSH username: vagrant + default: SSH auth method: private key +==> default: Machine booted and ready! +[default] GuestAdditions 6.0.8 running --- OK. +==> default: Checking for guest additions in VM... +==> default: Configuring and enabling network interfaces... +==> default: Mounting shared folders... + default: /vagrant => /Users/metze/Work/Kitchen/DiViMe +==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision` +==> default: flag to force provisioning. Provisioners marked to run always will still run. +Florians-MacBook-Pro-2019:DiViMe metze$ From 476bf9b029374a3d4b4d80ac4a6c004487061cad Mon Sep 17 00:00:00 2001 From: orasanen Date: Tue, 23 Jul 2019 15:14:20 -0400 Subject: [PATCH 290/299] updated WCE test, fixed Yunitator test naming --- launcher/test.sh | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/launcher/test.sh b/launcher/test.sh index 672eebb..b75abca 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash # # This script tests numerous tools # from a downloaded 5 minute section of the HomeBank VanDam daylong audio sample @@ -151,7 +151,7 @@ echo "Testing Yunitator..." # let 'er rip yun="universal" $LAUNCHERS/yunitate.sh $DATADIR/test $yun $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/yunitator_old_$BASETEST.rttm ]; then +if [ -s $TESTDIR/yunitator_universal_$BASETEST.rttm ]; then echo "Yunitator passed the test." else FAILURES=true @@ -185,18 +185,16 @@ fi # Testing WCE echo "Testing WCE..." -WCEDIR=$REPOS/WCE_VM/ -cd $WCEDIR -./run_WCEtrain.sh /usr/local/MATLAB/MATLAB_Runtime/v93/ demofiles.txt democounts.txt models/mymodel.mat configs/config_default.txt > $TESTDIR/wce-test.log || { echo " WCE failed - dependencies"; FAILURES=true;} -WCE_OUTPUT=$(awk '/adaptation completed/{ print NR; exit }' $TESTDIR/wce-test.log) -if [ $WCE_OUTPUT > 0 ]; then - echo "WCE passed the test" +sh estimateWCE.sh $DATADIR/test/ $TESTDIR/WCE_$BASETEST.csv +if [ -s $TESTDIR/WCE_$BASETEST.csv ]; then +echo "WCE passed the test" else + echo "WCE tests failed" FAILURES=true - echo "WCE failed - no successful adaptation" fi + # test finished if $FAILURES; then echo "Some tools did not pass the test, but you can still use others" From 7596e006c6cec89c62f3afe18d5857d27515ecfb Mon Sep 17 00:00:00 2001 From: alecristia Date: Tue, 23 Jul 2019 15:47:15 -0400 Subject: [PATCH 291/299] update recipe #88, added elan-importable csv --- utils/analyze.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utils/analyze.sh b/utils/analyze.sh index 65d0afd..560f288 100644 --- a/utils/analyze.sh +++ b/utils/analyze.sh @@ -57,6 +57,9 @@ cat /vagrant/${DATA_FOLDER}/files.txt | while read -r line ; do done fi paste /vagrant/${DATA_FOLDER}/base3.temp /vagrant/${DATA_FOLDER}/vcm.temp > /vagrant/${DATA_FOLDER}/base4.temp - sort -k4 -n /vagrant/${DATA_FOLDER}/base4.temp | sed "s/.rttm//" | sed "s/NCS/N/" | sed "s/CNS/C/" | awk -F"\t" '{print $1 "," $2 "," $3 "," $4 "," $5 "," $7 "," $8 "," "" "," $6}' > /vagrant/${DATA_FOLDER}/final_${line}.txt + sort -k4 -n /vagrant/${DATA_FOLDER}/base4.temp | sed "s/.rttm//" | sed "s/NCS/N/" | sed "s/CNS/C/" | awk -F"\t" '{print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $7 "\t" $8 "\t" "" "\t" $6}' > /vagrant/${DATA_FOLDER}/${line}.txt + awk -F"\t" '{print $9 "-wce," $9 "," $4 "," $5 "," $6}' < /vagrant/${DATA_FOLDER}/${line}.txt > /vagrant/${DATA_FOLDER}/${line}_forELAN.txt + grep "vcm" /vagrant/${DATA_FOLDER}/${line}.txt | awk -F"\t" '{print $9 "-vcm," $9 "," $4 "," $5 "," $7}'| sed "s/xds@//" | tr -d "{" | tr -d "}" >> /vagrant/${DATA_FOLDER}/${line}_forELAN.txt + rm /vagrant/${DATA_FOLDER}/*.temp done From 3ffcd03a5ef6302a39726d28649a478d8112c413 Mon Sep 17 00:00:00 2001 From: orasanen Date: Tue, 23 Jul 2019 16:19:10 -0400 Subject: [PATCH 292/299] fixed WCE test logging --- launcher/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/test.sh b/launcher/test.sh index b75abca..861dde4 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -186,7 +186,7 @@ fi # Testing WCE echo "Testing WCE..." -sh estimateWCE.sh $DATADIR/test/ $TESTDIR/WCE_$BASETEST.csv +sh estimateWCE.sh $DATADIR/test/ $TESTDIR/WCE_$BASETEST.csv > $TESTDIR/wce-test.log if [ -s $TESTDIR/WCE_$BASETEST.csv ]; then echo "WCE passed the test" else From 6f9082791d1cc35d1a52ac64488b4af455c39f34 Mon Sep 17 00:00:00 2001 From: orasanen Date: Tue, 23 Jul 2019 18:02:49 -0400 Subject: [PATCH 293/299] Updated WCE test + fixed Yunitator test. --- launcher/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/test.sh b/launcher/test.sh index 861dde4..b75abca 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -186,7 +186,7 @@ fi # Testing WCE echo "Testing WCE..." -sh estimateWCE.sh $DATADIR/test/ $TESTDIR/WCE_$BASETEST.csv > $TESTDIR/wce-test.log +sh estimateWCE.sh $DATADIR/test/ $TESTDIR/WCE_$BASETEST.csv if [ -s $TESTDIR/WCE_$BASETEST.csv ]; then echo "WCE passed the test" else From 2a5c131586234e26a90c321b6c8366c97af1a684 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 24 Jul 2019 17:00:42 -0400 Subject: [PATCH 294/299] various bugfixes, mostly related to test.sh --- conf/bootstrap.sh | 2 +- launcher/diartk.sh | 3 +- launcher/test.sh | 59 +++++++++++++++--------- launcher/yunitate.sh | 9 ++-- {example-logs => logs}/launcher-test.log | 0 {example-logs => logs}/vagrant-up.log | 0 utils/analyze.sh | 0 7 files changed, 46 insertions(+), 27 deletions(-) rename {example-logs => logs}/launcher-test.log (100%) rename {example-logs => logs}/vagrant-up.log (100%) mode change 100644 => 100755 utils/analyze.sh diff --git a/conf/bootstrap.sh b/conf/bootstrap.sh index d84d461..a034679 100755 --- a/conf/bootstrap.sh +++ b/conf/bootstrap.sh @@ -262,6 +262,7 @@ cd /vagrant/docs make SPHINXBUILD=/home/${user}/anaconda/bin/sphinx-build html # Installation status +echo "---- Build done ----" if ! $PYTHON3_INSTALLED; then echo "*********************************************" echo "Warning: python3 environment is not installed" @@ -289,4 +290,3 @@ echo "---- Done bootstrapping DiViMe @ `date` ----" # - vagrant ssh -c "yunitate.sh data/" (with a large wav file in data) # - vagrant ssh -c "utils/high_volubility.py data/7085.wav --diar yunitator_universal --mode CHI --nb_chunks 50" # ... - diff --git a/launcher/diartk.sh b/launcher/diartk.sh index dbd798b..555d13d 100755 --- a/launcher/diartk.sh +++ b/launcher/diartk.sh @@ -32,8 +32,7 @@ trs_format=$2 ### Other variables specific to this script # create temp dir -workdir=${audio_dir}/temp/diartk -mkdir -p $workdir +workdir=`mktemp -d --tmpdir=${audio_dir}` ### SCRIPT STARTS cd $BASEDIR/repos/ib_diarization_toolkit diff --git a/launcher/test.sh b/launcher/test.sh index 672eebb..a435071 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -32,7 +32,17 @@ VCMDIR=$REPOS/vcm FAILURES=false -echo "Starting tests" +( + cd /vagrant + echo -e "Welcome to DiViMe's test.sh\n\$ git show-branch" + git show-branch + echo "$ git log -1" + git log -1 + echo "$ git diff --name-status" + git diff --name-status + echo "######################################################################################" + echo "Starting tests" +) cd /vagrant/data @@ -72,6 +82,7 @@ TESTDIR=$WORKDIR/test # Check for HTK +if false; then echo "Checking for HTK..." if [ -s /usr/local/bin/HCopy ]; then echo "HTK is installed." @@ -80,13 +91,13 @@ else #echo " If so, then you may need to re-install it. Run: vagrant ssh -c \"utils/install_htk.sh\" " echo " HTK missing. You can probably ignore this warning, HTK is no longer needed." fi +fi rm -rf $TESTDIR; mkdir -p $TESTDIR ln -fs $TEST_WAV $TESTDIR cp $WORKDIR/$BASETEST.rttm $TESTDIR - # now test Noisemes echo "Testing noisemes..." @@ -112,52 +123,55 @@ else echo " OpenSmile SAD failed - no RTTM output" fi + # now test TOCOMBOSAD echo "Testing ToCombo SAD..." -$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " TOCOMBO SAD failed - dependencies"; FAILURES=true;} +$LAUNCHERS/tocomboSad.sh $DATADIR/test $KEEPTEMP > $TESTDIR/tocombo_sad_test.log 2>&1 || { echo " ToCombo SAD failed - dependencies"; FAILURES=true;} if [ -s $TESTDIR/tocomboSad_$BASETEST.rttm ]; then - echo "TOCOMBO SAD passed the test." + echo "ToCombo SAD passed the test." else FAILURES=true - echo " TOCOMBO SAD failed - no output RTTM" + echo " ToCombo SAD failed - no output RTTM" fi # test DIARTK -echo "Testing DIARTK..." +echo "Testing DiarTk..." cp $TEST_RTTM $TESTDIR # run like the wind $LAUNCHERS/diartk.sh $DATADIR/test rttm $KEEPTEMP > $TESTDIR/diartk-test.log 2>&1 if grep -q "command not found" $TESTDIR/diartk-test.log; then - echo " Diartk failed - dependencies (probably HTK)" + echo " DiarTk failed - dependencies (probably HTK)" FAILURES=true else if [ -s $TESTDIR/diartk_goldSad_$BASETEST.rttm ]; then - echo "DiarTK passed the test." + echo "DiarTk passed the test." else FAILURES=true - echo " Diartk failed - no output RTTM" + echo " DiarTk failed - no output RTTM" fi fi -rm $TESTDIR/$BASETEST.rttm +#rm $TESTDIR/$BASETEST.rttm + # test Yunitator echo "Testing Yunitator..." # let 'er rip -yun="universal" +yun="old" $LAUNCHERS/yunitate.sh $DATADIR/test $yun $KEEPTEMP > $TESTDIR/yunitator-test.log 2>&1 || { echo " Yunitator failed - dependencies"; FAILURES=true;} -if [ -s $TESTDIR/yunitator_old_$BASETEST.rttm ]; then +if [ -s $TESTDIR/yunitator_${yun}_$BASETEST.rttm ]; then echo "Yunitator passed the test." else FAILURES=true echo " Yunitator failed - no output RTTM" fi + # Test the evaluation echo "Testing the evaluation pipeline..." source activate divime @@ -172,6 +186,7 @@ else fi conda deactivate + # Testing VCM echo "Testing VCM..." @@ -183,6 +198,7 @@ else echo " VCM failed - no output RTTM" fi + # Testing WCE echo "Testing WCE..." WCEDIR=$REPOS/WCE_VM/ @@ -197,6 +213,7 @@ else echo "WCE failed - no successful adaptation" fi + # test finished if $FAILURES; then echo "Some tools did not pass the test, but you can still use others" @@ -207,24 +224,24 @@ fi # results echo "######################################################################################" echo "To wrap up, we will print out the results of the analyses that we ran during the test." -echo "Compare the following results, corresponding to your system, against the reference results printed out below." -echo "If the numbers are similar, then your system is working similarly to the original one." +echo "Compare the following results against the reference results printed out below." +echo "If the numbers are similar, then your system is working ok." echo "If you see bigger changes, then please paste this output onto an issue on https://github.com/srvk/DiViMe/issues/." -echo "RESULTS:" +echo "****** YOUR RESULTS BEGIN ******." for f in /vagrant/$DATADIR/test/*.rttm; do $UTILS/sum-rttm.sh $f; done -echo "****** REFERENCE RESULTS BEGINS ******." +echo "****** REFERENCE RESULTS BEGIN ******." echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm" -echo "LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" +echo "LINES: 10 DURATION SUM: 296.23 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm" echo "LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm" echo "LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm" echo "LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm" echo "LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm" -echo "LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" -echo "****** REFERENCE RESULTS ENDS ******." +echo "LINES: 60 DURATION SUM: 42.3 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm" +echo "****** REFERENCE RESULTS END ******." -echo "Evaluation pipeline:" +echo "Evaluation pipeline YOURS:" cat /vagrant/data/VanDam-Daylong/BN32/test/eval-test.log -echo "accuracy report" +echo "Evaluation pipeline REFERENCE:" echo " detection accuracy true positive true negative false positive false " echo " % " echo "item " diff --git a/launcher/yunitate.sh b/launcher/yunitate.sh index 50891ae..c221f63 100755 --- a/launcher/yunitate.sh +++ b/launcher/yunitate.sh @@ -22,12 +22,13 @@ if [ $# -lt 1 ] || [ $# -gt 3 ]; then exit 1 fi +DELSIL=true KEEPTEMP=false if [ $BASH_ARGV == "--keep-temp" ]; then KEEPTEMP=true fi -MODE=$2 # old english or universal +MODE=$2 # old, english or universal if [[ $MODE == "" ]]; then MODE="old" fi @@ -98,8 +99,10 @@ echo "$0 finished running" for sad in `ls $YUNITEMP/*.rttm`; do _rttm=$(basename $sad) rttm=${audio_dir}/yunitator_${MODE}_${_rttm} - # Remove not needed SIL lines - sed -i '/ SIL /d' $sad + if $DELSIL; then + # Remove not needed SIL lines + sed -i '/ SIL /d' $sad + fi mv $sad $rttm done diff --git a/example-logs/launcher-test.log b/logs/launcher-test.log similarity index 100% rename from example-logs/launcher-test.log rename to logs/launcher-test.log diff --git a/example-logs/vagrant-up.log b/logs/vagrant-up.log similarity index 100% rename from example-logs/vagrant-up.log rename to logs/vagrant-up.log diff --git a/utils/analyze.sh b/utils/analyze.sh old mode 100644 new mode 100755 From 7d90b1a240f0fb07cb5c80dad99dc29eb554e132 Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Wed, 24 Jul 2019 17:33:45 -0400 Subject: [PATCH 295/299] avoid starting an X-Server on some machines --- launcher/estimateWCE.sh | 3 ++- launcher/test.sh | 2 +- launcher/tocomboSad.sh | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/launcher/estimateWCE.sh b/launcher/estimateWCE.sh index c453f70..90ae424 100755 --- a/launcher/estimateWCE.sh +++ b/launcher/estimateWCE.sh @@ -49,7 +49,8 @@ fi MATPATH="/usr/local/MATLAB/MATLAB_Runtime/v93/" echo "Running WCE module (this might take a while...)" -~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL} ${OUTPUTFILE} > /vagrant/data/WCE_VM_TEMP/WCE_process_log.log +# The 'DISPLAY= ' part prevents an X-Server from popping up on some machines +DISPLAY= ~/repos/WCE_VM/run_WCEestimate.sh ${MATPATH} ${FILES_TEST} ${MODEL} ${OUTPUTFILE} > /vagrant/data/WCE_VM_TEMP/WCE_process_log.log # Combine filenames and output counts into one file paste -d ', ' $FILES_TEST $OUTPUTFILE > /vagrant/data/WCE_VM_TEMP/tempout.txt diff --git a/launcher/test.sh b/launcher/test.sh index 45dfb3a..24e9e76 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -204,7 +204,7 @@ echo "Testing WCE..." sh estimateWCE.sh $DATADIR/test/ $TESTDIR/WCE_$BASETEST.csv if [ -s $TESTDIR/WCE_$BASETEST.csv ]; then -echo "WCE passed the test" + echo "WCE passed the test" else echo "WCE tests failed" FAILURES=true diff --git a/launcher/tocomboSad.sh b/launcher/tocomboSad.sh index 2a91f49..ee57a9b 100755 --- a/launcher/tocomboSad.sh +++ b/launcher/tocomboSad.sh @@ -67,7 +67,8 @@ echo "finished" export LD_LIBRARY_PATH=$MCR/runtime/glnxa64:$MCR/bin/glnxa64:$MCR/sys/os/glnxa64: -./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt +# The 'DISPLAY= ' part prevents an X-Server from popping up +DISPLAY= ./run_get_TOcomboSAD_output_v3.sh $MCR $workdir/filelist.txt 0 0.5 $TOCOMBOSADDIR/UBMnodct256Hub5.txt #convert to rttms for f in `ls ${audio_dir}/*.ToCombo.txt ${workdir}/*.ToCombo.txt`; do From f2c4fd61ff16dba86665b97a3b9ddbc152103f1d Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Sun, 28 Jul 2019 00:11:53 +0200 Subject: [PATCH 296/299] Update troubleshoot.md --- docs/source/troubleshoot.md | 48 +++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/docs/source/troubleshoot.md b/docs/source/troubleshoot.md index 2b690fc..dff5cd0 100755 --- a/docs/source/troubleshoot.md +++ b/docs/source/troubleshoot.md @@ -1,7 +1,47 @@ # Troubleshooting ## Installation issues + +### If your computer only has one core + +Before doing `vagrant up`, open the file called `DiViMe/Vagrantfile` in a text editor. Change the following line: +``` +> vbox.cpus = 2 +``` +into: +``` +> vbox.cpus = 1 +``` +Then proceed with the installation. Also, if you have more than one CPU, and you do not want DiViMe to take over your entire computer, you can set it to any value >= 2, and you should be fine. DiViMe uses multiple processors, but we have not yet fully optimized for many cores. + +### If your computer has 25 GB or less of storage space + +If your computer has less than 25 GB of storage space, then *you cannot build a fully working DiViMe*. In this case, clean up your files to free up space. + +### If your computer has 6 GB or less of RAM + +If your computer has less than about 8 GB of RAM, then you may or may not be able to build and use DiViMe. You probably need to change the space allocated to the virtual machine. Before doing `vagrant up`, open the file called `DiViMe/Vagrantfile` in a text editor. Change the following line: +``` +> vbox.memory = 4096 +``` +into: +``` +> vbox.memory = 2048 +``` +Then proceed with the Installation. Also, if you have more RAM, and you experience issues during installation (or use), you may benefit from increasing this value, which should normally not exceed half of your total installed RAM (as a rule of thumb). + +### If your computer is running Ubuntu (16.04) + +There is a known incompatibility between VirtualBox and the 4.13 Linux kernel on Ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installationSimple), or install the latest version of VirtualBox, which should fix the problem. + +Again, there is often a lot of information available online, because Vagrant and VirtualBox are widely used tools. + +### If something else fails + +Please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output of the failing run there, so we can better provide you with a solution. Also, please provide detailed information on your host system (which OS, RAM, CPU, HDD), which changes you made to the Vagrantfile, and also provide access to the data the system chokes on (if any). + ### Virtual Machine creation + If your computer freezes after `vagrant up`, it may be due to several things. If your OS is ubuntu 16.04, there's a known incompatibility between VirtualBox and the 4.13 Linux kernel on ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installationSimple), or install the latest version of virtualbox which should fix the problem. If you are not on ubuntu 16.04, or if the previous fix didn't work, it may also be due to the fact that Vagrant is trying to create a Virtual Machine that asks for too much resources. Please ensure that you have enough space on your computer (you should have at least 15Gb of free space) and check that the memory asked for is okay. If not, you can lower the memory of the VM by changing line 25 of the VagrantFile, @@ -12,7 +52,9 @@ to a lower number, such as ``` vbox.memory = 2048 ``` -### Resuming the Virtual Machine + +## Resuming the Virtual Machine + If you already used the VM once, shut down your computer, turned it back on and can't seem to be able to do `vagrant up` again, you can simply do ``` vagrant destroy @@ -26,6 +68,7 @@ You can now try again with `vagrant up` ## Problems with some of the Tools + ### OpenSmile, DiarTK If OpenSmile, DiarTK don't seem to work after `vagrant up`, first, please check that you indeed have the htk archive in your folder. If you don't, please put it there and launch: @@ -46,6 +89,3 @@ MemoryError If this happens to you, it's because you are trying to treat more data than the system/your computer can handle. What you can do is simply put the remaining files that weren't treated in a separate folder and treat this folder separately (and do this until all of your files are treated if it happens again on very big datasets). After that, you can put back all of your data in the same folder. - - - From 6b4e60fe1fac277674ba532ffa019273ccaddd9a Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Sun, 28 Jul 2019 00:24:25 +0200 Subject: [PATCH 297/299] Update install.md --- docs/source/install.md | 45 +++++++++++------------------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index 56beebb..7361e7e 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -110,44 +110,23 @@ $ rm -rf DiViMe ## Troubleshooting -### If your computer only has one core +DiViMe is very powerful (and complex), and despite our best efforts, there are many ways to fail. The first order of business is therefore to pin-point the problem, which may or may not be related to DiViMe specifically. First, look at DiViMe's issue tracking system [here](https://github.com/srvk/DiViMe/issues) - maybe you can find the solution already. If not, read on below. -Before doing `vagrant up`, open the file called `DiViMe/Vagrantfile` in a text editor. Change the following line: -``` -> vbox.cpus = 2 -``` -into: -``` -> vbox.cpus = 1 -``` -Then proceed with the installation. Also, if you have more than one CPU, and you do not want DiViMe to take over your entire computer, you can set it to any value >= 2, and you should be fine. DiViMe uses multiple processors, but we have not yet fully optimized for many cores. - -### If your computer has 25 GB or less of storage space - -If your computer has less than 25 GB of storage space, then *you cannot build a fully working DiViMe*. In this case, clean up your files to free up space. - -### If your computer has 6 GB or less of RAM - -If your computer has less than about 8 GB of RAM, then you may or may not be able to build and use DiViMe. You probably need to change the space allocated to the virtual machine. Before doing `vagrant up`, open the file called `DiViMe/Vagrantfile` in a text editor. Change the following line: -``` -> vbox.memory = 4096 -``` -into: -``` -> vbox.memory = 2048 -``` -Then proceed with the Installation. Also, if you have more RAM, and you experience issues during installation (or use), you may benefit from increasing this value, which should normally not exceed half of your total installed RAM (as a rule of thumb). - -### If your computer is running Ubuntu (16.04) +In many cases, the problem will be generic, and related to Vagrant, Virtualbox, or some other underlying tool. In this case, there are often online resources that can often be found with a bit of googleing - and you should add the solution to the DiViMe knowledge base by opening an issue, and posting the solution. -There is a known incompatibility between VirtualBox and the 4.13 Linux kernel on Ubuntu 16.04. What you may do is to install a previous version of the kernel, for example the 4.10, following [these instructions](https://doc.ubuntu-fr.org/kernel#installationSimple), or install the latest version of VirtualBox, which should fix the problem. +If you cannot find a solution after reading https://github.com/srvk/DiViMe/blob/master/docs/source/troubleshoot.md, open an issue and supply as much information as needed for someone else to be able to (ideally) reproduce your error. Typically, this means -Again, there is often a lot of information available online, because Vagrant and VirtualBox are widely used tools. +- Your operating system and computer specs (RAM, HDD, CPUs) +- Your version of Vagrant +- Your version of Virtualbox (or any other provider that you run) +- Your version of DiViMe +- The command(s) that you type and the output that you get, ideally a log file (complete - not just the last line) +- You can find some example log files in the logs/ folder, so you can compare your output against the output we see +- Anything else that may be relevant -### If something else fails +We are monitoring the issues and will try to get back yo you. -Please open an issue [here](https://github.com/srvk/DiViMe/issues). Please paste the complete output of the failing run there, so we can better provide you with a solution. Also, please provide detailed information on your host system (which OS, RAM, CPU, HDD), which changes you made to the Vagrantfile, and also provide access to the data the system chokes on (if any). -### References +## References VanDam, M., De Palma, P., Strong, W. E. (2015, May). Fundamental frequency of speech directed to children who have hearing loss. Poster presented at the 169th Meeting of the Acoustical Society of America, Pittsburgh, PA. From 2af79066d1a17c1349c6071538d5e78ab33e14ae Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Sun, 28 Jul 2019 00:26:24 +0200 Subject: [PATCH 298/299] Update install.md --- docs/source/install.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/install.md b/docs/source/install.md index 7361e7e..1668d24 100755 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -114,7 +114,7 @@ DiViMe is very powerful (and complex), and despite our best efforts, there are m In many cases, the problem will be generic, and related to Vagrant, Virtualbox, or some other underlying tool. In this case, there are often online resources that can often be found with a bit of googleing - and you should add the solution to the DiViMe knowledge base by opening an issue, and posting the solution. -If you cannot find a solution after reading https://github.com/srvk/DiViMe/blob/master/docs/source/troubleshoot.md, open an issue and supply as much information as needed for someone else to be able to (ideally) reproduce your error. Typically, this means +If you cannot find a solution after reading https://divime.readthedocs.io/en/latest/troubleshoot.html, open an issue and supply as much information as needed for someone else to be able to (ideally) reproduce your error. Typically, this means - Your operating system and computer specs (RAM, HDD, CPUs) - Your version of Vagrant From 1fe83b3f6055c92932cdd5bc6b2ccd6fab4bca5b Mon Sep 17 00:00:00 2001 From: Florian Metze Date: Mon, 29 Jul 2019 11:47:20 +0200 Subject: [PATCH 299/299] various clean-ups, and split bootstrap.sh into two parts (bootstrap.sh is no longer used, can be deleted) --- .gitignore | 5 +- Vagrantfile | 13 +- conf/Dockerfile | 0 conf/bootstrap-system.sh | 102 +++++++ conf/bootstrap-user.sh | 175 ++++++++++++ conf/turnDetector.conf.inc | 0 conf/update.sh | 0 conf/vad_segmenter_aclew.conf | 0 launcher/test.sh | 4 +- logs/launcher-test.log | 53 ++-- logs/vagrant-up.log | 517 ++++++++++++++-------------------- 11 files changed, 540 insertions(+), 329 deletions(-) mode change 100755 => 100644 conf/Dockerfile create mode 100755 conf/bootstrap-system.sh create mode 100755 conf/bootstrap-user.sh mode change 100755 => 100644 conf/turnDetector.conf.inc mode change 100644 => 100755 conf/update.sh mode change 100755 => 100644 conf/vad_segmenter_aclew.conf diff --git a/.gitignore b/.gitignore index b8935e5..10cc183 100755 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,10 @@ docs/build/* docs/.DS_Store ldc_sad_hmm/ HTK.tar.gz - +HTK-3.4.1.tar.gz +MCR_R2017b_glnxa64_installer.zip +Anaconda2-2019.03-Linux-x86_64.sh +opensmile-2-3-0.tar.gz # History files .Rhistory diff --git a/Vagrantfile b/Vagrantfile index 342ff62..5a6791f 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -43,11 +43,11 @@ Vagrant.configure("2") do |config| # This needs to be set on a Mac - not sure if it causes problems on other architectures? d.force_host_vm = true # (too late?) - override.vm.synced_folder ".", "/vagrant", owner: "vagrant", group: "vagrant", :mount_options => ["dmode=777", "fmode=777"] + override.vm.synced_folder ".", "/vagrant", owner: "vagrant", group: "vagrant" + #, :mount_options => ["dmode=777", "fmode=777"] end config.vm.provider "aws" do |aws, override| - aws.tags["Name"] = "Diarization VM" aws.ami = "ami-663a6e0c" # Ubuntu ("Trusty") Server 14.04 LTS AMI - US-East region aws.instance_type = "m3.xlarge" @@ -98,11 +98,16 @@ Vagrant.configure("2") do |config| #override.vm.box = "https://github.com/azure/vagrant-azure/raw/v2.0/dummy.box" end - config.vm.provision "bootstrap", type: "shell", run: "once" do |s| - s.path = "conf/bootstrap.sh" + config.vm.provision "bootstrap-system", type: "shell", run: "once" do |s| + s.path = "conf/bootstrap-system.sh" + end + + config.vm.provision "bootstrap-user", type: "shell", run: "once", privileged: false do |s| + s.path = "conf/bootstrap-user.sh" end config.vm.provision "update", type: "shell", run: "never" do |s| + # This needs to be completed s.path = "conf/update.sh" end diff --git a/conf/Dockerfile b/conf/Dockerfile old mode 100755 new mode 100644 diff --git a/conf/bootstrap-system.sh b/conf/bootstrap-system.sh new file mode 100755 index 0000000..91da650 --- /dev/null +++ b/conf/bootstrap-system.sh @@ -0,0 +1,102 @@ +# Please note that the bootstrap.sh script runs as root and not the vagrant user + +echo "---- Start bootstrapping DiViMe @ `date` ----" + +# Some reporting +echo "-- System information --" +echo "uname -a:" `uname -a` +echo "nproc:" `nproc` +echo "cat /proc/meminfo:" +cat /proc/meminfo +echo "df -h:" +df -h +echo "free:" +free +#dpkg -l + +# These downloads take a long time, start them in the background +#echo "c3100392685b5a62c8509c0588ce9376 */vagrant/Anaconda-2.3.0-Linux-x86_64.sh" | \ +# md5sum -c --quiet || wget -qP /vagrant --no-check-certificate \ +# https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh & +echo "000b186207ad0eec7a667f34d82868f5 */vagrant/opensmile-2-3-0.tar.gz" | \ + md5sum -c --quiet || wget -qO- --no-check-certificate https://www.audeering.com/download/opensmile-2-3-0-tar-gz/?wpdmdl=4782 > /vagrant/opensmile-2-3-0.tar.gz & +echo "dd87c316e211891df8889c52d9167a5d */vagrant/Anaconda2-2019.03-Linux-x86_64.sh" | \ + md5sum -c --quiet || wget -qP /vagrant --no-check-certificate \ + https://repo.anaconda.com/archive/Anaconda2-2019.03-Linux-x86_64.sh & +echo "ef082e99726b14a2b433c59d002ffb3b */vagrant/MCR_R2017b_glnxa64_installer.zip" | \ + md5sum -c --quiet || wget -qP /vagrant --no-check-certificate \ + http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip & + +if true; then +echo "-- Updating system --" +apt-get update -y +apt-get upgrade -y + +apt-get install -y git make automake libtool autoconf patch subversion fuse \ + libatlas-base-dev libatlas-dev liblapack-dev sox libav-tools g++ \ + zlib1g-dev libsox-fmt-all sshfs gcc-multilib libncurses5-dev unzip bc \ + openjdk-6-jre icedtea-netx-common icedtea-netx libxt-dev libx11-xcb1 \ + libc6-dev-i386 festival espeak python-setuptools gawk \ + libboost-all-dev + +apt-get autoremove -y && apt-get clean -y && apt-get autoclean -y +fi + +if false; then +if grep --quiet vagrant /etc/passwd +then + user="vagrant" +else + user="ubuntu" +fi +cd /home/${user} +fi + +# Kaldi and others want bash - otherwise the build process fails +[ $(readlink /bin/sh) == "dash" ] && ln -s -f bash /bin/sh + +echo "---- Done system updates @ `date` ----" + + +# Install Anaconda and Theano +#echo "Downloading Anaconda-2.3.0..." +#wget -q --no-check-certificate -P /tmp https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com/Anaconda-2.3.0-Linux-x86_64.sh +echo "Waiting for Anaconda download to finish" +# Anaconda download should be the first background process +#echo "c3100392685b5a62c8509c0588ce9376 */vagrant/Anaconda-2.3.0-Linux-x86_64.sh" | \ +# md5sum -c --quiet || wait `jobs -p|head -n 1` +#echo "Installing Anaconda-2.3.0..." +#sudo -S -u ${user} -i /bin/bash -l -c "bash /vagrant/Anaconda-2.3.0-Linux-x86_64.sh -b" +echo "dd87c316e211891df8889c52d9167a5d */vagrant/Anaconda2-2019.03-Linux-x86_64.sh" | \ + md5sum -c --quiet || wait `jobs -p|head -n 1` + +# install Matlab runtime environment +#echo "Download matlab installer" +#wget -q http://ssd.mathworks.com/supportfiles/downloads/R2017b/deployment_files/R2017b/installers/glnxa64/MCR_R2017b_glnxa64_installer.zip +echo "Waiting for Matlab download to finish" +# This should be our last background process +echo "ef082e99726b14a2b433c59d002ffb3b */vagrant/MCR_R2017b_glnxa64_installer.zip" | \ + md5sum -c --quiet || wait +( + echo "Installing Matlab..." + cd /tmp + unzip -q /vagrant/MCR_R2017b_glnxa64_installer.zip + ./install -mode silent -agreeToLicense yes + +# check if matlab is installed correctly +if [ $? -ne 0 ]; then + echo "*******************************" + echo " matlab installation failed" + echo "*******************************" + exit 1 +fi +) + +echo "---- Done bootstrapping DiViMe @ `date` ----" + + +# To Test: +# - vagrant ssh -c "launcher/test.sh" +# - vagrant ssh -c "yunitate.sh data/" (with a large wav file in data) +# - vagrant ssh -c "utils/high_volubility.py data/7085.wav --diar yunitator_universal --mode CHI --nb_chunks 50" +# ... diff --git a/conf/bootstrap-user.sh b/conf/bootstrap-user.sh new file mode 100755 index 0000000..0781fad --- /dev/null +++ b/conf/bootstrap-user.sh @@ -0,0 +1,175 @@ +#!/bin/bash + +# Please note that the bootstrap.sh script runs as root and not the vagrant user +# bootstrap-user.sh runs as the actual user + +echo "---- Start bootstrapping user (${USER}) part of DiViMe @ `date` ----" + +echo "Installing Anaconda..." +cd ${HOME} +bash /vagrant/Anaconda2-2019.03-Linux-x86_64.sh -b -p ${HOME}/anaconda + +# check if anaconda is installed correctly +if ! [ -x "$(command -v ${HOME}/anaconda/bin/conda)" ]; then + echo "*******************************" + echo " conda installation failed" + echo "*******************************" + exit 1 +fi + +if ! grep -q -i anaconda .bashrc; then + echo -e "\n# For DiViMe and Anaconda:" >> ${HOME}/.bashrc + echo "export PATH=${HOME}/launcher:${HOME}/utils:${HOME}/anaconda/bin:\$PATH" >> ${HOME}/.bashrc +fi + + +# python3 env +echo "Creating python3 env..." +${HOME}/anaconda/bin/conda env create -q -f /vagrant/conf/environment.yml +if [ $? -ne 0 ]; then PYTHON3_INSTALLED=false; fi + +echo "-- Conda report --" +${HOME}/anaconda/bin/conda list + + +# add Matlab stuff to path +echo -e "\n# For Matlab:" >> ${HOME}/.bashrc +echo 'LD_LIBRARY_PATH="/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:$LD_LIBRARY_PATH"' >> ${HOME}/.bashrc + + +# optionally Install HTK (without it, some other tools will not work) +# the idea is to make users independently download HTK installer since +# we cannot redistribute +if [ -f /vagrant/HTK-3.4.1.tar.gz ]; then + echo "Installing HTK..." + cd ${HOME} + if [[ ! -d repos/htk ]]; then + cd ${HOME}/repos/ + tar zxf /vagrant/HTK-3.4.1.tar.gz + cd htk + ./configure --without-x --disable-hslab + sed -i "s/ /\t/g" HLMTools/Makefile # fix bad Makefile + make all + sudo make install + else + echo "Visibly HTK has been already installed..." + fi +else + HTK_INSTALLED=false; + echo "Can't find HTK-3.4.1.tar.gz. Assuming HTK not needed." +fi + + +# POPULATE THE REPOSITORY SECTION +echo "---- Changing into ${HOME}/repos @ `date` ----" +mkdir -p ${HOME}/repos && cd ${HOME}/repos + + +# Install OpenSMILE +( + echo "Installing OpenSMILE" + #wget -qO- --no-check-certificate https://www.audeering.com/download/opensmile-2-3-0-tar-gz/?wpdmdl=4782 | tar -xzf - + tar -xzf /vagrant/opensmile-2-3-0.tar.gz + sudo cp opensmile-2.3.0/bin/linux_x64_standalone_static/SMILExtract /usr/local/bin + sudo chmod +x /usr/local/bin/SMILExtract + +# check if opensmile if installed +if ! [ -x "$(command -v SMILExtract)" ]; then + echo "*******************************" + echo " OPENSMILE installation failed" + echo "*******************************" + OPENSMILE_INSTALLED=false; +fi +) + + +# Get OpenSAT=noisemes and dependencies +git clone -q http://github.com/srvk/OpenSAT --branch yunified # --branch v1.0 # need Dev + +${HOME}/anaconda/bin/pip --disable-pip-version-check install -q ipdb + +cp /vagrant/conf/.theanorc ${HOME}/ +#su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y --no-update-deps theano=0.8.2" +${HOME}/anaconda/bin/conda install -q -y theano cudatoolkit pytorch-cpu -c pytorch + +# Install Yunitator and dependencies +git clone -q https://github.com/srvk/Yunitator +#su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y --no-update-deps cudatoolkit" +#su ${user} -c "/home/${user}/anaconda/bin/conda install -q -y --no-update-deps pytorch-cpu -c pytorch" + +# Install VCM +git clone -q https://github.com/srvk/vcm + +# Install to-combo sad and dependencies (matlab runtime environnement) +git clone -q https://github.com/srvk/To-Combo-SAD +(cd To-Combo-SAD && git checkout 2ce2998) + +# Install DiarTK +git clone -q http://github.com/srvk/ib_diarization_toolkit +(cd ib_diarization_toolkit && git checkout b3e4deb) + +# Install WCE and dependencies +git clone -q https://github.com/aclew/WCE_VM +${HOME}/anaconda/bin/pip --disable-pip-version-check install -q keras tensorflow==1.13.1 +#su ${user} -c "/home/${user}/anaconda/bin/pip --disable-pip-version-check install -q -U tensorflow" + +# Phonemizer installation +git clone -q https://github.com/bootphon/phonemizer +( + cd phonemizer + git checkout 332b8dd + python setup.py build + sudo python setup.py install +) + +# Install pyannote (python 3) +## Need to add anaconda to the PATH to be able to activate divime. +export PATH=${HOME}/anaconda/bin:$PATH +source activate divime +pip --disable-pip-version-check install -q pyannote.metrics pyannote.core +conda deactivate + +#install launcher and utils +# cd /home/${user}/ +# git clone https://github.com/aclew/launcher.git +# chmod +x launcher/* +# git clone https://github.com/aclew/utils.git +# chmod +x utils/* + +# install pympi (for eaf -> rttm conversion) and tgt (for textgrid -> rttm conversion) +# and intervaltree (needed for rttm2scp.py) +# and recommonmark (needed to make html in docs/) +${HOME}/anaconda/bin/pip install --disable-pip-version-check pympi-ling tgt intervaltree recommonmark sphinx-markdown-tables sphinx_rtd_theme + +# Document the version of the tools that we have installed +echo "---- git logs follow ----" +cd ${HOME}/repos/ +for f in /vagrant *; +do + if [[ $f =~ opensmile* ]]; then continue; fi + echo -- git log ${f} -- + git --git-dir=${f}/.git log -1 +done +echo "---- git logs done ----" + + +# Link /vagrant/launcher and /vagrant/utils to home folder where scripts expect them +ln -s /vagrant/launcher /vagrant/utils ${HOME} + +# Silence error message from missing file +touch ${HOME}/.Xauthority + + +# Build the docs +echo "---- Building the docs... ----" +cd /vagrant/docs +make SPHINXBUILD=${HOME}/anaconda/bin/sphinx-build html + +echo "---- Sanity checks in user part of DiViMe @ `date` ----" + +# These files can be 'cached' for faster turn-around +[ -f /vagrant/opensmile-2-3-0.tar.gz ] && echo INFO: You can remove opensmile-2-3-0.tar.gz, if you don\'t plan on re-provisioning DiViMe any time soon. +[ -f /vagrant/Anaconda2-2019.03-Linux-x86_64.sh ] && echo INFO: You can remove Anaconda2-2019.03-Linux-x86_64.sh, if you don\'t plan on re-provisioning DiViMe any time soon. +[ -f /vagrant/MCR_R2017b_glnxa64_installer.zip ] && echo INFO: You can remove MCR_R2017b_glnxa64_installer.zip, if you don\'t plan on re-provisioning DiViMe any time soon. + +echo "---- Done bootstrapping user part of DiViMe @ `date` ----" diff --git a/conf/turnDetector.conf.inc b/conf/turnDetector.conf.inc old mode 100755 new mode 100644 diff --git a/conf/update.sh b/conf/update.sh old mode 100644 new mode 100755 diff --git a/conf/vad_segmenter_aclew.conf b/conf/vad_segmenter_aclew.conf old mode 100755 new mode 100644 diff --git a/launcher/test.sh b/launcher/test.sh index 24e9e76..991d40a 100755 --- a/launcher/test.sh +++ b/launcher/test.sh @@ -40,7 +40,7 @@ FAILURES=false git log -1 echo "$ git diff --name-status" git diff --name-status - echo "######################################################################################" + echo "################################################################################" echo "Starting tests" ) @@ -219,7 +219,7 @@ else fi # results -echo "######################################################################################" +echo "################################################################################" echo "To wrap up, we will print out the results of the analyses that we ran during the test." echo "Compare the following results against the reference results printed out below." echo "If the numbers are similar, then your system is working ok." diff --git a/logs/launcher-test.log b/logs/launcher-test.log index ba298ec..b7d1fc9 100644 --- a/logs/launcher-test.log +++ b/logs/launcher-test.log @@ -1,46 +1,59 @@ -FloriansMBP2019:DiViMe metze$ vagrant ssh -c "launcher/test.sh" +Florians-MacBook-Pro-2019:DiViMe-2 metze$ vagrant ssh -c "launcher/test.sh" +Welcome to DiViMe's test.sh +$ git show-branch +[master] Update install.md +$ git log -1 +commit 2af79066d1a17c1349c6071538d5e78ab33e14ae +Author: Florian Metze +Date: Sun Jul 28 00:26:24 2019 +0200 + + Update install.md +$ git diff --name-status +M Vagrantfile +###################################################################################### Starting tests -Checking for HTK... - HTK missing. You can probably ignore this warning, HTK is no longer needed. Testing noisemes... Noisemes passed the test. Testing OpenSmile SAD... OpenSmile SAD passed the test. Testing ToCombo SAD... -TOCOMBO SAD passed the test. -Testing DIARTK... -DiarTK passed the test. +ToCombo SAD passed the test. +Testing DiarTk... +DiarTk passed the test. Testing Yunitator... - Yunitator failed - no output RTTM +Yunitator passed the test. Testing the evaluation pipeline... The evaluation pipeline passed the test. Testing VCM... VCM passed the test. Testing WCE... +Running WCE module (this might take a while...) +WCE processing complete. Wrote output to /vagrant/data/VanDam-Daylong/BN32/test/WCE_BN32_010007_test.csv WCE passed the test -Some tools did not pass the test, but you can still use others +Congratulations, everything is OK! ###################################################################################### To wrap up, we will print out the results of the analyses that we ran during the test. -Compare the following results, corresponding to your system, against the reference results printed out below. -If the numbers are similar, then your system is working similarly to the original one. +Compare the following results against the reference results printed out below. +If the numbers are similar, then your system is working ok. If you see bigger changes, then please paste this output onto an issue on https://github.com/srvk/DiViMe/issues/. -RESULTS: +****** YOUR RESULTS BEGIN ******. +LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm LINES: 10 DURATION SUM: 296.23 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm LINES: 36 DURATION SUM: 31 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm -LINES: 36 DURATION SUM: 65.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm -LINES: 83 DURATION SUM: 145.8 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_universal_BN32_010007_test.rttm -****** REFERENCE RESULTS BEGINS ******. +LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm +LINES: 60 DURATION SUM: 42.3 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_old_BN32_010007_test.rttm +****** REFERENCE RESULTS BEGIN ******. LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/BN32_010007_test.rttm -LINES: 101 DURATION SUM: 298.637 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm +LINES: 10 DURATION SUM: 296.23 FILE: /vagrant/data/VanDam-Daylong/BN32/test/diartk_goldSad_BN32_010007_test.rttm LINES: 37 DURATION SUM: 31.9 FILE: /vagrant/data/VanDam-Daylong/BN32/test/noisemesSad_BN32_010007_test.rttm LINES: 88 DURATION SUM: 212.22 FILE: /vagrant/data/VanDam-Daylong/BN32/test/opensmileSad_BN32_010007_test.rttm LINES: 56 DURATION SUM: 63.66 FILE: /vagrant/data/VanDam-Daylong/BN32/test/tocomboSad_BN32_010007_test.rttm LINES: 31 DURATION SUM: 24.7 FILE: /vagrant/data/VanDam-Daylong/BN32/test/vcm_BN32_010007_test.rttm -LINES: 105 DURATION SUM: 302 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm -****** REFERENCE RESULTS ENDS ******. -Evaluation pipeline: +LINES: 60 DURATION SUM: 42.3 FILE: /vagrant/data/VanDam-Daylong/BN32/test/yunitator_BN32_010007_test.rttm +****** REFERENCE RESULTS END ******. +Evaluation pipeline YOURS: Evaluating noisemesSad on /vagrant/data/VanDam-Daylong/BN32/test with respect to : accuracy @@ -53,11 +66,11 @@ accuracy report item BN32_010007_test.rttm 11.24 30.80 3.11 0.20 267.57 TOTAL 11.24 30.80 3.11 0.20 267.57 -accuracy report +Evaluation pipeline REFERENCE: detection accuracy true positive true negative false positive false % item BN32_010007_test.rttm 11.24 30.80 3.11 0.20 267.57 TOTAL 11.24 30.80 3.11 0.20 267.57 Connection to 127.0.0.1 closed. -FloriansMBP2019:DiViMe metze$ +Florians-MacBook-Pro-2019:DiViMe-2 metze$ diff --git a/logs/vagrant-up.log b/logs/vagrant-up.log index cd522d5..dfe27c2 100644 --- a/logs/vagrant-up.log +++ b/logs/vagrant-up.log @@ -1,9 +1,9 @@ -FloriansMBP2019:DiViMe metze$ vagrant up +Florians-MacBook-Pro-2019:DiViMe-2 metze$ vagrant up Bringing machine 'default' up with 'virtualbox' provider... ==> default: Importing base box 'ubuntu/trusty64'... ==> default: Matching MAC address for NAT networking... ==> default: Checking if box 'ubuntu/trusty64' version '20190429.0.1' is up to date... -==> default: Setting the name of the VM: DiViMe_default_1562123904987_96609 +==> default: Setting the name of the VM: DiViMe-2_default_1564386654149_44009 ==> default: Clearing any previously set forwarded ports... ==> default: Clearing any previously set network interfaces... ==> default: Preparing network interfaces based on configuration... @@ -203,7 +203,7 @@ or /sbin/rcvboxadd quicksetup all Running kernel modules will not be replaced until the system is restarted vboxadd-service.sh: Starting VirtualBox Guest Addition service. -bash: [3153: 2 (255)] tcsetattr: Inappropriate ioctl for device +bash: [3160: 2 (255)] tcsetattr: Inappropriate ioctl for device root@vagrant-ubuntu-trusty-64:/home/vagrant# exit exit root@vagrant-ubuntu-trusty-64:/home/vagrant# /usr/sbin/service vboxadd start @@ -222,82 +222,66 @@ Unmounting Virtualbox Guest Additions ISO from: /mnt root@vagrant-ubuntu-trusty-64:/home/vagrant# umount /mnt root@vagrant-ubuntu-trusty-64:/home/vagrant# exit exit -vagrant@vagrant-ubuntu-trusty-64:~$ test - - -f /tm -p/VBoxGuestAd -di -tions. -iso && rm / -m -p/VBoxGues +vagrant@vagrant-ubuntu-trusty-64:~$ t -Addition -s.iso -vagrant@vagrant-ubuntu-trusty-64:~$ exit +e +s +t + +- +mp/VBoxGuestAdditions.iso.iso && rm /t +vagrant@vagrant-ubuntu-trusty-64:~$ +e +x +i +t + exit ==> default: Checking for guest additions in VM... ==> default: Configuring and enabling network interfaces... ==> default: Mounting shared folders... - default: /vagrant => /Users/metze/Work/Kitchen/DiViMe -==> default: Running provisioner: bootstrap (shell)... - default: Running: /var/folders/0p/f4ssc1410_sc6_9wkzz2d9100000gq/T/vagrant-shell20190702-5601-7btnlq.sh - default: root@vagrant-ubuntu-trusty-64:/home/vagrant# chmod - default: + - default: x '/t - default: m - default: p/vagr - default: a - default: nt-sh - default: ell' - default: - default: && -mp/ default: /t - default: vag - default: rant-shel - default: l - default: ---- Start bootstrapping DiViMe @ Wed Jul 3 03:19:24 UTC 2019 ---- + default: /vagrant => /Users/metze/Work/Kitchen/DiViMe-2 +==> default: Running provisioner: bootstrap-system (shell)... + default: Running: /var/folders/0p/f4ssc1410_sc6_9wkzz2d9100000gq/T/vagrant-shell20190729-49213-15owjqt.sh + default: root@vagrant-ubuntu-trusty-64:/home/vagrant# chmod +x '/tmp + default: / + default: vagrant-s +mp/vagrant-shelll' && /t + default: ---- Start bootstrapping DiViMe @ Mon Jul 29 07:51:53 UTC 2019 ---- default: -- System information -- - default: nproc is 2 - default: Filesystem Size Used Avail Use% Mounted on - default: udev 996M 12K 996M 1% /dev - default: tmpfs 201M 424K 200M 1% /run - default: /dev/sda1 40G 1.5G 37G 4% / - default: none 4.0K 0 4.0K 0% /sys/fs/cgroup - default: none 5.0M 24K 5.0M 1% /run/lock - default: none 1001M 0 1001M 0% /run/shm - default: none 100M 0 100M 0% /run/user - default: vagrant 1.9T 1.6T 325G 83% /vagrant + default: uname -a: Linux vagrant-ubuntu-trusty-64 3.13.0-170-generic #220-Ubuntu SMP Thu May 9 12:40:49 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux + default: nproc: 2 + default: cat /proc/meminfo: default: MemTotal: 2049736 kB - default: MemFree: 1525300 kB - default: Buffers: 18884 kB - default: Cached: 358164 kB + default: MemFree: 1523944 kB + default: Buffers: 18880 kB + default: Cached: 358112 kB default: SwapCached: 0 kB - default: Active: 243624 kB - default: Inactive: 215320 kB - default: Active(anon): 82028 kB + default: Active: 243108 kB + default: Inactive: 215260 kB + default: Active(anon): 81508 kB default: Inactive(anon): 324 kB - default: Active(file): 161596 kB - default: Inactive(file): 214996 kB + default: Active(file): 161600 kB + default: Inactive(file): 214936 kB default: Unevictable: 0 kB default: Mlocked: 0 kB default: SwapTotal: 0 kB default: SwapFree: 0 kB default: Dirty: 25272 kB default: Writeback: 0 kB - default: AnonPages: 81920 kB - default: Mapped: 9348 kB + default: AnonPages: 81336 kB + default: Mapped: 9324 kB default: Shmem: 460 kB - default: Slab: 37324 kB - default: SReclaimable: 26916 kB - default: SUnreclaim: 10408 kB - default: KernelStack: 1088 kB - default: PageTables: 3672 kB + default: Slab: 37236 kB + default: SReclaimable: 26924 kB + default: SUnreclaim: 10312 kB + default: KernelStack: 936 kB + default: PageTables: 3352 kB default: NFS_Unstable: 0 kB default: Bounce: 0 kB default: WritebackTmp: 0 kB default: CommitLimit: 1024868 kB - default: Committed_AS: 151508 kB + default: Committed_AS: 144456 kB default: VmallocTotal: 34359738367 kB default: VmallocUsed: 11116 kB default: VmallocChunk: 34359723004 kB @@ -308,36 +292,48 @@ mp/ default: /t default: HugePages_Rsvd: 0 default: HugePages_Surp: 0 default: Hugepagesize: 2048 kB - default: DirectMap4k: 36800 kB - default: DirectMap2M: 2060288 kB + default: DirectMap4k: 38848 kB + default: DirectMap2M: 2058240 kB + default: df -h: + default: Filesystem Size Used Avail Use% Mounted on + default: udev 996M 12K 996M 1% /dev + default: tmpfs 201M 424K 200M 1% /run + default: /dev/sda1 40G 1.5G 37G 4% / + default: none 4.0K 0 4.0K 0% /sys/fs/cgroup + default: none 5.0M 24K 5.0M 1% /run/lock + default: none 1001M 0 1001M 0% /run/shm + default: none 100M 0 100M 0% /run/user + default: vagrant 1.9T 1.5T 368G 81% /vagrant + default: free: + default: total used free shared buffers cached + default: Mem: 2049736 525708 1524028 460 18880 358112 + default: -/+ buffers/cache: 148716 1901020 + default: Swap: 0 0 0 default: -- Updating system -- default: Ign http://archive.ubuntu.com trusty InRelease - default: Get:1 http://security.ubuntu.com trusty-security InRelease [65.9 kB] - default: Get:2 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB] - default: Get:3 http://security.ubuntu.com trusty-security/main Sources [172 kB] + default: Get:1 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB] + default: Get:2 http://security.ubuntu.com trusty-security InRelease [65.9 kB] default: Hit http://archive.ubuntu.com trusty-backports InRelease default: Hit http://archive.ubuntu.com trusty Release.gpg - default: Get:4 http://archive.ubuntu.com trusty-updates/main Sources [431 kB] - default: Get:5 http://security.ubuntu.com trusty-security/universe Sources [102 kB] - default: Get:6 http://security.ubuntu.com trusty-security/main amd64 Packages [835 kB] - default: Get:7 http://archive.ubuntu.com trusty-updates/restricted Sources [6,313 B] - default: Get:8 http://archive.ubuntu.com trusty-updates/universe Sources [231 kB] - default: Get:9 http://security.ubuntu.com trusty-security/universe amd64 Packages [294 kB] - default: Get:10 http://archive.ubuntu.com trusty-updates/multiverse Sources [7,535 B] - default: Get:11 http://security.ubuntu.com trusty-security/main Translation-en [448 kB] - default: Get:12 http://archive.ubuntu.com trusty-updates/main amd64 Packages [1,177 kB] - default: Get:13 http://security.ubuntu.com trusty-security/universe Translation-en [162 kB] - default: Get:14 http://archive.ubuntu.com trusty-updates/restricted amd64 Packages [17.2 kB] - default: Get:15 http://archive.ubuntu.com trusty-updates/universe amd64 Packages [526 kB] - default: Get:16 http://archive.ubuntu.com trusty-updates/multiverse amd64 Packages [14.6 kB] - default: Get:17 http://archive.ubuntu.com trusty-updates/main Translation-en [582 kB] - default: Get:18 http://archive.ubuntu.com trusty-updates/multiverse Translation-en [7,616 B] - default: Get:19 http://archive.ubuntu.com trusty-updates/restricted Translation-en [4,028 B] - default: Get:20 http://archive.ubuntu.com trusty-updates/universe Translation-en [281 kB] - default: Get:21 http://archive.ubuntu.com trusty-backports/main Sources [9,709 B] - default: Get:22 http://archive.ubuntu.com trusty-backports/restricted Sources [28 B] - default: Get:23 http://archive.ubuntu.com trusty-backports/universe Sources [35.4 kB] - default: Get:24 http://archive.ubuntu.com trusty-backports/multiverse Sources [1,896 B] + default: Get:3 http://archive.ubuntu.com trusty-updates/main Sources [431 kB] + default: Get:4 http://archive.ubuntu.com trusty-updates/restricted Sources [6,313 B] + default: Get:5 http://security.ubuntu.com trusty-security/main Sources [172 kB] + default: Get:6 http://archive.ubuntu.com trusty-updates/universe Sources [231 kB] + default: Get:7 http://archive.ubuntu.com trusty-updates/multiverse Sources [7,535 B] + default: Get:8 http://archive.ubuntu.com trusty-updates/main amd64 Packages [1,177 kB] + default: Get:9 http://archive.ubuntu.com trusty-updates/restricted amd64 Packages [17.2 kB] + default: Get:10 http://archive.ubuntu.com trusty-updates/universe amd64 Packages [526 kB] + default: Get:11 http://security.ubuntu.com trusty-security/universe Sources [102 kB] + default: Get:12 http://archive.ubuntu.com trusty-updates/multiverse amd64 Packages [14.6 kB] + default: Get:13 http://archive.ubuntu.com trusty-updates/main Translation-en [582 kB] + default: Get:14 http://archive.ubuntu.com trusty-updates/multiverse Translation-en [7,616 B] + default: Get:15 http://security.ubuntu.com trusty-security/main amd64 Packages [835 kB] + default: Get:16 http://archive.ubuntu.com trusty-updates/restricted Translation-en [4,028 B] + default: Get:17 http://archive.ubuntu.com trusty-updates/universe Translation-en [281 kB] + default: Get:18 http://archive.ubuntu.com trusty-backports/main Sources [9,709 B] + default: Get:19 http://archive.ubuntu.com trusty-backports/restricted Sources [28 B] + default: Get:20 http://archive.ubuntu.com trusty-backports/universe Sources [35.4 kB] + default: Get:21 http://archive.ubuntu.com trusty-backports/multiverse Sources [1,896 B] default: Hit http://archive.ubuntu.com trusty-backports/main amd64 Packages default: Hit http://archive.ubuntu.com trusty-backports/restricted amd64 Packages default: Hit http://archive.ubuntu.com trusty-backports/universe amd64 Packages @@ -347,9 +343,12 @@ mp/ default: /t default: Hit http://archive.ubuntu.com trusty-backports/restricted Translation-en default: Hit http://archive.ubuntu.com trusty-backports/universe Translation-en default: Hit http://archive.ubuntu.com trusty Release - default: Get:25 http://archive.ubuntu.com trusty/main Sources [1,064 kB] - default: Get:26 http://archive.ubuntu.com trusty/restricted Sources [5,433 B] - default: Get:27 http://archive.ubuntu.com trusty/universe Sources [6,399 kB] + default: Get:22 http://security.ubuntu.com trusty-security/universe amd64 Packages [294 kB] + default: Get:23 http://archive.ubuntu.com trusty/main Sources [1,064 kB] + default: Get:24 http://security.ubuntu.com trusty-security/main Translation-en [448 kB] + default: Get:25 http://archive.ubuntu.com trusty/restricted Sources [5,433 B] + default: Get:26 http://archive.ubuntu.com trusty/universe Sources [6,399 kB] + default: Get:27 http://security.ubuntu.com trusty-security/universe Translation-en [162 kB] default: Get:28 http://archive.ubuntu.com trusty/multiverse Sources [174 kB] default: Hit http://archive.ubuntu.com trusty/main amd64 Packages default: Hit http://archive.ubuntu.com trusty/restricted amd64 Packages @@ -363,7 +362,7 @@ mp/ default: /t default: Ign http://archive.ubuntu.com trusty/multiverse Translation-en_US default: Ign http://archive.ubuntu.com trusty/restricted Translation-en_US default: Ign http://archive.ubuntu.com trusty/universe Translation-en_US - default: Fetched 13.1 MB in 6s (2,038 kB/s) + default: Fetched 13.1 MB in 5s (2,589 kB/s) default: Reading package lists... default: Reading package lists... default: Building dependency tree... @@ -809,7 +808,7 @@ mp/ default: /t default: Get:250 http://archive.ubuntu.com/ubuntu/ trusty-updates/main icedtea-netx amd64 1.5.3-0ubuntu0.14.04.1 [20.4 kB] default: Get:251 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe libhwloc-plugins amd64 1.8-1ubuntu1.14.04.1 [12.0 kB] default: dpkg-preconfigure: unable to re-open stdin: No such file or directory - default: Fetched 162 MB in 32s (4,985 kB/s) + default: Fetched 162 MB in 1min 6s (2,446 kB/s) default: Selecting previously unselected package libc6-i386. default: (Reading database ... 62899 files and directories currently installed.) default: Preparing to unpack .../libc6-i386_2.19-0ubuntu6.15_amd64.deb ... @@ -1695,34 +1694,27 @@ mp/ default: /t default: Setting up autoconf (2.69-6) ... default: Setting up autotools-dev (20130810.1) ... default: Setting up automake (1:1.14.1-2ubuntu1) ... - default: update-alternatives: - default: using /usr/bin/automake-1.14 to provide /usr/bin/automake (automake) in auto mode + default: update-alternatives: using /usr/bin/automake-1.14 to provide /usr/bin/automake (automake) in auto mode default: Setting up espeak (1.47.11-1ubuntu1) ... default: Setting up fonts-dejavu-extra (2.34-1ubuntu1) ... default: Setting up libstdc++-4.8-dev:amd64 (4.8.4-2ubuntu1~14.04.4) ... default: Setting up g++-4.8 (4.8.4-2ubuntu1~14.04.4) ... default: Setting up g++ (4:4.8.2-1ubuntu6) ... - default: update-alternatives: - default: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto mode + default: update-alternatives: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto mode default: Setting up liberror-perl (0.17-1.1) ... default: Setting up git-man (1:1.9.1-1ubuntu0.10) ... default: Setting up git (1:1.9.1-1ubuntu0.10) ... default: Setting up icu-devtools (52.1-3ubuntu0.8) ... default: Setting up libatlas3-base (3.10.1-4) ... - default: update-alternatives: - default: using /usr/lib/atlas-base/atlas/libblas.so.3 to provide /usr/lib/libblas.so.3 (libblas.so.3) in auto mode - default: update-alternatives: - default: using /usr/lib/atlas-base/atlas/liblapack.so.3 to provide /usr/lib/liblapack.so.3 (liblapack.so.3) in auto mode + default: update-alternatives: using /usr/lib/atlas-base/atlas/libblas.so.3 to provide /usr/lib/libblas.so.3 (libblas.so.3) in auto mode + default: update-alternatives: using /usr/lib/atlas-base/atlas/liblapack.so.3 to provide /usr/lib/liblapack.so.3 (liblapack.so.3) in auto mode default: Setting up libblas3 (1.2.20110419-7) ... default: Setting up libblas-dev (1.2.20110419-7) ... - default: update-alternatives: - default: using /usr/lib/libblas/libblas.so to provide /usr/lib/libblas.so (libblas.so) in auto mode + default: update-alternatives: using /usr/lib/libblas/libblas.so to provide /usr/lib/libblas.so (libblas.so) in auto mode default: Setting up libatlas-dev (3.10.1-4) ... default: Setting up libatlas-base-dev (3.10.1-4) ... - default: update-alternatives: - default: using /usr/lib/atlas-base/atlas/libblas.so to provide /usr/lib/libblas.so (libblas.so) in auto mode - default: update-alternatives: - default: using /usr/lib/atlas-base/atlas/liblapack.so to provide /usr/lib/liblapack.so (liblapack.so) in auto mode + default: update-alternatives: using /usr/lib/atlas-base/atlas/libblas.so to provide /usr/lib/libblas.so (libblas.so) in auto mode + default: update-alternatives: using /usr/lib/atlas-base/atlas/liblapack.so to provide /usr/lib/liblapack.so (liblapack.so) in auto mode default: Setting up libboost1.54-dev (1.54.0-4ubuntu3.1) ... default: Setting up libboost-dev (1.54.0.1ubuntu1) ... default: Setting up libboost1.54-tools-dev (1.54.0-4ubuntu3.1) ... @@ -1766,8 +1758,7 @@ mp/ default: /t default: Setting up libpci-dev (1:3.2.1-1ubuntu5.1) ... default: Setting up libhwloc-dev:amd64 (1.8-1ubuntu1.14.04.1) ... default: Setting up libopenmpi-dev (1.6.5-8) ... - default: update-alternatives: - default: using /usr/lib/openmpi/include to provide /usr/include/mpi (mpi) in auto mode + default: update-alternatives: using /usr/lib/openmpi/include to provide /usr/include/mpi (mpi) in auto mode default: Setting up mpi-default-dev (1.0.2ubuntu1) ... default: Setting up libboost-mpi1.54-dev (1.54.0-4ubuntu3.1) ... default: Setting up libboost-mpi-dev (1.54.0.1ubuntu1) ... @@ -1798,11 +1789,9 @@ mp/ default: /t default: Setting up libice-dev:amd64 (2:1.0.8-2) ... default: Setting up libid3tag0 (0.15.1b-10ubuntu1) ... default: Setting up liblapack3 (3.5.0-2ubuntu1) ... - default: update-alternatives: - default: using /usr/lib/lapack/liblapack.so.3 to provide /usr/lib/liblapack.so.3 (liblapack.so.3) in auto mode + default: update-alternatives: using /usr/lib/lapack/liblapack.so.3 to provide /usr/lib/liblapack.so.3 (liblapack.so.3) in auto mode default: Setting up liblapack-dev (3.5.0-2ubuntu1) ... - default: update-alternatives: - default: using /usr/lib/lapack/liblapack.so to provide /usr/lib/liblapack.so (liblapack.so) in auto mode + default: update-alternatives: using /usr/lib/lapack/liblapack.so to provide /usr/lib/liblapack.so (liblapack.so) in auto mode default: Setting up libltdl-dev:amd64 (2.4.2-1.7ubuntu1) ... default: Setting up libtinfo-dev:amd64 (5.9+20140118-1ubuntu1) ... default: Setting up libncurses5-dev:amd64 (5.9+20140118-1ubuntu1) ... @@ -2017,22 +2006,17 @@ mp/ default: /t default: done. default: Setting up libatk-wrapper-java-jni:amd64 (0.30.4-4) ... default: Setting up openjdk-6-jre:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... - default: update-alternatives: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/policytool to provide /usr/bin/policytool (policytool) in auto mode + default: update-alternatives: + default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/policytool to provide /usr/bin/policytool (policytool) in auto mode default: Setting up icedtea-6-jre-cacao:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... default: Setting up icedtea-6-jre-jamvm:amd64 (6b41-1.13.13-0ubuntu0.14.04.1) ... default: Setting up icedtea-netx:amd64 (1.5.3-0ubuntu0.14.04.1) ... - default: update-alternatives: - default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/javaws to provide /usr/bin/javaws (javaws) in auto mode - default: update-alternatives: - default: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/itweb-settings to provide /usr/bin/itweb-settings (itweb-settings) in auto mode - default: update-alternatives: warning: - default: not replacing /usr/share/man/man1/itweb-settings.1.gz with a link - default: update-alternatives: - default: using /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/javaws to provide /usr/bin/javaws (javaws) in auto mode - default: update-alternatives: - default: using /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/itweb-settings to provide /usr/bin/itweb-settings (itweb-settings) in auto mode - default: update-alternatives: warning: - default: not replacing /usr/share/man/man1/itweb-settings.1.gz with a link + default: update-alternatives: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/javaws to provide /usr/bin/javaws (javaws) in auto mode + default: update-alternatives: using /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/itweb-settings to provide /usr/bin/itweb-settings (itweb-settings) in auto mode + default: update-alternatives: warning: not replacing /usr/share/man/man1/itweb-settings.1.gz with a link + default: update-alternatives: using /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/javaws to provide /usr/bin/javaws (javaws) in auto mode + default: update-alternatives: using /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/itweb-settings to provide /usr/bin/itweb-settings (itweb-settings) in auto mode + default: update-alternatives: warning: not replacing /usr/share/man/man1/itweb-settings.1.gz with a link default: Processing triggers for libc-bin (2.19-0ubuntu6.15) ... default: Processing triggers for ca-certificates (20170717~14.04.2) ... default: Updating certificates in /etc/ssl/certs... @@ -2136,16 +2120,79 @@ mp/ default: /t default: Reading package lists... default: Building dependency tree... default: Reading state information... - default: -- System statistics report -- - default: vagrant - default: Linux vagrant-ubuntu-trusty-64 3.13.0-170-generic #220-Ubuntu SMP Thu May 9 12:40:49 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux - default: total used free shared buffers cached - default: Mem: 2049736 1307964 741772 444 61148 1043652 - default: -/+ buffers/cache: 203164 1846572 - default: Swap: 0 0 0 - default: ---- Done system updates @ Wed Jul 3 03:20:42 UTC 2019 ---- - default: Downloading and installing OpenSMILE + default: ---- Done system updates @ Mon Jul 29 07:53:42 UTC 2019 ---- default: Waiting for Anaconda download to finish + default: Waiting for Matlab download to finish + default: Installing Matlab... + default: Preparing installation files ... + default: Installing ... + default: (Jul 29, 2019 07:54:04) ################################################################## + default: (Jul 29, 2019 07:54:04) # + default: (Jul 29, 2019 07:54:04) # Today's Date: + default: (Jul 29, 2019 07:54:04) Mon Jul 29 07:54:04 UTC 2019 + default: (Jul 29, 2019 07:54:04) + default: (Jul 29, 2019 07:54:04) System Info + default: (Jul 29, 2019 07:54:04) OS: Linux 3.13.0-170-generic + default: (Jul 29, 2019 07:54:04) Arch: amd64 + default: (Jul 29, 2019 07:54:04) Data Model: 64 + default: (Jul 29, 2019 07:54:04) Language: en + default: (Jul 29, 2019 07:54:04) Java Vendor: Oracle Corporation + default: (Jul 29, 2019 07:54:04) Java Home: /tmp/mathworks_20942/sys/java/jre/glnxa64/jre + default: (Jul 29, 2019 07:54:04) Java Version: 1.8.0_121 + default: (Jul 29, 2019 07:54:04) Java VM Name: Java HotSpot(TM) 64-Bit Server VM + default: (Jul 29, 2019 07:54:04) Java Class Path: /tmp/mathworks_20942/java/config/installagent/pathlist.jar + default: (Jul 29, 2019 07:54:04) User Name: root + default: (Jul 29, 2019 07:54:04) Current Directory: /tmp/mathworks_20942 + default: (Jul 29, 2019 07:54:04) Input arguments: + default: (Jul 29, 2019 07:54:04) root /tmp + default: (Jul 29, 2019 07:54:04) libdir /tmp/mathworks_20942 + default: (Jul 29, 2019 07:54:04) mode silent + default: (Jul 29, 2019 07:54:04) agreeToLicense yes + default: (Jul 29, 2019 07:54:04) standalone true + default: (Jul 29, 2019 07:54:04) connectionMode OFFLINE_ONLY + default: (Jul 29, 2019 07:54:05) Starting local product/component search in download directory + default: (Jul 29, 2019 07:54:05) Searching for archives... + default: (Jul 29, 2019 07:54:05) Reading /tmp/archives + default: (Jul 29, 2019 07:54:05) 1569 files found in /tmp/archives + default: (Jul 29, 2019 07:54:05) Reading /tmp + default: (Jul 29, 2019 07:54:05) 16 files found in /tmp + default: (Jul 29, 2019 07:54:05) Archive search complete. 1585 total files found. + default: (Jul 29, 2019 07:54:05) Assembling product list... + default: (Jul 29, 2019 07:54:06) Completed local product/component search + default: (Jul 29, 2019 07:54:06) Starting local product/component search in download directory + default: (Jul 29, 2019 07:54:06) Searching for archives... + default: (Jul 29, 2019 07:54:06) /usr/local/MATLAB/MATLAB_Runtime/v93/archives doesn't exist ... skipping. + default: (Jul 29, 2019 07:54:06) Archive search complete. 0 total files found. + default: (Jul 29, 2019 07:54:06) Completed local product/component search + default: (Jul 29, 2019 07:54:06) Installing Product: MATLAB Runtime - Builder JA 9.3 + default: (Jul 29, 2019 07:54:07) Installing Product: MATLAB Runtime - Core 9.3 + default: (Jul 29, 2019 07:54:32) Installing Product: MATLAB Runtime - GPU 9.3 + default: (Jul 29, 2019 07:54:54) Installing Product: MATLAB Runtime - Hadoop And Spark 9.3 + default: (Jul 29, 2019 07:54:54) Installing Product: MATLAB Runtime - NET And XL 9.3 + default: (Jul 29, 2019 07:54:54) Installing Product: MATLAB Runtime - Numerics 9.3 + default: (Jul 29, 2019 07:55:01) Notes: + default: On the target computer, append the following to your LD_LIBRARY_PATH environment variable: + default: + default: /usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64: + default: + default: If MATLAB Runtime is to be used with MATLAB Production Server, you do not need to modify the above environment variable. + default: (Jul 29, 2019 07:55:01) Exiting with status 0 + default: (Jul 29, 2019 07:55:01) End - Successful. + default: Finished + default: ---- Done bootstrapping DiViMe @ Mon Jul 29 07:55:01 UTC 2019 ---- + default: root@vagrant-ubuntu-trusty-64:/home/vagrant# + default: e + default: x + default: i + default: t + default: exit +==> default: Running provisioner: bootstrap-user (shell)... + default: Running: /var/folders/0p/f4ssc1410_sc6_9wkzz2d9100000gq/T/vagrant-shell20190729-49213-6vqrk0.sh + default: vagrant@vagrant-ubuntu-trusty-64:~$ chmod +x + default: + default: '/tmp/vagrant +t-shellault: -shell' && /tmp/vagran + default: ---- Start bootstrapping user (vagrant) part of DiViMe @ Mon Jul 29 07:55:01 UTC 2019 ---- default: Installing Anaconda... default: PREFIX=/home/vagrant/anaconda default: installing: python-2.7.16-h9bab390_0 ... @@ -2443,148 +2490,8 @@ mp/ default: /t default: Solving environment: default: ...working... default: done - default: Preparing transaction: ...working... - default: done - default: Verifying transaction: - default: ...working... - default: done - default: Executing transaction: ...working... - default: done - default: Ran pip subprocess with arguments: - default: [u'/home/vagrant/anaconda/envs/divime/bin/python', '-m', 'pip', 'install', '-r', '/tmp/tmpDeepCN.requirements.txt'] - default: Pip subprocess output: - default: Collecting theano (from -r /tmp/tmpDeepCN.requirements.txt (line 1)) - default: Downloading https://files.pythonhosted.org/packages/7d/c4/6341148ad458b6cd8361b774d7ee6895c38eab88f05331f22304c484ed5d/Theano-1.0.4.tar.gz (2.8MB) - default: Collecting intervaltree (from -r /tmp/tmpDeepCN.requirements.txt (line 2)) - default: Downloading https://files.pythonhosted.org/packages/e8/f9/76237755b2020cd74549e98667210b2dd54d3fb17c6f4a62631e61d31225/intervaltree-3.0.2.tar.gz - default: Collecting pympi-ling (from -r /tmp/tmpDeepCN.requirements.txt (line 3)) - default: Downloading https://files.pythonhosted.org/packages/92/c7/90b4821910509e9c888d93386e6fe00efaf7dd5ae37fc607391d6838df40/pympi-ling-1.69.tar.gz - default: Collecting tgt (from -r /tmp/tmpDeepCN.requirements.txt (line 4)) - default: Downloading https://files.pythonhosted.org/packages/51/9a/25d82ed43c926e0234c8705e374323d7f9bfe0b311019fe3b1e2e445fbb6/tgt-1.4.4.tar.gz - default: Collecting ipdb (from -r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/6d/43/c3c2e866a8803e196d6209595020a4a6db1a3c5d07c01455669497ae23d0/ipdb-0.12.tar.gz - default: Requirement already satisfied: numpy>=1.9.1 in /home/vagrant/anaconda/envs/divime/lib/python3.6/site-packages (from theano->-r /tmp/tmpDeepCN.requirements.txt (line 1)) (1.16.4) - default: Requirement already satisfied: scipy>=0.14 in /home/vagrant/anaconda/envs/divime/lib/python3.6/site-packages (from theano->-r /tmp/tmpDeepCN.requirements.txt (line 1)) (1.2.1) - default: Requirement already satisfied: six>=1.9.0 in /home/vagrant/anaconda/envs/divime/lib/python3.6/site-packages (from theano->-r /tmp/tmpDeepCN.requirements.txt (line 1)) (1.12.0) - default: Collecting sortedcontainers<3.0,>=2.0 (from intervaltree->-r /tmp/tmpDeepCN.requirements.txt (line 2)) - default: Downloading https://files.pythonhosted.org/packages/13/f3/cf85f7c3a2dbd1a515d51e1f1676d971abe41bba6f4ab5443240d9a78e5b/sortedcontainers-2.1.0-py2.py3-none-any.whl - default: Requirement already satisfied: setuptools in /home/vagrant/anaconda/envs/divime/lib/python3.6/site-packages (from ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) (41.0.1) - default: Collecting ipython>=5.1.0 (from ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/9f/be/e7fcd8545f17902fb96ee62cdbb141f1054e579406fdc7f1da7504c1420b/ipython-7.6.0-py3-none-any.whl (774kB) - default: Collecting prompt-toolkit<2.1.0,>=2.0.0 (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/f7/a7/9b1dd14ef45345f186ef69d175bdd2491c40ab1dfa4b2b3e4352df719ed7/prompt_toolkit-2.0.9-py3-none-any.whl (337kB) - default: Collecting traitlets>=4.2 (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/93/d6/abcb22de61d78e2fc3959c964628a5771e47e7cc60d53e9342e21ed6cc9a/traitlets-4.3.2-py2.py3-none-any.whl (74kB) - default: Collecting pickleshare (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/9a/41/220f49aaea88bc6fa6cba8d05ecf24676326156c23b991e80b3f2fc24c77/pickleshare-0.7.5-py2.py3-none-any.whl - default: Collecting backcall (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/84/71/c8ca4f5bb1e08401b916c68003acf0a0655df935d74d93bf3f3364b310e0/backcall-0.1.0.tar.gz - default: Collecting pygments (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/5c/73/1dfa428150e3ccb0fa3e68db406e5be48698f2a979ccbcec795f28f44048/Pygments-2.4.2-py2.py3-none-any.whl (883kB) - default: Collecting pexpect; sys_platform != "win32" (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/0e/3e/377007e3f36ec42f1b84ec322ee12141a9e10d808312e5738f52f80a232c/pexpect-4.7.0-py2.py3-none-any.whl (58kB) - default: Collecting decorator (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN. - default: requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/5f/88/0075e461560a1e750a0dcbf77f1d9de775028c37a19a346a6c565a257399/decorator-4.4.0-py2.py3-none-any.whl - default: Collecting jedi>=0.10 (from ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/68/42/6309f3871b2f8361764ac5b2fe6719f9c6e6561d9307d8cecda319cf5843/jedi-0.14.0-py2.py3-none-any.whl (1.0MB) - default: Collecting wcwidth (from prompt-toolkit<2.1.0,>=2.0.0->ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/7e/9f/526a6947247599b084ee5232e4f9190a38f398d7300d866af3ab571a5bfe/wcwidth-0.1.7-py2.py3-none-any.whl - default: Collecting ipython-genutils (from traitlets>=4.2->ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/fa/bc/9bd3b5c2b4774d5f33b2d544f1460be9df7df2fe42f352135381c347c69a/ipython_genutils-0.2.0-py2.py3-none-any.whl - default: Collecting ptyprocess>=0.5 (from pexpect; sys_platform != "win32"->ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/d1/29/605c2cc68a9992d18dada28206eeada56ea4bd07a239669da41674648b6f/ptyprocess-0.6.0-py2.py3-none-any.whl - default: Collecting parso>=0.3.0 (from jedi>=0.10->ipython>=5.1.0->ipdb->-r /tmp/tmpDeepCN.requirements.txt (line 5)) - default: Downloading https://files.pythonhosted.org/packages/68/59/482f5a00fe3da7f0aaeedf61c2a25c445b68c9124437195f6e8b2beddbc0/parso-0.5.0-py2.py3-none-any.whl (94kB) - default: Building wheels for collected packages: theano, intervaltree, pympi-ling, tgt, ipdb, backcall - default: Building wheel for theano (setup.py): started - default: Building wheel for theano (setup.py): finished with status 'done' - default: Stored in directory: /home/vagrant/.cache/pip/wheels/88/fb/be/483910ff7e9f703f30a10605ad7605f3316493875c86637014 - default: Building wheel for intervaltree (setup.py): started - default: Building wheel for intervaltree (setup.py): finished with status 'done' - default: Stored in directory: /home/vagrant/.cache/pip/wheels/08/99/c0/5a5942f5b9567c59c14aac76f95a70bf11dccc71240b91ebf5 - default: Building wheel for pympi-ling (setup.py): started - default: Building wheel for pympi-ling (setup.py): finished with status 'done' - default: Stored in directory: /home/vagrant/.cache/pip/wheels/34/c2/ab/1107ef0b833e770faf53b41179884b4bfa6f5bd641dc74e8f4 - default: Building wheel for tgt (setup.py): started - default: Building wheel for tgt (setup.py): finished with status 'done' - default: Stored in directory: /home/vagrant/.cache/pip/wheels/d0/01/c2/7b18446d6ce6b1ced14c50044844180f89a51b960d0799802d - default: Building wheel for ipdb (setup.py): started - default: Building wheel for ipdb (setup.py): finished with status 'done' - default: Stored in directory: /home/vagrant/.cache/pip/wheels/59/24/91/695211bd228d40fb22dff0ce3f05ba41ab724ab771736233f3 - default: Building wheel for backcall (setup.py): started - default: Building wheel for backcall (setup.py): finished with status 'done' - default: Stored in directory: /home/vagrant/.cache/pip/wheels/98/b0/dd/29e28ff615af3dda4c67cab719dd51357597eabff926976b45 - default: Successfully built theano intervaltree pympi-ling tgt ipdb backcall - default: Installing collected packages: theano, sortedcontainers, intervaltree, pympi-ling, tgt, wcwidth, prompt-toolkit, ipython-genutils, decorator, traitlets, pickleshare, backcall, pygments, ptyprocess, pexpect, parso, jedi, ipython, ipdb - default: Successfully installed backcall-0.1.0 decorator-4.4.0 intervaltree-3.0.2 ipdb-0.12 ipython-7.6.0 ipython-genutils-0.2.0 jedi-0.14.0 parso-0.5.0 pexpect-4.7.0 pickleshare-0.7.5 prompt-toolkit-2.0.9 ptyprocess-0.6.0 pygments-2.4.2 pympi-ling-1.69 sortedcontainers-2.1.0 tgt-1.4.4 theano-1.0.4 traitlets-4.3.2 wcwidth-0.1.7 default: - default: # - default: # To activate this environment, use: - default: # > conda activate divime - default: # - default: # To deactivate an active environment, use: - default: # > conda deactivate - default: # - default: Waiting for Matlab download to finish - default: Installing Matlab... - default: Preparing installation files ... - default: Installing ... - default: (Jul 03, 2019 03:27:02) ################################################################## - default: (Jul 03, 2019 03:27:02) # - default: (Jul 03, 2019 03:27:02) # Today's Date: - default: (Jul 03, 2019 03:27:02) Wed Jul 03 03:27:02 UTC 2019 - default: (Jul 03, 2019 03:27:02) - default: (Jul 03, 2019 03:27:02) System Info - default: (Jul 03, 2019 03:27:02) OS: Linux 3.13.0-170-generic - default: (Jul 03, 2019 03:27:02) Arch: amd64 - default: (Jul 03, 2019 03:27:02) Data Model: 64 - default: (Jul 03, 2019 03:27:02) Language: en - default: (Jul 03, 2019 03:27:02) Java Vendor: Oracle Corporation - default: (Jul 03, 2019 03:27:02) Java Home: /tmp/mathworks_22207/sys/java/jre/glnxa64/jre - default: (Jul 03, 2019 03:27:02) Java Version: 1.8.0_121 - default: (Jul 03, 2019 03:27:02) Java VM Name: Java HotSpot(TM) 64-Bit Server VM - default: (Jul 03, 2019 03:27:02) Java Class Path: /tmp/mathworks_22207/java/config/installagent/pathlist.jar - default: (Jul 03, 2019 03:27:02) User Name: root - default: (Jul 03, 2019 03:27:02) Current Directory: /tmp/mathworks_22207 - default: (Jul 03, 2019 03:27:02) Input arguments: - default: (Jul 03, 2019 03:27:02) root /tmp - default: (Jul 03, 2019 03:27:02) libdir /tmp/mathworks_22207 - default: (Jul 03, 2019 03:27:02) mode silent - default: (Jul 03, 2019 03:27:02) agreeToLicense yes - default: (Jul 03, 2019 03:27:02) standalone true - default: (Jul 03, 2019 03:27:02) connectionMode OFFLINE_ONLY - default: (Jul 03, 2019 03:27:03) Starting local product/component search in download directory - default: (Jul 03, 2019 03:27:03) Assembling product list... - default: (Jul 03, 2019 03:27:03) Searching for archives... - default: (Jul 03, 2019 03:27:03) Reading /tmp/archives - default: (Jul 03, 2019 03:27:03) 1569 files found in /tmp/archives - default: (Jul 03, 2019 03:27:03) Reading /tmp - default: (Jul 03, 2019 03:27:03) 16 files found in /tmp - default: (Jul 03, 2019 03:27:03) Archive search complete. 1585 total files found. - default: (Jul 03, 2019 03:27:04) Completed local product/component search - default: (Jul 03, 2019 03:27:04) Starting local product/component search in download directory - default: (Jul 03, 2019 03:27:04) Searching for archives... - default: (Jul 03, 2019 03:27:04) /usr/local/MATLAB/MATLAB_Runtime/v93/archives doesn't exist ... skipping. - default: (Jul 03, 2019 03:27:04) Archive search complete. 0 total files found. - default: (Jul 03, 2019 03:27:04) Completed local product/component search - default: (Jul 03, 2019 03:27:04) Installing Product: MATLAB Runtime - Builder JA 9.3 - default: (Jul 03, 2019 03:27:06) Installing Product: MATLAB Runtime - Core 9.3 - default: (Jul 03, 2019 03:27:24) Installing Product: MATLAB Runtime - GPU 9.3 - default: (Jul 03, 2019 03:27:33) Installing Product: MATLAB Runtime - Hadoop And Spark 9.3 - default: (Jul 03, 2019 03:27:33) Installing Product: MATLAB Runtime - NET And XL 9.3 - default: (Jul 03, 2019 03:27:33) Installing Product: MATLAB Runtime - Numerics 9.3 - default: (Jul 03, 2019 03:27:41) Notes: - default: On the target computer, append the following to your LD_LIBRARY_PATH environment variable: - default: - default: /usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64: - default: - default: If MATLAB Runtime is to be used with MATLAB Production Server, you do not need to modify the above environment variable. - default: (Jul 03, 2019 03:27:41) Exiting with status 0 - default: (Jul 03, 2019 03:27:41) End - Successful. - default: Finished - default: Installing HTK... - default: Can't find HTK-3.4.1.tar.gz. Assuming HTK not needed. + default: CondaMultiError: ('Connection broken: error("(104, \'ECONNRESET\')",)', error("(104, 'ECONNRESET')",)) default: -- Conda report -- default: WARNING: The conda.compat module is deprecated and will be removed in a future release. default: # packages in environment at /home/vagrant/anaconda: @@ -2874,14 +2781,15 @@ mp/ default: /t default: zipp 0.3.3 py27_1 default: zlib 1.2.11 h7b6447c_3 default: zstd 1.3.7 h0b5b093_0 - default: ---- Changing into /home/vagrant/repos @ Wed Jul 3 03:27:43 UTC 2019 ---- + default: Can't find HTK-3.4.1.tar.gz. Assuming HTK not needed. + default: ---- Changing into /home/vagrant/repos @ Mon Jul 29 09:26:03 UTC 2019 ---- + default: Installing OpenSMILE default: DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. default: WARNING: The conda.compat module is deprecated and will be removed in a future release. default: Collecting package metadata: default: ...working... default: done - default: Solving environment: - default: ...working... + default: Solving environment: ...working... default: done default: default: ## Package Plan ## @@ -2900,8 +2808,9 @@ mp/ default: /t default: ---------------------------|----------------- default: binutils_impl_linux-64-2.31.1| h6176602_1 16.5 MB default: binutils_linux-64-2.31.1 | h6176602_7 9 KB - default: conda-4.7.5 | py27_0 3.0 MB - default: conda-package-handling-1.3.10| py27_0 259 KB + default: conda-4.7.10 | py27_0 3.0 MB + default: conda-package-handling-1.3.11| py27_0 260 KB + default: cudatoolkit-10.1.168 | 0 516.0 MB default: gcc_impl_linux-64-7.3.0 | habb00fd_1 73.2 MB default: gcc_linux-64-7.3.0 | h553295d_7 10 KB default: gxx_impl_linux-64-7.3.0 | hdf63c60_1 18.7 MB @@ -2913,14 +2822,14 @@ mp/ default: /t default: pytorch-cpu-1.1.0 | py2.7_cpu_0 53.5 MB pytorch default: theano-1.0.3 | py27hfd86e86_0 3.6 MB default: ------------------------------------------------------------ - default: Total: 171.4 MB + default: Total: 687.4 MB default: default: The following NEW packages will be INSTALLED: default: default: _libgcc_mutex pkgs/main/linux-64::_libgcc_mutex-0.1-main default: binutils_impl_lin~ pkgs/main/linux-64::binutils_impl_linux-64-2.31.1-h6176602_1 default: binutils_linux-64 pkgs/main/linux-64::binutils_linux-64-2.31.1-h6176602_7 - default: conda-package-han~ pkgs/main/linux-64::conda-package-handling-1.3.10-py27_0 + default: conda-package-han~ pkgs/main/linux-64::conda-package-handling-1.3.11-py27_0 default: cudatoolkit pkgs/main/linux-64::cudatoolkit-10.1.168-0 default: gcc_impl_linux-64 pkgs/main/linux-64::gcc_impl_linux-64-7.3.0-habb00fd_1 default: gcc_linux-64 pkgs/main/linux-64::gcc_linux-64-7.3.0-h553295d_7 @@ -2935,11 +2844,10 @@ mp/ default: /t default: default: The following packages will be UPDATED: default: - default: conda 4.6.11-py27_0 --> 4.7.5-py27_0 + default: conda 4.6.11-py27_0 --> 4.7.10-py27_0 default: default: - default: Preparing transaction: - default: ...working... + default: Preparing transaction: ...working... default: done default: Verifying transaction: default: ...working... @@ -3052,8 +2960,8 @@ mp/ default: /t default: Best match: joblib 0.13.2 default: Downloading https://files.pythonhosted.org/packages/2c/7f/c1da4e341d81840c2fa46d583cbc92bb02e5274fe601e9cbc72bcb78b2d7/joblib-0.13.2.tar.gz#sha256=315d6b19643ec4afd4c41c671f9f2d65ea9d787da093487a81ead7b0bac94524 default: Processing joblib-0.13.2.tar.gz - default: Writing /tmp/easy_install-TTrxOO/joblib-0.13.2/setup.cfg - default: Running joblib-0.13.2/setup.py -q bdist_egg --dist-dir /tmp/easy_install-TTrxOO/joblib-0.13.2/egg-dist-tmp-LNl2JK + default: Writing /tmp/easy_install-WZQDCy/joblib-0.13.2/setup.cfg + default: Running joblib-0.13.2/setup.py -q bdist_egg --dist-dir /tmp/easy_install-WZQDCy/joblib-0.13.2/egg-dist-tmp-WhDswX default: warning: no files found matching '*.rst' under directory 'joblib' default: warning: no previously-included files matching '*~' found anywhere in distribution default: warning: no previously-included files matching '*.swp' found anywhere in distribution @@ -3071,13 +2979,16 @@ mp/ default: /t default: default: Installed /usr/local/lib/python2.7/dist-packages/joblib-0.13.2-py2.7.egg default: Finished processing dependencies for phonemizer==0.3.2 + default: Could not find conda environment: divime + default: You can list all discoverable environments with `conda info --envs`. + default: DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. default: DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. default: Collecting pympi-ling - default: Using cached https://files.pythonhosted.org/packages/92/c7/90b4821910509e9c888d93386e6fe00efaf7dd5ae37fc607391d6838df40/pympi-ling-1.69.tar.gz + default: Downloading https://files.pythonhosted.org/packages/92/c7/90b4821910509e9c888d93386e6fe00efaf7dd5ae37fc607391d6838df40/pympi-ling-1.69.tar.gz default: Collecting tgt - default: Using cached https://files.pythonhosted.org/packages/51/9a/25d82ed43c926e0234c8705e374323d7f9bfe0b311019fe3b1e2e445fbb6/tgt-1.4.4.tar.gz + default: Downloading https://files.pythonhosted.org/packages/51/9a/25d82ed43c926e0234c8705e374323d7f9bfe0b311019fe3b1e2e445fbb6/tgt-1.4.4.tar.gz default: Collecting intervaltree - default: Using cached https://files.pythonhosted.org/packages/e8/f9/76237755b2020cd74549e98667210b2dd54d3fb17c6f4a62631e61d31225/intervaltree-3.0.2.tar.gz + default: Downloading https://files.pythonhosted.org/packages/e8/f9/76237755b2020cd74549e98667210b2dd54d3fb17c6f4a62631e61d31225/intervaltree-3.0.2.tar.gz default: Collecting recommonmark default: Downloading https://files.pythonhosted.org/packages/9b/3d/92ea48401622510e57b4bdaa74dc9db2fb9e9e892324b48f9c02d716a93a/recommonmark-0.5.0-py2.py3-none-any.whl default: Collecting sphinx-markdown-tables @@ -3132,11 +3043,11 @@ mp/ default: /t default: Successfully installed commonmark-0.9.0 intervaltree-3.0.2 markdown-2.6.11 pympi-ling-1.69 recommonmark-0.5.0 sphinx-markdown-tables-0.0.9 sphinx-rtd-theme-0.4.3 tgt-1.4.4 default: ---- git logs follow ---- default: -- git log /vagrant -- - default: commit 5606fa1ceae6563a25f784a9a15b1eed41a21b50 + default: commit 2af79066d1a17c1349c6071538d5e78ab33e14ae default: Author: Florian Metze - default: Date: Wed Jun 19 07:16:09 2019 -0400 + default: Date: Sun Jul 28 00:26:24 2019 +0200 default: - default: installation partially downloads in background + default: Update install.md default: -- git log ib_diarization_toolkit -- default: commit b3e4deb2465b36270cec0c934bd3f7be2f88e3fa default: Author: riebling @@ -3170,17 +3081,17 @@ mp/ default: /t default: default: added yunitator mode default: -- git log WCE_VM -- - default: commit ccef86bc3d23c24ace8a8c10d77de07fe274b65c - default: Author: orasanen - default: Date: Thu Jan 17 10:27:35 2019 +0200 + default: commit 0f78f59b9be6e9ed56367c3c81feb707638b5f2d + default: Author: orasanen + default: Date: Wed Jul 24 13:10:16 2019 -0400 default: - default: added WCE out-of-the-box model + default: fixed rttm_to_wavs underscoer bug default: -- git log Yunitator -- - default: commit 5f062e444351ca29c10bcb449b9afc8a1a34900b + default: commit d4b8b36b90347b7740a7d6835ffe119665e45049 default: Author: Florian Metze - default: Date: Fri Jun 21 20:11:31 2019 +0000 + default: Date: Wed Jul 3 01:05:08 2019 -0400 default: - default: better to specify the shell for extract-htk-vm2.sh + default: Delete 1-confidence-vm.py~ default: ---- git logs done ---- default: ---- Building the docs... ---- default: Running Sphinx v1.8.5 @@ -3208,7 +3119,7 @@ mp/ default: /t default: writing output... [100%] usage default: /vagrant/docs/source/formats.md:9: WARNING: None:any reference target not found: praat.org default: /vagrant/docs/source/formats.md:9: WARNING: None:any reference target not found: www.lena.org - default: /vagrant/docs/source/install.md:42: WARNING: None:any reference target not found: homebank.talkbank.org + default: /vagrant/docs/source/install.md:49: WARNING: None:any reference target not found: homebank.talkbank.org default: generating indices... default: genindex default: writing additional pages... @@ -3225,13 +3136,15 @@ mp/ default: /t default: done default: build succeeded, 4 warnings. default: The HTML pages are in build/html. + default: ---- Sanity checks in user part of DiViMe @ Mon Jul 29 09:33:25 UTC 2019 ---- + default: INFO: You can remove opensmile-2-3-0.tar.gz, if you don't plan on re-provisioning DiViMe any time soon. default: INFO: You can remove Anaconda2-2019.03-Linux-x86_64.sh, if you don't plan on re-provisioning DiViMe any time soon. default: INFO: You can remove MCR_R2017b_glnxa64_installer.zip, if you don't plan on re-provisioning DiViMe any time soon. - default: ---- Done bootstrapping DiViMe @ Wed Jul 3 03:30:01 UTC 2019 ---- - default: root@vagrant-ubuntu-trusty-64:/home/vagrant# + default: ---- Done bootstrapping user part of DiViMe @ Mon Jul 29 09:33:25 UTC 2019 ---- + default: vagrant@vagrant-ubuntu-trusty-64:~$ default: e default: x default: i default: t default: exit -FloriansMBP2019:DiViMe metze$ +Florians-MacBook-Pro-2019:DiViMe-2 metze$

)lhT+!{@^Of;nYunA01-<+>!UJ;(V&H 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�GVPbGqZtHDmOm z_lciM=__({FWge&@_WP;OD;(kV6GwN54DD>To3 zqV>mF#ok!Zsc4RQtYahAw+@klvh3(vF|JCCIS=w7GKQkxkN6TjQ=j9_Ut=FDI!}GT zI*IP9q96Eq=K2wR>Ss2)cpc}uUx`; z1lzs|yVW0C>?RI=lo-NCc4;Zlfa2J&@c5^n`m_G zPblLA*Kwb#FT+FE;k)y2{RAX?ArdUs^CnbU$z7ij`4G8^Y{XH@B2jCR!FhNkdlIui z_dt5bu(~I(A9t`yZ?PWBvApfzry_8g_+$iej!#HU6qLWhvqg7fv1W%7={*6Bu#(xW zM+O(d`-`BlK)#G53*4GHuSF6@Gs}VKo3*UbVdQKt@t9|fQ1sXn=fma4A1+B2Oq{qV zzMAk`GyJS}?BJ^KS3Tsg9wQRHv_;e@KUWukS4H>KN6h>#va<~N_{GnINZm9fDGCV^ zwY*-mmPvM`8s1zfe6&?~-=okwGm+<>czjFX*1}{59QePYx1#82ai6$_IE#8Aa~i-7 zVGZlDk~^N~zF*MGY0(M2&|ItFcX6Ku(DWjj>na}Z67<1P-mSs2x-nuAGe6AC??Zu3 z@L^pzpgdpYz#Bio`**_!l@qn_Y%JnY=$jlFX@(~{i_uMIz4mg?CCJz<{t{6!fftN} zidUHH?nFL2KzvBV1n;miA`U8aoQQ^6#K%Ry%=}PG^o17K0?|FG22nphbGgesZb7v$ za=Rz^P2^?#P@xp>|3>#0gxa0a1cP|~Y&>Go7k)O@ZY26a^kXl>6~(!G5Ved^a6nJi zcRF#uL3l42m{(!^+HCB*@}rfTVU-7CYeYTM7dYC1XWg8&766dAYQ&|7rq4M%FTLqQQm7hMIC5?77JmgGfyh!ahs ziJUpWiHSZP;jBbOt||u|t3y}O{cjSsyA3mL03X%B&Q&J9l!Uv5@mY}z5vZtF$e=(2 zKj%&Yn-GfcD|+0Ab8R#yR}_J>MJ%H#a@7lYs>_M_Pj&^#M=i%Gnbh&U&p@xE}U zE`07h(mtEm&q1`(9JJGA?tXzWeomxPW!5MbJn#VSRgJmUfuClxld6NX_lMuIVu5O* zNj=c867)%nJ;{gN%ue<#CmfldpOc|b0q(FAD>W5gVl1QT#Jp>BkJ8AA=)`Fu4Ps3` zGKZf$UGy6keFEPjD<9C}KUg`@QRyz&|VARfw7FXKin$3i*aa^P0;8#eDi>r zZ06@LW}7#WCN&es(i{8Rk?5-MoBJ`7mQZOh z5*!^1|NMvb7nVfyj808H;s=~8deph0PJVP)NoHSy*{0#IB79}xH<5b?zzH{?@n%+U z3UvOLpIf2$P-JmF)?^`QGdiR${>&xqW^n*;tYPn$+LOlJ7)L^t+17u+~?~cnqm)p6N>cuc-p=N@!kj@D6+V-S)a#nh0F?U!;==7M$rxPApiBF!*}!hU1%cEr$Q6# z#TsN{j$fc#1?HCxY4z~GVB$2QQ&9yt;tKb>$Y{>PVIQI6DCoDFSXyp& zE!~I!bY@18>>_g#X>X2J4#q1ULDabgS*l^o%mcSI!zUkuH?toPE+>^oW!MG2p@z5$ zHBM`Z4xPrMD@x^85l*$)3Z)vbTZxeVg)=;yBPr?;vO~-3)G~}`H|)2nQ8`wTx{jIb z_zw~_J7TtFUq2g7xSIDCk(pW#_f2HAo3qavNUS)mGypl`6iewHK4U(1rgMpVEFfC< z3L93DsO>}Q)E*HLiNjkX0%kxB4Zf@X2t!zXzx=^c}kxn8Lq_bF_BSgusNF_N{wyBat@ylVHq@7&3 zOnvD;$~AWUg{VUAC3WV^w;EW`F7{BO+(foHX|NQr?l5yRmG`a9okk&Jtud4nV(Syf z-$VzEO}Rla$hb<{Gu4Sl7rF_dd=msml4fUt>xx_=334! z?PN^Tx9Tm8T0CQ+agG?@Q2uJdQx=C3+~P!@2T7CY+93K$wFEod!)k4=HclDO zjafzsqqz}kbkXbTUSlpNYL_sEP``bMTH!fXb==vnbS4AE?pQ{IvJLe(sfh$ll*=d$ zmAP_7xs|+_%4eCUH>EGxFY2q;OF4;Re!+8b+b`+uB03S|rdD~8nbW+&3?~@3jhvho ze4KdZ6yt;Ow^`0y%Sc|Cq8pQD)kj{RBEyE`sPs|ptz=W{svnj6NFlSD<>bNNaxO-(m8u0r0;5ZuknRuE{5|HBx_NqOeTIHjpKKg8rW@7ttAQecA=*;C zHRtlSGhOB}W1SHux_D6avV#19IJdSdHQ#UKnaXN)w0c9?tCUmEs9T|C0X4mP3w}wW zJXGeg$_14tbf&qBe>aYNSP|(hT5F5-*vMd9H9An=9AY*z*6TI(+Z*7oitL3o1*NSnaTHSBMIZleR0VoL`)) zT+du(Tt}Tz&L%G1^~{~mQ^#}9J=e8BEw2R0zZ`Sul(JHq=D2A^m<#nd?WVRyOQsjo zn{f9?ZF?XPsH@G@HfzoFV@7&vTyvs3Tp;Era|(D6-2fga6P)#&@01PlXyVHy;LISU zr&?9*E1!4Jw}de*v)bT$=0gV_vKCVHpPr~@I_swS!Q4pg*BJ6snaCZ*)BmNpl@|{9 zD=|B93~L=s6fYgsW7FhKvMFVC+$Msz)efVUKb5o-Th)n*xLnwPnPixz+XvAy&ykjI z^puG;dvV&@C+jc##?ENzL0GgtWIQs;I$Ec=GDbDfLyIJ)EhXlhjnIqGnVk z$idPUD!6L0j~ZsBHj5aC^jPg=pkkn=Hbvj2Z_suJ>S+OeztM(X9%C%9-gv+(9nYk# zN=Mb}EbZ*;obNpDyaM-JR9~vuoL$taN-24!v=6VNsD0BcY1T9H=sh(>>!=;lifTUs z;{rJXF9U0|5dDFE%1CRzHCJFG(%=!+V4oXG_1a^yn;*#+9HS?RN^b;P8pw&H&*hpj z{TrlHL{t7Ho7;yt{SZepELlF{>g|d7$KxFd6#PD_uV=`9IYPGSLC{wIf&Au{lcO_I zE1l_J>6JG~t2woApdC&QIFc?|$*qp&N8=IMhe!Hb&85%N_vnB0L&if+FRy9#H6n~< zMmbh28U9jxBGBCv&nnDGChl)}fjo{L2Zd3{1rjeKaN1=c~Enip~f|6!Bv zk*(YycU2my1J%ZADfObVMQ$ctWDnbx3~WXzqa!cpe7>WL#uoC>2do%#1HEK2(0%Iy zIdV?n<7CpDcQ=pX5}!K8R?BUJr!E>tJxUe-@q$vfTuB;xWP6lLOHA~Q&TxNs}}clv8I)KufP{!OoItT&pOx2S<%MC^YEb(Wye9fdi$`WF&fgpM-* zq3_?Tot>N1=kjh=F}3`W?2M1`Y_S*-b`DQYtDd2 zyO)Vz-lGpsd8HK@=Xg1{YN(l=MbyU1RdUfLcK9g%2fe1@hAd_yx@R;q(;BPvi_mF? zUP!O6U(j0^Cyb)>5W3IUuHjj($Io1cx0WBj?=?{uhsKI(vp_ z;{F%uDA5X9>;?gpfF@}|zSWJCY?g;Ait0XVy|J&;xT zLLZ{71pgTl5>{rNbVOz#J4E8a38pq2E@O<;~nG#AMp(o$x1RB61|#K zc_B!NUF6^P(uuZ+6bk>JB~DYCYMYY8C{M7z68of8><)TB#rF7>u~KHaF6f4bd~yt3 zW@UOLMUvZzB{rUdE?BF`hb7_FoE6SZUb`+)u37ZcnL!4m5qq7{@Q?~R#&j%!CWGaU z$ay+?A1z`>kQYu|Lxsn`U?A#pa{5ZT8C|DOQ9iS!dCshXH&vLJ%LLFr2dOOfKudwZ z64{~=>^|qP^ZH5Ool~stYicS^k3F0WnE5wwBmc@# z@@=^bHNL;4mh?=Sgiq*V&$9#H{4V>U2uEXkDkz~`czw^oX&lBcyN%Cq%XnvGM~3Tg zAjd7Ep83>_vZk;@*u|QUq6#@iswW?pS11RSRZ2Z&r2K^%$=U3UYU1VBv2$3aF^61g zJ)^LZ!f+Tpj2ifQ?Lh84#bOR3dX|?x@>oYDGO^pGD)Kr!$L_5ERjkDWa`|iMeKLVg zEUD-?wF_)dZ%(0aj%LZrj->@1ZdX`N{NGcFCpA~Z3%E`vmt5Gns-V4IgMn%aUg#)! zscl%zEQve#=j>=FpwGhO9dc|+50^u*13;()CRgV!C5Zt)8FmsRW!Ka!9AO_sX{ zodY}|I;N6^&PBy}Jv_aR?7a>ljdAR*a`K4+=%w@QMc!e(@{o@V2CH)ri?xhCIbY=> zic7f;AGDL3FpfKP9mxjPAf8=(0dk1h$Rw_%=Dnra$7pPHH=5!ZyP@nDGp}jUYo?Cb z-|P&wU^Uuqg4L8A45#fd>WS=szDikG|BK27rHYbAsf;&XTM5QDZU{##ld6L;X+#GU zk);XcH3F&a%J{pmdS%EE##-&!6&@gtk(=1jaCSt)+0*?ZqSTn!!brMf_hz*#u-@D7 zZ9iG(KyN(c_g$buHc;~(u%=Vxmz^A88~QEZftMPP^M8nkxtzV4>1cx7u1EG9VB(9@ z5v?(}uSgJNTj+GQ$t({($uct%Ny=x>;O-rXdwjH4V!`WC4}VzdDTgZcl`={$WtrTD z9!cfEnk<%|gMNDhPl+?MUb6y2(A%BJvla)NvyckjE1+{$l5stQH-C`4atA9Z)^9Rd z(xKq1dJ;XZ$n&}qft-Pai;9HCaLr+2D@)11FXFHA>>TQI#eAX+K5FTH(KTv}^o#Y) zpV(J=DEcTK{)oo&yiO!<2%7lK89Dr?c3l6`%xCTA8ed^!eOK=C=-#cFs|j6?r1Lq1sdV4_1D>5~4m;Mk{-i zwMu&>3Xf$7_@@IPkY=*C3#Jo=jULTNU#lNRlyTD70}p00ud`d(2S0YfPN$=H#vOLJ zoL^5};(K(5Sf`ZIbvU35XofP<8Z2W&a(a!4Xl-K$myQaY?&ytZs~%C4g~W?;5oNte ztTPXh=)>&khmrg8Aw3=O5CC=cM>A4Jdu-gG&6{;YU&{fNI$g0Gj7E!a;yX%s8ek(#JdSkr7M6c-H;AVfa7MH9P^q6TvW%v*@ zgNy1%l~M0Oaz3DaWsq9skby~P+*d?wi;xW*PNb|L=;kg&L?WSeZANs|%8w5%`Y_kS z>#WVLRrR~S2e zuiTRC=xJo&0Flf_=>IK5*XZyB4kR;K<*M*@U+{$YSnu1!s*VzIs*8nhi-gTaE3{{9 zN68DFKoZcENY7ETINc8K8E1_Q<{)AW^}t2ULZd(8+=H9M`?iytEDtXDGdQId*u4b# z4z@3ca#X%1ALX}u@+f*j?w6i|z8#5;O$QPp6Mn=;;u8_XKz}3kx8cba_+&xEzD}{G z>xcoZwVpuRqxdD0=qR!n`F(6vf@16We<^g~^kp-tyNflsSvKVX+K7_?U_x~k?wdk2A` z*+?&i+W5X#iCG)ieCmW*k7&HT^59gGV7o7X0ulA5CBf-jf)Y*P%6DkXtZ-seB9A}8 zV!t&@pf97%&E^SwEPv6JWy$gc9FcgQZRvVd4xH$3JR?8c8pYp-(Ujwm z%*SZ&dGKcwbki-QbrW>yh`tgT-z)f@$*}MOB{Q6is!Ljr7vhJPMYqTY;4hnFp$4&j zwfKI)8jD`~PLHaTSemxbGAD8O+(gJl%}*2=h+k-i2(-XhBC$UmUGbI5vY)9aCE)!; zB1xynIMm{Eo1sfr_Wa^38*yr*j~T7QyUfS?1+cv>Kq`cwN8TYnPq2%F>3G}-*>qbQ zvB24}FlF#^`hz}hz%vWOcg^S#vWT5!1pRC8(PcMOo{kh8C5F=ue5Vhz)G1{3552A` z$*1A1;UEu3k|+C{7dU0K4NSu;hro+KO)ipz0fnqi74eHqV>c`FkTW}+kkex z&8xrp0NGwn_t^62^$A3IC9+G8S({I2)+yMQ7*@9qve1LQNJ+34bJ%x?o=U0Uy&6Qt z)7$5eq%ojhmxJVMgs<|!x{MB+iGMMf)e0t4yBVF4G0{W34Cdr_yO|rI`%M?6rp3 zS*2-aHmQgwG*I00J0h1}FYHp%dhr(=WrB}NPpu!p9>@6PeO$_)g6W%^ClgfnqEB1& zzwK;qLS6BWB(eML@oDqwQ-8LLxoI?v&Hehfo+8QFUw707;Ze@EhNZTbtLQz<&i1Qd z#eFaKy~FK!>yOg@1l`cDn)_W5&P|TJ>Rabc^{iCL-03}^W}BJGyF7XFpueOw0bPF_ zc%G2bSJ>JhmkX%=FTRIA@_&2!>HDukKRq$Y6aG`P#!il}9Xje;JOAs5Lvj(9D`ocN zR@&#u!@LphVIj>_D{#T{ok&6z=XK>^LhJ7{?d)<*-znp!_T*1OV4QzM+=2M(zQ_6! zE1A@Qc!S}1uIJYqTKyEmPHSy;g{C+X)+qc!iuS>s9hcnKf~zP>u;vWY`Z{gLl7xr; z;6KXu^MR$xR&A=CQcso;EYDEx8Y}f^OH&TJ-UY4lTvG~#P7X^geUQf{{ivU|QY7u| zSSJ6YUX;6X7~&D-yPDU`s=YJ1+G)+50qlvkG3J6)$urMaAg;A<$nWhx>-^r9(9)MG zey2A7Py640|C!*!juLZM0>|tso*eE>>S43QpGCfbx<9bPu|V6S?;;Kx5qRj!DxEM= zyRLY3DP8D6XTOl{slr3Mhn)}VqoRkzF|7?Z!K8a=lX5MNiXCh%Hu#$ zy_b<9kj-%-F!%R1-{ph{)|sI7a(3x^5;>@xXL)jG>U}9crMi{!R;sy4zF2jn)FH)P z)y&PhN7*ffTCK=yT+r(T{-uBAdF_mqB+yvT<)~umc5kbxe`G>Mf3!c;C?K6M+gp*! z4Y|K^P-^WQ7nI*|$jTBv+1?vB)pEwHiH-0(NcHz7gQ*8QCR>Dll1 zaaVqpGE*pDR6XRf@jm!^(nHdeklpfVHHGV<{?J|0wcp*!bxI0tm+B-W2XK*{5kH!tv6F&9sN-1^T79Ozut z&Ti&>8}upkZrJ7&JtK-G*`HKTzSf&Pcu>e6#p(3vE9|I*i{-Uub{)~1k*E$#z)p%!9_a>#Jw^Deaq}!6K>C2|55|JlM zXqxRweLVm*Ty z71(Y5?ulEeC?z&;0mHc)qE6JbUz7YTTKn42Nwsth4Ur0A^($Hhx zb0MvgjtxH^aw+ViJK)OYx}@a`>`KsnuaB$$r|g%v(Zzoi{$4%$@(=Itr(dP7kA9u` z{qNT@*Y+B!|C^P|*kS$c?CC1)?&;WRMtXE_C8fQ0WKb_pN=-O3`xWf5`-~mro9_AhX(NnC|4FM1)-*^hDA#d!@J717ySlsD+a2Wu*KqZWYlnJA9;asZ zY;~uSJFE5OL5_#+d#-3_FC{yX%pvR|n)#P$xe~6#?T zC8gW;PIEOrLId(T-2y}blo0c^xl?MH@Hu8pAU-~6LLT|5mciJj>TXx)@6fcNZ9_bv zJ45dTbqRSNJl;7^?dRAjfA9n;Eu3$qD#i$Z&cIAli!0|ltzXpg`AogB6lrt_LP2|a6m>K?jgN8$d8m}kU0Zo< zA0?~3!O@G_gT8v_xbCd)NUH={*eg~O;x#?YT4V?w1_qGtGWGO!A4e%y&!F|*B8=Lv zv~~1y_wckL^3_BsE9argae@3&dau+`4$D~_f6J@YxkRiwDNnU=R&`e?DXYBEyCo#r zdn(BC&T{2-M>~2b1=YWl4$i`!#cFB!m+Q6?=UAe)0^2^{IgERCruyuuRodP!<+t{k zM>H+rm+y2;v6#Iv6=Qz*{!Pf}Kc<;xHb-)Kg`HLD>#C!ccAZx?y6(F5pgzHo-h1BP zE-koz@E6xOcdTon^O-{@3!h-j*0bv;wEKF%H&AO}e2$9=ywqIr|M{yK?-EXEwT$!$ zd#w{n4tt|C*tybiPC4ez>Rj!7>w4@t9Fi}1LvYLRc(m|F*GTr6y`+Ao;<%zmXp6NX zfwTVqd>7(x#r01Z?T?8Y5dWWk-l(XBT8p(a=3GZwshzsh>2kFVUK#o`MhLkjt$87Fe(UjeT?BTh8jJr=H_BzjH8Se2|um(`k44l z)<83jmP<+@e~@=8i>1@*eD^c3EUDDSj#ElEb&^!WGr=i&ZU?vWoOT}wPU9KlZSQ`e zG*gSo+00^ggs~&;WMI8E(pN5_PGG0s=j$E+z}L;UJGR)L+cD4L7RD9zKQ%^~jUBJ0 z8cGdUaZe3zim;xc)q*mF&JBJRb||D-$ef@GK}9^J)J=+IwGC|03;C18U-IRPi~m*r z=l<`(zgGUt5+4D>-~QAr{kXp-(g=bzuTzhh?U06p;CnUhILM=2GrN?>Ykg< zp6(YO%k@Zo=_=}(;!2}VAkWP?sMZ#{p0(Lf?IC71YT$|+w*tEjIy;)nt@*|Re{JnQ zy`$dFUpirXK+$3nF8ZUjQhGSva$$$tnamxl+;VmD-UI3yfoCCn}(_+q0>x zsj6gheo=-y2Y6n2MtZV%Cb>??jh&aB6V-vPiSFgZ6dTUBv$4cjX*)ktkDWx4m_@7!G?2C?e+TcJn zZCc-hsK14bZJuWSCWyUIC;*0xm|IyX6+J7-C6jOtQqbuM1vLi+B;%0-=D z)M!Vn(MH>Bwvi7@=gd;9QGlm_3f3|PwgvJAn(7DjGJ(wG)hC*1?c-WHZAQQuC}M%h z#Y(+$D(YM^dUKo)U30yky)S}NxJRiU$*TWwzEwjUF9L0ibmjn~KIoT>+EC-Hnb}h0 zzZ~hQh(1W2n8!SCT=K8dbDQtTsE^k721X{FO31F&x6YfTO-|}G&X`l|HO37yLV2p> zRTRf}E#8Q-vY97r1;6Kqb)CNFFYOmpQWrHAY45b1`XJqJxlrb8=1R4EHlv zX;&rrhEl>Arex-fw`riGQqmFrHQ1xRb`PnO^Pbw?C99|83`!yOyENb2saG|&fsYua zH3%qib$mwy>7YhweXm|sPo)jhdg;aO>rxS=plhLPy?cqr&y3f*t~pP7SA`@EIql6A z^iNO+cV~5g?6bc*j;XnopH{rqUrX)p5ZGki)*9*0G}AZE_d4Ng+<)R{+~kCl@of`) zfpvi`{+WRxMx33_dDofG`OY;lD5ZC|CwIs@j~aX`bZ(Fyv@GbMXHZa%p!=Sz?i=nq z>NYvX6)TGqgx=|+^}$+NZM(mU?@hus-RnOTKPxu*?-sGGeGdZ_^qu;0Go@pX^g(Uv z%%Pt5tV=R0JS?nE=!%e0VV6US1|9L9bj^1*b1(KD@ElWJN>}2ugY0ppTfgcL5B$W3 zGmImFhq`K}3v3QVnI8f@v~xxiqZ%29O?H(0$XVVMtbB1alG4&ky(e*`ElMu;Y3E0& zk9+}M>mxmr)2aoC6BLyltlB7}9GSK!=%@rUojysQYvd)DlEfIHO)w7VDgFQWek8AITB|*#GO0;$)mC;ZgPqMhp~2}w`iJxg3ia*| z$rOCqv)MJ$DJy3jNr+t^F2 zFV8VjXy*fE^emPRF6+2H#lK1GWQsmq$E*ktDO0GrEs# zs$JE!%6|D@sTHy655(OiW1RlMSglLOFKxZ{RSOB!3slh~wS$^vcDFNHH8^!=GgW~% zWmS!oM=7JpAH@>6uIrrVD(ounp68BoPj)qPmQpt;x4?b%kS3Akcu!vD5Y@Lii1e%k zNwd+eZgnF|zm=GJerc{USq(TJyO+AxIm;?V(6~Qb#ayQInsXZal{Unbn#rBMl z%wV)O-r{rDuusYbm1v?=k>CNI+gtH9zDWnGfG{iWRbRk`ATP1 zGJ^GFfjzzy@mJ!O$KQ=#8Q&{Dy}ySML6?YdyOX1qoIr%)h^wUgj&r8kRym<`Q);S9 zobS{TMB{2oZ9xZqF&gLtvQwN6&QxWmOsNN?orswoeVwkWBc^}z3ZRoX~3sWm%gH#fV|E5N}iu${j&l7j3t1sOlM#?RTQjRpI8QsijdUNfDe}ymH|1Gd5@Hvo5 zJFQnTN18{8la@5++QZogA12b+MBd8YVz>I1D#x2KS?x2U8^jPhwR#EcHuO-7V+stAd)|=|t{R{jj0yniYU~IZr&56<0;Y5%wN=C46 z{n6uwl3BHt^v><-T5xK0)y>jUJmY=VC-VfBC!^LNGAT=m zla^8nIv2V>xtF_RJbAoNyk)#A-Rqt8)ugIl{#WU)%;RjDRAe%zQ&m~S(cda>tPLat ze&LM`)bXVEjctkGxJLKo|oApFgk0@P0D>WdJxEv110#|%@?316XIh=o- z+g(|lEr~@`aE2)T9oy)TuwB=ULuLUZ5EzDcoy0g`9MNxU@%kM-NV^?a6e!|9=`W`B z(@JW`^_1pAd#c<>o#E>5-sO(+9uMl~T^4jd=&n}^dg@u}s_V+-j&tYn7Qg}(RGMJb zFI$z&Vc5v!T6e9qc36wj3Tn4Cht@*dryn*F%t7QkOOkg#3no&buhwm_L*vk1B^~#r zmP(xRQ0<_8R)W-l;0Zdgzd4VtSj>r0H~HK{Fc$ZS)%Q2o=%2JKdIqDk-d$@Gi1#-R zYz@Q(8Uz+;wavlwS}$mhGjGxNxhl5HLtdM%nV>Mb+J&udRw-kg(cVf1V(B($^{sH!wXxflD#{Q^T{Dl*Y+~o1L zl7;xij_W;Gx_i=NBy~CXlG92{^}AZsIo^3py{{BfG`y_lQd(x30V<0cjlpDne>t|0 zUs_LXV@bygum;niY;Q8B6J<+2tGrPrD(jSK>HxJT=&LW_xV&-!X*5q?10uW^Ipv*1 zYle_l2?q<3Tq;9mWgi}fo2)rCvUUR4fSPprSWZr3jN_G*P4USy(k@j*LSey8t!6h8P~(@*Dvox|VphXTz6v6ABpIhFWFAD$@(Ku3 z+Yv%O{;_mSDvy5q2ixD>k<}h=Mj0FMkSgf1(O55~ZPmi{zD6v_w>J7xqc1k;2kX|= zz7EpjKK_?PUcaQ05(M}Ky2QLBk95E~YD_ZASci<-Ac%Gum5ugBMe~}O0^R-Cm`ett zyEO?5u^MZa3XF9!d9-{8T+V8+3ah}gj3n`igB2~kCOddiGsnSo5uu<~WOpsMX4j zvWnnWKENk=#P04iws8VTy>4I)W{?|8fWC{VnMiJLLtc_#cN&w~_FMGklQvUjvXaW; zwo(jZxk{&sJs?Jxfm?ats86S$#!@LqKG1D3?5#g>x=%go4-L?|i^-raqDEpS-u47} z7D&2r@@eIRG88ZDr!q#B@HJ{HvK%GyX5dD~Fyji`jk65N877CrkK&<*bH1+V{&N~c zZxgUIm%vGUM~|c?XIGm{G9#t>q7r8ye}=#IktHt9-Ren-+(^y{vgZWZz&QNaJkk}a z5)OlPNJl0zyPXXbRtIVb63pJ@6$`Th!S*g>{3>&ZGly_ySwZ4r1x?M|jpXgIzmfUe zPGwe6JoqJ2cFwuUCoe*C{NN<7uQfIQ$T^4T-dbyaLIkaQ?XBH84xPeJ#yRLC~9ii6w< zqXL!w@@SET;B?YS^z;T_6lP~fV&Brs%Wo_&`h&{~BBS5W@>v5w%yb8DU57ZvUPhON zd~^>GZMEdx_$#Vhm5xcGKX?^TSf|K#4|j|wdRP?v?O>1%R~YYY)-9D|B;5Mdj)TG- z!R)r;kE4d@8I~ykCN2)n8$-Nj zAyPg8s>{?rh)SX~%ujS%d&=q!1Uoa7dY$riGGrl_Jq35< z|B8N9tLV2@l$>Z^@Wn&Gg_Q*#Llz9=R8_}xFj9NK6FmSUQ3qNK1GkgTJ`9H8E%%9_ zFO9TQY*hfv+CVIENu;6*Ct!X@v%P0`IE3yE`;mZL zoO3Y{{9OdQoa5ANC1X9xgK?;u=xa^FGhYXfw*=kz5h*K(FR&5x+;3h>K@wP0?W_Q6 zTZb{Lbb@=x(>{RH{Dfyw9aKz8b1A5Zwb;kwpfy*52O0;0<0dtGV>m&k4LFFs^aARI zRwxPo?dNR3UTCJ=j%A=fZXmI_?8)F5HY3ZuIH&NUnbd5~9jB1bzDoC+Dc}pwlF>ed z1}%w<6#`vU7Y*K=o_VD~-R*#5CV|n)L50*4@>PYfdDr00#jMB<_74rfhl$fc2Gdcn z4g4w2ZjE9eS_T}zRqit#+dCbdG866B9IMe9?NAUrNef={!3fO<5hD5!uVZB|vA(+# zI}eQKS*y|She0dM0aNe-Q@6nu%7o?qmxs^ zLl2>nI5Tq?2<57HtpZ~(1o9x%7;jJZOhPk2dDrS2Hnkdw?bwP{N=UjxR zaP%IKKB5}13Ed)s@#@|XJ2(dquB5iJ9<-SborbU?r&+1#P;xeP$2ZY+Z}E8Nf%L2* zoy6xp0Rk%m899nY5a$VaL26t>zE{A}e?U?s1-mvB>{TmJhI=^=>I*M-qDB#?rXPb# z!K8uLyGT@O0Dr#*kJK5C?855*hpzr3oAX!erUnAkOPIfc&Q!env`PqGJgA2H3gY&^(&_Pz)!te8e*lHR@gP=4+ydQ&7qKf!U8h zN^Ih9S3$GfgsxHON{Oh^BP>P)E0qji>NoaG!NyKQHbpPml#HT0)?_0q(w@=PW?Ze% ze=(rV-!i)^%=<82Yc72E)_8Rl;O;!w=eyANIy!L?b+N<1r;b3koP}o&!n5z;)5p9c zx{LM1BP<1KJFAq24sT!avP8vr0mcx5MSIE$?Lijf*qw<^$>-1&2~b@D({=*y(WE<| z=z5fc&P_w{Zg$~qHz#W!iiJx8^6v_A(wDI>P3%%o2z2K&>V(Vj=|0S+22$7#Dv93j zgF$SSKqI=SffhaKKB4!{B5Mz@ws-LX>VRYJgg?*#Srq-jw;~;GqBHriZ^OWpj^NV; zz>|tD_GjVRHE?4e^hh7Lw>~y*EA-xs=J^7@odd1+7E9?w%5-KH3+AmkPcFk~oLHBl z%v1D$y~kWrQTOzl&x-CmOTg8QWwl%LvpY2=^%H9r+S{4=?H%~*M(k}~S}|50JQUG` z{1LR9#R#5(!nFe1-Vhwj-!_#5?{EXxw{8$^=uTNK}tjJjbsyY9odMXRLUUYiW zzz3%S)7JtGHH!7#i>`9RonAQOIU3^`&pF2U1hQ~7IN8BmbrNkl5+1L_IOib)>lm}Z zY}RBn8<59tygMsV%Z|m9T8Q@E$x0t%T|=S6P4v$lkoUK__7?ks1mb5NdJPl=4_OWV zOU~14z+<8hVqUZ(=Wo(i;tmq`jQh;M3m%DdRY4-!FoH1V{pg!0|&x8wRlDWo_H52y#ozyFuO?RBr1PH;HNK8 zG#}h5&Vnw(=g0FZ5B6>>GCGEP48dx2!UMXC&R>NNZoyx*`7WyP2eV(;$+J!%ua)7V z8H{2oa@!ML9E_e6HIftPS#*Q@T%l{rBRKMZ_iW8`x-<8Rd~yi3p$ooTgj5diA_?6< zf8%Mm@o$n!x4@Yf08=gQu>~x&SNg^C_Hv)=qDBTeZj0tF#%M-?cwEm_r}*9(iY(-g z57ESjxPK&njmE+}VKiI$l+Y|$Scj~9zsNdm;q{Ox-!uH)9r)Jg__-Sm5Q>%%-L^F} z#04ZH8F;=D@J%M-q@oV~1sK9J=*iREVJ^F|3~+Wf>dD9P>E8558v&<`XFXT(brqR; z$*Qg5x*kYUf9%UF5ZfDgb^&DP4JghmaHZ(7^94P35j&O_3v!B;Isw-X=8ogglgqf% z8n{kK)NJa?v+&+~Fn;a$OLPNTgk-g0yubL=|LWaGfyhrr)%Iv+7LNx18x2|ydv+7P zZqDC*;HQgl*F*58Ef{qR`z8q5A4p}9OCyNx&&;1o}waUHqtg5`MtyUNF-|kqq+&bR>6f6k&cUaL2Kc_S9}-U z5lkXk7NhM3ca33>)eahmEj*4){{^xlfH& zZ46I$#qSVOFa>E^i2pJgp6dlK6#IWNG6DX-jx9J1?{CF3J_pv9Of6P$7td#(h;AK| zxKCb6zuWuxBm3}Y`r~`dU__(%)CzcaDvz8 z^hX|^yAZT%H{`kwR-is3{s2-xI+1b#^ldX}Q;nxiSaQ}T)wJMbh2U)fL@XS{5+J54VDbcVNd#kT_ zF@>lEDhNOKga2Q0o#+p@j+JfC*M9U^FKqNKK0Ojm-jv?dnaHYSWUniOUeApeo&sIH z7R-z2aeNCd`#+}615Aoy``g_;yGzblM35vXiUbkNil~S=fB`dRLFJm$HD}Bj6>~&U zL=aKTfB{8Of+C23k~1v3JJbEW@6>;v`|Uille#OM^E;tVRh`;}SMy@`M3#o3tL|j= z^=N9o7fE`V5^n(~ci?{x9gqF^ z8vNCV$_FwU-VT4@0Ce6y&|o8SeGB?(7r1*c-(CwsPDB3u-4O+Vrv%)(x;r-UEC zXmdCaPVz8=Oatybl&jl9Suz+-KIR&EWVI#XhS-<>OPVGClfC^7JThV>&~N%IrbU1#8W$v{w*d_ zH5@rU6x6;4#z)~h-A`MG@a@%=qtm`)guRH-=t4Za<+Su4+WHRq$g=`+Sc+15*9xn#818!7!8+_kIiEg2 zPn&`8LrPvn+h3r~YQvwYXFA@j*MZ#!SF3{te z^u4hFt&rDqK;9W((UaGnMVcMQu4jkTM09R}=UR4BY( zG)ALyx#Mm0@Jn2I5vU%*p1~n#j1Kg(6z+K9gC}opgr19`#~=C47 z7=Ge#eCliXq!u+F(*&-W1X9hp`4uSn5d3}wHk6uQ@mGGQrZLE$x!i6CQ7=;JJ=A+6 z_us=~I5y$}%6|%}dkEZJ3J#y-%A3I5eUxq%hw;2Sl+o*j+;uI#48h+$pLZwV`JRja z-H-ogf<4cMeVG1S3Hrv+#}C2ebmaCcTKgWjTm%+9JIOu8j#H}87*gMiZ99Rz_t06j z!Pog{zl+eUkHhD4K%M8zzk?p}#ELz@*y-rf!@=l<;PC{;8&?vcs6+0bKbRdLPXu=R zO!W9%cr%LLyh}UI!`3~7)IEfSx)W}$Aw&3NywY`G^iPoXDtI~^ZPyGfSy80cCPs5@ zu^1VxbS$ttT6-Yc`6$XB!z#x|keNZ~@g>k~E%`)uBT`lu$$bS2HwXFqmC@A`@M|ha zI{_TGW$yhgvWwdC|>KI%(-n&PhxM{CURxpPZaTf zW-b~M|7(Y(uOg278&R6x?4`YxsLD`cr(4)XKOotYS)oVh-HpWI590gh$b|4EkH*a9 z_l)1d|6{I`*{mP&S(j78PT*xfc5$^J?tdW|y961TL@(b$W3{Cf%b{gsT5%8hd?@zw zJ-)BY-saKlb!mc({LT)p^T13yJj3>s-o5D0orBlrIRtv9C!w7$!Vj86eC25gT8PvfLT3G6@wVqc*{x{-s`fxS zW-<%W8*O(Rao@v;lm5tlpxNYOzMMIZzldu624;uhiFgvxuaq*C^6KNc=2*LME7Ert z^72mcT<25q7_K4S@+6l2X?XPv2;3JPygj;S5PEqa@tHhYdknU1P|=sxrf#B^UzTcnfO$MkgJPO|2gu`8{A+6?Z^E4<5I=F{kNXX5U2h;y}~ zuN^?|!(^D;IsTEj$!+lO_V@$#kZs_!fp6G>^c)e8Q^8A0lx_lTYloa}U{CF*L@*k} zjfjox!|v|K!15WyVQ*kQrDeR5y>6Y^yL2&;*j4PA8bg`46QTWy2z3wkcb>s6&q4fd zw&pXKH+Y;qNjGv@_<_t4y@}m9i3n9|Mpqx9q2I#WTmtVdX9w71)&)*3yw7f=70fDk zA@e~mb{U>RHkr3TR9ocYb@Yy>YeZ1aGaBc>#aYOc3+r?) zqmyDpN&7QXl;J^r|*dL41h;h@mSdF@Hpf5ce!hFPh zbpF^X6hQ~XRcauQa@08q?HrJumb!dNUY+4WK>uC}XOP&I`On$t z732TYXoKUsNkxz5ZrWh%{$l!YJ+|=$@b(rhtKc~g?wQ3g!ynLV`5p-_VITKGVhGEK zK(xa{`bw8xr)1tFT_aoA`t1>V4n9p7>Zqs^t=j{@4^oB$16RW9(F^cbmxjP z+PIlg*3hymh#~gF6EG{x-k_>Kv6BJNv4Z*eeTnh4Ku%jQmQLCAx+!hLZ|5?qy&BK& zZs>eBa(oBqe--RhFdnGD>u-%-wtX}4Z5D#VCP+k6(ElP{*5&l}NxZL@(d74Y*TZP- z@4?<5w0|LEiVnz}CxNzvH(im3ZnW2YudR?debKd0b1oG8jZx>O;>ace?{m5Hk0SNV zE4~+e=nG=ZvN{Ysbt2Efpz%1kHvns5w&-qf^d6+@O!T1gU@p;`Ah|oTJ_P;I1L-*n z-|G@|&DC)F5qN(Zlsp~3s3-hwgdFcmi)x?=TcZcMVBtIsu@-Bio`gpe@$x>yl0FX& zJ_iY&(btxd_f&X4gYQ3Koc1OBzY1^iO}^=gZoCl0-BLu@vB<$|$jvN9x0BHX596~u z3@;ZldZ=K&c|4Ny8@}2rcr?$TgD;_nMxvK<8X~#Ex==VR252m6~ z-oT4A`Zopc&A`IHfP}sZKRq3}GgvM`YvhWE_#Tv2g4VT2@4MiBH5mU5RO|b$0O!lN z|8K1O79too(^ZtFn=HTH9PRf;Bh)*qA`u|$991VdQAuNdpGEna(^@W-j;6;=GQ%ts|%5l-e{}i z!OV#~PXc*2ASFu6iP+JzdFNPhKWO(K>N*Gy>|oF&w)W=wBaqMz=)Q(n;O&@|Quq9Y zKKT_ne43uzO@Cj7W?w^}kD-n+;-47%`~haZfMV02$~U~Xm!4)|K9;YL=fzl}&ybb{ zAZR7M-w7;ipxj;I`1T-qC)%EicF?K~ecG{TAGU+KW;O3Y zzs*S19$M^&1oS9s)F#~7hU<5xwBJFsS>mr}^mrp2y^}sW0(_LQ%0#q+2}D_eqh~5;I5S44m5Qu(()9(?~jBu=W`B}wB-Lb ze4i@XQNno6^U2rJ!iDf~Dee9q?z{kJFF`J@1Gys@JwJ~QzYIU*0md+ci!)effa(iC z`#D&bn;7>GhaR_Z^~2mX90_@ztKLBFrea0DMS6ax7S9y@j#|tPJ&n(Guuy+OtED`b z&|mxK4Af#id(Ox9w7C&raB4^_X54c`Fs&PzZ9?O2xR1xB3ecgVf;@q za`QU)Ka9Jan`}ex^%zUwb_F%9K`YIrO;bScWO_Q4_kYns&p2$#HO;882^1}ZD?5Q7 z*E@FS*&9@vMYHlZhXg741bRFOA_)o{q!j?|(h?+*g^rdK`a>E3X$5nLTa{g)yYNAlgC{C+Mv zw-sF9nWrbG524@x!5-X-WS@&~a3@ynekA5fG~<;>%rKs2&#tXaKbC^p0yLQm>OKO2#%SK-^(&Au8XfvAe14MeKE=*Ig$#^ED$KI<0k%&W zHxu_#_`C)^>sc9|4!eQgFNMF0;k#Mb*Yiyy5WEi0vUZVPHK1(`dg)m&N=1s#wiEOz zg-#9dd%E%3kY0PPsrI2Z$Zx>=HqfUPlxqhKJMw=A9u486HeMgIgq~&aC&i8|rB_R7 z;a5d%G?5;TMfZP5FW+IzGK+E4mqm$N0q?ZwU-Q|lHuFL10=Vc2o&aMwaiIP~=rx(gTipF2j~V>-KEFBR^mCC4KS3e=a?cK5h^FvN_iJE zv@9LrbQ|vW9G13}s~_16+ScQ>DgVQ1yzB9hJonXedF!B+<%?$uX_4!2Pc8n}gv#}( zxd~j_4nMFFa?*kKp;jo3YuOvA^ZWg)0ss?0O0hJTJx5W*YER3pV54t&CVI zxT_wx^CV?YG&Xm(XLQ#EnQgez(+j%7%iXBeQ+lm)Jygq(wFKbxCHUXISHVfgQGfA&4TxU}O_m}B8bVEqkG!5J@C9~ zV|q1s^*m%(gEWCxo~6{362sZWb@@h(RfF>C@Qk>_^RLbJ@93noSi60#f+C)+>=-nr zeBXPvZ3X&b6ZMLelr#D-Y<6=k5`iW7ITb@b{8=zJRr5S&vq8Qwdt>?J_jU7O?#Q6PvNX)QDM!s zd3w&X<=ZN`>?tz-nnKSidgVFd<-C(mDOY>uwx@jC2a)e7%#PDH^C|+g`&;0!=L{5h zid4^~2^b8gHJ4M;W**_pg!RQcV`wS1t*gNA(q$_=_fOi`l0xy9(EEy_B~R#+aS2~N z3%!gUmC_q6Q^Nl|<#@t+4%(OUl%EA!6vL^6-l`ESPwsejw3G;^Ro5-jOS<`uS6QOh zdv>|6(#-m#N+oDxvms?l<2-FHP_sU{SW)sEBlw*tl_sR7##8%3k)>ckWM4#t=_`7Fi`CBOu`6fz4s*;~klc#&zGW+7g*(|Ru5}rs4E(OAIH|i(e^fWL=q1YHYcP5>H}mD>QM& z-}$w`<88c_^YCPM5l~TlI2I}|UMJ&ez^%CC2MLCjM#^8eX4;sb(N(-e@(m)P~ zAoYf=6dRt3Bf^bwIJ+pe#fEsVmWhr0YM<@9=h8@_N}ggTreA>yUN03r0lkX<(oV{3 z9tX&P`874u_<*~f8y-G+ay-#>A|NTb!DnnZaEY;^z9m)|KY7&tV zBs1tnYt!$D(Q0|xZ_5+Dv+q*K&vHwyZsYx?qCMEas}%9%6Gy7+_|_BOJyl8z5k76= z^Hx5Ub7d7Jd7g_Umh+vKR4t(tsmXF!M_Z@7dy1L8t6Ri_xKLiy`eLOnSE~8McEExh zOOa{sH~}GMl}4drCZNa84nz_U4AS2)q?6dErR+ySR(DAzKp%{ zw31Rhg@n&dialw7lr-WQV<#K(Y{vIxd{d9>6RxOBDV}m7mF%bA)#AT&6Zh7ywo@|Y zySmH1*naJu5j`c?v*fqIU3~`q5wW_4YelywzSZD0;6scg&`vudN7S{J7U(4n<*V9K z>9dtJxLW;M1?RT%Yw&^fFGYmZvGv;PaHqVn6tN;6lx2ISo~%o0N`X{UyHs<~_3Uy= zy85T&<@r_4$qhNKZP8y6Iobeq$YyG{UVEVom(W6A!~L6}hxX3jq-CC-Y1c!~#fMr) zi7lt4%98b0+g2q>Z&S_UpORo-wKtAyY@Obf6bSaK2JMqxa#U?6T9kKno?4(js4nFj ze<|aWIM>sx$LF9s^^b!mQr&Yc*Jk=`5A>#NgRg2H+aYi5msk(>Tx~ABgT+@e0)ORz zT1`5Lb}^&YlFxqct5E>^SCem*D-maneiv$23yT`*?^CIiK8^+S>qVr!v!^8>-ak(u z^OM@I2G5}V#I?Mv#AjExDckB9WnU@qlO>7+5u^=OU#cPWz3TI8kloVat1YVs|E)or zD6K3n!~YCEffA*x%V)VC`sh`*Maw2_q>io7iul=4w&kc>Jw;7at0i3D7e2cZ#+F#7 zXXlj_uL|P>EtGz%+FF#zM@K5^HvL@brMy?rN+VdJS;_XVls4E_eL|&94pmaCmf!ld z_{ydBtS0T#`_+zVCB(FvPA^bd_CDpoZ*7aVQJ#yMJm1RcaHS;_C`*4-n@|&f!oCI# zT7bU#T2YZ=VqqICulD4WP&uUJ==DeRQo9x;OC2Xp6L@D|HuHuH)Ty@^w6}HI{xHJOVk)V@TH4;t&_vH)>C&I` z3_z`lzNaHiQ7lfpc1sZ>>au`Za}77;p4CN^X)#2Rcobpl&~w3ls|S=nZN&zzb#&?& zL4QD+^VVaE`K1o!*5*ESsi%!&=S^0`oj#CqXy4$t>8W} zAF<*uP(;nBj4O39cZKn(;~Xhf3W{6sTTLPjT1n~P*izYYEoCK~lk!dIwSChc)T%n4 z?AW_jaV+XQm-5%CcwY(e7(EkhtB*}^Ae^5jMf6Ypq2>l$zk;6EV;)N#=Glgpv63Dr zPpfIa@$?jKZ)KKc4Zlm7C4AaI9AYiJma9v7UC%u^b|-3|jJp_@^=#$8p@rVJex+v$ zFDE8lpv)bhws>Dn)L67NVHQF}s)KB?T5>%+YY1iP@|!1Ks%=Y&<0y|!p+LgQU~yD~ zyTwu^JPE#^Hc-vIjh3qmjk0)po&MEw?&&~u#z>)jarEcvR;|7i)>=qmHPa^U&xja0 z-u9F}X(u8!!5a~zgy^Rf^&C{K?LYsz^B39b) z{c=ioe~=#Wc4#wErnWamqc>y;_RtlR+Kd?fu7?(lpo*Hz((CZh8X2vqMOzxcUv+gk zt2Rpbte$OWF+{SOLb(P+!SsMV6SOALfBn!O*oRV|8JS&a_f+;2mqlawW=HmLw5IOQ z;Y2G=v{(V>E8)(M)aGf8|Iml!XogOlZf7L6HS^6Ypzl0rSA$=c7jaT3O5kd!B?hPQ zTQBZi#II(B{*h~1fn?Vp>$mdd^bYTpeUakd2P;bt&5S{Z>e!8JArEnHLNv3lG1ztOOk%s98; z(?)tylXauUmscZA5$HLPGFQ@L<*PFsaaMmDGUBPQa&0ZwHG^m3%{A7>KU>l+Js?lA z-2t9&&OT#Tg?wv|&J!`yvoqMY|3UTzd(|GvE+u>P=Im)WTAO)|H=vMbggTp)g1);! zQ%~yA{>^}nv!KH&`nfZ7@?^q~i7l!p$QMJaj8knOdfk(ry-j^RSPQ-rbJ*pqvdV}* z|HB%?6-1#$UIK4hfVpYVyEk-LPG5ebH!G2;9a#}mgDCR^_}YoRk4yNb73-e!**?gX z8bC>2OIw<_cOxy9rIKT;f)?l74iMmSzp@aiJSjG=iiaFjA2m|yjQ zM6Dixt6g?s2h+b~2l|!vcZojAPNUZov+K}XW66KD2!yLE_C#0Jg0uB#XGhAMO>KMg z`Uju(q(}OK&AERw+CfXX9xT@4du`?#_^(glEJs4WTsJY37T1OPD`}6uhElx~lCl9L zdMaxrG*8hUCGg)*O`y^`@V*|dG~_Nv0~yF}#?|wSeJ_XRp6$FnrL2NVbE%YxnBIk8)5_1{&6aW<9Lt zP^%_at)mX_QPLa>1uwHh5kc;UEzlx;8NG@|XgmKalX~1rruO-7J~gEVYh4E=j1uZs zc!l-r{p#Nsqi{aN9_bzFZ`20Ij&@g2##-pqmS5IzcqPEp_x#fWt;;^}>AsQh$TKY}2stO%o^ko^esG#03!{N!iu5qkHlWLI{ zQ;yL@_lVa)3oQp-TY2Z)p;%tY_v)4iidXUK{F-v4R(3>X{Lufw5{SQ2DB-A}gqqc_ z?ig~Ew1SfBQ;su4n`pbGTaO%38a6@!XA7Mn43T_C=Bp`5OPfMhN8}smowIz>*Lgu> zUXCbhphH|k=jhQ$R2jeP8S4#+goeBeJyp6K5$P|AL&vrHQ+djCo=m^Tv1b^|>l;X& zFq>h_)UmBGF-NcN+Hr)xwTNvab5dDvRNgyVzJd3S!=#52v5oc{{n6JhDe=)FeudB|AQL{NSvCpNuoA8};qQjR=s zZI@9tY1V-6obNTxrLK3?pq@Z8?ySeF(LH@+=VuCNLaEgh${U~8vo?zB=-W}S`mH|g zGMZqVU?YeL5k{rkvF;}72+@=+(A@aCqebT}j7}JfHD==|!w71wSdTFb^@y=M$GuhH z(vl~WejV{PdN6OArTCNl{u3!{Wzej#MZk6Z$qOWV+HMq`F z^mCnM@z=W4?MOxs+&*hr#IJRPIRnQh&OB+2jN__XJ1fg?Ny>GfF02jVRTi zT9Hwy+BRj*|lvZT%jjFk9vDH4M=6z^f3fT*`Uma5ILzgl={Za+n?@zOv$wV1S#2hOg@ExiSGfIL-BtX-+J z1-3;BhNQ%xCUR@O zbQO``*aJ&(Jg#n*295(P$9L+9Fpr`3515os!2(LPYRV{kfkt`-YB{eCsCIrsk1EXN zggH+wiT+m(Ny)HvdZgk@?XIQ_ex2V)B|k}xKzk`4X5Gb>n$_1jMUDmDSf2VU*Z}D* zMMb{f1c?)?T6(pP_E65*wlE_rN9B?d7T((%t*QFnUqqv$CuP{xQSJ&-Mx4df=e2x2 zM5QxeQcbEQ@FC{xh3L~~(OXa|g9etL%4e{G`rUde@=L1Pe=WN_QIja^wl3H-ErUpr zJ7IlTuycAMa>?2qc_<0$T%}*S*h_IOg#tS5y}DP6Brg4AUwo&Y4}X@UURJ^^Kdk2q ztBdS`I^FN&j527;ywh@(UQrkLV)@n|^pA3C&+Lc#SKSciBORysYtSfCEX?`_@6}d# zr-+e4wpq<-?P1(tSz$&#Xj>`iua@XN_AdBEwpS~YFqZLmM;z)KTcl;Q=dOcO`vpA{ z?4ProB3IsP1;QM7(Ba}q%OBdO*HMphyjz6ZHea=Yftt2a)QDjz7IcPV9Up4LFn=5{ zthb=N1dS%817@VVl5UGdoRaS+sip0+Mq3aNr*>8Y*yDiHFzVGqw)Aj^QY!bPTktnR zn}c;#>)UE;mWttOI#X<)T1_mTO%DWZ4GSW7&J#sFz|%QdLf<3xbVv z&PwjcJEhKc2SnL=YYcP_)<()I>y{GqT96I7CRVkJ)zT)mf{v5d&YRb!4)s*Pie7}h z4C_>b-!9U;&%Ro|J&`N6*Oq9L^cMWa9{cWpnni3#d8z01QqcFoe(AX=(Uz-)SB9mW z*GV_;wwL;bVV#n^()S3yp1iQPwk^n?y_OH^CQqgq=Na3D3+i(2>pdE{CveL{I- z?4;U{ma6vAzrf*OgDk^`HpHjMvR#&7?b6VG25EOxqBaatD;?~IB?j4$*4`u4Eh+dN zLFz+av=E_OG301I)K@)5RCkG#ARU%1Eu~BFt)yMRh#Jv%YCt`sfN!N%&g(6Dj|fvT z!h135pZ}$}NVa!krrKW!xCwN&p8@Z-A?TyP4Kbq3_?_=V|D~TCl?t{@q=wcgrRp|U zMOk~mrTq$;xmwCagnmGX>jj@RScAYdwSdT%Z$1OBv`Ya?0Wa#HKt(l57?ImTwV%9F zD%E#Vxms5_j#uvougUwwi=To7iC6n#8FEE>*w3ITg4K1UO0e?sStYBrW%d3?D`(w?a z{Ay`dh6Bw)9bOy80#aH%Yh6-Q`{OzasTRHqHA)H59=w)dOT5qeEK`|r0 zYxG_4@8nhW_*n`Ejt6-Ts8PD~Qng2Fvv8FfDd-pZZK>f;G=|<8xe30hKDO5wwNO6= zuQ$kd`0u^JAF&6bCTM7_i1bx&{Lh!s=hfQjs~bbLmf#U9AC@Q|q>a*|e$c=3o1j^P zS1F35zikhi%lFD@;EAnN%i5kGC(>IFM!wr?|H~KY?VoxsL>~Ojh>!YGuU9lXn-ErW zt38xf$4w&0(TdkN`xMrM>H7p5XnTzGSx+_IZFSHh)l{q2RZ`jamM%hUt1@O^<+m}I zfVLomYRceEOHFBLG&S%m&?iW%rG|)$Hc&}WTUtw?UXU&2H`qqU_{N)q4`l2>j!HXw z>7NoAQ0_Ob6!bud>?xaaGUzH>5vU}8#lN_4OlMp~4ER4pw`_^B z6sV%5x6M*JtVGoM>&tn?|KAcdp7As_Yd}%xY49?F9NH?M%BD6XT&I)+EN7#FNN%Zx=<~lPLazM#GGfdK4C69`xdj>U=cI#OL;6~ z#%3imIL4f4_Zf-fm`}ouiftI!{Rm z^s=Y&(C;0eh3KtRu)HAmmTTLLOK3YpUy!Y!Yt&xaA+J*=tkvt3Mk(dh!PZpMz8c^1 z#eRf#%Wv(6dc_u4mVR`#_6XX`+JpQVQ8FUuP9ob7^on@Yx@vfA+i#9D5h+U*1;CoJ~5)S`lqf8ZL-XOz-o*6KTK#hwkchqcfq3#);f4fA|QC?wP>xsTZ>l&d9yd(FQo&*M6YZ6 zMX0M`9O(xQ>?px;ys?V6H%+&?o8j{(4 zU-G}*%ueZV@QM1fi+wCP6UUQ5Y&>~UjwN@+nUrg0M^~scU`5nWdSFhB)vVB&#>$^9 z*=MZrT8ozdoW0nu@c4{%cdLr?P_^j&b?lPAfO1b}hJ6LAP|VA-jMW~$a81gm1-v$) zzCZoInl;vsYd~HiRq5lJFM0zZcL`*OeTFN0 z8BSh+(PZiSiq|vA39>z$ab4al)(?IQ-AXCJjGMJtb#*3rlCC13z~#Im@H{8#}{$}Laq2GGT-!xCey|P$?p6IXA$&C4^H>wRKA9ssC8-jHW|dakkfEH zJnK#llV@nbVo=b59QBvRZ^To{A-FXDgmV=RjJw43;|kh12w8lXd=v+g?Y9ynRi+)u zbW|H^i~_;C(w7g&XlH)eTI9K3$Qci7$jJ5(c@ZMkcdlk{{s-*k9}fjbk_WgKImRx{ z#uPD82YDF+%FX~YCqc`7X;Y3ou)o9a)gbFevSJJ*dsqK#d-9T*FMS=k^nT;966III zcm2qeF$T#zfvi}+P=6Cnfaw&sCR^c;WK+8gDRiIsELw02xvXynS>vGaC-9{aD=_{6 z$u&UD74ZC1GDgp)<=r^xVpp;>XMBFSmjowyq(2 zJhQz0LD++wd_6fKrB6HpZ2ykzt>C;j*LiQpyT{36GLW3k1Ig9D z2j`#cU(7n*gUndNXop!LA~I~;1aGg04}C!QxkafrBSV3;NQa?2x1&G($ux5wnMe*I z*US&(aoQa!HDwjiw@~VR@}HQmtT{QQJHY#yoJja9r$`<^wwTM&^T)#9`^ob37#gfz zd>AJ#`~savQ0L3!_6Tc8Tmk+$86)iZpX7eI6k6O$$*z2HRo!AJFo1h5BG<=2%4voa zO(Yx2o#=q`DZeQzRWBwp-VyNUT*{b){&Pi18Li(7#G03XI*(7uB)f=wQ@QvH>aP>; z7>^XDRYKXI1GUGIo28&d+4=9s&mjaL>zGU$VJ*BH82M)^%9B zf?)R{BvAbYa_3Iw`6#*N)`IwPP`!#Q8j(EQh%rBB*vW6xxfvFQykWu$`^Z^4p+9 zJ8X4Z=x`c#Wi=yOK1|%B??;g;}h;>x*US z1453VgtM^Fmm!V&lWnsPG-wSbp2uoD#fspk$oe@Pp5KoqeiUo?K5b}*6+VTWEk}_* z?^ZbH8j5<@yA)ZvkK8=ZlS6+5cCJ4y7zUjOARTu@!8+K5Ib=HBDeeWro{n!Oi|PLH zK%RS%z48QdT_*9p*nnO{=Rd^0yn?Pg3jMetZJBK$x90w29;{25XTaZEux$4tajur? z4L62?_&31b5opWPpxGo=>kiGf;{>N#=)62x7Eeu&Cp+sti{lH(8k>v11GNn}9cl`c?L%uk4e3B+wiLwfiCpf9<+=mAdolKLCOOs0ImN1s z{vQ$Fgyp!6Q^4=zjK_V+$;p|wP}A6?rBwFOW|)aoYuzPd+OF@>Etv* zHq6iYGick9J|0i*BDLc)XxtOgxg$Z}0eE5VNSK0_nSsT40GgU*=@~TL3;16Tg4G#l z(AuHJ9!DZQ z7l4o<=(l_EW6V~0AMO2&9=yd><~v-)4u@y(C0`+%mOA7*GBplCH(Xb=DDR-hucn_5 zk$veMe9dWC%IVz2spUvyGyKu6c&LtfTx}l=9b|T)w(X(s z5^C~P&wY^8J&OA6Gh%(Le)f4`AMnZO{6%Enb+tZtUko`({-io@nr=L6V zYb#oOH2oL~_s^j>r=k~*2DxXW3yyUb)2S%-FLir?f;mYCJjuJB(8ZRTc+K;vJaMDO}#Y@`|g-=Z~lGU|99EIm`q zICmci8I8TT6+Jx+`*9_i+a3Wco*48T2sRV{Xwc=!0-gi)0VOY_?0@-gGQC=eUpbEQ z$05bnU16fQ1~k{0sGILNPj`kBY?$c|as z$03{J!1e@egIP{J@n{k?tpl^O(HraOyFFYE|LfCZxz?SLOFeL~AAB)m|K8Y_Ug)8= zMGvGuS*<)hq$6_H3hr%J)KF$bKM1@X1_JuS>j6meQAKa+I5fqP+&P%XUht?ZwV27X zlG@D{@el282F1Bv9!3`I8}UAF;{6dw*nS{-AAUcC z{_jmo4+H7jDB}*6_PGX9>NU&K|E{c>Dk&=Cf09271jMU3qkTC$6sn zo!Ub24tS^QxoZP_R44ucF2vPLH0KQN8;3=E0PkZw7<&O)nGNo9u9(2@fAEm&KXLbR zFy#JW^Ji7Z7Hd-SCi-Ruvy6RpI~Cj66*=ur%gxAYR_0c4-ArgwzzSX}>FrD_L=CE6h0Mj!Sj1C)yd^ zHY3?`P~&dgf1$?$XyA?kXEn_?+ku`QiEbGLw?&27{SH8H1>M^g8ni1?paWMoheDnK zYupFEh}K3$JL>MhKcU@xq<0yw zi)o)xaaRDlv+Q?zXf_%xp&6vLgFkS^JpP*-^)DW)z`T+2X0)RfwX~vDEs(kHMM*X5 zr2EQRz%zF&*`C($-jyM)=xs=^j9fM6>Ym_pSGd;~-Q0u6E>Pfbq}%LwyF-!Pc-@(A z&CI<6rPPILEkKQ#8MlWXBDO0Jv7%LJ!>>xdQMab>C4(dG)vd=bEqS=7pb78I2-*fZ znn^WejSFix+*4DRwm0SuBY*CRH?y)k?>+s@72-z!of**Hx<|vh%w1__!p^iv3|e|a z%4&>nT90-c&kR|^oHf{hu3t_Wj_%D7w+K9&GtPY^Yxve2aqi7^HK4nA7je~J)W3+w zTsSiy1bz)KenM;g2v*&}>HCG?)pKM1fNy5wUC5OyDA%%fEifL~4NiSf=5<265w-`ApN&d!H5p2l*G!G=9oX2o=`yj=E7 zpjJH0ty2p=HHN;%LyhbjF?Zj;DZe2KZm=;w%GyQDQ&JE z$9MW$#>QP&Xg1JRAhHd3YXyeXV#-=ade)l$x=&o3HK6DIuE%DU!*={;CO-Fb)&?ue zZUcUEzi~@S>&ReD1*Y=2~pYtMqqv*HuQ&W0+;dSrS*axW>#?tfD+*O_5Ue z$vAqUNIj#^?hW%bWEQj}XN8T5JKyA-V_1K$UUAMqyXcx!DYOadgjH(p_jC@zYeH72JNKlyGI%4e z&JVd})Y($8?S9NqWRF4mmO2wF4D^oF%4&I^bMU&9VCF>J;Z=WCq5 z3Nwdl33syDa_5Wn0F+{7+1wENVa`)K7Z&8$xj-=-aO0e_R0->)tLMsWkF#seMA=jI zc$jN($AB%;Z+FL}pUl8uf8E9DJdmvv^X7jr_o%Zo>V<|}?Tm|aOEsWI9q8abP4jRz zDPHf+9G~{xIi%{jQ|B9PgR`rlrZ68Vt+hf@-gy)s&Nl~LD~0S`pou*WYeXH3IYVfk zJaw&h{o+iRWm^c(L8t4i%#m`&8P4D*Qr zIrhc=`JKHBc(#m?^()LgOIQ0Bp4FTeB_Xp|*zc&u&^C%huMF$fUBxa>oI?*Z2=k?4 z!IiPL%$~^gFkc&1C8$}Pz16o@HyAPSlNbm)g46`cQqV<8i8Kjw+RBrNa{g3Wgw@3A zvcT!UA1Q6QVda7KS+{slPw-NtWWa^9sNyQDSapumeKOj5=h4F)wfwdW@f2p!#e0}( zmdDmEG6Ock>KpNEjUrmPwk-SLni%ChL`tMw*ijX{n7|jkjj*!HHU^YgbC~tEG-(&+ z!Lwn|OV|w*B_rz=tqb z9x$p+5r=_0p$~y8(%1e5`|6#}YKIcUNa&0IU3nDbO8#p7dEqaVYI_1#ZJWMp;97XK zmXJ9o%=`!0b*+Xx3hUHtx%{y&UadDLroASt1JP4--d-;G=Ld;Jor6vKCfTRImI~M^yJBtlJV_)*tGyWGQ3$u7U`DLs-8chx}6- zs@FJ#wKM^3QYB!`HH$$`#Gq6N-b>Km+WX+w1e66oPMQSCwl(rl#M+XuI?UO2>8QW1 zo|GzTBkPu9KEk>!G4Jjr_c>~hefrSixYE;=ZzA6Nq>r=VjXs+AQ&)tQoMAa^_{Mnjd*VKX{$lts|?O=P9pMV}q4;-`CwpyA8T>H7&>kE5{q`B7Hwu(aW=sVG6 zpMxz3`YPymbx)8TEv3BI*RX~D54N|uR&BQ}4``8(a!Oll`SRH7gGEt0X;E#BeuQ?y zPeIF7qbB$lu0shU5zBBbqU{VeLG%Y*VC`Ygux-%82#8bS!fGj3V)=d8S05~A(1Wf8 zGqa(T@S#5Rll=2@@Sdf(zXd54qv{ZQ8PM)0*ThI0>8Uo68loZ~EZ7o9-g@zYqScnp zlDtm261n1E39)y+Q zP53rwao_9rI1+aRq;AuT6K&E%DNswgM%B{8`aLsngf-LlM@%Yn-r--+w0fv3RqfVI(c&N=U(xO4J9gYtj5qk!LyNo?cO4PesX#;f{J2BIw?b*KQ z|5Pw9;ut~fO1TEqBL8-zZLV%=1dT$r05jc~g+~c@gr;V81&`Ud8ZyhEj&Q_oDV{bG z*43Gt%&d6@ep$olSTr~`F@xd1)bj%m&x|P}^3aq1HfAQ!*smvdwSdF>6RrM*Q$x39 zH?V@>P-dxLDK>3&DfIx}-z z$;{ZHWPsYrEXZBiE5xwPwl{z|oBJ4p=ZPK<;#9gV*~P>^zGmJd7hMVsuFLkLck`L8 zFdko%=%2IXzh(DEx6rQ|Q1X}Tdgyo$z3NTAtwzL9hcFX$1R1klB1hWY^tuM^kBP$1 zA(qoV8ppiKSY}{9ze6}?Mj-~;IQdv*x-4T&Bhj!;e?-e%3i{Y2b6IrBy0z>UdP z^=fei!xSiX8SPs~G_@fS%Yj7jrxAJEA-af?rqPog#6X(T&a;SPx=wBh5#djXG$+(= z9!N8fIeOeiq}6$sRm>CWrF=z1{Bqj)GBW}{F^_URS1cx8{ZRG<6pooQI|#1zjc(1( zV%5_h4F_jUSs z2v@fvi(D`8^&I>%+gxpOR(WqFmLFmrPbC_Rvf?q6g|Giq2tMla83J_tH&%Z?@v zyaj46!ZZC9D$L=k(r6+S|CMtjo!$MuI2+Op6gB0$dbG2ISi|AWeKw$lok8hHV#Xyz z(`&=WmLR4ExUCC1%nxO3^L?W6^+Ej;#7=i3zuZ53`kAYKBeK7gIO+x>qnom}wC!)| zZA`DGz)w$w`=2WA^txE$r}tR+JmNnQ9EYBoJs9Z%bi8319JO=1Wy+EmYx{N zFh)F;woT>TTxjtfb?3=pXH2shtsak@mn@&B(vmGn77wGmOt8@7fp9YoK>+ zc0YW&gE_o2nIYenjZg1PkB{ndis_%(nDnCT2Ud%9iOyoC&^h1Fk)BJVHt|~^Ye~8w zdz6!_&!n7H(Ck#!6x<9i=ksYGI9ZcjLi;;KuOJDY`Qo|T-*MeRP^K^a{);)s8;Mt+ z$$VFXs2epL&Fm@Xxn;MdIm)^u8qLhiLa5EEz337o;t!$>HK4&jsA?pw7t-?))M&?? z#_90mKI*xO^T9SSCu&xkU5TE42Q7|;zMeZZ3!Uh>e6x}Dl4t}{F^C!FZOm8Q%Ut^j ztPk9q6)@|w%b>(-P_{L58CQe-dg#&TLE9A0|6?EBzzehzQg*Jm%;0&tO|PpDQXHQJT3b-o>RGgDr}+gC1@qji(K{U}%=)DbXUjr}aa(@H)G&AU++!X`r9L?~g%`s}x#+nK>U%cTsanWU4`|mOvk4KIh8Nt zl=B{}eEL0V8efMj9mlz|P2;aQL$h7Hd)ynnHzIq370J&-m)YqJtlS!aWa@qWfgZXX zs((o@pU1NQleXpL;9EJ1d0Am%;q$`4v?eRE4^Jnh&9a)TT0093{0%y!ANbvzjRpl~ z2KxxvoPhoR2+KVU3F(9_`jItLJG0ukH>(i$N*+u`CTAq;+;zE+lGBo_ zI*fC(&rWYjhow(pAztOXmUw*QnKwL>H41aG2huNDyS=E;qwrwi?ZQKa`GqgjcF5j# z@UX zoZg!6Q8g?-H2pG~6n~K$RdRCfy<~juiIP?&Z{#jXHpK5Gr%?Yv$qmuB>E^0_6<3#E zyzQ#WWy>HK_;{5km}3nS8*tjO6u z`Xv56`7LHeKPv@4WzF{nXnHj|=p(FHZ9Lqi=@IGK>5{_c{NIJC**!@64p`g<(H`+; z*659h-%MsF70IgHs9csb&&^Jju|{}q+%b8M7G9M+60eE-CB0eW_jWQk*FJYlu5+$+ zvW?TrS7pcL$8FoLa%17HXk)xbZhlfXUXfq6?TqrTwtZQ3VD=^&XACR%lc;b0?aB^S z?b9)F&D@o_LCNf_Px@tkMAg`;jp_c$n@PRg1-Vm8_AR}o^zf3wNgm!_5I+Y(>n4Mv zI|_X(+HAgL(-B)bZktlsz3Qg?{QUaD!t|7=N3uG3H1}}H*xZ8nk>tJH6}i2VPqT;f zmsZZIyt;Byeroz(PLy8+8tSHX^9%ELrLW)<<)Ybfy`*byW6~gbDB3N%zmUuK&7YfJ zShyj51#MQI4#hf|Pjx5u3k=L1RC-tGM`d@E-CVkJZe{cxD>x5lCFg|r4)znYORkEK zXXWo-(b9NLuDo=gvJGWZ%RbKaO6P95bK`wmcBnieZIW~T(@6v2FG=hYfCOD?Oggv@_Y7vx<|f$RoncZRrL!ygOi@oYw3W(3snoMF3*2dxGnoQ z8lN;Tty?y@?7EVplL66%=^lkP`Bhad@(-ppk)N^Y;=&UtK3r6Yzt7!P@@(l-Wu0mq zRpW{p3u@d@%%|jfEwh(t4Zgu779KffWOz zy1DyG4=;PZv^?vbZ&P_&dVR8%k<-lR%Vf{eeDYMl@)hn50zY3dUV;S(gh{^ zWy7n!sa#Z86rY)_h;NAZC~01Ebj`C$_Ro418f4R>W0UXDW}hd8Xk=m6%EjB}R6doj zsvNU*pYoyk-QxSB`RU;F`*c%uOngZ6MtVj%0X;DqFR8e`qI>?V zY-n-`SDcu>#H!+#3rD8SqZzE(Jw2{S?kYL5tZ~_1xeaMm<>i%YD_0aQjQ@_0K(mgC z-^KTCAD@sc%>9`>8($W`ms?Z%W7$1rCzQTha&5_*C0Cd2Ro1@rliUu;d)d8J8!PWG zOp6C6KSU$a(Us*}Z{2!IWvyslZb|7~Wld|`Te^F0c|0|$Oh3ubuj-gTw(u#Q)g^__ z+fLa0_NHlDr&peZ?5~cGPqxJCz+h+W;t$E#(k5jWm7Q6mf6Z+*PAR=CUYMSnzLU+3 zmc>UzZx^1)msGW_oVD%g^4aCTY)#5LRD4}^Z=qLVUH-$uI_%jkXqR8J#pvPF&|yc% zaGbiPs4uk`R5Z;bi2PXH$aq@L?aPI!xA<1Le{QNEXd#c{9yr!ykx+I$uO^ipf2W5DC zNwR-(QC!97Xj5`(X=&-sC8y-xix14+Dtw1spHg7WQhaV)FFGaLH+{V@yHJ&uMEkQ! zdue=V@$vg2s(a-S++Sot0G=7H_@`JKt(zo(YSM8F2wd$(;1!>3hpTgygLT<@U zNcTwFGm?A)`*Kv$F?kp7x?46l?U5dru48xJW^!@A99N;APfA)ukLGu(np*iz{^P>L zbYj#z8JN6IZ>!>;l946*l)RYxIk%N*kkO?#m2}GejlVNBn^D-7p8!uEK*H}%3+Wkn z$^R0vY@a@n4U5~yXCcXT<6H5}y5VJi!Z@u1nb|)B3m>E};P>}tH^dR?0{o6!@I%Kl zCY+7$FgmV``?AktBvFpDh`zOnZ%STGdPSF{pQV2lI;JP#{m;x!V!gNVqMKOdeSG{~ zd{_KU{C=DyM<)~G&sphzV_Yj~%f6Quaaa8NG`+g;OMZ0zvix&Z4f0d+WAb(LTdOX} zkImOCoL{J4=vcV6FtX4jy*9gsT@|~rj{Zt)O}}_T)II(udlS4}TsS5DIGtG7A+1cC zGtOTS^@<1Jcb!U1WkGamd}I7td`o;N7nee8OzA85gzgh@jFTHT%%+X-u%0aI>#~QUdX-I#furmJc+KIPcyj_-xtf1GIG$L#EAho$JszKk>3!LoO9ZSr0GA-epWc*kS} zyEayGYQkacAjz?d=E>;c`26@0#^X=1uK)A+S3K@%jM1K9%>3W%f~X|s^bGd09LvtE zvG{2f^l*H9SyDF{9<`2}C5I%flQ-i@M8@tUrs%4@ccYO||KzB9_CTRm+AI4tS_9_3 zAR2HYdng{omp%oaz0G*4FFWa4v-j@eXjOV@;oJNZ`4RcTzO3V0XshS zjsJ>Yir2G$atdSkZrKIwxafjU_GH?Dy_UZgdaz&TtMq#!5`E%%@!I%uXg!8Im&Y48 z4dFo|2eY%W&~YL=#O?(X&!nFeeh2esA+_&k{~?amh`l<`#Ov9Uxl`0c0&S3tL#?! z33@Cn+*-J*a8$Z0(W7HQ#J5BiZ(<*13&zbqu-B#;alE6WR_r^xF`mK-RaRqX7en=C zSp|FC3TZ!DJQz*;QnUbS-WR{eezaZVf8x86w#m{sADx>`PVY^}6xyW^Gv0iVo^(i` zg(6LehFnQ3q&|1P6xYD^{DP-@Y5ZTt(XZ2Y_HjiwXJ@cysv}XPFYpxxFwa<;E zJ$tgF>nHY3UYxZ`Pe_Mnm!@0MyK#0>dJP^_U*a>1LDqB8+&E)L*mcRaWKBGpJx=f7 z5!6mT!GaviICOBjClQ^IX$^KA*2zk+IiF>(p~Ws^WVRr^mzeGoM0@^A)Z$=bLdI;z zQ}ZRD^~r2j6oY~jq14-qpz9;`?A*)R#TUbm7vd|x_z}5>iCS)oClXT_5O;-tw?|iI ze-w@;PIxhtzZUdPPdh}nq))QLacwpNN$wOS_@!Nmq`w|@ji+U2M5Cg{>;rr>el6=- zm6oN4#)mpk{w&PKYk9q zeFw1&Bd~i%gW=yF=+lbAlkxV+!or_u<2iT+uSI{SH?d1}O?p?df_TWsjQ-c>S8|Td z24Y5)Xzn)(GwAoR(f9crT6$BVPjXT=H{CZnD;bslD7pqK_D}j1yY`l)pC&u7-oAwS zfrnCK{w=b_g^RP^Xy%&uPPf+*9In==T6d=U1m= zhycXt&e^MRt*8sLwfiCI{fOLlj{hK@^?lru$liX8{QD7?x+Zrd+}kOc7vB|q9DkmT ziBF4ni902`z|ppxJu@5|)hXSbNbBZ&KXyxwD(qMIAl;lEm)}ygD*s^iYE_T?OZjz$ zy9=Y!7YnBrdS`L^X8H&5&Ysy2{Qb|s{e-kZynF7T_{b!U55c29Ha9rFfr#Aj=%;vg z)+Js5-5-wrDtwS%Obqao{LI2Oypc(1lej_2Ug)Od{NAg)gVTd z3oDk?a~h!1(*O zC{5oYj{Osnm<4g)sC~8^Z9k7u^mm0P(;u=8`6cP~xlf~EX3!=x zlhC+uUSVC;bCt8ICRI*EcIshgN2axysxQk=t=c^sk(-xXQCe2=eD3YIBsnRmmn_fq z$X!qT;m)#|M6gCATcf>+@6^hTEE!zdqhwRuzVHj9y%!jhjKW_$JzJ7Lyz1eq$rbmN zKUuN7a>x8}`BC{XRX4P^$f*H(Z~(I)r$Y7T@mj|gUdzg(-IHIy!yr7+$Kr#M*15+@ww6AZ8$`UWXL1X1 zo^zu+8Pj$k!u1|IIVTj3%AZ&DMCGNGSLdIp`l0gS%ITH6SH4owrJ`lkO@%x2KNH3L zzOXzUmyXUZimr+m#@8kjbN3K$x;^(=$=|shN{`HKpL|CA>+7TfKctdK^H2C}1Jm=< zd(w(R|H6LxYYSToCHa#I4cIMuOx6J3Wg+8)Ty`pvzt8cQXAol^N*;udj-s5HH!Yz1G_mNd&G5*I*Sjg9+ zw#0JJrhmt>`?nV3x5v{@@ai7UcE?Njf_fXJYtoXG>7T?QgeSbzIhbF%z zJC{@v-Ca=9tnBHMpOf2jU*$UF-e+|5#Q$UIEWo44nl;=y62l!9cXwFaT^85HZGpwz z-QC^Y-4}Ov2*C*!BtA2(_wD@m;Ymm)Gu`LZDX*`prDO6(Jf4AMwYmu(tt@s;JBL*e zOZC$nZ_YIK<15uOyv7xMp1z!Tq_yGGKIupGQN}*=jnUXlg^oRE{zqgLMz*>M+Vdiw z&uC7fG8U^UwY<9g{E+PPL41MU}iGwU(x4d#eR|Ze%aBDpA>9Z;!M#(ChvIKYov$99#R5-B!XwbV)0v{p=`{ za!#HM|Cf+jN+t2AZ;92U=U8;IocI7o?Wt7J1L*6{wq$iPmz!tJ+tvc}j9JiHV)@ME z_@bGJV!BXsdSiL0Kn1hTQ1nuikcueCBDWVMrX+vf9J*bQ{)ETBIWKW;M~E2HVu3zz#jjLM##yiM87JAVlPvvkGWVyb zDEf(0C*l)+!@qotruOlk$3%Cl&9+u7(fS(fY_R|!9u`K!VyrR>)+koh$9kE>j?D06Ry3$&RO|499n1ig% zE%abje9T&CT{Jqi#R9C!>0kYm&gA`6Pp9Jxv=aI=rKcxeac^`;HM0J){Ss>Qu!dQ~ z@U#ce^?iUnoVT7^hv@DP=9zX2?1NNfhU0%F6N6cYhx*`f^ovK#K%FiN@!}gipA|&! zP7WX!zRoQ05DU?Jz3|e`6ZP~*|Y4UhIkYbR5YaAk-J*iM^LH{a`hc zJPJwf#YwuD&|-mdajL^Jkn^^}MrxIvsXJD}3!jXSwx62iH9miaOv607U+JbGGJj7E zdNaEm2tN$uULUC#52T`25PxowO%9mfe9-F$@xpxK;9#Z|g`rdGv+fnVrowsg_nzw z1{H)#c05&)+)R8pNz_mVpME>MQw0uLf=6}-kNZ5e)Qk37a6mbzmEHtP(UaG~hvB!^ zB92Ihe{zOcV+@lxir{JXhRRupjhcZA*oFqGLB8S(HSc&TjJLVx1n3<}O|>Apc@myW zCp1+NuCa<&H@`?B@MS_gI^J^7WkSl3i!9K7)BD}1y^TvdU?Y7z_W z7BY)}L-DqF{E;AsvU0}x;G-4rgO_~BB%<*sJiTdP1viPSplpeKF^Rf&%4;E5N7 zLWAJ42CVT6){JO`NMR%qi1U=Qa58!y(YaB)$4k7Hm-9M}zkUrWUcq}`ZvA0ZvBJ%B zW}Gzw3OOCa579rVc;`l|8YqCt)axz^jYJ)}TFb4`U<~?Hhg<4`2>cDk`!qj5j!dzm!YGMH>vJ5|awB3kU zShS0Zf5BZ1pkowTwwf>n&hXoltfp3dVJPcAM{aS7wb%a6_ia`aZ0koWy|@u?W~rc1 zogR&UmS7bXc8hP(X!oi1oy?)p^MUX+ZDpnF^Q_Wg{B%18z%9hpNfS)K;sZ7?3o#GArW&=7x;f#gY=)b=9C$i`xS z@=5)$lLfKDb2)th8964th1+Kc+eLvm|C|s-mA(pk_B1$_sb~%lSg)Lbqc3_W z{8z=^VP(VGtTR>euZzitM3}Rw*nK8r)EVz>xV4JC?k1lyTv!bcKF6O3Cw`tQJ`;kZ z!b&6Az^e$B24S}|lIIrj6b|C^trIGfv6yF1urgYu(I3(5cO?1xcn}}s$#MJ8u%oE8 z&Lvl}MRH5S#5?#>{qaCAOPZ8Y`Xv1)t(D5l1EpB8G4;=};&Z&2N@Ntv*?Fy5=HKRA z;{a8IGWt@g4{6Ol#&bP|S(o`5kM7x+c`a3zdpUkwmVb;a!X0WSTUrYu6E1zYNGd$T8@(M%VVW$ z_EYnkF~n$zuiRXpqsM3=+Gqb9Ut0fCe>v@=R!6I4?6SUcZta9T!~*%jS11y-Ju$0% zSMjK-GG5*xTS{@NTp`qs%P2XhwXBlANM3n4Rh>t|K#%>iaDW0BrluWw{BH4p~h zwdDG2V}ZHZcw}6_u3SL({ll!>lHcP7_QITaQ0WwJ{OvqOzf+H5UCTcTA81pBM{lWF$?4g7n3 z75qm6j4@Od>~*oD2~g$!@tTmgXO9VjVlP`4}WhOEV+! zjURobll@69_mOOgN*Uh$5%~!fk|WAaS1;FU_anFJ$?6U$*O{}F2*1}QhPfk5Wj-CV za?Iw2pL!%2enE#p*w+fy0rR=#AR}|y(bOddF^?@BmG#bCMYC?;>n5Y3(b}xdNjx{3 zp?N2XrN}xP;&iEl)Jy&*HX{Nm58rkW^4no#1QPH#a$6VmD_T1JrM|{!YZNv5nm?@Z zWH<^+!>J|(h+Yzq=jKwpR7~lle3x&^d6cK{?P~EVe$#3sxw`caGkxxpr@MtmwTjAp zD#4AXan0&O^*9y2Zt^;*`$hDN=N|-WEJ|UM-aw-$#svrtJ zQ>9tT#H#^lxQAFd$*yfhQ`P)wEZ5@$ulyqdn*wkRYa_2DbNK*|LBkF!!Y~jy*Nm!0 zN~0q6r;A1t^O^M%>v0$>dlXKJ$KPHKhU%v97de$fOg+@ZJkk*9h@_(*Me!$Eb~~PN zL*k~o#4s*AlZ{}nt6`&32%DM0^xZl^43x!s2V!NGG1hEnjs}Nv2rV$qoMZlBJ}~|^ z>KQqxB;TiU+Yy_#6RJyM0WqUgftaqcbeWn+DXFhqg_!*~SSCqoj*od6>vqEWN@V=i zOt1ti8<{o*R6qxEy8Wd_Xly4#RarjESN}|7ET)2SU9z zW=&H-vo=CwyNK56fkfL12K6y9{ZlgMAITZ`q(aIb<+$`qEFm_Q#z{Vry0w@Jzqt?I z!hCAJk;EW7tSGM3-pothvLm_mFy@*q#-n=#y{F-4SH%9j!ZW-I`tB}sD~FP;AAm>E zmq}$4Ks%i!@3aA&)LAszerR71IW8wI6Q>f{u4Iy0aegij-Cv5UrCjn7xs9Aj4hFk) z37s~I%u8xGFFo;AX%M1OR9)TH74v|(AM130O5+E^GQNWHD9CEAIj9(X!j)isF5`#J z#zrpz+0~b`-+*VE2fwkrP#LsT9Vxk3fqZ^Ae%&r+d{h9*SR8L`jL?Q`f=1$*Hh8b4`W{^Qq@FB)&RMB`JbTP8M>0RfzKZctRVA zRjZQ=qdJ7=yGe)G;_~+ZLsZ;=pAaD7I zI4{CuiB?0qI90g_D_umob?Q}n~}+=LT$$~ zCz##M=H@}OD4s@POC}RmfGE?M8xTvx`cdd9mXp4UE2QH@`v;{{(jn;y_PCmqjcQt9 zxT3t+f$Cx(Xdg-zD;1H%H){so%O+%gjX58D;}SDFGFzQ99YQ?zka?1Lwqi~`ds2*| zI=T*I+DR(3K0F#adx#QmBU1tRW}{WvT5onV8<`vNdMmK=C)DV+g9uzpOmvPoyfKk@ zVRUtI(IrMQo3oK<33J7fVgx+i3yIA^?WiD;Z2{&1Mw83<5C6)kZ}cXMT#;#`8SFb& zUDiIAn(aWYdXW59EMDtBR88OEaV`)miw2eL^vv{ILEW;Yc$UaMH{1y6{;?yo*G9>pj*VT;~bZgiw5j4^*(-R0_Qy+ZN%8&Ly&xq++0phKZ+$ z+#GCf6x{2khO!D;r69NVhWg(Xt2z{0i3F4+*3HUa=s zU~HR^RR|*QI)qnak(M-Q?SIkP75JJBh1wzmsmKGpvZ7hlPS$&sm31T{iXigLj*blC zywVdRNbEd2(Umiw@E5hH+t{vl)V`~8mciV0G`Q+n&Y`OXM*#kn1ZPMq#?B}7yFOr>0E4F8sC8-lf!5Q7j`fX)5BKmzUyXy*dJAkCULZo^g zAGX?tI*N!2^=!hOxs4ERat_HKa$HawEXuI2FHi}W#?Mt2XDkrxS zO<09Utr`|>5v%LTZ04by=@hF8wUkI}CmG>zd?}HuPleVOpwcecZ%9cT`SEe^TN$`wF!=xZXaMIa_D#6r5^T*vjK{@j7j>`aw=hV$4e~7 zNkeXxI6CxlCiS>&V@HF?sU2c>M_9o<_|Ae04g1V+N1c5*a9!O z4U(6g+-F-}bEfFsC%b+aPviw0{DM#2=NgU3VoySsv`6osL zCg;&J!Nki&@J9x6r43N-80+iCTAM;MXU@`9R^rTV8FD=pNceuhh&U^$C$ z%_+Ef7W%#k9YiPC?+MO#E1sZ?xA+2GaR|;n$k$=+>P%WZfb?9Ta`^@-Z-w)7!{>jY zzx|v*Cgj$6O2KO~zaHlBeL}`EfMn9~m(!qeovELNxXMFbaV8g3WxrnX$06vScAQT` z=#UH_ygvH*9hkrNVh`e(ir}9%Ae@k8DZ{Pbrh0!vt7xt^b^Vy$UoWNCH6o2< zW*O|_4ltWCu~KgEc7^CFm`rpd6S>Zj(pGEL ze(Y;5d$jcdyud4cpI*WUGR6`0Ts7Vrm-J)W1!JAr7hhR~V%_L6sZ73nx|m5SO9aso zjOJl!9r=b9@=q|WS>->KmE@X=NYz1{E)i#fj(s7v5XvDfTd_O>=*W2N`f<}i2+bgu z@tiKE&cvNtgeq2j^Dq0RlvSOlK9jcDdyMG7G5v%6TK-2ZDke7sZId?K%m_LwkC{7p$Z9MVitdAy@6da#U4!s2lGrBhQ0xm| zb$y3cT0f*^G5$6s;`LbTIr;1da=?|<8}Ck`%#$P4i{1{QH^Qz5pK*Ps&RI+S>Ae>m z@2M#dHeUOV_bKaX}!$S1JBj{0n*n3M5WUjL^=!9q2g`{3`Tt$YgHshFx#5nH zhbXVrx~{#haPJaNFLyHcY1d89HD#Wq7~Pbw-YCy_1}hkWD!y~^9$zc*KaVV}i{BG< zJFbksn(+Y*aMcXb-zDY<{2@gMi_E!JQ*nfPLit3kvc3F7EGggdc!IkGjg(WF3+(oC zeot7?s-REuNOQ9ZPSV zVjAOy@da<>f>GYwD$h&yJ9LWo23d(n<%hb{^EhOE^8BG;Y8A7g^-^-XZ@5pYE2Onn zTp*3VbK);w^T2xTy51bQTbs=i z(oyf3kbA*9-5*`0T`A?Qaxry{OLeDF*GV=y`xSWSEkv^Ch${rUD@d8*#(gj`K52$D z-rVJ%uT8c}$PHW@lxTaYe$rnx(Ax?Z&&cnDibh*4N}CLhxTmF%gUoDIMmIG!x|`jt zjADqKURfs8B0CgerIeb>&s~MQq3+UR4|*^Xg*Iwo&pvl&MK|a8&Lp~xa?)8PO2}bU z)Oz`zCzSGgjlH%cy|cR*ZtbG~kXFy`D`isltHsn*@(nA!c|>@x{&p|&oKy=cAB2x) zg8tZ^q-0X_h?C9C##3!)V1xgORuv6X(3-5}49p6|1nOx8&HX|uX_9o)K20`fi?u=e z&wbY$4cD}!^DDo!Q;qRV@ho-qlxJhRoeIE1X}+>SzHevOUioJF_v#gm6X?Q=`r|;D z|BUZ?;F7rt>o$%!d$u@&4AU~DiuaG;1HlD?pLiark@9x+v3Gw+nxJsiC3m*78V@u} ze}{jY!l>v!>MQ0y@5|#K=g*)e^Pf#@si|0pY1#n)Us|{{#Z^cyDy5Wv$@%E6JEcAk z${#dcsUj^B4=O!fSEccGTeFXTMNe&XHVT+QT99v7Vqd>U8>3&;lWVj6GXj;3Mq(Rz z0v!bd#ROuO7V=#+*watVMyK-tvA%p>%0%TirTx{+Wehh88;M2(y-A>gF%4Ab47-SV z&Nya8h_Z6ZmDW96^(xt=eo{GAbLR{`9yHiBoXqJ^BE6dAfE$Vr?ZM_#{Z?R0X%l?P?X&x8eHimLhKl7p;g^;wCgkVys7^7%sSITI=Lqyn zEW_Bq9sc|JH=%=4*>%g+&~;Cpt1KhW{f9ea@S)IF!M~Kf#x1h59mQ922H7L_(bFd0 zP5d0#q-Qg}`jREAO^ggQ(|!jmEnY7`Evr72`&DT0-0}_8=Sc`wgZios_`NeH@sGR= zERbN`^KFj%mT;Qv_D!u~;HhtRV)um83AF=rjNXDK^;GUFWz?#!itg&(?ZNZHs;2mn zyi;g7&t;{T8m~@u2fNq1KFh1D>ppkFEZ?2LIBlK(YC^Sy@VEuB|HTzcEaEF3i1il= zxQycF4zLfu$USzjTZq+_;;xtK2c@69S-Pz}b6xQs2u>N&Kd4a9dv94!1(#pV>G>Tz zD5R{XqOwk?X_>|fOB# z2dj`%FKevQas~PZ!i-8}Xb*~m)T6>Df(!9i3vtc z{EAS$PoS0mc;H{-H`w3n^ao6mhRMy9UFswEhT!ZWd(gMGx1vW^W97VZgj`-OBXl(` z`0M#k_>F{^__gsV6W=E0N}QOG%D+e}rybK%TI=cl86dxq8@ax@H@H8#_q#^9!rTwk zEy^_IlX6$dAp5alHr}+K{*G-t%ji8Q=RMSt2Z?v(g31nQGL@k%(nhf(S+9O_3)d>S zku}zLI=+%m(MMRVgpHO@7e?p&nG%d)8gTbKU(!jT76^<98lw_Jdxeuli=Kl9tjpn$eq+ zw2WF6{i{|^kJd`)53LdMYFB>uTsa3dgX+?1X_0(HdcqWl8^#oWoNrvf8)&2*)wTqt z86KgklEFP+O`)dt+zOf(GA;CO=$z1&A)SK$b*FG2b`_RID@K24Rxyw1(-T`qKmD00 z`d9q?gsy&%F;hQm_6`IB$Ao(7U~f@(xLXYF8}!mWS6NK$;<@m{yl%|2`isBKcZqM} zuEy8$CD+GO)141CWDNNDjdDg;cJ-A~(4{LATqj(ulxMDUGTi#4;N#wLO~KjuJ}Qx3Tma@hxtss%Lvp z*3cE+tlk>IZ-Nf7$CIwU;BQx00e?yVwfJrc2ja@cuSocw*g5V{Vi$di)lM{(@k(X6 zvob>UdwK-j4@#TtpnEfT-k$n;EiRDU9~b*RT8Up0pCfUWZ%(||pV!jl%kC8+@yTOT z_fM^)%Ae-1vU5V`z9T7bzZlo`p z86&J^c%bH;5&S!3Qb_iY5h2rp8+rx@)%Ip`-B&DYeC$hK#l*WYj}q3!kBys|*w42v zF;eefQ`=B4xXhpfAw@zqhwSh^lv{`^q|ETbvd$;GAJ7Z7- zHIMlu@Y;&=Gz{9{nx#&6)$#rjR9Eien-H7&SIGB#(WBxfCZ^G=CYZ6_grA8Xql%PV zZl`_=@uet}@lw{anavFOQs43H1ONR1q{(=zuP;2dO>|IH$M2(m{`fH``e9s_guer~ z=wkH-ElajIYB(ve{sr*|VrM2~^6&7qHqHu$Ym~QYP;j#7 z$dKcq z{*am>-$G6&D-`3m$tL%+=J?`cv&X)VEfL!ypyp35%^gdOf|ZvCEikzM_}QXD%R%xq~OY%`|g}-#z6*s)XhaYZ1C2 zB&&D4T-eHPRHo~DAPAA{Vj+8#b}+8-&p|(~#l-t=o5_Xu%H*J1A!XE}QWiPNIzb;q z4QZEmXHYuV5^IJpCN{ILQ{ad{%s<7K*O)1ElV3@-l|#xb`L~tQjI<|7De3cQDU38? z^!Da8u%q-VQzuGCO<<>-%iTFRF1W2XrR%p`P8nOKH+s+xMz{c1YafN(E{ndTf z|0U2i@I&umRM)m@q8_I&M~kO*4fZr}NylrGH8&ut9zoF z(lu1dZ~vuV4HVQP13eOr_(OrkdUoTql|`s6`IR>6R`sZRwC9{>fSO-gCKZ>OS_iZd ziSH8@YI*eyS~&~*2%hDf*i81TC)~Z=F?92PR~D+*<<(R&9-6NiYuPt3!dJz=$NxyL zX{6WBX%jvdWFON_zDqY<}J)7nGJRxhep_ns_o?06tqczdEV`Q>wh!vD{ zvJBU6_P9cahTL)QQ4R^|tm8(aIaYi~R_B0F!m46+qD!Q=QOGD_-m_d-pF-j-=`V4V z{lHjijTX~_Fgs=!pyy(&QlBSec|aiN5`L3sIA=_>su^XqvDz_m1p|!{+AAX+S+e$$ zPwuBaa32eri9A$d)c?`_XVKs}Zu6uaUnvktQ-#qg?4LqOJl;UQy z1~`^K^o{sjKaDKlJ{nP3@-dRIq%2Ckm00&o*CDz&j){H2=G`(1>!b7QyO4ssTUMXOm&^r0I25JXZ1*RL@&BbCV*E3gb*9En{dQ6?CjFB_paUTP*kwz+Q zk1!esWd9~#9baYt!N4MYpEX-br_5E3y6U@XsHWtn_ss<3xkzYYzc5nc-xdu-`AhgM zU!10!S?pC}F13v}+RN+$X_^=$ua)vjf07IQAPlyr8fsu{psc@oVwr?tzLZ+PoJ&=r zF~00frG#=(5{bMwxdyqbtG$#RiY^@n&*Cyy8i&ckeAUZ=pD4w1H;Y+2g*i$xb*7qL zjgxCDI-T}ULFgYs!`&2WgQ=RX|I!nUJ;rr?x?WeGfG;#!)RnHTyRKd80apvpGS7YY zAFg5QJ~>DjYla%Pv;umsz#ZQne=^-=EYPkpz;&-S$jD>uvTI-~+A5orXYy+K0s11+ z@}eK!8u_iiKp4fEDa?(5)LJJ!jirlI8fl~`Y5@Tl=2(0cP*%Mj-p-} z1}5W!d4khSZKk&ul6%#~lw=t{$*IWqb&~zyuBu7($Jbbi(&eebbhpQVNQt6;7tfTH3e@FlgXHZ?7Qa9Bfh^W0qnvrg zjAD+Dmrmb8Qa4uaOu{R}3Tn{Vd6sPX3@Gt}nLY!-6Pr|W+B^7pvA0}K8Owf3N~$zl zXam;sm9@m)L;Y$NdG`7CYbv6RsVZ)xVtg1RY(*(Tz6N*KB9mX4>P1cJVGqH6X8`Bk zlzQmZ*R3^w2ZPsNJ>K{e8zNS2)ST5CYUZ=ss}myj9RI8R2~P2OBWKNX@o%|S~K z6ndc_SAqJK#CK5bIDOBrgp}eCD*N;3(G8O-(n+_JO2Z1O_$9&FuO~AbO(pm&`~3pW zp1KMMg(o0W{sW<1gPJqQZR&@uK<6e{HkF;K)MKim2~IE>Bb-judE|Ct=_;s8jj$FS z%2la2%!jrup!_S)B3p>=dVxJ2Yf623%dUHwIEG)6Q zvzuOY?M9o|%~nKIE-+(vtWm-eo@LAY2Cx^orSZ};sW}M67%F3LKtN<+DoR!JZzEhk zsfX)>u&Ozs#w+y2elp}YsV(JTF3xz68)wKZl?63a$T~%qrVMz`Vn!BokyVUILf=4h z{Spf?If7mtI;19{^BYSucsgKb5awU3PiAQ*i;TrCS>_lfAg)7tih<}VD}o^x$4LKB zkIuoYFG*Z$Z?f(%jp9CYJkpwPKz@FQciu8jq@WzblWosa75a~=Z#2`~5~;#fqEDg) z{=;lKg3jVeJfdUky`;)%(Dr%7ZRqTk)L6G#$G~Y60(CK#`szx0Kc}NtTvTV?QM1cP zl|+XJCxB*ZOFiTiyD&}WHFfSYT%{)kN1Qo{_VjE^h{Rt*(qx6lbPABNRxB{ZSoHZZ3&MdPF zD9E+u32PX2aE1EOQE)U_L8(5aZ!T2I4lit@pJo{6Qy4tlbSn+BLY^>-EfrN($2-18 zRc$_Xume0R_%-@!BKqx)m5ILC{#c>;Rt0)2c2YkKr`P!)h?wExIVQJ^;%T>E>Cw4E zO}#j}qc|M`t*F<$hl5%ny&bt@SujR%)a3G^X@-Frb=hcDEL;^c-dqL7{xbRI{#<<< zRkE5OuNr{xa&(*X>|eT7Y|AoCw^_g(WBy}JqZec$mC1Ef@OI$mo??2)O!AF$sE8~D zZDXM!CWBsiP6amwvsl`p1^0s^NlQh&9@S})$uNbfhu)&j`+yie@obcor=XC-u(GnexoxUhZH^5&o= zx}ty5AqhRH3=RVYksOX*O~+GPG)Zx~UoODoms#Ni>XF}&aHj0x+f}93IvC``W%L|A z8fU(ad;S!z(ghz6+NBMZ_Z`%r`#{l})WGvmjct$Scnk)t8=YVOg6`PNNsLE2#&VC0 zphwH{xwqH{6SU|IX7TL;Lz2b1O@E4IPGeHT468GF#Cfcx1N7Vn4sbLmmgLO4=_ekB zb0&i3`2$p^m-9cv%(xkJ;oL;xrz82!bgRbHGykOzDqeI`7wa$D;5Al3zwY>+U)h24 zg!hfe);Q|mKI*pdpvcaUS(_|Q1*M17f*Tk}$J#(@+Rc!z6ksnZf?62`AC3g&#oP|t z;Iub@zV8ouVgdWO2>$2}XF3Od>JJ5u(mUi#t+_xgIvM@gj_&Wzoy$^L?`Th^;@60s z+RQ=84R<991;i>~?AK6X?hL0&XahHRg-d+u6I%Y2)t5^2U~mihz)0?4#zQC?wT0M= zO7c-ovY>Y+CfNkkO)aX)+nKks9$j}I-*zRK9%lmLMUbn9=`qM^?J<33 zS-hLP)*^Gf^}@ag^0Pbj#{Bd<#xrT6BHsKYkQX!Q7-0?v*wU1&`-Ej!%g{zExPwEF zCip4S;C7F=1DzmOc8@d2txAfB#rD%Fs_=k%NofRBq~Gdqdd#sA>fR&a6^5D9-G z=T3#(>GBH(2|o&(_ud)+62S#W6#_qTfb+f1JttF%Itm)62OTF>#D{$TGP|Dv7N88Z z^1nItv2>*sLmskHwckOF;x$?|0~+=%`r}V@^#!P_L!lSe4=`C9!B2R3{~7L>292_u z-@nqgF;(~vv_nZO&c8^?d-(7h+V&KPqmF2U&iE5+z>=ot>iLKZnzEPg&}Sg%&1T#` z8yr4>eTHKb-oOhYxbqosdl9tP3uLbhzDimUH;vG%M?i9I2CXm|1c~#cpCR^jPI58Y zrzbcA4+u@?S=OVF;aaTD!B?*Ysbiu|Dq<_zbB*NSFs^{hihw@ZKt>e;S(1XuJ9nU( zGZ`@r()JKr5r1fvr^LyR%qERSDWAAH|)`VO+oBjrW(j+d4P z$up&*VjW>9-qmQcoiWDPXjEgeT}5NHxzWlFh5uvDZw{>LV>)P#NcHI~@rb9uq`pV% z&VXu*!R;}#gb5{WEt*5Ioq-95Lg3HEyUxByzJgS1ClEKQ(m{x)9ec{*I3e%yw1 zx9&qX?zSY(>yIS-*=C^+p411f>;jklfmmY$o$0U4|FA@{cym=ilNSPCo{jgXVpd@# zDM1R7>r0w=oGClE@H89aKeRSa8o_2FdA2%c5AgJ@&^GJD{Bj)A+qNpVmF-F+<)l1N zE+eH8o5LeFt;J>!vnu{V0#oT$m}&5roC(CAm~rp|o|u5Fj09b5fo~iECg8kv9T}UA z{@ev7XAvuT!7P&qF&)T_2k4mTOb5vY@^&izR5B~V?1$%kiWC0>?BzvJSt8y?GPo*| zX*SC zGZab5Y&J2=5Fa+gyYsQmoAP{lkyKl4A-@(Lh_~rHeQ5lx?=uz#jKI>sOJCo>nZPvd zB6D7kqvsEcnW)eFQkE+t-5ThOH%eYk*qo$G2jjn#jn`=g7vd~U6 z``Qc5uKG-^vAzZb&L@9zy{KktyNxSmUZ#gQ)u{gN_Uc(>sXMuQrE8dyQdvb;Z%XU8 zp23U?l+=T?n*OO;cfB(67}lFu2PXK&if5&_>R`1V=%;GRETxP*1I@69tkO@ilWmZh zqh=Oza}UhS_z`(Q#Mic?%wo33x}zV!V`)OhYoS#RPj&>FY9U(VIb9na=_7b8kCH|S zk3fIPRECaG?e4^6#O7e6RFFsK$x6HuN6Lm$!rjOld8cJ^Bl#d4n0I~VO+E3f$-%Sp7KGppt_k3y1}j~?$7EF z<+u`~%$I7DC&^3Cetvzgrs)c(nYMv$dNuZ6%v@%b!Gqc&ycc`WwKR-god2YCWUUH` z1CZ*0V7>0)gGP|CFqnjsR&0f(PlliPnJ(KXv#@>4j06R?)%;>sFy`x>h*v8R5f2c) zO52r=N(nW+J6z4|s^to%4mVYf6nBb;sP-?h(iqqD&)PwK5`AFJ^isw?=4CCmHZj#} zpR_;>K(|o2q10L#PUYeYy$>Ix&0>0@YmYMvQA#J5Vm{<+d7M-S%U)erZml)y>Z!Ft z`t?9cpBNacFZY-7chfstZ<*qy3nP`w?jUb7R~PrUpoN|jN-1WA&X(NvVeC^zrXNo7 zm-f#ITnoI@b{XxgzwqQfiJH`fO!pnRH#OU*VtKn5n5=YG0e!H4qkh?3#eB$t))6Tu zmEg}xn7f}lQL$x@t1^h3-e~3y_C)=?zgr-MzgFObzcJXHn???H*9b&$wQgTWPz+oGuqw+E7 zC`js(^ei=Df{_njxE!8hWqUf(dJQ>saF31XS(%C-_6_vnZ!6NsZ~ma7|5jTYxTM|H zn`oJ}3`T!*74cGjp^?-{$*m4hZpsVPhOUc>UnxH+ z>9B1;k4b9cm&HWAOYtQ7GSP7+eN2Cfd+?1vTDSQ-bB@42P6vx$8kD(01leD@A$E}J z%a`e0Y|SSNh+FKe%yyf^q#?x+trDha%pw*$fi;M=BZ-;63Z=wV#1P5FPxK}590#&# z7wtt>clx-n%;@e|V(&$O;Fbjd6*so{S{p8^L)AyN` z4nSsD+Q+F--j#YO>C_rjTDGcp)j!lrN(8c+QYk3clAp`D$Vgv63JZuU@ebA#LC>~& z(M{OTxS*8^sDW>Reu4e|qgr9(v%bOb;;&U;m(|5~*o*s;$@J;Z(oCt5I0D4ya`W=*4`A)2MABA%h2b^!6=WIXuhWN`6uAW;l>?(2lKv@!QIZh!?E;&s`$+bQVIAd znrY`p(0qWefT z@V?oO-1koAN3>wV+!1jo6Jv&nhoskdgQ4)`3*zq8b~q7nMyBQLAm;hc+Q*6t6KC|p z=ikMgzfMAG=G=tgwb^7UC9pzAnL5>juhaCVU85JIuJ~tCzg`=%ro)iU7UUHdGYdC8 zIj+CWz4V`bCeu|9fBc!SU);d+4L*xIm<)f7Jk2ybi^A}34!XM@itEWCSEqX{z}=bP zgC?oS+`;Qf8IbSfEav0!zo(mXvf0~Gh4$p>8qsld1-&?x?8q-7?hxi1o|D3#2Fjx z-EzG3cQ(Bd`9=^ zXC}7&#`~@5Ym$|z)?=luQXDg+Dxp(q zfXlv(-+qNYlK+@QQyDMh2-uao=3pjJp_eDoYW#s0}&r>p}<4qZ*TC8j{)1 zN8I`aymMAKD+S)x86w}mm=ZOaY|>pa;$h_Gx6+f)4W#^i>rZmMyzidu zx-qf;Jt`NYIE$*R^A6HHn@)i#Ai+d_cb3iP{DJ z`hb%>K!$HH6^5~7Za(9Cw5QW0BRQtu+#?qe#~yOVL+A_0K?dLx&t@2cW^PNQQHnVb z8_AnfgJ7!5S29ZP=xNzP|3_!&HI+PNIx?M`>Ak2-B;@pn%QU7pkq3$-geNMhoDG+^BMs^ z_9VKxOIGG0Rmn44u`C@&&eO1qK+So`e_LYUg7l}HC#vjE#6OhGrbtF(4RxkF#7C3G zrOhb068XdC3 zk>^KbShtYRDM#PRVfeS1y^s6!q`tGyI!XQD1Uz?!&ZgHynd`6|Rp88pbbw?hO8<*~ zkj&6-A=$?V|U}cW60LDgwiTJUyvwuH}{xKr78HP0gw-@>`O;P!Z}g!^qFRgwL+Crk{9WndrtW%!CkT zo?3rmxnjtfGaZs^&teK)3#NHary|pjT-#PWtRVaWg$X+a=+5tgZp_6bmW_O$LY6~d zmicmWE#1(_Vq{Z~UeX<=Zo(-;Yo*Q$4SD%q*szAKF7`h%{mj#IkhI1wZ zpx<{matZmSR%GA$kehCW_5aNECz8n=36++U`Mp7&WEpnX0&%~d?CS_}^gr?DOOb7K zo@17eJ|N~n;dvB-zqY{FE~oSuJ#yNo6Jd`<8&Icy5+2W9oeta z7kKrWuqLWwf_it#WaQ^m`9OzE=Pz7Gz5C5OCvQTMCPj2-B zyWd3pVI}p3^T^Z$_LGf!C8E0`;F3Ym@h;rEjR;~mnzI!9D24WO!S73wx&jwNodtAS zZsoU~WHFz?OXbnjRoTlOXy7Bi5J8{QC-lfGXcI){Xb+tE3yn8~&kn&poj~4S(UY`> zOx_J*)PY0}C(!B>(2xI+A1+Lm?I?ES7&-p~>}(CZx|kimr`mrB-CLaazcdmMiAK8( z_Z^2aA9%+a_uW)ynkaoA^CHsB30n{@Dn0;SOYe7Fyr|dw7Wc z^kc*CL%;d_{E>efkx(0}f1USv$?2wNl~<_5I8QhXL60}0P7p^nZ@irnE^oo<9>U)V zqZ{r|>~aM$FWnyb=$h@xjEmd!ayveJWjwN*RN8HPeW$x}EYzJu&h!D+!Rcdb!oE(i zuQJT)>%zNsv1gO~p3`gRbUd5XZ<%OA-JuShcxX7}p)gjy4pgqi>n{HHp?`Lu*{;C% zd)Uh!IytXV8Tv(Rd!HS(qyF{^ZJCz{$Hg@xIEez#>K6Y$g9eFYVEyQ|o5U;Ih%2AN zdugEdVJ6|XVD{W`I4Tayk_PMk1n=e{{?K!%7DdHwBs;m9WC8aP2?FIfn37yk(g*5C_{L;Fi!@0Urz5PU zIy7{2`Yd$PTh1$i|C`d2mYM5k^nu&>?lSp@5wjTX#CrPX;x-5z*78|V2AJrNE)93Cr5 z=VTW6sUcj|fS*2NA)F_rHp2UKVxH5;jr0FK=#qe!@dJ+Wf&NGhuN0s{p?-j*EEDa4Cpeajoni+VlGWQCQ`;Ou)&%wQs(0ws$bSgiq(M~?_ zFpiZhnM9M$XuamFssz2TUaDjFk-ctk&=x-R5Bc@2Q1BJMITg4M{G68i`Pto6bo3zf z><~EbUu1HK<99=|IaH!=;%~I%=Y{CzLPTyGSY>u-ni<`yLi3F1xN~ThW}Mr3BF~zf zW?edh=b(`np@ptuv3lU0x8}UkqUX{>r&Gv7B2my1cw!g&cnDv;;Jit!@HDSp;jH7} z+u!JzSIDT-u^Pqy?>MPgcJFj5e}*Q`yq1^9)I0dfc`AEm_S26#W-IKy)8Fo_I5Q{X zV|@`^D*}%F##MDbsj`-w#KtM`KwfY*<=Br4Tu@Zfxm`o&ZNX3MgvMKmeDuaX?!d|o z;`Ke~_Sg6)$FTu!o>3W&Ts`N+-@{SwSl2rwp*$MD0jF39TK0gJTj210tG}tTllp3vGo61cCIB*O*sX%PggsY|I_l)pkFzYVGNq%NUX`yg7R{af1{@`@- z;%{b#`je)j*>RXXl0< z3y1~p5fPr_1lDt<=By?!9CaAEIEx>%3eKAj1xBL_FQFUm5ChC*Eh(X747$2DyKfC; z>vFF7xql%}-FX827r6BfcliWw-nTp8QH+OIM#H6N@PJdH`-*UW8TfnyK0O;58;hP> zglvpQ7ZvBVMEE9_JzRl@4x*tO!E;OSFV^DOgu)+{IN!>A>IinB6=z(Eljy?w8>97$ z!5uf*`EHc6kYL>y!?6($S*TuNr+)WUNsaCv2PPART82Du*$ zb;d!}wydW$I@!5$I(RHHN#Ae6JDh^;YDqk^2pZ30orn0_duaC>`rqdJ4|Ks0IQRs$ zy8Fb?Px$8nGv!Pi+)X`vIDd8Kjtt_SY2d6#PUa$Oy2zDQqT5d+b1yl&@6h59biK-s zoLRHsoZ)fqa2{)V0c{nIR(_A1zrqG@W=G%9$O%}s6zF6pf_0unxtY~m;{6Bt+zYJV z3EoY%g>xQ>ZtqN#*Z~{bA8j}rY2L#Qg3#Y-;j+2JB5zoIN@DpAJo%#+(@4U=x2#P% z_jvBNnX?^$578N&T958}(@I6Ac`c0g{|6cA54GoUhhE&NCS2#t%$>uz>>xr~&5Q(RK7k3n4HRl+pAj4FObB^{G(X|I z-m{kNob?T~)PDHm9{<)OVQ;VpFZgT_wkI#%ZX;}^j;46eDZhndiW3_-Pvb64rYaZu zFb7=rkgF_*veTiPGhJc_6#Wm~oDsh+l&gGZh0l>vXBI_mY;ilJVKMvo507jWkyAZ% zobv?hNI35fdgWA-tiNQv*V$n>=X3}zJ52mDg%zK}PgxD09fD(La<3P>`w6_@$KE&M zq>FPNt&%K!Mx@ZkC!GA&N!GuUcRNUu+pI=HXM2$PmYh{jq_HbHV+?0j4}K}lo<6hV zHE6eaoX~vuU>iK(XsxkOX&M@973;akdL2Yrf8=@>c+{7i*d_7}GuclAv{xp)4mUo- zJy!oCNt#zN>1q>epMyWN1};C%6;!lVS~xa6GUYrWJ{_7UHGWnec&a>>vO3qwgQh5e zJy7|p3mupe-`ttVlN0Ul;2V;0TIrMS_L1{{#yLCQ_9JZdH~3b;8xqj}&Qs*Kp?_K-6OEFzX=yZPF|Lvxtr3cjc4k}i2r{hKP3U_9pZ_FMIg4|=08LjS zYxCiut^DOb{=Gos>FCnb(7|~gd-%HMZo&&;a^ROowJM);&uIJRI za$f7}=eXX;`7>S4<(agCDjO-1~x)cgw|FNwV0#g3gP z4_j!_H*iEaQG&zC*Z7L&x_9BG@4Pb-8bsoyyiAJbu5!NDu`+kykI#JW3$*)z{`u6hV% zqB%{6yRx(U9DG%VDwX+c1-|~^)im7Ec`E!Tc))pn^KYbDOY-nsa8EFvfiqRb4`npY z@&~cZ7bta~_r|d5SN#8$9lhcdu5mvnr|ahmpZIQZZ<=WM#83YBpn*iZREhPbgnBA` znx3yPPC5mzgmCVm@Ki2-O2bN%!-p#Gvbn-fzP>=aS8zi#UqAUC$x6R)7a>U&Qu4V! z;Qm5zx#LM>=DMl*uJV6wg;O1$ z)Q0{VKgA#q&Rm>O&O8-=3*)?XzNg{y4&N(D>(r5_uh1x#)g|(&Sk60<*BmMP#qZ7@ ze)38HiU`OWbxeMW=I=kbgY(bNJq-RX^4D0nF#rvNS*0UEK3>(iVl?k^?m;IwD|D=l z!e7-Ss-@t)srf00J*H*nX`y0rzGvc9XYVPHSZ8l$(zW9`r{7#rOZwg6{NVrRWeJ+P z`Dd~olQkOLGl5mcbJqaxkKuDaxxd4ozu}2*{ME^$7_3KzM$VZyvhMi#iM+?z&$lER z{N!`ax&7w%Xuc<~`vB{3R^m|SGyli&35PB|u4iyJhrTjjj((AoC>_iWoqdb^@8&1R zuF0IBlg;w-swe5)UM#!~Wkk+M;4d&_*_`h z-$g#_O8Tsazd0x1@T2qGdy!q5(B7eopEWwCWw7%9otcmO#PIctzv%p3<=u`XI27SQ zNPIc3nY>@)uZdj4Iq&cM{EOFq@mc3R&fjQt;hhTqbgu2}&iUu;+|7!EI8l`qI)8V# zH=b)b{2E|o(aKqIy!L|=aroZL>%XCuKWSfn?%+si3QkSo&i*9ncc|h_ zpwih#B6pYgYY6*@gVMjaV}Ev7}y3>;v5GtlQBY z?^uJ23b6=1Zn7egsO>j)+wsVqbvU`Qv#dB1^z@=7??SuWd@4CS`W$*x;+om9YTsE! zZtfOCCDqS0i{hIEqYuNmVlFDi5;n|{)HF$PQc>u<9GPpx*+r61yMixJgf*Ic=J@}$ zbRTeEjqe}8&-s@2)Sf7%5*j2U8CfB+g^=tWvPH-qDMZM~hzNHT)39xmz{q+0w}_G8`{D&@*#Y&wul9>Ryc5bmwMyzdW5GZo&N z>|gKXZ5C`fYBk8dNPc#r?X3J0D6%p3;yOM1ORev+td4x(f?`uUuk6U;WXyNWcZ-h6 zllk<0%ynlnAlu3J9+vH9cg{Vtm6&(7%0oVRol`rnuw zr-E}QPFl#nK3&yqo+?zFhqob{Vn?f$`U83-6ZDtg2hXPKOn2f1*^KnyQV(ZM_+o9H z$+tZ{f~P&)2@ThzhvV;8*pg1p`}~Futj*)HkA!u)M`d;fzyEvEa+j5Ck)A7}IigT4 zZ!ZozH+zl`J}5b?umjF}PzS^wJLn`Rqoeb2X*;`@yz4~6>T1Cm#KIrW)_W&EEB!gY+Ua`-h)aG$e<-hSfhi0AhDV!sES}9s?mljf)Lv`NgpnC_OGk^dtCbUqHO#ad_G-<^D%od!iY zKW~-YmTq&J-`$Wa2NZuy4lcCSlQlW{t2jR&nwA#p*TFAivt`L-wVBCqFHZN#yB6*z zhdq+#R6}Oj>t-i($%V-&+2^wT_K#H8{HfT%4DW`0{hbVSh0hvlt?R3S-bjmHuLJ5P z@kkM}=O)_i(qvWEAL^#Ex{kAGihDb?_ETLhjnkpd+ZswE9pId#2eYkFXBFYy>ATC4 zzl+Od2g+q9q4z9(9N(+*jZnN7}4DOAqB(;MC( zn??K8$$G*{%f`F+zh=LscyC(6SxnPC;U;oDJngUhbFupEJ^7Yom@0YVEYA;cZS1;x zM|x^9yZ8m2n_20e&RnVDcLzH2CVK+xt)5cf*mrj>ZtT4Hv1s@m()dHZh)kvVLFrkL zQQg#7uhdfz^?^og{(FDZ}!NoKDnd zPD)Qm%8MhPfnMlD-v3rvUz-glTUF5PX&qb*VXxoBmvh{uqyEBfY1#BNr*B;$w>b`$ z@R9t>5~Ny_!iJ=cJ8e;EES;ZRSn14|%hFut^8ppQuws?Pq4&#U4NU4~$EzZ)%6g^M z(=u{jrM!De`XR*NAmceV>r{9@xuVz$M(8tsTuT|N7EU_5RcFhCSvNJViTsqVD9{lC z-~m?SHK&U^p&-2(9_Iy|_cWVRU#xjMT{9-Vk7n#gzdmJ_<8^P2rz^L?Gn5sf?=Kqv z9*(L31o}0yQ%?C|zox(}-U37W9xTm%#Y>Wh3w`aK`Do$EEcz8%(55wYQ@!MQ4-`L6 z8ndl^^B#q{+0Di0oNRL?kLmSnz06H({mA#E-^04Rt3s9OWgd?!-by~oZsl*hmEDoG zBI$=4-EQ<$<-9_AsMQ#y+h%oEK5fIUw=~8LDygqo=P$FstDcknVn37B&gEJli@G=jqlci$KF znRKJ8uc0rmPW9uu)AeZ;*|$EtjH&#p?`Wpc_;{C7YnqUqC(&|E(l(u*U9GSAdj7|6 zs^rJy*Q5{A?VHtw&*sC`=Z}8DzKqW{+p}#a9ejh{k1O)-*-3QZnrw_LS{=RRd+O1+ zoMcW;FHXM8#<7@tlw{m$n)_4P19D~j11HRWk#>R1`6X@Ojy>QkE=pR_Z%3t1WTW#t z(?fCc={&J_(zmlt+1T_9XYT&#(^B~u_ONeq13UJN^A%d~qdsOU7i0xirZ>GQgJeBh zvtniV0mbZ567Y-Dn0m9!wesC%RV%RA3-hPbCbHIcPB;4Bc#I3&d7?9@-ZhJt)iQQv z2PDU*qq1-EUFlX_cqKVI&-|{ko8&|3;CyQFJo5fk_8~o1fDfs`KfgEm3>QyGFW^0& zAx?fv2^UU)K!PP@FM`gwUe4tHE96Ft!0^)Fh#@_1&u-2Mx& zBxyPlj;f}$df8L%$DJ?9u^*6bhdWsU3o%3{ZYaFM`)Z3Tv(@=c$+m0@F4z|Sbyimg zSsC8`HSFn+*%eOMeaJ{x(l@6<@Z8A%zJtBnAL8eDIk*YQA+rCclarC|_$s<~!)fJU z)>e61H}$LLM)U$}+*%z*-V|k@;x`@5Te(iAt8DsIHjGczgMIxeyAcKVBT02x0e92y z_=Sk3Av-jm{^&%vE;Hsu*#O$*b$^{IyY?#!^`p2UvZyI93yz(C@@(2OpGC)=mqC{J zq*hu^HKQ}F{~}u7XE%vfyx|@^g686@w&ZnfRzrOC3;k4I7xQuI2VaO0ZsaTU<1Jhw z@77G@wTUhmo4l64mWA!Q*LeGh@_OnY`j=c?BGcU4(?YJRqWVbPr2E-HU?Z(NmJj-Y z{Nj)53xVBGM~t+d&tVSO)ta)!y{I+uBCVs-P!-`&Q6_dmYqFsFc0k}p69T9jN0Ab zEcOaHhPf#GIvSsEf7d23#CPil+?(zDh6L>+lJ5;^a~bO~D(RLk5LYe@&!4_|6W-$) zcfSi-W1F*@EA!LGMl}qk;Tx1{kxs;0qdjvh?zo3;nk+Jmof}4qP=7JYwsiU%IH8R@ zt;7i*LYtoKq}0Lg(3x#+AOha31M_dy)SK9-=xl8&KRgak>)Nqb^!ltJv|xL9$Yx}| zm2dn_r>;{=8YO}qhf^!d)(t_1$H~pSnQnli?yL^~rV;fO5nSS42c;u$b=|a& z8qx?B8m`mfrxE99v?^w z?>4IwL~|QR(J`taH;d?+qh=H5<6Q~Ib%3)T-YwaeqpW=u0=N1WYkMvH$WXlW0L}h$ zR?(9mmn%3tX-BHZ(kczCQq|7v}L$_v4X0NeauRXVLx_ z$VfFs)vtLjM>tEc1v<6XNqQ@ce-|<|NIu{@pWWh|=tp90-R&cm;7#+pH96DM+q>ch zsI6XlP2b@4{K{v$k!M>h$qO{&Gdze&>*T@v%2{`Y1%^AqW5>~DZ$j;yiLR4)BW=Z9 z^Ngn|t{SgCJV;jH71FgFeaa+p^2ckm;bG3`dy_u@oCmj>k1~ND)|4Mmft_0+FZ3td za%R%Yx{j2Id5&D(K_Xw`B^~T(aq9g}mZ%Z^exo|wUi^h+xbpzI{&+so-n7toE7J{% ztsMU7MY2}V6=mp=^Y|@oc*FxxtB#D!T>3nvQ{F;>KAzlBw7k)`&+y*GBEQbCYxHbsXejZly*$1EAlgH^9zxw9IeCm4c(;!X>B+L7&MVxP){*p1dik+_r zV=)bl%JPmD^VuR7-_Lkr_xicyzMxlOwC}wEtM#}}(!)sDIp%ej5jN*lUdF!nj9f!L znuh5rMmfvL+8tH*TanW~X8yTcO%s}+kCFdOUV8JjrqI7<^5(|k#7Z>TP!d!@#j~E# zT5%bj&1zT|qvQUlad^57Cp}MhRYQlPO7M4fh(NhXR&YAp-Kkb@9sSi=rtN(E@pp2% zF%ClAN3DG??=0r!e`0-`qwp#ka;V%(Z?@=hsO1OTC35rARI4uZ`ZRpMC+qz@QH2Fldze~Ldj)`QRA?}<>FV~TgT903j z=hY3ORm-p^yP??+bZuRHUxUWH8Or%c@y6ABul?AD_4wu&qkGR&1{>)l-uf-zO(>DUN)JeS6-@oQP-6!%1uS2n~4<14VIBC0$2fU8rg^4NiIpE{NLTY;t$M z3~OtiVXW71nxT}8PkDMY@%j&I_K-FH5(hm;E)JFv`CHZ`!Nm=EvRlZ+N!Gfj`7hvK z%_o=hcoh$!#Cy1+h53yZhy23c*Tx_HWCC`wCnwQ0cjCM5>_dCpA612=sCtVhp8&CT z49&C#mrRhGTwPK{oheFdE$jKJ*Q<@PDLeC}dklnDdXm=J3s=T&Fe8m%u9?@BnH%Do zUyU~K&o9bR732+@pv4LHc?vx4&v<5Evi=Ew^GtuY^!J%Yd=d+ls?~NTX-6AT?y~_T z^e_=+4WIQf?!cQIAzlt7;&%7Eg9lU1doSa^PO_&*+U;VtXsVVK?Ckr!c*AegmUT(& z?__QzD|^2Ae&V|i$uRV$DMowd?L3NG#T`$J9p00hxLURN9A4ft`XWwu*HJnoj<$Xs z(l?B+4dlv)Jix)OSe&f&t;+BKd!$hx9%9dy!|>)}Ho1qpUCJ-%DXM#)Cco1v#6BTq zMdlMxXeLg17$v9Uyc_B7?xO1{X0kWj$~9EwkLO+}_;X=0ZqdD5+joAJ2W$_~Hxp;A;dVLJ7yI55 z|F4}DZGx`Hs@5KjW+%`v{rPPp@Zk+|)Q^?u)HqXZ7*0CG(}Kg>((XI){9HNZnfUQZ zRH;A`E+##DiKQRKQGIx;FPPa2c8xRR zli8|Cq;-kB>0{`6z3U!Dw?};X4P9_2Pwy4>KTeA1=iS~c)fm3P-Nv;$jq-=Cq(B!` z5YHZH-Phx-s8Po`&oxQ$srYN1?+hSK7paBbfLGeU`82s884e?zz?ZA@Fa))lLU|&|ck!M`x)t#={ti$VO*@GQ4 z-!3E6?~baU(4RY5>5oW7DOz+MZ+NT>!3_RXU<{)c{)R~XW^;V+o2s!MZY}wCoI;tcCBkGQVTY zYBKsaK>u&i;R4!hywQJ$N2`m`XYk}IxS~EEc}w01=f_!fOG)uEYq8GkH<;Dm?8iTN zZHJZGVMZ;?dMRFSV;0rOOntbQKdn-V*8)qhzY)!2k(&FoEN$2w_f4{5x0qpR-bWKO zJ=DCalVs5pF1)~8SG)5Sv}+UVQJzNr$y4_tJ@tM2cbrg-Hk^R!li8-vc{OqB(Oeup z2q#VF5sV`%x1jiN@#q+<@;Gb%5qTQTbBjHb0$uoozo+`d`XkS(%?G^IGgf;Qh{mt+MjgBzKGmVPFENY2 zY%KKYI`{p_EaFV_75+-iX)5`zjVjaJp#iyAhr^2ORe99<&=ot_ss=di4;25A)op-& zf8jE_cUh$aOKNZNyf{g`7d}|%n}@qgMfW_w+V7;j&ohqNIHWBK*T-l5QF8~YdA@Z& zi$@#%DfhXy4Igk1eBF)KuV+o_sQ#R6jk~gC4OzLcT!E!*hdcLh_Z#`aTK zt#QqMe)gbAnww#De7q4q*Fmqgq$&^#jf}G%ecsHcA!Sh~Z{}wz`ZZShJlxoV>la!5 zfAH^ozo%H4b=GwZ3Eb-Ur&e>V)%^kQEJ5v0aK#U@lym5oKt23!^)~yNWCdp9{ixus zx324b7I?Ciq&j$g8Xhc59wvI)yWU&jNwFFe$-^dpO)l{mr{lL(?l7)oR9{;4S=Muj zJCsI=E&i%R`$R1_x*#qhY~*`ZxxXCA9lV7XMW<)c_%Hb0>8?D=I-cOpfe{YO;E}xFrX|u?0iRT| z2El(vc=B&%xEXyXp+hC!|G(^AMZVs8lwWEVfeibX4*ZD*3C<1-Q$~LTB4iQYI!?4( zOJY}}(+uy#s%)Z9m!f3u>V@uFPIls3GE$8O-r+7=Y1$ns(dBVf-4b0|n+7Y71{*!A zI<2$|ugCd_3#@)U-v1n&5!mLPq@|vFN7cPFivHo78$5Zo=LDi;yKDX^i4wM!tnYmD z*y^g^jkFxU=wF}D_r0=o&cD`WxiKy=rd`Ip(HhP-_SDm6lJ~zOv*cM5%)-e4sF7L! zrJlFOT>|;A2^~U819?^SX*{b6+HN)HSl6;NW+UIKZ_I&)se%{6KILe<-8ZYE^zLTc z+$R-DaZM7l-IMqA?Wls!$^R)yTw_etz!7vHalOIo={UD6VmyoT<$ zOSWn+`XaDO(GgVIh*tVW4e>)DGd7iQ|8!g$*t9?+MEw6VT{@jUnr!x8(TSr;%`etH zkkdb+*^gvx3ElcP8}krZn#PX&>hFoH`p>8`1$9=G$kBJv6 zz%}s`IKO>Sqd8u0ZJv9Rls$d74Gp*_N(BX*_@q$@J@@gAI&@G){IC-IA@_m$3%wUIvCSRjhUw5P zz8`a1=3ATppCW;23H`Ccd$T-owd+>7BCafBjDfyO%_#a1{zGg9o@k@-??wVQxNF?0 zjNgF(iyoZ{B%&0)4s=|gRRi@^hHR~N&%lBPI;ftz?Tt!-&}`s$MJrv#GxqT54l=Tv zvF?VRfq1IIs&1#3HhEScSOcF^mOY5EgMmi&?553YLMO!Y-4plfdQ;n@^>{? zSNAVaSan?;+97e@m{T*aYkFN7P2;)Y<<&K+YQ|C;&8oS7XzTbXi&AAgE%2c+gTTWD zet0`>TZ-SquC6QLys*4~qToLzD<4?7qCc=oEOf?Q}%o>;e;( zqgh2yD`&RVjI4@xY8rphD(&w5I7hIQF~^)L8&@D9cQ@{!MGZfJe=P6nm{pAuUZ~{V zKmZ0>vXbxDH21P4^eFE;fi?_`Txj-KzsT+c7CfF(z(1v}NxZ+)@4zJnDl8Cg+i+5# z-hw89L#*JgS;@BpvGyPK&9>;S3)EeP8@Bm>H?Ir0Ik1v}#^2z65s3tLaHn?yrMA<* zKxzioEs&)_t+14V`CE@(fivA+@;hWOJ`J?odOtzYz)}VpHSQPG4t-a&a>0{aqbKPuAA;sI> zD-d`gkrliOtY+{`oYq*zs+afbKMZAHB%^;M{*QmT@dhTnl+niDVR3^NfsBq%Hu*n# z!*-cnpdJ(46fzxGhR?m)Ct=&;eu3Bv3IrCilJyRa8~){7al#|0RF*INj644>I=zYg zi(O+!$$7Wdh57~j&J%u5fnumETm7flVGKTAB*!_zoQ`*=XJwT3fgZ(KLf9S7(sZ6QN2RRnUm(Wn)<&xO3017v&yi+7l(59QN+LnB`g z|1p(^wZH7#q5Q!Gaw${gBi`XfvK_da9idgAUUW!4tvk6G1`>MJ+N172zE=9>3?DF2IZ4fFhMvduD<;`})(WIk6t z`bsR`KxA0UtRr?l()WLqakn!(?|qhR`JZ^QCVA;V<{t6tbQWP4bmMFC)q5G)37-6f z_oEi@O-Z)$F~0m(ao$IGdMq2?jAn{+UJu0=Ihp$!1uD6!3BDbV-zVVG=tuq8dOQCU zPmI6~&1KWiMBin&<#rqrJl9lSxh~H?@Tn17ek4L4S90w*S-J1)K^A}^zn zwY+*I+`m-r8I(|x;` zP4ps+N7)LVytk(=#j(wdF*4A*eD7y+umW{DvcpxZ_C({3_^i1ViXOhr{Gd7|mg6Mj zEsvuAnrqenx9&0jb-bVDxH~n&z=Y35-`T#gmNy(2+UO{%Z?x-VQogb>3(&Q(*Za|! zv8VJR*RJsF0!>hr9azKn9%Izuy@cNv@lEXEJcC?D)bhL0t|Uu=OOK3O^bv&D^oQA0 za);KcAyFMHkLxR1>7A_X8Y8RXllmo=D0&PQ`>BRID!X#Edo9H=%gpQ#K3hS2RnA?e zd46;Tg})mfR`{^fJ^dfNv)s=ruQ&Kz*Hg-&&L8FiD}iUK((_g5;DRSC#UGP#P{OY6 ziz>CC0iv!N@n!T})G)`|#ue{Y!oNYoRk&)kC)cG{s(T#~^naZb5r-~C*OZ+7ZnbxK z72f#&JbM9t3=eU=u|@tZa#_24znZ&NH^x=gCOp}oXduMHK1H`{_#-j?uwI$*MPE`= z{1xr3db@y$gpcD>_zTYM#*OnGZ{%7av89{V!Y<6{6yzuLG;M4MW zxty6tWj-+E^L&50nPqsVT#2mBESdLISA?$=)<5Fl|5jy{*@PXBneT9AjBTZL2x$w; zU)d=B>$lnDy6|MfdY3ki=(Y*ed-zi8-7$Q#&^8I)Dr>FFpwBj39=0%i)4*?Wj zRJQ)nlM)_#*nq(7$EsAur_r+#zT*yDx!N5!`D{0I%Y85Wo7hc$Gb%^#b>w%$*2f+- z;cvt@x0I|;VDs0xV^ATwAEE;wy!_}@2!F2u$&T2&mY?V_3hoPzh>nh`{*Q6SJJBgn znw*566ckuZ?!r@xe01<)EmuZQP|Ptr(eQ?8`|4K<=8?7yCo@YM_M7`gWfo?Y1p_C?34bWQMf`1sL5 z6Bl>fON&@D;^^?kV*mGoRrts2Z6)zyF8Ylz~jdQ90qZgy1_jZ)fu%=fb3rjtB3^JMmNS?rP5}=kw^6+F?E+SsRQFQW{T0>{6zL`jL+b&S_xA;jvaj%@}Vr zBVI|9SHK%VhoE6;x;T8+O5O`T53e(1ZMBg_x6^;oW$Y7>yE6Rdy6zq;yob9*mt^?1 zQ9+4lAarENc=T$-oMO&9d27*O5`4KgjX4L;MBLnz#6)JQ6*<|dB9hQ1nc41P+|h|K z%ezf^5y2DFcyrOqUx{vw{-VhLMowryHOicQUyAd?BQCI}f6?0?qEl$ZW$*+0@d~=I zi;2(c^DA1S)<_wsTI^gzJ5}iW`d$!(>t7iC{U zDZZFYPp*d$7?8D3PSIg8B=1%jTb!FTg`zk!d)sPUoODkgE!MKfSDIGKXUf>x7YL%^ ze0Kj;Rfe|w{CiQThy3pOd^`0@;~JXYolVTgq-#VB6S6(hwlMEQcuODgg!?7uXBkw; zWiWd0skh}k)%EIl4`w^_<%Ru|Pm6~+%jIsksuxJ(fkydCGR;1*LC-zhqbbSw2^PAU z9+GJrWgLZ9C-YIO_*+023tuAM{SDvL8WdDOk7!SF3 z0Cd@0KH$sgbh_nOn678&%6e%n$oHRc>5J)gyr6wbEr*;xBki2L?bP8k8<@{3?2{dx z&Pxx>9!T%aZnw5I^FF1X+|?@G;=LnqM>`yOP<~#zAN+A2{S1wq6*|y!>Sj-7R~CNA zj)ugV>IAcW)A`v}(r`;&4OQ2u@SF=Z*&*4jaAj6ZZcn@Cl?uPxi~RLMJAF0B@pxOL z%OG8@Nc&|Y$!8Un)6eL;)+G6rRMsH90aq?pVH;6Aq0k#H`9yo}O)q|zKbSt7)YH3C z-aJRB;_iUoxHOxmr)W@?@aU(D{yM<2FG7hs^@i*N@p&rz#}ruEW2}4&k=?~QaW>}{ zr5BL4p6TV#gcZ~_?uN^1o81d_o@I)r;pz8`JZa|gYDQg zBfGX_519kWck5(ucCgsvX1hV00`YFwcD1!t;-d|sg=h1gX$Na^W%_OQX|ZGaV{#jP zd$2gxPG3%l>0s0!;qQs*(RP*EB?h<}QhIZ-0nB`h?9;qTp`ASmtE9g{0PLUsnZ1?0 zR2Xg-!~t~r+0LJwmVBIc&Cksyd*+F{4Q4>C{ibqLNiEdgijeg^@kBdV-m>~aj-p>q zBr(^MgF5LdJBv0f40CGC?uC6w!RtKh(kdV|k`K-3Q;5Pj)^nP=#<{p4V&HA^jW1{R z4NR-T`o9mkxu;Lcii1)A}xiIveEE*YRww(tV3MxtwIkY{ho(bD_NKoU=62YUPh=>%K!WyF2U;M~ zDQlOpUfIeH99QOjWVd(r%dr;peh^%C75Bj~J|kZ9+y1AWBS^RrK2!c#WosN_x- z;+o{eY%G_6_>GsSXpy>emyN!8Wk^V&f&$Xw= zHauOFd3aXr{);NZm3r+5n&D+7kB`79zv)M8mQ=+jKl2UFw!&Q?Mb`6H4rM_`rCYKK@@eV%>~y<~T&U)I zX4cnw|B{sxW4`Rw3>eOiY|{I5!kX;6%zpZMiKf9%b+xbcb>@8=_TdlDQzfNgq_Cb6TS4Acl6K;J;VY{1crXsC&HP(I2Sj#~6@#LdPo;67BNhfD5^S6C#8V{(u+}OGD zD(920H{_P?&I{=z>uOIP@&CcRk5fqZ^R$Njc2ItA^Lj{s(GxtQ>F98ju8XC7m)juF zI?)=pvZy!HsZ(W~9^`S%k$G7zqq7HTm}*7tC5inZ@_Nwd6L@u}=)*Z0D&{#+>K6AK z2W>hS_n+XYuNVacll;l4DEg<~j2Sp$FhAl(6n`51>ZSGUYV-$<($`<_B)97GS%wOS zC6DXBY)g74cyd{Dya~o~Cpl;abM~gS?GL#y-hA)jH68<1dl`J5UM(o=Ta8D5tnAlV zymTEOa4O!d#7}vHZ@Eyu=P7t1=uaH>Dt~R1tVqNN!_4$-l&g=Dx!mKwGLQGVVxM$3 z`utTr0UFz1K`v@eWJbN#{o0 zx)AC-(^5Rr<8fwA`inAB-AXzEo*@BSvdo@#?diB$$>wZ4iGGYHH<{n_3VrcyvMzfA zo}i@9lJEVmd9@ZBUxDvC@Y>p2>+{$g`;Dc$%(El3^#{DS9c1GJGn*xkw%nTED3Z}T zY*cURlh{j#&i;5cu;FFM<5@a{V$Z1CRqt=-GwnsgkMNYt|6jqy?v0N3@t)74`C77N zucFOnx~MvT^aQ(sUPl`Ym4zJS#IKPgxi7DJ4a)SjD$mf14_VLQ@`Dc=%QX8ex5RJP z@=AjiSK))t-R&IX{X*8_PP*(MSI=Xq7tlbvvmaOC%B$5?yIQ@EAX;uShpIe_-p1n$ z2XeQWlzt5@cLR!cf(&gX3%Wl~Jkm>Zumn-#ah|ajOBWl zEN^EE4`lCVlZC;0a{`}x8_gNJtsKcqe*#MJdhfl;nqC#>Pp0*axoXYRR(sDXlf6d;T2kVWA-EoTZ;=%;;F>$Lv5`}ReQe< zGsm~&*sr!4+lqhTfJ)9gI3)iy>sr|8O!%JZ+H5}SbPe3XJu2b%TlKfo^Y|>S_0Zju zK9SU<{|-&s7LIpvI;=3;yhOLt#ZG|i0x$iq{&%Ma=@R{)vl3d!6}M#*ejwRXSg0L% zyQrt>5q#DT;?s#E*}nSH=ZWf8XDdj{%B+s=?2*1vhm~%oA7!?#%8N?6B~voL_T?>UYHtUg7Ko)FS29!E}clyNv!)$NYef3^+!u`@NerkZL4?bSi9@KOcS=E z7l-JL(A{Zu?InZDj>Ffl`|BM25LYByvoE0D>gYeJtfOPQF1|8qDW^aqo?&(F$M^Ff zW_gGDQCiXs&Ds1~X&`?3pwJz3!4O#5)%@TW@njQnJD!&BAgg{cT_4EuC2A`hlV7vC zR(1(}_A3uxewKgrEZ*)SclZ?Q{$zbNKrPxsfIZCV=`W4?GdiVx=;yRC54kx_*vhEv zqD+(4=36XPr8$wlsY}yG-liX3-kNnZl0*EpfyDmC4j!i(P=N<^uAIavxS)()iHGs> zt#npkoNl##9qH)PQ1c}`0--O^>k^PRhPtMLumSi94_`5({8(QWD z5$X=M?HGHz_R^8vKD~?%pQu+TC&!IEwY2qVn!iz;11)!O_9x5tW%e@7GK}RPo-HNy z!*pR^>HPQqk%CD$vQyGofBiB=_YCx_v$c|7Pp`B01bTZcFoq(=Ht zVWsm7zDZxQQ+~5FE!?0#p-LKBd|x;<9THZ01Rr!!*1^sI8|?>hU$!$lFsY*Ve7x?5 z!|aee*h;T}L9Rm2_ovOfTe;!<(%2K@*mOLrcfJm#o8h=_fYJZbPHNxt5*u0Db+l0b zY_5I$e$R$wTZ`N1s*{}sSRrecUv8_E9y)MF(JM1xonOOmN9u@K$%A;>zStA!yUXon ze-CT3XZi#mZ{PHJXDz;i`#Yxv=TvO-)Js%_I;3w|xBJuK?(;}mFK_8wvYEQ-YZn*W z|9{x7*NaEw(Cm5FG~ldby|b`c+I|K0b}3t--Qq^Fi>h5OQv zRUsSET0gNIPxCCh=x801&GEFd*-`oPPdGKVL*BkHg{A9QsOcQp`nq6tH_~TW-`M&1YxXI24_u&^`+6E|fJkgKD;h|r zJK5Cj>}78`g%K=9)%0|>;iU9Q*71HGZ)3TrTWE(rcpM8Nufu~`sM@rUZ7W549Z!x{ zu}shNPo6}JF|sr-x#D~t&mE%8gT!Sg@hJANUqW?qyCIv(bNScxC$h8s*^}F8%290i zVv+OTER0jv@#_ofmPeAN6Zv$N>8kftzVD?qhKO~d=dK<9bXWEm`COZ=aPrS*G{liC zeGSpm?#Vv-N~1#lKCf#8AM+8CRs%OI6>%<*jX718Ep|=3h$UU)nl&t8EB;0qyS@Le zXE4*FJJ?wW4P|p0I~ik3`i0)hMt0YKmu9&_ug4LD@bL^f^CIifTIRQ_e9%kz^D+Z1?CcRc^i)r~>cH;KQyouF^|1rM1lN6_pR+Cc z9`5ghNX$C1&2ll%YBudrymzcIb+s;UvoLFTPe;<+6=e}0;bXqb#~kZy#D*G(tg(NF6ZYiODouA^tQB-^Z)L^eSOlG z;uLc6a1&#Sz3M;2X{FikHFjtpm+_^XcXEoDCj8;!Q0zq-b28i7gGV)l&+|fh8c*sF zd^ehYu5Uy;)Kt~+OL+avAyWIP??07vicW392wQ<=+tV%!H zpg#+GID5Az4bjP|sfVHQX8EVnc~HwB9cFv-tyZ#qGE4>>dX|?oM8t3lPh@~dX*$i@ zR%W3INjzDX`z2`8l9zUrXME1)7PIbriO{#*zG-tvrafqSv{i zja4jh?DT)SXk$-RkvK8$B)-4p<9XQ=U#BG-d-iKAK;TZEj|`6vmxDd? zVVv67)1E}jL-}3NUHLknYyr)=h?Ff+Kj|tW8ztJ=Lf75x4vToCm++u@M z+G?|kUW+|dnL^XST9ful{ObF~sQ-%f|0f@;reNgHyUz;!0u9-t&dI^)GdSg2 zJkcJ%{3J?<-jz#OspudH)Yg3RdbBwXBSGhw<*9ndJ_rO%S`ayW$e(S3`!Bc3ZS)Qu zN*d1*bzVtU&oHaf@^KCM7O}%u89Mr9(bOGm^BeMQ?|Oa%r_dZk3ZsLlDjNL4V)Z4- zo9I>ckDuGyZr2~lwVfbq_5khh03M2J)m`ky`S_$Z+*CVuv%hEjNY5P0JNcRivyLQ` zNAsK6!CLfd75-mMe(*cA%1UuvN1t`)QwP%c95gsoPf=M~XNGm$+kE%5ws+IPQZ`P9KWT*I1t|x=fwI>W%}*RGf;kuddrFbVD;E z*^@QZ8z!dSCFehe&-D;Xe4jkwW<3k1;<_3#8b_&(7tJ#;5c|`y<4N@_^J^}i4;08s z(vTU+vFz{%Jf_d&GdBAFavs?V+TjS1$c1d`WZZl0qAX)>D*@mAUJH%DOcaO-9pJQL>C1(2uOwB%K82Ey*WOyygyhUd`g)$f6 zvnBLyFWqPNqu!zTqP*FjOK#$%mT!3w2c<8|FMNUf4&vQEAVQ5j&PVYsUc$lStyM*t zokLiqdiZyV+)OX`+F$g45&nCRHGbDD?!x;~EBVr^uK4x?RO!ewS|yjY(N)LOMWbni zeNd$lu8Mv69x}V=seaw=XOYM4&p*0EMq>oYt)}7_ou3V52i}qM`I|LpZB?T?v;pmV Kglcx}hO2B!nJ%3q>bX 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%0D+C64-$o19My|m7SajSn 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