From f1c315783c773581995050c3f346adda31011bcf Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Tue, 13 Feb 2024 15:24:42 +0000 Subject: [PATCH 01/12] Test the success of refocusing --- .../things/autofocus.py | 25 +++++++++-- .../things/smart_scan.py | 42 ++++++++++++------- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/openflexure_microscope_server/things/autofocus.py b/src/openflexure_microscope_server/things/autofocus.py index 4e966d27..f833ba53 100644 --- a/src/openflexure_microscope_server/things/autofocus.py +++ b/src/openflexure_microscope_server/things/autofocus.py @@ -26,6 +26,7 @@ from pydantic import BaseModel Stage = direct_thing_client_dependency(SangaboardThing, "/stage/") Camera = raw_thing_dependency(StreamingPiCamera2) +WrappedCamera = direct_thing_client_dependency(StreamingPiCamera2, "/camera/") ### Autofocus utilities @@ -206,12 +207,14 @@ class AutofocusThing(Thing): """ repeat = True attempts = 0 + backlash = 200 with m.run(): while repeat and attempts < 10: if start == 'centre': - stage.move_relative(x = 0, y = 0, z = -dz / 2) + stage.move_relative(x = 0, y = 0, z = -(backlash + dz / 2)) + stage.move_relative(x = 0, y = 0, z = backlash) i, z = m.focus_rel(dz, block_cancellation=True) _, heights, sizes = m.move_data(i) @@ -226,8 +229,24 @@ class AutofocusThing(Thing): ): attempts += 1 start = 'centre' + stage.move_absolute(z = peak_height-backlash) stage.move_absolute(z = peak_height) else: repeat = False - stage.move_relative(x = 0, y = 0, z = -dz) - stage.move_absolute(z = peak_height) \ No newline at end of file + stage.move_relative(x = 0, y = 0, z = -(dz+backlash)) + stage.move_absolute(z = peak_height) + return heights.tolist(), sizes.tolist() + + @thing_action + def verify_focus_sharpness(self, sweep_sizes: list, camera: WrappedCamera, leniency: int = 1): + '''Take the sharpness curve of the autofocus, and the size of the current frame + to see if the autofocus completed successfully. Returns True if current sharpness + is within "leniency" number of frames from the peak of the autofocus''' + + current_sharpness = camera.grab_jpeg_size(stream_name='lores') + + peak = np.argmax(sweep_sizes) + accepted_range = [peak - leniency, peak + leniency] + + sharpness_range = [sweep_sizes[i] for i in accepted_range] + return current_sharpness >= min(sharpness_range) \ No newline at end of file diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index b03c2d93..2c38c7a6 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -640,24 +640,29 @@ class SmartScanThing(Thing): attempts = 0 if self.autofocus_dz > 200: while True: - autofocus.looping_autofocus(dz=self.autofocus_dz, start = 'base') + jpeg_zs, jpeg_sizes = autofocus.looping_autofocus(dz=self.autofocus_dz, start = 'base') current_height = stage.position["z"] + autofocus_success = autofocus.verify_focus_sharpness(sweep_sizes = jpeg_sizes, camera = CamDep, leniency = 1) + logger.info(f"We just tested the focus! Result was {autofocus_success}") - # if there have been successful autofocuses in this scan, find the closest one in x-y - # test if the change in z between them exceeds a ratio (indicating a failed autofocus) - if len(focused_path) > 0: - nearest_focused_site = focused_path[closest(loc, focused_path)] - result = limit_focus_change( - nearest_focused_site[0:2], - nearest_focused_site[-1], - loc[0:2], - current_height, - 0.3, - ) + if autofocus_success: + # if there have been successful autofocuses in this scan, find the closest one in x-y + # test if the change in z between them exceeds a ratio (indicating a failed autofocus) + if len(focused_path) > 0: + nearest_focused_site = focused_path[closest(loc, focused_path)] + result = limit_focus_change( + nearest_focused_site[0:2], + nearest_focused_site[-1], + loc[0:2], + current_height, + 0.3, + ) - # if there haven't been any previous autofocuses, we have to assume this one worked + # if there haven't been any previous autofocuses, we have to assume this one worked + else: + result = "accept" else: - result = "accept" + result = "reject" # if the autofocus worked, add the current position to the list of successful locations if result == "accept": @@ -762,6 +767,15 @@ class SmartScanThing(Thing): def max_range(self, value: int) -> None: self.thing_settings["max_range"] = value + @thing_property + def stitch_tiff(self) -> bool: + """The maximum distance from the centre of the scan before we break""" + return self.thing_settings.get("stitch_tiff", False) + + @stitch_tiff.setter + def stitch_tiff(self, value: bool) -> None: + self.thing_settings["stitch_tiff"] = value + @thing_property def skip_background(self) -> bool: """Whether to detect and skip empty fields of view From aed5a229835f433f822426088902242db3126e09 Mon Sep 17 00:00:00 2001 From: jaknapper Date: Thu, 15 Feb 2024 11:02:44 +0000 Subject: [PATCH 02/12] Autofocus verify based on sharpness range, removed repetitive logging --- .../things/autofocus.py | 10 +++---- .../things/smart_scan.py | 27 ++++++++++++------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/openflexure_microscope_server/things/autofocus.py b/src/openflexure_microscope_server/things/autofocus.py index f833ba53..ab1325dd 100644 --- a/src/openflexure_microscope_server/things/autofocus.py +++ b/src/openflexure_microscope_server/things/autofocus.py @@ -238,15 +238,15 @@ class AutofocusThing(Thing): return heights.tolist(), sizes.tolist() @thing_action - def verify_focus_sharpness(self, sweep_sizes: list, camera: WrappedCamera, leniency: int = 1): + def verify_focus_sharpness(self, sweep_sizes: list, camera: WrappedCamera, threshold: float = 0.95): '''Take the sharpness curve of the autofocus, and the size of the current frame to see if the autofocus completed successfully. Returns True if current sharpness is within "leniency" number of frames from the peak of the autofocus''' current_sharpness = camera.grab_jpeg_size(stream_name='lores') - peak = np.argmax(sweep_sizes) - accepted_range = [peak - leniency, peak + leniency] + peak = np.max(sweep_sizes) + base = np.min(sweep_sizes) + cutoff = threshold * (peak - base) - sharpness_range = [sweep_sizes[i] for i in accepted_range] - return current_sharpness >= min(sharpness_range) \ No newline at end of file + return current_sharpness >= base + cutoff \ No newline at end of file diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index 2c38c7a6..8f3bd0eb 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -642,7 +642,7 @@ class SmartScanThing(Thing): while True: jpeg_zs, jpeg_sizes = autofocus.looping_autofocus(dz=self.autofocus_dz, start = 'base') current_height = stage.position["z"] - autofocus_success = autofocus.verify_focus_sharpness(sweep_sizes = jpeg_sizes, camera = CamDep, leniency = 1) + autofocus_success = autofocus.verify_focus_sharpness(sweep_sizes = jpeg_sizes, camera = CamDep, threshold = 0.92) logger.info(f"We just tested the focus! Result was {autofocus_success}") if autofocus_success: @@ -655,7 +655,7 @@ class SmartScanThing(Thing): nearest_focused_site[-1], loc[0:2], current_height, - 0.3, + 0.5, ) # if there haven't been any previous autofocuses, we have to assume this one worked @@ -721,6 +721,7 @@ class SmartScanThing(Thing): logger.info(f'Rejected moving to {i} as it is out of range') path = temp_path.copy() path = sorted(path, key=lambda x: (steps_from_centre(x, true_path[0][:2], dx, dy), distance_to_site(loc[:2], x))) + self.create_zip_of_scan(logger = logger, scan_name = scan_folder.split('scans/')[1], download_zip = False) except InvocationCancelledError: logger.error("Stopping scan because it was cancelled.") @@ -1036,7 +1037,12 @@ class SmartScanThing(Thing): ) if not os.path.isdir(images_folder): raise FileNotFoundError(f"Tried to make a zip archive of {images_folder} but it does not exist.") - logger.info("Creating zip archive of images (may take some time)...") + # logger.info("Creating zip archive of images (may take some time)...") + + from pathlib import Path + + root_directory = Path(images_folder) + print(sum(f.stat().st_size for f in root_directory.glob('**/*') if f.is_file())) zip_fname = f'{os.path.join(scan_folder, "images")}.zip' @@ -1050,8 +1056,6 @@ class SmartScanThing(Thing): # get a list of files in the existing zip current_zip = self.get_files_in_zip(zip_fname) - logger.info(current_zip) - # get a list of files in the folder we're zipping folder_path = self.scan_folder_path(scan_name) files = glob.glob(folder_path + '/**/*', recursive=True) @@ -1065,11 +1069,14 @@ class SmartScanThing(Thing): with zipfile.ZipFile(zip_fname, mode="a") as zip: for file in files: if any(banned_name in file for banned_name in files_to_delay): - logger.info(f'we only add {file} into zip at the end of the scan') + # logger.info(f'we only add {file} into zip at the end of the scan') + pass elif file in current_zip: - logger.info(f'{file} is already in zip') - elif ".zip" in file: - logger.info('Not adding the .zip to itself') + # logger.info(f'{file} is already in zip') + pass + elif ".zip" in file or 'raw' in file: + # logger.info('Not adding the .zip to itself') + pass else: logger.info(f'appending {file} to zip') zip.write(os.path.join(folder_path, file), arcname=file) @@ -1090,7 +1097,7 @@ class SmartScanThing(Thing): if any(banned_name in file for banned_name in files_to_delay): logger.info(f'we are finally adding {file} into zip') zip.write(os.path.join(folder_path, file), arcname=file) - + logger.info('about to download zip') return ZipBlob.from_file(zip_fname) @thing_action From e6eb4d419d93e73a32042963f4d9892b46ca72df Mon Sep 17 00:00:00 2001 From: jaknapper Date: Tue, 20 Feb 2024 10:51:32 +0000 Subject: [PATCH 03/12] Live logging (requires unbuffered program output from stitching) --- .../things/smart_scan.py | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index 8f3bd0eb..dbe5177a 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -14,7 +14,7 @@ from scipy.stats import norm from scipy.ndimage import zoom from copy import deepcopy from datetime import datetime -from subprocess import CompletedProcess, Popen, PIPE, SubprocessError, run +from subprocess import CompletedProcess, Popen, PIPE, SubprocessError, run, STDOUT from threading import Event, Thread import glob import zipfile @@ -1003,12 +1003,29 @@ class SmartScanThing(Thing): ) -> CompletedProcess: """Run a subprocess and log any output""" logger.info(f"Running command in subprocess: `{' '.join(cmd)}`") - output = run(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True) - for pipe in [output.stdout, output.stderr]: - if pipe: - logger.info(pipe) - output.check_returncode() - return output + + + p = Popen(cmd, stdout=PIPE, stderr = STDOUT, bufsize=1, universal_newlines=True) + os.set_blocking(p.stdout.fileno(), False) + logger.info(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))) + while p.poll() == None: + try: + output = p.stdout.readline() + if output != "" and output != None: + logger.info(output) + except: + pass + + for line in p.stdout: + try: + output = p.stdout.readline() + if output != "" and output != None: + logger.info(output) + except: + pass + + logger.info('Stitching complete') + return p @thing_action def stitch_scan(self, logger: InvocationLogger, scan_name: Optional[str]=None, overlap: float = 0.0) -> None: @@ -1039,13 +1056,6 @@ class SmartScanThing(Thing): raise FileNotFoundError(f"Tried to make a zip archive of {images_folder} but it does not exist.") # logger.info("Creating zip archive of images (may take some time)...") - from pathlib import Path - - root_directory = Path(images_folder) - print(sum(f.stat().st_size for f in root_directory.glob('**/*') if f.is_file())) - - zip_fname = f'{os.path.join(scan_folder, "images")}.zip' - # Create an empty zip file - we don't want to autofill it with files, # as some of them should only be added at the end (as we can't overwrite) # them once they change From 2c8660e01f9f8175ea80a57e75511bddfd8273ef Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Tue, 20 Feb 2024 12:11:04 +0000 Subject: [PATCH 04/12] Capture metadata before image to ensure consistency --- src/openflexure_microscope_server/things/smart_scan.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index dbe5177a..cb2a5a5e 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -573,6 +573,7 @@ class SmartScanThing(Thing): """ try: capture_start = time.time() + metadata = metadata_getter() raw_image = cam.capture_array(stream_name="raw") acquired.set() acquisition_time = time.time() @@ -590,7 +591,7 @@ class SmartScanThing(Thing): ) exif_dict = piexif.load(os.path.join(images_folder, name)) exif_dict["Exif"][piexif.ExifIFD.UserComment] = json.dumps( - metadata_getter() + metadata ).encode("utf-8") piexif.insert(piexif.dump(exif_dict), os.path.join(images_folder, name)) save_time = time.time() From c3742565b64f5ae4740ad5faf7df488f04b886eb Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Tue, 20 Feb 2024 12:15:42 +0000 Subject: [PATCH 05/12] Readd zip name generation --- tests/test_zip.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/test_zip.py diff --git a/tests/test_zip.py b/tests/test_zip.py new file mode 100644 index 00000000..a2a01710 --- /dev/null +++ b/tests/test_zip.py @@ -0,0 +1,49 @@ +import zipfile +import shutil +import os +import glob + +def create_zip_of_scan(folder_path): + """Generate a zip file that can be downloaded, with all the scan files in it.""" + + print("Creating zip archive of images (may take some time)...") + zip_fname = f'{folder_path}.zip' + + if not os.path.isfile(zip_fname): + shutil.make_archive( + folder_path, + "zip", + folder_path, + "images/" + ) + + current_zip = get_files_in_zip(zip_fname) + + files = glob.glob(folder_path + '/**/*', recursive=True) + files = [i.split(f'{folder_path}\\')[1] for i in files] + + with zipfile.ZipFile(zip_fname, mode="a") as zip: + for file in files: + if file not in current_zip and ".zip" not in file: + print(f'appending {file} to zip') + zip.write(os.path.join(folder_path, file), arcname=file) + else: + print(f'{file} is already in zip') + + images_folder = os.path.join(folder_path, 'images') + # Promote key files to the top level of the zip + + for fname in ["stitched_from_stage.jpg", "stitched.jpg"]: + fpath = os.path.join(images_folder, fname) + if os.path.exists(fpath): + print(f'copying {fpath} to upper level') + zip.write(fpath, arcname=fname) + +def get_files_in_zip(zip_path): + + zip = zipfile.ZipFile(zip_path) + zip = [os.path.normpath(i) for i in zip.namelist()] + # list available files in the container, relative to the base + return zip + +create_zip_of_scan(r"G:\stitching_tests\zip_test") \ No newline at end of file From bba0ab1853e40ea64f6ad81c0ff9d9e9eebcf435 Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Tue, 20 Feb 2024 12:21:21 +0000 Subject: [PATCH 06/12] Revert "Readd zip name generation" This reverts commit c3742565b64f5ae4740ad5faf7df488f04b886eb --- tests/test_zip.py | 49 ----------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 tests/test_zip.py diff --git a/tests/test_zip.py b/tests/test_zip.py deleted file mode 100644 index a2a01710..00000000 --- a/tests/test_zip.py +++ /dev/null @@ -1,49 +0,0 @@ -import zipfile -import shutil -import os -import glob - -def create_zip_of_scan(folder_path): - """Generate a zip file that can be downloaded, with all the scan files in it.""" - - print("Creating zip archive of images (may take some time)...") - zip_fname = f'{folder_path}.zip' - - if not os.path.isfile(zip_fname): - shutil.make_archive( - folder_path, - "zip", - folder_path, - "images/" - ) - - current_zip = get_files_in_zip(zip_fname) - - files = glob.glob(folder_path + '/**/*', recursive=True) - files = [i.split(f'{folder_path}\\')[1] for i in files] - - with zipfile.ZipFile(zip_fname, mode="a") as zip: - for file in files: - if file not in current_zip and ".zip" not in file: - print(f'appending {file} to zip') - zip.write(os.path.join(folder_path, file), arcname=file) - else: - print(f'{file} is already in zip') - - images_folder = os.path.join(folder_path, 'images') - # Promote key files to the top level of the zip - - for fname in ["stitched_from_stage.jpg", "stitched.jpg"]: - fpath = os.path.join(images_folder, fname) - if os.path.exists(fpath): - print(f'copying {fpath} to upper level') - zip.write(fpath, arcname=fname) - -def get_files_in_zip(zip_path): - - zip = zipfile.ZipFile(zip_path) - zip = [os.path.normpath(i) for i in zip.namelist()] - # list available files in the container, relative to the base - return zip - -create_zip_of_scan(r"G:\stitching_tests\zip_test") \ No newline at end of file From eafeaca3ffa8257bebd6e60029115a51fa978777 Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Tue, 20 Feb 2024 12:22:06 +0000 Subject: [PATCH 07/12] Readd zip name --- src/openflexure_microscope_server/things/smart_scan.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index cb2a5a5e..7613c59e 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -1057,6 +1057,8 @@ class SmartScanThing(Thing): raise FileNotFoundError(f"Tried to make a zip archive of {images_folder} but it does not exist.") # logger.info("Creating zip archive of images (may take some time)...") + zip_fname = f'{os.path.join(scan_folder, "images")}.zip' + # Create an empty zip file - we don't want to autofill it with files, # as some of them should only be added at the end (as we can't overwrite) # them once they change From 169df15fd170ba4f254b8b38832f24010ac01540 Mon Sep 17 00:00:00 2001 From: jaknapper Date: Wed, 21 Feb 2024 14:04:07 +0000 Subject: [PATCH 08/12] More restricted range --- src/openflexure_microscope_server/things/smart_scan.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index 26a2473d..a3c0e5d1 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -654,6 +654,7 @@ class SmartScanThing(Thing): while True: jpeg_zs, jpeg_sizes = autofocus.looping_autofocus(dz=self.autofocus_dz, start = 'base') current_height = stage.position["z"] + time.sleep(0.2) autofocus_success = autofocus.verify_focus_sharpness(sweep_sizes = jpeg_sizes, camera = CamDep, threshold = 0.92) logger.info(f"We just tested the focus! Result was {autofocus_success}") @@ -774,7 +775,7 @@ class SmartScanThing(Thing): @thing_property def max_range(self) -> int: """The maximum distance from the centre of the scan before we break""" - return self.thing_settings.get("max_range", 70000) + return self.thing_settings.get("max_range", 45000) @max_range.setter def max_range(self, value: int) -> None: From 43cf7e837a9df7060f0237675a540e9125ee1e7e Mon Sep 17 00:00:00 2001 From: jaknapper Date: Wed, 21 Feb 2024 14:42:52 +0000 Subject: [PATCH 09/12] Produce tiff as property --- src/openflexure_microscope_server/things/smart_scan.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index a3c0e5d1..fa22b76d 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -783,7 +783,7 @@ class SmartScanThing(Thing): @thing_property def stitch_tiff(self) -> bool: - """The maximum distance from the centre of the scan before we break""" + """Whether or not to also produce a pyramidal tiff""" return self.thing_settings.get("stitch_tiff", False) @stitch_tiff.setter @@ -1045,6 +1045,11 @@ class SmartScanThing(Thing): """Generate a stitched image based on stage position metadata""" images_folder = self.images_folder(scan_name=scan_name) + if self.stitch_tiff: + tiff_arg = '--stitch_tiff' + else: + tiff_arg = '--no-stitch_tiff' + if overlap == 0.0: try: with open(os.path.join(images_folder, 'scan_inputs.json')) as data_file: @@ -1053,7 +1058,7 @@ class SmartScanThing(Thing): overlap = data_loaded['overlap'] except: overlap = 0.1 - self.run_subprocess(logger, [self._script, "--stitching_mode", "all", "--minimum_overlap", f"{round(overlap*0.9,2)}", images_folder]) + self.run_subprocess(logger, [self._script, "--stitching_mode", "all", f"{tiff_arg}", "--minimum_overlap", f"{round(overlap*0.9,2)}", images_folder]) @thing_action def create_zip_of_scan(self, logger: InvocationLogger, scan_name: Optional[str]=None, download_zip = True) -> ZipBlob: From 97c114b77e8aefcc31ab6ad955d42300b8ba4260 Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Wed, 21 Feb 2024 15:47:42 +0000 Subject: [PATCH 10/12] Show scan folder instead of name --- .../src/components/tabContentComponents/slideScanContent.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webapp/src/components/tabContentComponents/slideScanContent.vue b/webapp/src/components/tabContentComponents/slideScanContent.vue index 5618db5e..d82f0557 100644 --- a/webapp/src/components/tabContentComponents/slideScanContent.vue +++ b/webapp/src/components/tabContentComponents/slideScanContent.vue @@ -112,7 +112,7 @@

