macro "cross_offset" {
  saveSettings;
  jpeg_directory = "/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/exported_layers_on_grey";
//  scoremaps_directory="/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/scoremaps";
//  results_directory="/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/cross_offset";
// scoremaps_blurred
//  scoremaps_directory="/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/scoremaps_sharp";
//  results_directory="/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/cross_offset_sharp";
  // used old files for now
  scoremaps_directory="/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/scoremaps_blurred";
  results_directory="/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/cross_offset_blurred";
  
//L3-1691017293_032075-7285_82.jpeg

  scoremaps_suffix="-scoremap";
  norm_radius = 20;
  thresh0 =     0.6; 
  thresh1 =     0.7;
  sigma =       10.0;
  min_height= -0.1;
  max_height=  0.18; // 0.25;
  maxmin_min = 75;  // 82.0; //difference between local maximum and local minimum (norm_radius) should be not less than this
  maxmin_max = 150; //difference between local maximum and local minimum (norm_radius) should be not more than this
  maxmin_rad = 15.0
  // for illustrations - run for one pair with disabled close() in the end
  // scale_prod=-40000 to get meters of height (depends on image offset), negative if first image is taken from higher point on the image map
  //>>> dx,dy (-59, 985) pixels, l = 987 pixels = 19.7m

  File.makeDirectory(results_directory);   
  // negative disparity
  getCrossOffset("L3-1691017293_032075-7285_82.jpeg", "L3-1691017285_820540.jpeg", -0.060, 0.998, 150, norm_radius, thresh0, sigma,  thresh1, min_height, max_height, scoremaps_directory, scoremaps_suffix, jpeg_directory, results_directory, maxmin_min, maxmin_max, maxmin_rad);

  getCrossOffset("L3-1691017285_820540.jpeg","L3-1691017293_032075-7285_82.jpeg",  0.060, -0.998, 150, norm_radius, thresh0, sigma,  thresh1, min_height, max_height,  scoremaps_directory, scoremaps_suffix, jpeg_directory, results_directory, maxmin_min, maxmin_max, maxmin_rad);
  
  
  
  function getCrossOffset(src1_basename, src2_basename, kx, ky, scale_prod, nrad, thresh0, sigma,  thresh1, min_height, max_height, scoremaps_directory, scoremaps_suffix, jpeg_directory, results_directory, maxmin_min, maxmin_max, maxmin_rad) {
    nrad_dd = 10; // normalization for directional derivative
    min_dd = 0.3; // do not boost dd if scoremap less than this
    score1_file = src1_basename+scoremaps_suffix+".tiff";
    score2_file = src2_basename+scoremaps_suffix+".tiff";
    open(scoremaps_directory+"/"+score1_file); // use for derivative
    selectImage(score1_file);

    // save normalized src1 to be used for mask to disable points far from src1
    src1_dup = "src1_dup"; // will have grown, normalized candidates from the first image
    run("Duplicate...", "title="+src1_dup);
    selectImage(src1_dup);  // just in case - duplicate changes selection
    run("Subtract...", "value=" + thresh0);
    run("Min...", "value=0");
    // grow with GB, then re-normalize
    run("Gaussian Blur...", "sigma="+sigma); // Maybe different sigma?
    run("Differentials ", "operation=[Normalize by local maximum] multiply_d/dx_by="+kx+" multiply_d/dy_by="+ky+" normalization_radius="+nrad);
    
    // put src1_dup aside, continue with score1_file - directional derivative
    selectImage(score1_file);
    src1_dd = src1_basename+"-directional_derivative.tiff";
    run("Duplicate...", "title="+src1_dd);
    selectImage(src1_dd);
    print("operation=[Directional derivative] multiply_d/dx_by="+kx+" multiply_d/dy_by="+ky+" normalization_radius="+nrad);
    run("Differentials ", "operation=[Directional derivative] multiply_d/dx_by="+kx+" multiply_d/dy_by="+ky+" normalization_radius="+nrad);
    saveAs("Tiff", results_directory + "/"+src1_dd);  
    src1_dd = src1_basename+"-directional_derivative_normalized.tiff";
    rename(src1_dd);
    // normalize directional derivative by the limited by min local maximum of the scoremap
    selectImage(score1_file); // original scoremap
    src1_dd_norm = "src1_dd_norm"; // no need to save
    run("Duplicate...", "title="+src1_dd_norm);
    selectImage(src1_dd_norm);
    run("Differentials ", "operation=[Local max] multiply_d/dx_by="+kx+" multiply_d/dy_by="+ky+" normalization_radius="+nrad_dd);
    run("Min...", "value="+min_dd);
    imageCalculator("Divide", src1_dd, src1_dd_norm);
    saveAs("Tiff", results_directory + "/"+src1_dd);  // now src1_dd is normalized directiona derivative 
    
//run("Window/Level...");
//setMinAndMax(-0.50, 0.50);
    selectImage(src1_dd_norm);
    close(); // src1_dd_norm is not needed anymore
    open(scoremaps_directory+"/"+score2_file); // use for derivative
    selectImage(score2_file);
    src2_dup = "src2_dup";
    run("Duplicate...", "title="+src2_dup);    
    selectImage(score2_file);
    run("Subtract...", "value=" + thresh0);
    run("Min...", "value=0");
    run("Differentials ", "operation=[Normalize by local maximum] multiply_d/dx_by="+kx+" multiply_d/dy_by="+ky+" normalization_radius="+nrad);
    
    // save normalized score2 as intermediate result
    score2_norm_file = src2_basename+scoremaps_suffix+"-norm.tiff";
    rename(score2_norm_file);
    saveAs("Tiff", results_directory + "/"+score2_norm_file);  
    
    // create same-size sampling, not just same max value
    run("Differentials ", "operation=[Local ismax] multiply_d/dx_by="+kx+" multiply_d/dy_by="+ky+" normalization_radius="+nrad);
    run("Gaussian Blur...", "sigma=2.0");
    run("Differentials ", "operation=[Normalize by local maximum] multiply_d/dx_by="+kx+" multiply_d/dy_by="+ky+" normalization_radius="+nrad);
    score2_normsize_file = src2_basename+scoremaps_suffix+"-normsize.tiff";
    rename(score2_normsize_file);
    saveAs("Tiff", results_directory + "/"+score2_normsize_file);  
    
    imageCalculator("Multiply create", src1_dd,score2_normsize_file); // score1_file was directional derivative, now src1_dd
    img_prod = "Result of "+src1_dd;
    selectImage(img_prod); 
    run("Gaussian Blur...", "sigma="+sigma); // max= 0.000541
    run("Multiply...", "value="+(-scale_prod));
    setMinAndMax(-0.50, 0.50);
    img_rslt=src1_basename+"-"+src2_basename+"-GB"+sigma+"-scale"+(scale_prod)+".tiff";
// 2180, 2429    0.2046-> 0.1269 0.2227??     old: 0.1183  -> 0.2136 (-0.02405 / 0.7425)  -0.03189 + -> 0.2832 (0.1123) 120/300 -> .0113 150/300 -> .14
// 2172 3350     0.1131->0.09811 * 1.2 0.1134 old: 0.09811 -> 0.1131 (-0.01059 / 0.7407)  -0.01423 + -> 0.1524                  -> .061  150/300 -> .076
// 131.44, 250.05
// 2008 3164 0.008551 -> 0.2039                                      (-0.01463 / 0.03470) -0.02909 -0.01443->0.0290-9 ->0.4082  -> 0.2014
// save as intermediate result  
    saveAs("Tiff", results_directory + "/"+img_rslt);
    print(results_directory + "/"+img_rslt);
    grow_gb=0; // 3.0;
    grow_gb_thresh=0.8;
// create mask
    run("Subtract...", "value="+((min_height+ max_height)/2)); // average
    run("Abs");
    run("Subtract...", "value="+((max_height-min_height)/2));  // half range
    run("Multiply...", "value=-10000.000"); // just a big number and inverse, so good are inside the [min_height,max_height] range
    run("Min...", "value=0");  // limit to [0,1] range
    run("Max...", "value=1");
// grow it with GB filter
    if (grow_gb>0) {
        run("Gaussian Blur...", "sigma="+grow_gb);
        run("Subtract...", "value="+grow_gb_thresh);
        run("Min...", "value=0");
        run("Multiply...", "value=10000");
        run("Max...", "value=1");
    }
   img_rslt=src1_basename+"-"+src2_basename+"-GB"+sigma+"-scale"+(scale_prod)+"-height-mask.tiff";
   rename(img_rslt); 
   saveAs("Tiff", results_directory + "/"+img_rslt); // now it is height mask
// Multiply mask by src1_dup
   imageCalculator("Multiply create", img_rslt, src1_dup);
   img_mask2 = "Result of "+img_rslt; // combined mask - has src1 maximum, not too high
// measure difference between local maximum and local minimum for the input image2 and mask out to little and too much
    jpeg2_file = src2_basename; // +".jpeg" is already included
    print ("opening: '"+jpeg_directory+"/"+jpeg2_file+"'");
    open(jpeg_directory+"/"+jpeg2_file);
    selectImage(jpeg2_file);
    run("32-bit");
    run("Subtract...", "value=128");
    run("Differentials ", "operation=[Local diff] multiply_d/dx_by="+kx+" multiply_d/dy_by="+ky+" normalization_radius="+maxmin_rad);
    // save intermediate result
    img_minmax2 = src2_basename+"-minmax_diff"+"-r"+maxmin_rad+".tiff";
    saveAs("Tiff", results_directory + "/"+img_minmax2);
    run("Subtract...", "value="+((maxmin_max+ maxmin_min)/2)); // average
    run("Abs");
    run("Subtract...", "value="+((maxmin_max-maxmin_min)/2));  // half range
    run("Multiply...", "value=-10000.000"); // just a big number and inverse, , so good are inside the [maxmin_min,maxmin_max] range
    run("Min...", "value=0");  // limit to [0,1] range
    run("Max...", "value=1");
    img_minmax2_mask = src2_basename+"-minmax_mask"+"-r"+maxmin_rad+"_"+maxmin_min+"-"+maxmin_max+".tiff";
    saveAs("Tiff", results_directory + "/"+img_minmax2_mask);
// combine masks - multiply existing by the new for object contrast    
   imageCalculator("Multiply create", img_mask2, img_minmax2_mask);
   img_mask3 = "Result of "+img_mask2; // combined mask - has src1 maximum, not too high
   selectImage(img_mask3);
//
// save mask file    
    img_mask="mask_"+src1_basename+"-"+src2_basename+"-GB"+sigma+"-scale"+scale_prod+"-min"+min_height+"-max"+max_height+"-grow"+grow_gb+".tiff";
// save as intermediate result  
    saveAs("Tiff", results_directory + "/"+img_mask);
// create pessimistic scoremap (higher threshold) and multiply by the mask    
    selectImage(src2_dup);
    run("Subtract...", "value=" + thresh1);
    run("Min...", "value=0");
    run("Multiply...", "value=" + (1.0/(1.0-thresh1))); //  will still be much less than 1.0, just expanding [thersh1,1.0] to [0,1]
    imageCalculator("Multiply create", src2_dup, img_mask);
    img_prod = "Result of "+src2_dup;
    selectImage(img_prod); 
    run("Find Maxima...", "prominence=0.01 output=[Point Selection]");    
    img_result_score = src2_basename+"-rslt_score.tiff";
//src2_basename    
    saveAs("Tiff", results_directory + "/"+img_result_score);
/* */
//now open are 10 images
    close();
    close();
    close();
    close();
    close();
    close();
    close();
    close();
    close();
    close();
/* */    
  } // end of function
  restoreSettings;
} // end of macro

