diff --git a/Smartscope/core/db_manipulations.py b/Smartscope/core/db_manipulations.py index 337d4023..8b0095b0 100755 --- a/Smartscope/core/db_manipulations.py +++ b/Smartscope/core/db_manipulations.py @@ -131,7 +131,8 @@ def group_holes_for_BIS(hole_models, max_radius=4, min_group_size=1, queue_all=F f'grouping params, max radius = {max_radius}, min group size = {min_group_size}, queue all = {queue_all}, max iterations = {iterations}, score_weight = {score_weight}') # Extract coordinated for the holes prefetch_related_objects(hole_models, 'finders') - coords = np.array([[list(h.finders.all())[0].stage_x, list(h.finders.all())[0].stage_y] for h in hole_models]) + coords = [] + coords = np.array([h.stage_coords for h in hole_models]) input_number = len(hole_models) # Generate distance matrix cd = cdist(coords, coords) @@ -282,7 +283,7 @@ def add_high_mag(grid, parent): def select_n_squares(parent, n): squares = np.array(parent.squaremodel_set.all().filter(selected=False, status=None).order_by('area')) - squares = [s for s in squares if s.is_good()] + squares = [s for s in squares if s.is_good() and not s.is_out_of_range()] if len(squares) == 0: return split_squares = np.array_split(squares, n) @@ -302,7 +303,7 @@ def select_n_holes(parent, n, is_bis=False): holes = list(parent.holemodel_set.filter( **filter_fields).order_by('dist_from_center')) - holes = [h for h in holes if h.is_good()] + holes = [h for h in holes if h.is_good() and not h.is_out_of_range()] if n <= 0: with transaction.atomic(): @@ -340,13 +341,13 @@ def select_n_areas(parent, n, is_bis=False): if n <= 0: with transaction.atomic(): for t in targets: - if t.is_good() and not t.is_excluded()[0]: + if t.is_good() and not t.is_excluded()[0] and not t.is_out_of_range(): update(t, selected=True, status='queued') return clusters = dict() for t in targets: - if not t.is_good(): + if not t.is_good() or t.is_out_of_range(): continue excluded, label = t.is_excluded() if excluded: diff --git a/Smartscope/core/grid/run_square.py b/Smartscope/core/grid/run_square.py index a4182f6e..6df01f6c 100644 --- a/Smartscope/core/grid/run_square.py +++ b/Smartscope/core/grid/run_square.py @@ -54,7 +54,7 @@ def process_square_image(square, grid, microscope_id): if is_bis: holes = list(HoleModel.display.filter(square_id=square.square_id)) holes = group_holes_for_BIS( - [h for h in holes if h.is_good() and not h.is_excluded()[0]], + [h for h in holes if h.is_good() and not h.is_excluded()[0] and not h.is_out_of_range()], max_radius=grid.params_id.bis_max_distance, min_group_size=grid.params_id.min_bis_group_size ) diff --git a/Smartscope/core/main_commands.py b/Smartscope/core/main_commands.py index 330c9880..121e742a 100755 --- a/Smartscope/core/main_commands.py +++ b/Smartscope/core/main_commands.py @@ -122,13 +122,8 @@ def regroup_bis(grid_id, square_id): holes_for_grouping = [] other_holes = [] for h in filtered_holes: - - # h.bis_group = None - # h.bis_type = None - if h.is_good() and not h.is_excluded()[0]: + if h.is_good() and not h.is_excluded()[0] and not h.is_out_of_range(): holes_for_grouping.append(h) - # else: - # other_holes.append(h) logger.info(f'Filtered holes = {len(filtered_holes)}\nHoles for grouping = {len(holes_for_grouping)}') diff --git a/Smartscope/core/models/target.py b/Smartscope/core/models/target.py index 6025d401..ef3b3e23 100644 --- a/Smartscope/core/models/target.py +++ b/Smartscope/core/models/target.py @@ -82,6 +82,8 @@ def is_good(self): return False return True + def is_out_of_range(self) -> bool: + return not self.finders.first().is_position_within_stage_limits() # def css_color(self, display_type, method): # if method is None: diff --git a/Smartscope/core/models/target_label.py b/Smartscope/core/models/target_label.py index 57ab9aae..aa569ae7 100644 --- a/Smartscope/core/models/target_label.py +++ b/Smartscope/core/models/target_label.py @@ -3,6 +3,7 @@ ''' from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType +import math from .base_model import * @@ -32,6 +33,13 @@ class Finder(TargetLabel): class Meta(BaseModel.Meta): db_table = 'finder' + def radius_from_origin(self, offset_x=0, offset_y=0) -> float: + return math.sqrt((self.stage_x + offset_x) ** 2 + (self.stage_y + offset_y) ** 2) + + def is_position_within_stage_limits(self, stage_radius_limit:int = 975, offset_x:float=0, offset_y:float=0) -> bool: + ##NEED TO ADD OFFSETS AND NOT HARDCODE THE LIMIT + return self.radius_from_origin(offset_x=offset_x,offset_y=offset_y) <= stage_radius_limit + class Classifier(TargetLabel): label = models.CharField(max_length=30, null=True) diff --git a/Smartscope/core/svg_plots.py b/Smartscope/core/svg_plots.py index a3e06334..4889833e 100644 --- a/Smartscope/core/svg_plots.py +++ b/Smartscope/core/svg_plots.py @@ -91,6 +91,9 @@ def drawAtlas(atlas, targets, display_type, method) -> draw.Drawing: if color is not None: sz = floor(sqrt(i.area)) finder = list(i.finders.all())[0] + if not finder.is_position_within_stage_limits(): + color = '#505050' + label = 'Out of range' x = finder.x - sz // 2 y = (finder.y - sz // 2) r = draw.Rectangle(x, y, sz, sz, id=i.pk, stroke_width=floor(d.width / 300), stroke=color, fill=color, fill_opacity=0, label=label, @@ -131,6 +134,9 @@ def drawSquare(square, targets, display_type, method) -> draw.Drawing: color, label, prefix = css_color(i, display_type, method) if color is not None: finder = list(i.finders.all())[0] + if not finder.is_position_within_stage_limits(): + color = '#505050' + label = 'Out of range' x = finder.x y = finder.y c = draw.Circle(x, y, i.radius, id=i.pk, stroke_width=floor(d.width / 250), stroke=color, fill=color, fill_opacity=0, label=label, diff --git a/static/reports.js b/static/reports.js index 7eb6d2fb..206f184f 100755 --- a/static/reports.js +++ b/static/reports.js @@ -118,6 +118,9 @@ $('#main').on('click', '.showLegend', function () { function selectElement(elem, selection) { + if (elem.getAttribute('label') == 'Out of range') { + return + } if (selection.includes(elem.id)) { console.log('Unselecting') elem.classList.remove('clicked')