Repository: deepjavalibrary/djl
Pull request #2080 (2022-10-12 17:04:18)

[api] Allow to show NDArray content in Debugger 2
## Description ##

The previous solution still suffers from a slowing down when printing the string outside the debugger mode. Here the solution is to utillize the existing pruning mechanism, and put the execution of `init(array)` also under the condition that the array is not too large.

A testing code is added.

codecov-commenter: # [Codecov](https://codecov.io/gh/deepjavalibrary/djl/pull/2080?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary) Report
Base: **72.08**% // Head: **70.26**% // Decreases project coverage by **`-1.82%`** :warning:
> Coverage data is based on head [(`5201359`)](https://codecov.io/gh/deepjavalibrary/djl/pull/2080?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary) compared to base [(`bb5073f`)](https://codecov.io/gh/deepjavalibrary/djl/commit/bb5073f7ffc33f1883621fc1783dbb01e70b418f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary).
> Patch coverage: 72.33% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff              @@
##             master    #2080      +/-   ##
============================================
- Coverage     72.08%   70.26%   -1.83%     
- Complexity     5126     6074     +948     
============================================
  Files           473      603     +130     
  Lines         21970    26890    +4920     
  Branches       2351     2912     +561     
============================================
+ Hits          15838    18893    +3055     
- Misses         4925     6585    +1660     
- Partials       1207     1412     +205     
```


| [Impacted Files](https://codecov.io/gh/deepjavalibrary/djl/pull/2080?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary) | Coverage Δ | |
|---|---|---|
| [api/src/main/java/ai/djl/modality/cv/Image.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L0ltYWdlLmphdmE=) | `69.23% <ø> (-4.11%)` | :arrow_down: |
| [...rc/main/java/ai/djl/modality/cv/MultiBoxPrior.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L011bHRpQm94UHJpb3IuamF2YQ==) | `76.00% <ø> (ø)` | |
| [...rc/main/java/ai/djl/modality/cv/output/Joints.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L291dHB1dC9Kb2ludHMuamF2YQ==) | `71.42% <ø> (ø)` | |
| [.../main/java/ai/djl/modality/cv/output/Landmark.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L291dHB1dC9MYW5kbWFyay5qYXZh) | `100.00% <ø> (ø)` | |
| [...main/java/ai/djl/modality/cv/output/Rectangle.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L291dHB1dC9SZWN0YW5nbGUuamF2YQ==) | `72.41% <0.00%> (ø)` | |
| [...i/djl/modality/cv/translator/BigGANTranslator.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3IvQmlnR0FOVHJhbnNsYXRvci5qYXZh) | `21.42% <0.00%> (-5.24%)` | :arrow_down: |
| [.../ai/djl/modality/cv/translator/YoloTranslator.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3IvWW9sb1RyYW5zbGF0b3IuamF2YQ==) | `27.77% <0.00%> (+18.95%)` | :arrow_up: |
| [...modality/cv/translator/wrapper/FileTranslator.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3Ivd3JhcHBlci9GaWxlVHJhbnNsYXRvci5qYXZh) | `44.44% <ø> (ø)` | |
| [...y/cv/translator/wrapper/InputStreamTranslator.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3Ivd3JhcHBlci9JbnB1dFN0cmVhbVRyYW5zbGF0b3IuamF2YQ==) | `44.44% <ø> (ø)` | |
| [.../modality/cv/translator/wrapper/UrlTranslator.java](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3Ivd3JhcHBlci9VcmxUcmFuc2xhdG9yLmphdmE=) | `44.44% <ø> (ø)` | |
| ... and [524 more](https://codecov.io/gh/deepjavalibrary/djl/pull/2080/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary) | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/deepjavalibrary/djl/pull/2080?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary).


Patch:
diff --git a/api/src/main/java/ai/djl/modality/cv/output/CategoryMask.java b/api/src/main/java/ai/djl/modality/cv/output/CategoryMask.java
index 4cdc75e21..c7d5414da 100644
--- a/api/src/main/java/ai/djl/modality/cv/output/CategoryMask.java
+++ b/api/src/main/java/ai/djl/modality/cv/output/CategoryMask.java
@@ -130,26 +130,26 @@ public class CategoryMask implements JsonSerializable {
      * Highlights the detected object on the image with random colors.
      *
      * @param image the original image
-     * @param transparency the transparency of the overlay. Value is between 0 and 255 inclusive,
-     *     where 0 means the overlay is completely transparent and 255 means the overlay is
-     *     completely opaque.
+     * @param opacity the opacity of the overlay. Value is between 0 and 255 inclusive, where 0
+     *     means the overlay is completely transparent and 255 means the overlay is completely
+     *     opaque.
      */
-    public void drawMask(Image image, int transparency) {
-        drawMask(image, transparency, COLOR_BLACK);
+    public void drawMask(Image image, int opacity) {
+        drawMask(image, opacity, COLOR_BLACK);
     }
 
     /**
      * Highlights the detected object on the image with random colors.
      *
      * @param image the original image
-     * @param transparency the transparency of the overlay. Value is between 0 and 255 inclusive,
-     *     where 0 means the overlay is completely opaque and 255 means the overlay is completely
-     *     transparent.
+     * @param opacity the opacity of the overlay. Value is between 0 and 255 inclusive, where 0
+     *     means the overlay is completely transparent and 255 means the overlay is completely
+     *     opaque.
      * @param background replace the background with specified background color, use transparent
      *     color to remove background
      */
-    public void drawMask(Image image, int transparency, int background) {
-        int[] colors = generateColors(background, transparency);
+    public void drawMask(Image image, int opacity, int background) {
+        int[] colors = generateColors(background, opacity);
         Image maskImage = getColorOverlay(colors);
         image.drawImage(maskImage, true);
     }
@@ -159,12 +159,14 @@ public class CategoryMask implements JsonSerializable {
      *
      * @param image the original image
      * @param classId the class to draw on the image
-     * @param color the rgb color with transparency
-     * @param transparency the transparency of the overlay
+     * @param color the rgb color with opacity
+     * @param opacity the opacity of the overlay. Value is between 0 and 255 inclusive, where 0
+     *     means the overlay is completely transparent and 255 means the overlay is completely
+     *     opaque.
      */
-    public void drawMask(Image image, int classId, int color, int transparency) {
+    public void drawMask(Image image, int classId, int color, int opacity) {
         int[] colors = new int[classes.size()];
-        colors[classId] = color & 0xFFFFFF | transparency << 24;
+        colors[classId] = color & 0xFFFFFF | opacity << 24;
         Image colorOverlay = getColorOverlay(colors);
         image.drawImage(colorOverlay, true);
     }
@@ -182,14 +184,14 @@ public class CategoryMask implements JsonSerializable {
         return ImageFactory.getInstance().fromPixels(pixels, width, height);
     }
 
-    private int[] generateColors(int background, int transparency) {
+    private int[] generateColors(int background, int opacity) {
         int[] colors = new int[classes.size()];
         colors[0] = background;
         for (int i = 1; i < classes.size(); i++) {
             int red = RandomUtils.nextInt(256);
             int green = RandomUtils.nextInt(256);
             int blue = RandomUtils.nextInt(256);
-            colors[i] = transparency << 24 | red << 16 | green << 8 | blue;
+            colors[i] = opacity << 24 | red << 16 | green << 8 | blue;
         }
         return colors;
     }
diff --git a/api/src/main/java/ai/djl/ndarray/internal/NDFormat.java b/api/src/main/java/ai/djl/ndarray/internal/NDFormat.java
index c60998c13..2bb36da49 100644
--- a/api/src/main/java/ai/djl/ndarray/internal/NDFormat.java
+++ b/api/src/main/java/ai/djl/ndarray/internal/NDFormat.java
@@ -83,6 +83,7 @@ public abstract class NDFormat {
             sb.append(" hasGradient");
         }
         if (!withContent) {
+            sb.append("\nCheck the \"Development Guideline\"->Debug to enable array display.\n");
             return sb.toString();
         }
 
@@ -114,9 +115,7 @@ public abstract class NDFormat {
             int maxDepth,
             int maxRows,
             int maxColumns) {
-        init(array);
         sb.append(LF);
-
         long size = array.size();
         long dimension = array.getShape().dimension();
         if (size == 0) {
@@ -130,6 +129,7 @@ public abstract class NDFormat {
         } else if (dimension > maxDepth) {
             sb.append("[ Exceed max print dimension ]");
         } else {
+            init(array);
             dump(sb, array, 0, true, maxRows, maxColumns);
         }
         return sb.toString();
diff --git a/docs/development/development_guideline.md b/docs/development/development_guideline.md
index 1b043de3b..a4d8e42b3 100644
--- a/docs/development/development_guideline.md
+++ b/docs/development/development_guideline.md
@@ -156,12 +156,11 @@ IntelliJ allows you to [customize the data view in the Debug Tools](https://www.
 You can create your own NDArray renderer as follows:
 ![](img/custom_debug_view.png)
 
-Please make sure to:
-
-- Check the "On-demand" option, which causes IntelliJ to only render the NDArray when you click on the variable.
-- Change the "Use following expression" field to `toDebugString(true)` to show NDArray content
-- Change the "Use following expression" field to something like `toDebugString(1000, 10, 10, 20, true)`
+Opening the IDE Settings/Preferences (`⌘ ,`), in *Java Type Renderer* section, you can enable array display by:
+- Change the "Use following expression" field to `toDebugString(true)` to show NDArray content.
+- Change the "Use following expression" field to something like `toDebugString(100, 10, 10, 20, true)`.
 if you want to adjust the range of NDArray's debug output.
+- Check the "On-demand" option, if you want the IntelliJ to render the NDArray only on clicking the variable.
 
 ## Common Problems
 


Test patch:
diff --git a/api/src/test/java/ai/djl/ndarray/internal/NDFormatTest.java b/api/src/test/java/ai/djl/ndarray/internal/NDFormatTest.java
index f629f51b4..9b3f0294c 100644
--- a/api/src/test/java/ai/djl/ndarray/internal/NDFormatTest.java
+++ b/api/src/test/java/ai/djl/ndarray/internal/NDFormatTest.java
@@ -136,4 +136,14 @@ public class NDFormatTest {
             Assert.assertEquals(str, "ND: (3) cpu() float64" + LF + "[  1.,   2., 100.]" + LF);
         }
     }
+
+    @Test
+    public void testLargeArray() {
+        try (NDManager manager = NDManager.newBaseManager()) {
+            NDArray large = manager.arange(0f, 100000000f).reshape(100, 100, 100, 100);
+            String str = large.toString();
+            Assert.assertEquals(
+                    str, "ND: (100, 100, 100, 100) cpu() float32\n[ Exceed max print size ]");
+        }
+    }
 }