@@ -407,6 +407,9 @@ def build_image(self, progress=None):
407407 def build_image_and_layer_image (self , progress = None ):
408408 """Build echogram image and combined layer image.
409409
410+ Uses fast vectorized get_image() for the main echogram when no main_layer
411+ is set. Falls back to per-column iteration only for layer processing.
412+
410413 Returns:
411414 Tuple of (image, layer_image, extent).
412415 """
@@ -415,29 +418,34 @@ def build_image_and_layer_image(self, progress=None):
415418 ny = len (cs .y_coordinates )
416419 nx = len (cs .feature_mapper .get_feature_values ("X coordinate" ))
417420
418- image = np .empty ((nx , ny ), dtype = np .float32 )
419- image .fill (np .nan )
420- layer_image = image .copy ()
421-
422- image_indices , wci_indices = self .get_x_indices ()
423- image_indices = get_progress_iterator (image_indices , progress , desc = "Building echogram image" )
424-
425- for image_index , wci_index in zip (image_indices , wci_indices ):
426- wci = self .get_column (wci_index )
427- if len (wci ) > 1 :
428- if self .main_layer is None :
429- y1 , y2 = self .get_y_indices (wci_index )
430- if len (y1 ) > 0 :
431- image [image_index , y1 ] = wci [y2 ]
432- else :
421+ # Fast path: use vectorized get_image for main echogram if no main_layer
422+ if self .main_layer is None :
423+ request = cs .make_image_request ()
424+ image = self ._backend .get_image (request )
425+ else :
426+ # Slow path: need per-column iteration for main_layer
427+ image = np .full ((nx , ny ), np .nan , dtype = np .float32 )
428+ image_indices , wci_indices = self .get_x_indices ()
429+ for image_index , wci_index in zip (image_indices , wci_indices ):
430+ wci = self .get_column (wci_index )
431+ if len (wci ) > 1 :
433432 y1 , y2 = self .main_layer .get_y_indices (wci_index )
434433 if y1 is not None and len (y1 ) > 0 :
435434 image [image_index , y1 ] = wci [y2 ]
436435
437- for k , layer in self .layers .items ():
438- y1_layer , y2_layer = layer .get_y_indices (wci_index )
439- if y1_layer is not None and len (y1_layer ) > 0 :
440- layer_image [image_index , y1_layer ] = wci [y2_layer ]
436+ # Build layer image (requires per-column iteration)
437+ layer_image = np .full ((nx , ny ), np .nan , dtype = np .float32 )
438+ if len (self .layers ) > 0 :
439+ image_indices , wci_indices = self .get_x_indices ()
440+ image_indices = get_progress_iterator (image_indices , progress , desc = "Building layer image" )
441+
442+ for image_index , wci_index in zip (image_indices , wci_indices ):
443+ wci = self .get_column (wci_index )
444+ if len (wci ) > 1 :
445+ for k , layer in self .layers .items ():
446+ y1_layer , y2_layer = layer .get_y_indices (wci_index )
447+ if y1_layer is not None and len (y1_layer ) > 0 :
448+ layer_image [image_index , y1_layer ] = wci [y2_layer ]
441449
442450 extent = deepcopy (cs .x_extent )
443451 extent .extend (cs .y_extent )
@@ -447,6 +455,9 @@ def build_image_and_layer_image(self, progress=None):
447455 def build_image_and_layer_images (self , progress = None ):
448456 """Build echogram image and individual layer images.
449457
458+ Uses fast vectorized get_image() for the main echogram when no main_layer
459+ is set. Falls back to per-column iteration only for layer processing.
460+
450461 Returns:
451462 Tuple of (image, layer_images_dict, extent).
452463 """
@@ -455,32 +466,37 @@ def build_image_and_layer_images(self, progress=None):
455466 ny = len (cs .y_coordinates )
456467 nx = len (cs .feature_mapper .get_feature_values ("X coordinate" ))
457468
458- image = np .empty ((nx , ny ), dtype = np .float32 )
459- image .fill (np .nan )
469+ # Fast path: use vectorized get_image for main echogram if no main_layer
470+ if self .main_layer is None :
471+ request = cs .make_image_request ()
472+ image = self ._backend .get_image (request )
473+ else :
474+ # Slow path: need per-column iteration for main_layer
475+ image = np .full ((nx , ny ), np .nan , dtype = np .float32 )
476+ image_indices , wci_indices = self .get_x_indices ()
477+ for image_index , wci_index in zip (image_indices , wci_indices ):
478+ wci = self .get_column (wci_index )
479+ if len (wci ) > 1 :
480+ y1 , y2 = self .main_layer .get_y_indices (wci_index )
481+ if y1 is not None and len (y1 ) > 0 :
482+ image [image_index , y1 ] = wci [y2 ]
460483
484+ # Build layer images (requires per-column iteration)
461485 layer_images = {}
462486 for key in self .layers .keys ():
463- layer_images [key ] = image . copy ( )
487+ layer_images [key ] = np . full (( nx , ny ), np . nan , dtype = np . float32 )
464488
465- image_indices , wci_indices = self .get_x_indices ()
466- image_indices = get_progress_iterator (image_indices , progress , desc = "Building echogram image" )
489+ if len (self .layers ) > 0 :
490+ image_indices , wci_indices = self .get_x_indices ()
491+ image_indices = get_progress_iterator (image_indices , progress , desc = "Building layer images" )
467492
468- for image_index , wci_index in zip (image_indices , wci_indices ):
469- wci = self .get_column (wci_index )
470- if len (wci ) > 1 :
471- if self .main_layer is None :
472- y1 , y2 = self .get_y_indices (wci_index )
473- if len (y1 ) > 0 :
474- image [image_index , y1 ] = wci [y2 ]
475- else :
476- y1 , y2 = self .main_layer .get_y_indices (wci_index )
477- if y1 is not None and len (y1 ) > 0 :
478- image [image_index , y1 ] = wci [y2 ]
479-
480- for key , layer in self .layers .items ():
481- y1_layer , y2_layer = layer .get_y_indices (wci_index )
482- if y1_layer is not None and len (y1_layer ) > 0 :
483- layer_images [key ][image_index , y1_layer ] = wci [y2_layer ]
493+ for image_index , wci_index in zip (image_indices , wci_indices ):
494+ wci = self .get_column (wci_index )
495+ if len (wci ) > 1 :
496+ for key , layer in self .layers .items ():
497+ y1_layer , y2_layer = layer .get_y_indices (wci_index )
498+ if y1_layer is not None and len (y1_layer ) > 0 :
499+ layer_images [key ][image_index , y1_layer ] = wci [y2_layer ]
484500
485501 extent = deepcopy (cs .x_extent )
486502 extent .extend (cs .y_extent )
@@ -679,13 +695,18 @@ def get_raw_data_at_coordinates(self, x_coord, y_start, y_end):
679695
680696 ping_idx = ping_indices [0 ]
681697
682- # Convert y coordinates to sample indices
683- interpolator = cs .y_coordinate_indice_interpolator [ping_idx ]
684- if interpolator is None :
698+ # Convert y coordinates to sample indices using affine transform
699+ if cs ._affine_y_to_sample is None :
700+ return None
701+
702+ a_inv , b_inv = cs ._affine_y_to_sample
703+ a , b = a_inv [ping_idx ], b_inv [ping_idx ]
704+
705+ if not np .isfinite (a ) or not np .isfinite (b ):
685706 return None
686707
687- sample_start = int (interpolator ( y_start ) + 0.5 )
688- sample_end = int (interpolator ( y_end ) + 0.5 )
708+ sample_start = int (a + b * y_start + 0.5 )
709+ sample_end = int (a + b * y_end + 0.5 )
689710
690711 # Get raw data
691712 raw_column = self ._backend .get_raw_column (ping_idx )
0 commit comments