Mercurial > repos > gregor.m > spyboat
changeset 3:4d7f30a7e2f6 draft
"planemo upload commit d070f1ba04a5141a65487f45b29c22767639e44b"
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OutputReport.html Tue Nov 24 13:06:26 2020 +0000 @@ -0,0 +1,247 @@ + + <html> + <title>SpyBOAT Output Report</title> + <head> + <!-- that doesn't work with galaxy.. --> + <!--link rel="stylesheet" href="styles.css"--> + <style type="text/css"> + body{ margin:10 100; background:whitesmoke; } + /*body{ margin:10 100; background:darkslategrey; }*/ + .center{ + text-align: center; + display: block; + margin-left: auto; + margin-right: auto; + width: 100%;} + + /* matplotlib output at 1600x1200 */ + .distr_gallery { + display: grid; + margin: 0 auto; + text-align: center; + /* border: 1px dashed rgba(4, 4, 4, 0.35); */ + grid-template-columns: repeat(3,1fr); + grid-template-rows: 20vw; + grid-gap: 0px; + column-gap: 0px + } + .distr_gallery__img { + width: 100%; + height: 100%; + object-fit: contain; + } + + + /* matplotlib output at 1600x1200 */ + .snapshot_gallery { + display: grid; + margin: 0 auto; + border: 1px dashed rgba(4, 4, 4, 0.35); + text-align: center; + grid-template-columns: repeat(2,1fr); + grid-template-rows: repeat(2,20vw); + grid-gap: 5px; + } + .snapshot_gallery__img { + width: 100%; + height: 100%; + object-fit: contain; + } + .subheader{ + text-align:center; + font-size: 160%; + color:#363333;} + </style> + </head> + <body> + <h1 style="text-align:center; color:#363333">SpyBOAT Results Report</h1> + <hr style="width:50%"> + <h1 class="subheader"> Distribution Dynamics </h1> + <div class="distr_gallery"> + <figure class=”distr_gallery__item distr_gallery__item--1"> + <img src="period_distr.png" alt="Period" class="distr_gallery__img"> + </figure> + + <figure class=”distr_gallery__item distr_gallery__item--2"> + <img src="power_distr.png" alt="Power" class="distr_gallery__img"> + </figure> + + <figure class=”distr_gallery__item distr_gallery__item--3"> + <img src="phase_distr.png" alt="Phase" class="distr_gallery__img"> + </figure> + + </div> + + <h1 class="subheader"> Output Movie Snapshots </h1> + + <!-- trigger the javascript at the end---> + <div class="center"> + <button class="w3-button" onclick="plusDivs(-1)">❮ Prev</button> + <button class="w3-button" onclick="plusDivs(1)">Next ❯</button> + </div> + + <!-- defines all elements of the "FrameSlides" class ---> + + <div class="FrameSlides"> + <h3 style="text-align:center; color=#363333"> Frame Nr. 2 </h3> + + <div class="snapshot_gallery"> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--1"> + <img src="input_frame2.png" alt="The Input" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--2"> + <img src="phase_frame2.png" alt="Phase" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--3"> + <img src="period_frame2.png" alt="Period" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--4"> + <img src="amplitude_frame2.png" alt="Amplitude" class="snapshot_gallery__img"> + </figure> + </div> + </div> + + <div class="FrameSlides"> + <h3 style="text-align:center; color=#363333"> Frame Nr. 18 </h3> + + <div class="snapshot_gallery"> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--1"> + <img src="input_frame18.png" alt="The Input" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--2"> + <img src="phase_frame18.png" alt="Phase" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--3"> + <img src="period_frame18.png" alt="Period" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--4"> + <img src="amplitude_frame18.png" alt="Amplitude" class="snapshot_gallery__img"> + </figure> + </div> + </div> + + <div class="FrameSlides"> + <h3 style="text-align:center; color=#363333"> Frame Nr. 34 </h3> + + <div class="snapshot_gallery"> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--1"> + <img src="input_frame34.png" alt="The Input" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--2"> + <img src="phase_frame34.png" alt="Phase" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--3"> + <img src="period_frame34.png" alt="Period" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--4"> + <img src="amplitude_frame34.png" alt="Amplitude" class="snapshot_gallery__img"> + </figure> + </div> + </div> + + <div class="FrameSlides"> + <h3 style="text-align:center; color=#363333"> Frame Nr. 50 </h3> + + <div class="snapshot_gallery"> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--1"> + <img src="input_frame50.png" alt="The Input" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--2"> + <img src="phase_frame50.png" alt="Phase" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--3"> + <img src="period_frame50.png" alt="Period" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--4"> + <img src="amplitude_frame50.png" alt="Amplitude" class="snapshot_gallery__img"> + </figure> + </div> + </div> + + <div class="FrameSlides"> + <h3 style="text-align:center; color=#363333"> Frame Nr. 66 </h3> + + <div class="snapshot_gallery"> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--1"> + <img src="input_frame66.png" alt="The Input" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--2"> + <img src="phase_frame66.png" alt="Phase" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--3"> + <img src="period_frame66.png" alt="Period" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--4"> + <img src="amplitude_frame66.png" alt="Amplitude" class="snapshot_gallery__img"> + </figure> + </div> + </div> + + <div class="FrameSlides"> + <h3 style="text-align:center; color=#363333"> Frame Nr. 82 </h3> + + <div class="snapshot_gallery"> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--1"> + <img src="input_frame82.png" alt="The Input" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--2"> + <img src="phase_frame82.png" alt="Phase" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--3"> + <img src="period_frame82.png" alt="Period" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--4"> + <img src="amplitude_frame82.png" alt="Amplitude" class="snapshot_gallery__img"> + </figure> + </div> + </div> + + </div> + + <!-- javascript with escaped '{'---> + <script> + var slideIndex = 1; + showDivs(slideIndex); + + function plusDivs(n) { + showDivs(slideIndex += n); + } + + function showDivs(n) { + var i; + var x = document.getElementsByClassName("FrameSlides"); + if (n > x.length) {slideIndex = 1} + if (n < 1) {slideIndex = x.length} ; + for (i = 0; i < x.length; i++) { + x[i].style.display = "none"; + } + x[slideIndex-1].style.display = "block"; + } + </script> + </body> + </html> + \ No newline at end of file
--- a/SpyBOAT.xml Mon Nov 23 14:38:37 2020 +0000 +++ b/SpyBOAT.xml Tue Nov 24 13:06:26 2020 +0000 @@ -1,10 +1,10 @@ -<tool id="SpyBOAT" name="SpyBOAT" version="0.0.2"> +<tool id="SpyBOAT" name="SpyBOAT" version="0.1.0"> <requirements> - <requirement type="package" version="0.0.4">spyboat</requirement> + <requirement type="package" version="0.1.0">spyboat</requirement> </requirements> - <version_command>python $__tool_directory__/cl_wrapper.py --version</version_command> + <version_command>python $__tool_directory__/spyboat_cli.py --version</version_command> <command detect_errors="exit_code"><![CDATA[ - python $__tool_directory__/cl_wrapper.py + python $__tool_directory__/spyboat_cli.py --input_path '$movie' #if $gauss_sigma: --gauss_sigma $gauss_sigma @@ -13,8 +13,8 @@ --rescale $rescale_factor #end if - #if $masking.selection_mode == "create_fixed_mask": - --masking fixed + #if $masking.selection_mode == "create_static_mask": + --masking static --mask_frame $masking.mask_frame --mask_thresh $masking.mask_thresh #else if $masking.selection_mode == "create_dynamic_mask": @@ -54,7 +54,7 @@ <!-- The following Wavelet parameters must have the same numerical type as defined in the - argparse parser in cl_wrapper.py + argparse parser in spyboat_cli.py --> <param name="gauss_sigma" type="float" label="Sigma" @@ -71,12 +71,12 @@ <conditional name="masking"> <param label="Masking the output" name="selection_mode" type="select" help="Create a mask from the (blurred/rescaled) input to mask out regions without oscillations/signal in the output"> <option selected="true" value="no_masking">No masking</option> - <option value="create_fixed_mask">Create a fixed mask</option> + <option value="create_static_mask">Create a static mask</option> <option value="create_dynamic_mask">Create a dynamic mask</option> </param> - <when value="create_fixed_mask"> + <when value="create_static_mask"> <param name="mask_frame" type="integer" value="1" label="Create mask from frame" - help="Creates a fixed mask from the chosen frame of the input movie."> + help="Creates a static mask from the chosen frame of the input movie."> <validator type="in_range" min="1" max="99999"/> </param> <param name="mask_thresh" type="float" value="0" label="Threshold" @@ -154,7 +154,7 @@ <help><![CDATA[ **What it does** - Wavelet transforms a 3d-image stack (time,Y,X) pixel by pixel and extracts/evaluates the wavelet ridge. Removal of low-frequency trends is provided via sinc filtering. + Wavelet transforms a 3d-image stack (time,Y,X) pixel by pixel along the time axis and extracts/evaluates the wavelet ridge. Removal of low-frequency trends is provided via sinc filtering. There are four output movies generated (phase, period, amplitude and power). They have exactly the same dimensions (time,Y,X) as the (rescaled) input. Pre-smoothing of the data with Gaussian kernels is supported and often recommendable. @@ -185,6 +185,8 @@ Given in %, downsamples the spatial resolution of the input movie. This speeds up the whole analysis by a lot. + - Masking: + SpyBOAT offers 'static' and 'dynamic' masking. 'static' means that a single mask is created by thresholding from a user selected frame. 'dynamic' creates a mask for each frame by thresholding, works better for moving/expanding/shrinking oscillatory fields. - Sampling interval: Time passed between consecutive measurements, e.g 'an image every 10 minutes'.
--- a/cl_wrapper.py Mon Nov 23 14:38:37 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,196 +0,0 @@ -#!/usr/bin/env python - -## Gets interfaced by Galaxy or bash scripting -import argparse -import sys, os -import logging - -from skimage import io -from numpy import float32 - -import spyboat -import output_report - -logging.basicConfig(level=logging.INFO, stream=sys.stdout, force=True) -logger = logging.getLogger('wrapper') - -# ----------command line parameters --------------- - -parser = argparse.ArgumentParser(description='Process some arguments.') - -# I/O -parser.add_argument('--input_path', help="Input movie location", required=True) -parser.add_argument('--phase_out', help='Phase output file name', required=True) -parser.add_argument('--period_out', help='Period output file name', required=True) -parser.add_argument('--power_out', help='Power output file name', required=True) -parser.add_argument('--amplitude_out', help='Amplitude output file name', required=True) -parser.add_argument('--preprocessed_out', help="Preprocessed-input output file name, 'None'", required=False) - - -# (Optional) Multiprocessing - -parser.add_argument('--ncpu', help='Number of processors to use', - required=False, type=int, default=1) - -# Optional spatial downsampling -parser.add_argument('--rescale', help='Rescale the image by a factor given in %%, None means no rescaling', - required=False, type=int) -# Optional Gaussian smoothing -parser.add_argument('--gauss_sigma', help='Gaussian smoothing parameter, None means no smoothing', required=False, type=float) - -# Wavelet Analysis Parameters -parser.add_argument('--dt', help='Sampling interval', required=True, type=float) -parser.add_argument('--Tmin', help='Smallest period', required=True, type=float) -parser.add_argument('--Tmax', help='Biggest period', required=True, type=float) -parser.add_argument('--nT', help='Number of periods to scan for', required=True, type=int) - -parser.add_argument('--Tcutoff', help='Sinc cut-off period, disables detrending if not set', required=False, type=float) -parser.add_argument('--win_size', help='Sliding window size for amplitude normalization, None means no normalization', - required=False, type=float) - -# Optional masking -parser.add_argument('--masking', help="Set to either 'dynamic', 'fixed' or 'None' which is the default", default='None', required=False, type=str) - -parser.add_argument('--mask_frame', - help="The frame of the input movie to create a fixed mask from, needs masking set to 'fixed'", - required=False, type=int) - - -parser.add_argument('--mask_thresh', help='The threshold of the mask, all pixels with less than this value get masked (if masking enabled).', - required=False, type=float, - default=0) - -# output overview/snapshots -parser.add_argument('--html_fname', help="Name of the html report.", - default='OutputReport.html', required=False, type=str) - -parser.add_argument('--report_img_path', help="For the html report, can be set in Galaxy. Defaults to cwd.", default='.', required=False, type=str) - -parser.add_argument('--version', action='version', version='0.0.1') - -arguments = parser.parse_args() - -logger.info("Received following arguments:") -for arg in vars(arguments): - logger.info(f'{arg} -> {getattr(arguments, arg)}') - -# ------------Read the input---------------------------------------- -try: - movie = spyboat.open_tif(arguments.input_path) -except FileNotFoundError: - logger.critical(f"Couldn't open {arguments.input_path}, check movie storage directory!") - - sys.exit(1) - -# -------- Do (optional) spatial downsampling --------------------------- - -scale_factor = arguments.rescale - -# defaults to None -if not scale_factor: - logger.info('No downsampling requested..') - -elif 0 < scale_factor < 100: - logger.info(f'Downsampling the movie to {scale_factor:d}% of its original size..') - movie = spyboat.down_sample(movie, scale_factor / 100) -else: - raise ValueError('Scale factor must be between 0 and 100!') - -# -------- Do (optional) pre-smoothing ------------------------- -# note that downsampling already is a smoothing operation.. - -# check if pre-smoothing requested -if not arguments.gauss_sigma: - logger.info('No pre-smoothing requested..') -else: - logger.info(f'Pre-smoothing the movie with Gaussians, sigma = {arguments.gauss_sigma:.2f}..') - - movie = spyboat.gaussian_blur(movie, arguments.gauss_sigma) - -# ----- Set up Masking before processing ---- - -mask = None -if arguments.masking == 'fixed': - if not arguments.mask_frame: - logger.critical("Frame number for fixed masking is missing!") - sys.exit(1) - - if (arguments.mask_frame > movie.shape[0]) or (arguments.mask_frame < 0): - logger.critical(f'Requested frame does not exist, input only has {movie.shape[0]} frames.. exiting') - sys.exit(1) - - else: - logger.info(f'Creating fixed mask from frame {arguments.mask_frame} with threshold {arguments.mask_thresh}') - mask = spyboat.create_fixed_mask(movie, arguments.mask_frame, - arguments.mask_thresh) -elif arguments.masking == 'dynamic': - logger.info(f'Creating dynamic mask with threshold {arguments.mask_thresh}') - mask = spyboat.create_dynamic_mask(movie, arguments.mask_thresh) - -else: - logger.info('No masking requested..') - -# ------ Retrieve wavelet parameters --------------------------- - -Wkwargs = {'dt': arguments.dt, - 'Tmin': arguments.Tmin, - 'Tmax': arguments.Tmax, - 'nT': arguments.nT, - 'T_c' : arguments.Tcutoff, # defaults to None - 'win_size' : arguments.win_size # defaults to None -} - -# start parallel processing -results = spyboat.run_parallel(movie, arguments.ncpu, **Wkwargs) - -# --- masking? --- - -if mask is not None: - # mask all output movies (in place!) - for key in results: - logger.info(f'Masking {key}') - spyboat.apply_mask(results[key], mask, fill_value=-1) - -# --- Produce Output Report Figures/png's --- - -# create the directory, yes we have to do that ourselves :) -# galaxy then magically renders the html from that -try: - - if arguments.report_img_path != '.': - logger.info(f'Creating report directory {arguments.report_img_path}') - os.mkdir(arguments.report_img_path) - - # jump to the middle of the movie - snapshot_frame = int(movie.shape[0]/2) - output_report.produce_snapshots(movie, results, snapshot_frame, Wkwargs, img_path=arguments.report_img_path) - - output_report.produce_distr_plots(results, Wkwargs, img_path=arguments.report_img_path) - - output_report.create_html(snapshot_frame, arguments.html_fname) - - -except FileExistsError as e: - logger.critical(f"Could not create html report directory: {repr(e)}") - - -# --- save out result movies --- - -# save phase movie -io.imsave(arguments.phase_out, results['phase'], plugin="tifffile") -logger.info(f'Written {arguments.phase_out}') -# save period movie -io.imsave(arguments.period_out, results['period'], plugin="tifffile") -logger.info(f'Written {arguments.period_out}') -# save power movie -io.imsave(arguments.power_out, results['power'], plugin="tifffile") -logger.info(f'Written {arguments.power_out}') -# save amplitude movie -io.imsave(arguments.amplitude_out, results['amplitude'], plugin="tifffile") -logger.info(f'Written {arguments.amplitude_out}') - -# save out the probably pre-processed (scaled and blurred) input movie for -# direct comparison to results and coordinate mapping etc. -if arguments.preprocessed_out: - io.imsave(arguments.preprocessed_out, movie, plugin='tifffile') - logger.info(f'Written {arguments.preprocessed_out}')
--- a/output_report.py Mon Nov 23 14:38:37 2020 +0000 +++ b/output_report.py Tue Nov 24 13:06:26 2020 +0000 @@ -39,11 +39,13 @@ fig = ppl.gcf() out_path = os.path.join(img_path, f'input_frame{frame}.png') fig.savefig(out_path, dpi=DPI) + ppl.close(fig) spyplot.phase_snapshot(results['phase'][frame]) fig = ppl.gcf() out_path = os.path.join(img_path, f'phase_frame{frame}.png') fig.savefig(out_path, dpi=DPI) + ppl.close(fig) spyplot.period_snapshot(results['period'][frame], Wkwargs, @@ -52,13 +54,14 @@ fig = ppl.gcf() out_path = os.path.join(img_path, f'period_frame{frame}.png') fig.savefig(out_path, dpi=DPI) + ppl.close(fig) spyplot.amplitude_snapshot(results['amplitude'][frame]) fig = ppl.gcf() out_path = os.path.join(img_path, f'amplitude_frame{frame}.png') fig.savefig(out_path, dpi=DPI) + ppl.close(fig) - logger.info(f'Produced 4 snapshots for frame {frame}..') def produce_distr_plots(results, Wkwargs, img_path='.'): @@ -87,14 +90,44 @@ logger.info(f'Produced 3 distribution plots..') -def create_html(frame_num, html_fname='OutputReport.html'): +def create_html(frame_nums, html_fname='OutputReport.html'): ''' - The html generated assumes the respective png's (7 in total) + The html generated assumes the respective png's have been created with 'produce_snapshots' and 'produce_distr_plots' and can be found at the cwd (that's how Galaxy works..) ''' + # -- create a gallery for every frame in frame_nums -- + + galleries = '' + for frame_num in frame_nums: + new_gal =f''' + <div class="FrameSlides"> + <h3 style="text-align:center; color=#363333"> Frame Nr. {frame_num} </h3> + + <div class="snapshot_gallery"> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--1"> + <img src="input_frame{frame_num}.png" alt="The Input" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--2"> + <img src="phase_frame{frame_num}.png" alt="Phase" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--3"> + <img src="period_frame{frame_num}.png" alt="Period" class="snapshot_gallery__img"> + </figure> + + <figure class=”snapshot_gallery__item snapshot_gallery__item--4"> + <img src="amplitude_frame{frame_num}.png" alt="Amplitude" class="snapshot_gallery__img"> + </figure> + </div> + </div> + ''' + galleries += new_gal + html_string =f''' <html> <title>SpyBOAT Output Report</title> @@ -105,10 +138,11 @@ body{{ margin:10 100; background:whitesmoke; }} /*body{{ margin:10 100; background:darkslategrey; }}*/ .center{{ + text-align: center; display: block; margin-left: auto; margin-right: auto; - width: 40%;}} + width: 100%;}} /* matplotlib output at 1600x1200 */ .distr_gallery {{ @@ -117,7 +151,7 @@ text-align: center; /* border: 1px dashed rgba(4, 4, 4, 0.35); */ grid-template-columns: repeat(3,1fr); - grid-template-rows: 25vw; + grid-template-rows: 20vw; grid-gap: 0px; column-gap: 0px }} @@ -143,11 +177,16 @@ height: 100%; object-fit: contain; }} + .subheader{{ + text-align:center; + font-size: 160%; + color:#363333;}} </style> </head> <body> - <h1 style="text-align:center">SpyBOAT Results Report</h1> + <h1 style="text-align:center; color:#363333">SpyBOAT Results Report</h1> <hr style="width:50%"> + <h1 class="subheader"> Distribution Dynamics </h1> <div class="distr_gallery"> <figure class=”distr_gallery__item distr_gallery__item--1"> <img src="period_distr.png" alt="Period" class="distr_gallery__img"> @@ -163,27 +202,38 @@ </div> - <h2 style="text-align:center"> Snapshots - Frame {frame_num}</h2> - <div class="snapshot_gallery"> - <figure class=”snapshot_gallery__item snapshot_gallery__item--1"> - <img src="input_frame{frame_num}.png" alt="The Input" class="snapshot_gallery__img"> - </figure> + <h1 class="subheader"> Output Movie Snapshots </h1> - <figure class=”snapshot_gallery__item snapshot_gallery__item--2"> - <img src="phase_frame{frame_num}.png" alt="Phase" class="snapshot_gallery__img"> - </figure> + <!-- trigger the javascript at the end---> + <div class="center"> + <button class="w3-button" onclick="plusDivs(-1)">❮ Prev</button> + <button class="w3-button" onclick="plusDivs(1)">Next ❯</button> + </div> + + <!-- defines all elements of the "FrameSlides" class ---> + {galleries} + </div> - <figure class=”snapshot_gallery__item snapshot_gallery__item--3"> - <img src="period_frame{frame_num}.png" alt="Period" class="snapshot_gallery__img"> - </figure> + <!-- javascript with escaped '{{'---> + <script> + var slideIndex = 1; + showDivs(slideIndex); + + function plusDivs(n) {{ + showDivs(slideIndex += n); + }} - <figure class=”snapshot_gallery__item snapshot_gallery__item--4"> - <img src="amplitude_frame{frame_num}.png" alt="Amplitude" class="snapshot_gallery__img"> - </figure> - </div> - - - <!-- *** Section 1 *** ---> + function showDivs(n) {{ + var i; + var x = document.getElementsByClassName("FrameSlides"); + if (n > x.length) {{slideIndex = 1}} + if (n < 1) {{slideIndex = x.length}} ; + for (i = 0; i < x.length; i++) {{ + x[i].style.display = "none"; + }} + x[slideIndex-1].style.display = "block"; + }} + </script> </body> </html> ''' @@ -196,4 +246,4 @@ return html_string # for local testing -# create_html(125) +# create_html([0,20,40,60,80])
--- a/run_tests.sh Mon Nov 23 14:38:37 2020 +0000 +++ b/run_tests.sh Tue Nov 24 13:06:26 2020 +0000 @@ -1,13 +1,10 @@ #!/usr/bin/env bash -# example command, minimal options: no detrending, -# no rescaling, no masking, no amplitude norm., no blurring INPUT_PATH='./test-data/test-movie.tif' -# INPUT_PATH='./test-data/SCN_L20_Evans2013-half.tif' SCRIPT_PATH='.' -python3 $SCRIPT_PATH/cl_wrapper.py --input_path $INPUT_PATH --phase_out phase_twosines_out.tif --period_out period_twosines_out.tif --power_out power_twosines_out.tif --amplitude_out amplitude_twosines_out.tif --dt .5 --Tmin 20 --Tmax 30 --nT 200 --ncpu 6 --masking dynamic --preprocessed_out preproc_two_sines.tif --gauss_sigma 3 --rescale 50 --Tcutoff 40 --masking fixed --mask_frame 10 --mask_thresh 8 +python3 $SCRIPT_PATH/spyboat_cli.py --input_path $INPUT_PATH --phase_out phase_twosines_out.tif --period_out period_twosines_out.tif --power_out power_twosines_out.tif --amplitude_out amplitude_twosines_out.tif --dt 1 --Tmin 2 --Tmax 30 --nT 200 --ncpu 6 --masking dynamic --preprocessed_out preproc_two_sines.tif --gauss_sigma 3 --rescale 80 --Tcutoff 40 --masking static --mask_frame 10 --mask_thresh 8 printf "\n" # printf "\nError examples:\n"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spyboat_cli.py Tue Nov 24 13:06:26 2020 +0000 @@ -0,0 +1,210 @@ +#!/usr/bin/env python + +## Gets interfaced by Galaxy or can be used for bash scripting +import argparse +import sys, os +import logging + +from skimage import io +from numpy import float32 + +import spyboat +import output_report + +logging.basicConfig(level=logging.INFO, stream=sys.stdout, force=True) +logger = logging.getLogger('wrapper') + +# ----------command line parameters --------------- + +parser = argparse.ArgumentParser(description='Process some arguments.') + +# I/O +parser.add_argument('--input_path', help="Input movie location", required=True) +parser.add_argument('--phase_out', help='Phase output file name', required=True) +parser.add_argument('--period_out', help='Period output file name', required=True) +parser.add_argument('--power_out', help='Power output file name', required=True) +parser.add_argument('--amplitude_out', help='Amplitude output file name', required=True) +parser.add_argument('--preprocessed_out', help="Preprocessed-input output file name, 'None'", required=False) + + +# (Optional) Multiprocessing + +parser.add_argument('--ncpu', help='Number of processors to use', + required=False, type=int, default=1) + +# Optional spatial downsampling +parser.add_argument('--rescale', help='Rescale the image by a factor given in %%, None means no rescaling', + required=False, type=int) +# Optional Gaussian smoothing +parser.add_argument('--gauss_sigma', help='Gaussian smoothing parameter, None means no smoothing', required=False, type=float) + +# Wavelet Analysis Parameters +parser.add_argument('--dt', help='Sampling interval', required=True, type=float) +parser.add_argument('--Tmin', help='Smallest period', required=True, type=float) +parser.add_argument('--Tmax', help='Biggest period', required=True, type=float) +parser.add_argument('--nT', help='Number of periods to scan for', required=True, type=int) + +parser.add_argument('--Tcutoff', help='Sinc cut-off period, disables detrending if not set', required=False, type=float) +parser.add_argument('--win_size', help='Sliding window size for amplitude normalization, None means no normalization', + required=False, type=float) + +# Optional masking +parser.add_argument('--masking', help="Set to either 'dynamic', 'static' or 'None' which is the default", default='None', required=False, type=str) + +parser.add_argument('--mask_frame', + help="The frame of the input movie to create a static mask from, needs masking set to 'static'", + required=False, type=int) + + +parser.add_argument('--mask_thresh', help='The threshold of the mask, all pixels with less than this value get masked (if masking enabled).', + required=False, type=float, + default=0) + +# output html report/snapshots +parser.add_argument('--html_fname', help="Name of the html report.", + default='OutputReport.html', required=False, type=str) + +parser.add_argument('--report_img_path', help="For the html report, to be set in Galaxy. Without galaxy leave at cwd!", default='.', required=False, type=str) + +parser.add_argument('--version', action='version', version='0.1.0') + +arguments = parser.parse_args() + +logger.info("Received following arguments:") +for arg in vars(arguments): + logger.info(f'{arg} -> {getattr(arguments, arg)}') + +# ------------Read the input---------------------------------------- +try: + movie = spyboat.open_tif(arguments.input_path) +except FileNotFoundError: + logger.critical(f"Couldn't open {arguments.input_path}, check movie storage directory!") + + sys.exit(1) + +# -------- Do (optional) spatial downsampling --------------------------- + +scale_factor = arguments.rescale + +# defaults to None +if not scale_factor: + logger.info('No downsampling requested..') + +elif 0 < scale_factor < 100: + logger.info(f'Downsampling the movie to {scale_factor:d}% of its original size..') + movie = spyboat.down_sample(movie, scale_factor / 100) +else: + raise ValueError('Scale factor must be between 0 and 100!') + +# -------- Do (optional) pre-smoothing ------------------------- +# note that downsampling already is a smoothing operation.. + +# check if pre-smoothing requested +if not arguments.gauss_sigma: + logger.info('No pre-smoothing requested..') +else: + logger.info(f'Pre-smoothing the movie with Gaussians, sigma = {arguments.gauss_sigma:.2f}..') + + movie = spyboat.gaussian_blur(movie, arguments.gauss_sigma) + +# ----- Set up Masking before processing ---- + +mask = None +if arguments.masking == 'static': + if not arguments.mask_frame: + logger.critical("Frame number for static masking is missing!") + sys.exit(1) + + if (arguments.mask_frame > movie.shape[0]) or (arguments.mask_frame < 0): + logger.critical(f'Requested frame does not exist, input only has {movie.shape[0]} frames.. exiting') + sys.exit(1) + + else: + logger.info(f'Creating static mask from frame {arguments.mask_frame} with threshold {arguments.mask_thresh}') + mask = spyboat.create_static_mask(movie, arguments.mask_frame, + arguments.mask_thresh) +elif arguments.masking == 'dynamic': + logger.info(f'Creating dynamic mask with threshold {arguments.mask_thresh}') + mask = spyboat.create_dynamic_mask(movie, arguments.mask_thresh) + +else: + logger.info('No masking requested..') + +# ------ Retrieve wavelet parameters --------------------------- + +Wkwargs = {'dt': arguments.dt, + 'Tmin': arguments.Tmin, + 'Tmax': arguments.Tmax, + 'nT': arguments.nT, + 'T_c' : arguments.Tcutoff, # defaults to None + 'win_size' : arguments.win_size # defaults to None +} + +# --- start parallel processing --- + +results = spyboat.run_parallel(movie, arguments.ncpu, **Wkwargs) + +# --- masking? --- + +if mask is not None: + # mask all output movies (in place!) + for key in results: + logger.info(f'Masking {key}') + spyboat.apply_mask(results[key], mask, fill_value=-1) + +# --- Produce Output HTML Report Figures/png's --- + +# create the directory, yes we have to do that ourselves :) +# galaxy then magically renders the html from that directory +try: + + if arguments.report_img_path != '.': + logger.info(f'Creating report directory {arguments.report_img_path}') + os.mkdir(arguments.report_img_path) + + # make 6 times 4 snapshots each + Nsnap = 6 + NFrames = movie.shape[0] + # show only frames at least one Tmin + # away from the edge (-effects) + start_frame = int(Wkwargs['Tmin']/Wkwargs['dt']) + + if (start_frame > NFrames//2): + logger.warning("Smallest period already is larger than half the observation time!") + # set to 0 in this case + start_frame = 0 + + frame_increment = int( (NFrames - 2*start_frame) / Nsnap) + snapshot_frames = range(start_frame, NFrames - start_frame, frame_increment) + + for snapshot_frame in snapshot_frames: + output_report.produce_snapshots(movie, results, snapshot_frame, Wkwargs, img_path=arguments.report_img_path) + + output_report.produce_distr_plots(results, Wkwargs, img_path=arguments.report_img_path) + + output_report.create_html(snapshot_frames, arguments.html_fname) + +except FileExistsError as e: + logger.critical(f"Could not create html report directory: {repr(e)}") + + +# --- save out result movies --- + +# save phase movie +io.imsave(arguments.phase_out, results['phase'], plugin="tifffile") +logger.info(f'Written {arguments.phase_out}') +# save period movie +io.imsave(arguments.period_out, results['period'], plugin="tifffile") +logger.info(f'Written {arguments.period_out}') +# save power movie +io.imsave(arguments.power_out, results['power'], plugin="tifffile") +logger.info(f'Written {arguments.power_out}') +# save amplitude movie +io.imsave(arguments.amplitude_out, results['amplitude'], plugin="tifffile") +logger.info(f'Written {arguments.amplitude_out}') + +# save out the probably pre-processed (scaled and blurred) input movie for +# direct comparison to results and coordinate mapping etc. +if arguments.preprocessed_out: + io.imsave(arguments.preprocessed_out, movie, plugin='tifffile') + logger.info(f'Written {arguments.preprocessed_out}')