|
632 | 632 | }); |
633 | 633 | }, |
634 | 634 |
|
| 635 | + reloadMetadata: function() { |
| 636 | + // Reload metadata (name, dataset, channels, pixel sizes, ...) for all panels |
| 637 | + // Fetch each image's data once per id, then apply to all panels with that imageId. |
| 638 | + // Reload here must not change edits made by the user (channel LUT, contrast, field of view, ...) |
| 639 | + |
| 640 | + var panels = this.panels; |
| 641 | + var ids = {}; |
| 642 | + panels.each(function(panel){ |
| 643 | + // Make a set of imageIds |
| 644 | + ids[panel.get('imageId')] = true; |
| 645 | + }); |
| 646 | + var imageIds = Object.keys(ids); |
| 647 | + if (imageIds.length === 0) return; |
| 648 | + |
| 649 | + let cors_headers = { mode: 'cors', credentials: 'include', headers: {"Content-Type": "application/json"} }; |
| 650 | + var fetches = imageIds.map(function(iid){ |
| 651 | + // singe fetch per imageId |
| 652 | + var imgDataUrl = BASE_WEBFIGURE_URL + 'imgData/' + iid + '/'; |
| 653 | + return fetch(imgDataUrl, cors_headers) |
| 654 | + .then(rsp => rsp.json()) |
| 655 | + .then(data => { |
| 656 | + |
| 657 | + // values returned here are caught below in the Promise.all handler |
| 658 | + if (data.Exception || data.ConcurrencyException) { |
| 659 | + return {id: iid, error: true, msg: data.Exception || "ConcurrencyException", url: imgDataUrl}; |
| 660 | + } |
| 661 | + return {id: iid, data: data, url: imgDataUrl}; |
| 662 | + }) |
| 663 | + .catch(err => ({id: iid, error: true, msg: err && err.message ? err.message : String(err), url: imgDataUrl})); |
| 664 | + }); |
| 665 | + |
| 666 | + Promise.all(fetches).then(function(results){ |
| 667 | + results.forEach(function(res){ |
| 668 | + var iid = res.id; |
| 669 | + if (res.error) { |
| 670 | + // Show an alert but continue updating other images |
| 671 | + alert(`Image loading from ${res.url} included an Error: ${res.msg}`); |
| 672 | + return; |
| 673 | + } |
| 674 | + |
| 675 | + var data = res.data; |
| 676 | + // Update all panels that share this imageId |
| 677 | + panels.each(function(panel){ |
| 678 | + if (panel.get('imageId') == iid) { |
| 679 | + var new_channels = JSON.parse(JSON.stringify(panel.attributes.channels)); |
| 680 | + for (var i=0; i < data.channels.length; i++) { |
| 681 | + new_channels[i].label = data.channels[i].label; |
| 682 | + } |
| 683 | + |
| 684 | + var newData = { |
| 685 | + 'name': data.meta.imageName, |
| 686 | + 'datasetName': data.meta.datasetName, |
| 687 | + 'datasetId': data.meta.datasetId, |
| 688 | + 'channels': new_channels, |
| 689 | + 'parents': data.parents |
| 690 | + }; |
| 691 | + |
| 692 | + // Unset to start afresh |
| 693 | + panel.unset('pixel_size_x'); |
| 694 | + panel.unset('pixel_size_y'); |
| 695 | + panel.unset('pixel_size_z'); |
| 696 | + panel.unset('pixel_size_x_symbol'); |
| 697 | + panel.unset('pixel_size_z_symbol'); |
| 698 | + panel.unset('pixel_size_x_unit'); |
| 699 | + panel.unset('pixel_size_z_unit'); |
| 700 | + newData.pixel_size_x_unit = 'MICROMETER'; // Set back to panel model default |
| 701 | + newData.pixel_size_x_symbol = '\xB5m'; // µm |
| 702 | + |
| 703 | + if (data.pixel_size) { |
| 704 | + if (data.pixel_size.valueX) { |
| 705 | + newData.pixel_size_x = data.pixel_size.valueX; |
| 706 | + newData.pixel_size_x_symbol = data.pixel_size.symbolX; |
| 707 | + newData.pixel_size_x_unit = data.pixel_size.unitX; |
| 708 | + } |
| 709 | + if (data.pixel_size.valueY) { |
| 710 | + newData.pixel_size_y = data.pixel_size.valueY; |
| 711 | + newData.pixel_size_y_symbol = data.pixel_size.symbolY; |
| 712 | + } |
| 713 | + if (data.pixel_size.valueZ) { |
| 714 | + newData.pixel_size_z = data.pixel_size.valueZ; |
| 715 | + newData.pixel_size_z_symbol = data.pixel_size.symbolZ; |
| 716 | + newData.pixel_size_z_unit = data.pixel_size.unitZ; |
| 717 | + } |
| 718 | + } |
| 719 | + |
| 720 | + panel.set(newData); |
| 721 | + panel.trigger('change:labels', panel); |
| 722 | + } |
| 723 | + }); |
| 724 | + }); |
| 725 | + }); |
| 726 | + this.set('unsaved', true); |
| 727 | + alert("Metadata reloaded for " + this.panels.length + " panel" + (this.panels.length > 1 ? 's.' : '.')); |
| 728 | + }, |
| 729 | + |
635 | 730 | // Used to position the #figure within canvas and also to coordinate svg layout. |
636 | 731 | getFigureSize: function() { |
637 | 732 | var pc = this.get('page_count'), |
|
760 | 855 | right = this.get_right_panel(sel), |
761 | 856 | bottom = this.get_bottom_panel(sel), |
762 | 857 | left_x = left.get('x'), |
763 | | - right_x = right.get('x') + right.get('width'), |
| 858 | + right_x = right.get('x') + right.get('width'), |
764 | 859 | top_y = top.get('y'), |
765 | 860 | bottom_y = bottom.get('y') + bottom.get('height'), |
766 | 861 | grid = [], |
|
797 | 892 | }else{ |
798 | 893 | c = {'x': left_x + left.get('width')/2, 'y': c.y + row[0].get('height')} |
799 | 894 | grid.push(row); |
800 | | - } |
| 895 | + } |
801 | 896 | } |
802 | 897 |
|
803 | 898 | // get the row id of the most left panel |
|
807 | 902 | left_panel_row = i; |
808 | 903 | } |
809 | 904 | }); |
810 | | - |
| 905 | + |
811 | 906 | // define the spacer between images |
812 | 907 | var spacer = left.get('width')/20; |
813 | 908 | if (!isNaN(parseFloat(gridGap))) { |
|
849 | 944 | } |
850 | 945 |
|
851 | 946 | // set the row position (i.e. y coordinate) of each row |
852 | | - var ref_y_offset = max_h |
| 947 | + var ref_y_offset = max_h |
853 | 948 | var rows_position = {} |
854 | 949 | max_h = 0 |
855 | 950 | // for rows above the reference row |
|
872 | 967 | max_h = Math.max(max_h, row[c].get('height')); |
873 | 968 | } |
874 | 969 | } |
875 | | - |
876 | | - // update position of panels |
| 970 | + |
| 971 | + // update position of panels |
877 | 972 | for (var [r, y] of Object.entries(rows_position)){ |
878 | 973 | var row = grid[r]; |
879 | 974 | var last_column_id = -1 |
880 | 975 | for (var c=0; c<row.length; c++) { |
881 | 976 | let panel = row[c]; |
882 | 977 | var closest_column = this.get_closest_column(panel, reference_grid, last_panel_width) |
883 | | - |
| 978 | + |
884 | 979 | if(closest_column >= 0){ |
885 | 980 | // update closest_column id to take into account spare panel positions |
886 | 981 | if(last_column_id == closest_column){ |
|
920 | 1015 | if(current_distance < min_x_distance){ |
921 | 1016 | closest_col = col_id |
922 | 1017 | min_x_distance = current_distance |
923 | | - } |
| 1018 | + } |
924 | 1019 | } |
925 | 1020 |
|
926 | 1021 | // if the panel is located far away from the last reference column, |
|
945 | 1040 | return p; |
946 | 1041 | } else { |
947 | 1042 | return top_left; |
948 | | - } |
| 1043 | + } |
949 | 1044 | }); |
950 | 1045 | }, |
951 | 1046 |
|
|
0 commit comments