/*
//#6 -  2180, 2428    0.12
//#7 -  2172, 3350    0.1
//#12 - 2295, 3238 - new? 0.06
//
// 2291, 3241

(-0.05979131273315754, 0.998210899019664)

open("/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/test_macros/L3-1691017285_820540.jpeg-scoremap.tiff");
selectImage("L3-1691017285_820540.jpeg-scoremap.tiff");
run("Subtract...", "value=0.7");
run("Min...", "value=0");
run("Differentials ", "operation=[Normalize by local maximum] multiply=0.000 multiply_0=1.000 normalization=20");
run("Window/Level...");
saveAs("Tiff", "/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/test_macros/L3-1691017285_820540.jpeg-scoremap_lm20.tif");
open("/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/test_macros/L3-1691017285_820540.jpeg-scoremap.tiff");
selectImage("L3-1691017285_820540.jpeg-scoremap.tiff");
selectImage("L3-1691017285_820540.jpeg-scoremap_lm20.tif");
selectImage("L3-1691017285_820540.jpeg-scoremap.tiff");
run("Subtract...", "value=0.500");
run("Min...", "value=0");
run("Differentials ", "operation=[Normalize by local maximum] multiply=0.000 multiply_0=1.000 normalization=20.000");
selectImage("L3-1691017285_820540.jpeg-scoremap_lm20.tif");
selectImage("L3-1691017285_820540.jpeg-scoremap.tiff");
open("/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/test_macros/L3-1691017293_032075.jpeg-scoremap.tiff");
selectImage("L3-1691017293_032075.jpeg-scoremap.tiff");
run("Differentials ", "operation=[Directional derivative] multiply=-0.0598 multiply_0=0.998 normalization=20.000");

selectImage("L3-1691017285_820540.jpeg-scoremap_lm20.tif");
selectImage("Result of L3-1691017293_032075.jpeg-scoremap.tiff");
close();
selectImage("1691017283_609002-RECT-UM10.0_0.97-PIX0.02-CROP-PAL0-RANGE250.0-preview.jpeg");
close();
selectImage("1691017285_262848-RECT-UM10.0_0.97-PIX0.02-CROP-PAL0-RANGE250.0-preview.jpeg");
close();
imageCalculator("Multiply create", "L3-1691017293_032075.jpeg-scoremap.tiff","L3-1691017285_820540.jpeg-scoremap_lm20.tif");
selectImage("Result of L3-1691017293_032075.jpeg-scoremap.tiff");
setMinAndMax(-5.000E-3, 5.000E-3);selectImage("L3-1691017285_820540.jpeg-scoremap_lm20.tif");
selectImage("Result of L3-1691017293_032075.jpeg-scoremap.tiff");
saveAs("Tiff", "/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/test_macros/Result of L3-1691017293_032075.jpeg-scoremap_prod.tif");
run("Gaussian Blur...", "sigma=5");
run("Save");
saveAs("Tiff", "/media/elphel/SSD3-4GB/lwir16-proc/berdich/annotations/collages/pattern-matching/test_macros/Result of L3-1691017293_032075.jpeg-scoremap_prod_gb5.tif");

run("Close All");

*/
