From 4dddc8c1e52f61d42d4fa61d508fe29c77bffac8 Mon Sep 17 00:00:00 2001
From: Robert Butora <robert.butora@inaf.it>
Date: Thu, 25 Apr 2024 16:28:14 +0200
Subject: [PATCH] implements PIXELS param (cfitsio extSyntax
 [1:10,1:50,1:1000:10]) has precedense over POS,BAND,POL,TIME

---
 .../servlet/src/main/java/cutout/Cutout.java  |   8 +-
 .../src/main/java/cutout/CutoutImpl.java      | 166 ++++++++++--------
 .../src/main/java/webapi/ServletCutout.java   |  25 +--
 3 files changed, 109 insertions(+), 90 deletions(-)

diff --git a/data-access/servlet/src/main/java/cutout/Cutout.java b/data-access/servlet/src/main/java/cutout/Cutout.java
index 33d5080..37a210d 100644
--- a/data-access/servlet/src/main/java/cutout/Cutout.java
+++ b/data-access/servlet/src/main/java/cutout/Cutout.java
@@ -14,11 +14,13 @@ import vo.parameter.*;
 public interface Cutout
 {
 
-   public void doStream(String relPathname, int hdunum, Pos pos, Band band, Time time, Pol pol,
-        OutputStream outputStream) throws IOException, InterruptedException;
+   public void doStream(String relPathname, int hdunum,
+         Pos pos, Band band, Time time, Pol pol, String pixels,
+         OutputStream outputStream) throws IOException, InterruptedException;
 
 
-   public CutResult doFile(String relPathname, int hdunum, Pos pos, Band band, Time time, Pol pol,
+   public CutResult doFile(String relPathname, int hdunum,
+         Pos pos, Band band, Time time, Pol pol, String pixels,
          boolean countNullValues, FitsCard[] extraCards)
          throws IOException, InterruptedException;
 
diff --git a/data-access/servlet/src/main/java/cutout/CutoutImpl.java b/data-access/servlet/src/main/java/cutout/CutoutImpl.java
index d5ff731..9fc4275 100644
--- a/data-access/servlet/src/main/java/cutout/CutoutImpl.java
+++ b/data-access/servlet/src/main/java/cutout/CutoutImpl.java
@@ -94,11 +94,20 @@ class CutoutImpl implements Cutout
       return region;
    }
 
-   public void doStream(String relPathname, int hdunum, Pos pos, Band band, Time time, Pol pol,
+   public void doStream(String relPathname, int hdunum,
+         Pos pos, Band band, Time time, Pol pol, String pixels,
          OutputStream outputStream)  throws IOException, InterruptedException
-      {
-         Instant start = Instant.now();
+   {
+      Instant start = Instant.now();
+
+      boolean has_overlap  = false;
+      boolean pixels_valid = (pixels != null);
+
+      String boundsString = "";
+      String absPathname = settings.fitsPaths.surveys() + "/" + relPathname;
 
+      if( !pixels_valid )
+      {
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          if(bos == null)
             throw new AssertionError("byte output stream for bounds was not created, is null");
@@ -112,8 +121,6 @@ class CutoutImpl implements Cutout
          String coordString = jReq.toString();
          LOGGER.info("coordString: " + coordString);
 
-         String absPathname = settings.fitsPaths.surveys() + "/" + relPathname;
-
          /* calc bounds */
 
          String[] cmdBounds = new String[4];
@@ -126,59 +133,63 @@ class CutoutImpl implements Cutout
          execBounds.doRun(bos, cmdBounds);
          LOGGER.info("execBounds exitValue: " + execBounds.exitValue);
 
-         bos.close();
-
          boolean has_result = (execBounds.exitValue == 0);
 
-         Instant boundsDone = Instant.now();
-         LOGGER.info("EXECTIME boundsDone: " + Duration.between(start, boundsDone));
-
          if(has_result)
          {
-            String boundsString = new String(bos.toByteArray());
+            boundsString = new String(bos.toByteArray());
+
             // remove end-of-line (was added by vlkb_ast.cpp: cout << ... << endl)
             String lineSeparator = System.lineSeparator();
             boundsString = boundsString.replace(lineSeparator, "");
             LOGGER.info("BOUNDS: " + boundsString);
 
-            if((boundsString != null) && boundsString.trim().isEmpty())
+            has_overlap = !((boundsString != null) && boundsString.trim().isEmpty());
+
+            if( !has_overlap )
             {
                throw new IllegalArgumentException(
                      "region in file does not overlap with region defined by SODA parameters");
             }
-            else
-            {
-               /* cutout -> outputStream */
+         }
+         bos.close();
 
-               String[] cmdCut = new String[6];
-               cmdCut[0] = "/usr/local/bin/vlkb";
-               cmdCut[1] = "imcopy";
-               cmdCut[2] = absPathname;
-               cmdCut[3] = String.valueOf(hdunum-1);
-               cmdCut[4] = boundsString;
-               cmdCut[5] = settings.fitsPaths.cutouts();
+         Instant boundsDone = Instant.now();
+         LOGGER.info("EXECTIME boundsDone: " + Duration.between(start, boundsDone));
+      }
 
-               if(outputStream == null)
-                  LOGGER.info("supplied outputStream for cut-file is null");
+      if(has_overlap || pixels_valid)
+      {
+         /* cutout -> outputStream */
 
-               ExecCmd execCut = new ExecCmd();
-               execCut.doRun(outputStream, cmdCut);
+         String[] cmdCut = new String[6];
+         cmdCut[0] = "/usr/local/bin/vlkb";
+         cmdCut[1] = "imcopy";
+         cmdCut[2] = absPathname;
+         cmdCut[3] = String.valueOf(hdunum-1);
+         cmdCut[4] = pixels_valid ? pixels : boundsString;
+         cmdCut[5] = settings.fitsPaths.cutouts();
 
-               Instant cutDone = Instant.now();
-               LOGGER.info("EXECTIME    cutDone: " + Duration.between(start, cutDone));
-            }
-         }
-         else
-         {
-            throw new IllegalArgumentException(
-                  "overlap computation could not be completed with the given arguments");
-         }
+         if(outputStream == null)
+            LOGGER.info("supplied outputStream for cut-file is null");
+
+         ExecCmd execCut = new ExecCmd();
+         execCut.doRun(outputStream, cmdCut);
+
+         Instant cutDone = Instant.now();
+         LOGGER.info("EXECTIME    cutDone: " + Duration.between(start, cutDone));
+      }
+      else
+      {
+         throw new IllegalArgumentException(
+               "overlap computation could not be completed with the given arguments");
       }
+   }
 
 
 
    private NullValueCount doCountNullValues(String absPathname, int hdunum)
-      throws IOException, InterruptedException
+         throws IOException, InterruptedException
       {
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          if(bos == null)
@@ -226,61 +237,64 @@ class CutoutImpl implements Cutout
 
 
    public CutResult doFile(String relPathname, int hdunum,
-         Pos pos, Band band, Time time, Pol pol,
+         Pos pos, Band band, Time time, Pol pol, String pixels,
          boolean countNullValues, FitsCard[] extraCards)
-      throws IOException, InterruptedException
-   {
-      LOGGER.info("trace: " + pos.toString() );
+         throws IOException, InterruptedException
+      {
+         LOGGER.info("trace: " + pos.toString() );
 
-      CutResult cutResult = new CutResult();
+         CutResult cutResult = new CutResult();
 
-      if(settings.amqpConn.isHostnameEmpty())
-      {
-         LOGGER.info("Using doStream() to local file");
+         if(settings.amqpConn.isHostnameEmpty())
+         {
+            LOGGER.info("Using doStream() to local file");
 
-         String absSubimgPathname = settings.fitsPaths.cutouts()
-            + "/" + generateSubimgPathname(relPathname, hdunum);
+            String absSubimgPathname = settings.fitsPaths.cutouts()
+               + "/" + generateSubimgPathname(relPathname, hdunum);
 
-         LOGGER.info("Uses local filename : " + absSubimgPathname);
+            LOGGER.info("Uses local filename : " + absSubimgPathname);
 
-         OutputStream fileOutputStream = new FileOutputStream( new File(absSubimgPathname) );
+            OutputStream fileOutputStream = new FileOutputStream( new File(absSubimgPathname) );
 
-         doStream(relPathname, hdunum, pos, band, time, pol, fileOutputStream);
+            doStream(relPathname, hdunum, pos, band, time, pol, pixels, fileOutputStream);
 
-         // engine returns absPathname see common/cutout.cpp::do_cutout_file()
-         cutResult.filename = absSubimgPathname;
-         cutResult.filesize = Files.size(Paths.get(absSubimgPathname));
+            // engine returns absPathname see common/cutout.cpp::do_cutout_file()
+            cutResult.filename = absSubimgPathname;
+            cutResult.filesize = Files.size(Paths.get(absSubimgPathname));
 
-         if(countNullValues)
-         {
-              cutResult.nullValueCount = doCountNullValues(absSubimgPathname, 1);
-         }
+            if(countNullValues)
+            {
+               cutResult.nullValueCount = doCountNullValues(absSubimgPathname, 1);
+            }
 
-         if(extraCards == null || (extraCards.length < 1))
-         {
-            LOGGER.info("Adding extraCards to cut-file not implemented when using 'vlkb' exec (implemented in engine vlkbd/AMQP)");
+            if(extraCards == null || (extraCards.length < 1))
+            {
+               LOGGER.info("Adding extraCards to cut-file not implemented when using 'vlkb' exec (implemented in engine vlkbd/AMQP)");
+            }
          }
-      }
-      else
-      {
-         LOGGER.info("Using AMQP");
+         else
+         {
+            LOGGER.info("Using AMQP");
 
-         JsonEncoder jReq = new JsonEncoder();
-         jReq.add(relPathname, hdunum);
-         jReq.add(pos);
-         jReq.add(band);
-         jReq.add(time);
-         jReq.add(pol);
-         jReq.add(countNullValues);
-         jReq.add(extraCards);
+            JsonEncoder jReq = new JsonEncoder();
+            jReq.add(relPathname, hdunum);
+            jReq.add(pos);
+            jReq.add(band);
+            jReq.add(time);
+            jReq.add(pol);
 
-         String outJson = doRpc( jReq.toString() );
+            //         jReq.add(pixels),   FIXME implement to supoort PIXLES in vlkb-legacy by AMQP
 
-         cutResult = JsonDecoder.responseFromCutoutJson( outJson );
-      }
+            jReq.add(countNullValues);
+            jReq.add(extraCards);
 
-      return cutResult;
-   }
+            String outJson = doRpc( jReq.toString() );
+
+            cutResult = JsonDecoder.responseFromCutoutJson( outJson );
+         }
+
+         return cutResult;
+      }
 
 
 
diff --git a/data-access/servlet/src/main/java/webapi/ServletCutout.java b/data-access/servlet/src/main/java/webapi/ServletCutout.java
index be98798..344716d 100644
--- a/data-access/servlet/src/main/java/webapi/ServletCutout.java
+++ b/data-access/servlet/src/main/java/webapi/ServletCutout.java
@@ -88,6 +88,7 @@ public class ServletCutout extends javax.servlet.http.HttpServlet
          +  "<PARAM name=\"BAND\" ucd=\"stat.interval\" unit=\"m\" datatype=\"double\" arraysize=\"2\" xtype=\"interval\" value=\"\"/>"
          +  "<PARAM name=\"TIME\" ucd=\"time.interval;obs.exposure\" unit=\"d\" datatype=\"double\" arraysize=\"2\" xtype=\"interval\" value=\"\"/>"
          +  "<PARAM name=\"POL\" ucd=\"meta.code;phys.polarization\" datatype=\"char\" arraysize=\"*\" value=\"\"/>"
+         +  "<PARAM name=\"PIXELS\" ucd=\"instr.pixel;meta.dataset\" datatype=\"char\" arraysize=\"*\" value=\"\"/>"
          +  "<PARAM name=\"RESPONSEFORMAT\" ucd=\"meta.code.mime\" datatype=\"char\" arraysize=\"*\" value=\"application/fits\"/>"
 
          +  "<PARAM name=\"POSSYS\" ucd=\"pos.frame\" datatype=\"char\" arraysize=\"*\" value=\"\">"
@@ -114,7 +115,7 @@ public class ServletCutout extends javax.servlet.http.HttpServlet
    }
 
 
-   protected void doCutoutStream(String id, Pos pos, Band band, Time time, Pol pol,
+   protected void doCutoutStream(String id, Pos pos, Band band, Time time, Pol pol, String pixels,
          OutputStream respOutputStream) throws IOException, InterruptedException
    {
       LOGGER.info("trace" + pos);
@@ -122,12 +123,12 @@ public class ServletCutout extends javax.servlet.http.HttpServlet
       Resolver rsl = new ResolverFromId();
       rsl.resolve(id);
 
-      cutout.doStream(rsl.relPathname(), rsl.hdunum(), pos, band, time, pol, respOutputStream);
+      cutout.doStream(rsl.relPathname(), rsl.hdunum(), pos, band, time, pol, pixels, respOutputStream);
    }
 
 
 
-   protected DataLink doCutoutFile(String id, Pos pos, Band band, Time time, Pol pol,
+   protected DataLink doCutoutFile(String id, Pos pos, Band band, Time time, Pol pol, String pixels,
          boolean countNullValues, String respFormat)
          throws IOException, InterruptedException
    {
@@ -166,11 +167,11 @@ public class ServletCutout extends javax.servlet.http.HttpServlet
 
       final String DEFAULT_TIME_SYSTEM = "MJD_UTC"; // FIXME take from confif file
 
-      if(pos  != null) pos.setSystem(DEFAULT_SKY_SYSTEM);
-      if(band != null) band.setSystem(DEFAULT_SPEC_SYSTEM);
-      if(time != null) time.setSystem(DEFAULT_TIME_SYSTEM);
+      //if(pos  != null) pos.setSystem(DEFAULT_SKY_SYSTEM);
+      //if(band != null) band.setSystem(DEFAULT_SPEC_SYSTEM);
+      //if(time != null) time.setSystem(DEFAULT_TIME_SYSTEM);
 
-      CutResult cutResult = cutout.doFile(relPathname, hdunum, pos, band, time, pol, false, null);
+      CutResult cutResult = cutout.doFile(relPathname, hdunum, pos, band, time, pol, pixels, false, null);
 
       DataLink dlk = new DataLink();
 
@@ -292,22 +293,24 @@ public class ServletCutout extends javax.servlet.http.HttpServlet
             Band   band = Band.parseBand(params, DEFAULT_SPEC_SYSTEM);
             Time   time = Time.parseTime(params, DEFAULT_TIME_SYSTEM);
             Pol    pol  = Pol.parsePol(params);
+            String pixels = SingleStringParam.parseSingleStringParam(params, "PIXELS");
 
             String respFormat = sodaReq_getResponseFormat(request, DEFAULT_RESPONSEFORMAT);
 
             LOGGER.info("responseFormat: " + respFormat);
 
-            if(respFormat.equals("application/fits"))
+            if(respFormat.startsWith("application/fits"))
             {
                response.setContentType(respFormat);
-               doCutoutStream(id, pos, band, time, pol, respOutputStream);
+               doCutoutStream(id, pos, band, time, pol, pixels, respOutputStream);
             }
-            else if(respFormat.equals("application/x-vlkb+xml"))
+            else if(respFormat.startsWith("application/x-vlkb+xml"))
             {
                boolean  countNullValues = vlkbReq_getNullValues(request);
                response.setContentType(respFormat);
 
-               DataLink respDataLink = doCutoutFile(id, pos, band, time, pol, countNullValues, respFormat);
+               DataLink respDataLink = doCutoutFile(id, pos, band, time, pol, pixels, countNullValues,
+                     respFormat);
 
                /* FIXME errors from engine not checked - cut-file might not have been created */
                LOGGER.info("DataLink - id:" + respDataLink.id + " url: " + respDataLink.accessUrl );
-- 
GitLab