- Scan ID: {{ scan_name }} + Scan ID: {{ lastScanName }}

@@ -190,6 +190,7 @@ export default { if (mtime !== null) { this.lastStitchedImage = `${this.$store.getters.baseUri}/smart_scan/latest_preview_stitch.jpg?t=${mtime}`; } + this.lastScanName = await this.readThingProperty("smart_scan", "latest_scan_name"); setTimeout(this.pollScan, 1000); // keep rescheduling until it's stopped } } From 361130eea6b748ab7296607095b162e4198005cf Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Wed, 21 Feb 2024 16:36:17 +0000 Subject: [PATCH 11/12] Download zip button from scan tab --- .../tabContentComponents/slideScanContent.vue | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/webapp/src/components/tabContentComponents/slideScanContent.vue b/webapp/src/components/tabContentComponents/slideScanContent.vue index d82f0557..0bd7559a 100644 --- a/webapp/src/components/tabContentComponents/slideScanContent.vue +++ b/webapp/src/components/tabContentComponents/slideScanContent.vue @@ -97,19 +97,30 @@ +
+ +

Scan ID: {{ lastScanName }} @@ -157,6 +168,9 @@ export default { }, computed: { + createZipOfScanUri() { + return this.thingActionUrl("smart_scan", "create_zip_of_scan"); + }, backendOK() { return this.thingAvailable("smart_scan"); }, @@ -193,6 +207,17 @@ export default { this.lastScanName = await this.readThingProperty("smart_scan", "latest_scan_name"); setTimeout(this.pollScan, 1000); // keep rescheduling until it's stopped } + }, + async downloadZipFile(response) { + const scan_name = response.input.scan_name; + const filename = `${scan_name}_images.zip` + const url = response.output.href; + const link = document.createElement("a"); + link.href = url; + link.setAttribute("download", filename); + console.log(link); + document.body.appendChild(link); + link.click(); } } }; From f2cfa9faf88da58607ff369ba3e4f18e81f234ba Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Wed, 21 Feb 2024 17:45:39 +0000 Subject: [PATCH 12/12] Working delete all and auto reload when deleting or opening tab --- .../tabContentComponents/scanListContent.vue | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/tabContentComponents/scanListContent.vue b/webapp/src/components/tabContentComponents/scanListContent.vue index 917f0c26..efd52abc 100644 --- a/webapp/src/components/tabContentComponents/scanListContent.vue +++ b/webapp/src/components/tabContentComponents/scanListContent.vue @@ -1,5 +1,8 @@