diff --git a/nal/opennars2/vision.sage b/nal/opennars2/vision.sage
new file mode 100644
index 0000000000000000000000000000000000000000..80f59e1d6108986790e6db751610328dcd13331d
--- /dev/null
+++ b/nal/opennars2/vision.sage
@@ -0,0 +1,13 @@
+#Generates input for the vision system, use https://sagecell.sagemath.org/
+A=random_matrix(RR,30,30)
+size=30
+for i in range(size):
+    for j in range(size):
+        A[i,j]=random()
+with open("Output.txt", "w") as text_file:
+    for i in range(30):
+        for j in range(30):
+            di = i/(size-1)*2-1
+            dj = j/(size-1)*2-1
+            text_file.write("<A["+str(di.n())+","+str(dj.n())+"] --> [bright]>. :|: %"+str(A[i,j])+"%\n")
+show(plot(A))
\ No newline at end of file
diff --git a/nars_core/nars/main/NAR.java b/nars_core/nars/main/NAR.java
index 3bc3f90826c1e5053a7309d08f630ad94c082217..95ce17050ddbb8ea7a2625133f19554608523f03 100644
--- a/nars_core/nars/main/NAR.java
+++ b/nars_core/nars/main/NAR.java
@@ -39,6 +39,7 @@ import nars.language.Term;
 import nars.storage.LevelBag;
 import nars.io.events.Events.CyclesEnd;
 import nars.io.events.Events.CyclesStart;
+import nars.io.events.OutputHandler;
 import nars.language.Inheritance;
 
 
@@ -267,6 +268,21 @@ public class NAR extends SensoryChannel implements Serializable,Runnable {
             if(t != null && t instanceof Inheritance) {
                 Term predicate = ((Inheritance) t).getPredicate();
                 if(this.sensoryChannels.containsKey(predicate)) {
+                    Inheritance inh = (Inheritance) task.sentence.term;
+                    Term subj = inh.getSubject();
+                    //map to pei's -1 to 1 indexing schema
+                    if(subj.term_indices == null) {
+                        String variable = subj.toString().split("\\[")[0];
+                        String[] vals = subj.toString().split("\\[")[1].split("\\]")[0].split(",");
+                        double height = Double.parseDouble(vals[0]);
+                        double width = Double.parseDouble(vals[1]);
+                        int wval = (int) Math.round((width+1.0f)/2.0f*(this.sensoryChannels.get(predicate).width-1));
+                        int hval = (int) Math.round(((height+1.0f)/2.0f*(this.sensoryChannels.get(predicate).height-1)));
+                        String newInput = "<"+variable+"["+hval+","+wval+"] --> "+predicate+">"+task.sentence.punctuation+ " :|:";
+                        this.emit(OutputHandler.IN.class, task);
+                        this.addInput(newInput);
+                        return;
+                    }
                     this.sensoryChannels.get(predicate).addInput((Task) task);
                     return;
                 }
diff --git a/nars_core/nars/main/Plugins.java b/nars_core/nars/main/Plugins.java
index 219706c37bc83548df49bf42c93c7189a2a5e214..9a947fd4e8b9966fc4648e3d2d0d4c33bd7314f0 100644
--- a/nars_core/nars/main/Plugins.java
+++ b/nars_core/nars/main/Plugins.java
@@ -22,7 +22,7 @@ public class Plugins {
         n.addPlugin(new Anticipate());      // expect an event 
         Term label = SetInt.make(new Term("bright"));
         n.addSensoryChannel(label.toString(),
-                            new VisionChannel(label, n, n, 1, 1));
+                            new VisionChannel(label, n, n, 30, 30));
         boolean full_internal_experience = false;
         if(!full_internal_experience) {
             n.addPlugin(new InternalExperience());
diff --git a/nars_core/nars/plugin/perception/SensoryChannel.java b/nars_core/nars/plugin/perception/SensoryChannel.java
index 595e1b75cd0bb8b2a31aef7a9dfa988509f3036e..027e79f3ced3d754f7e3d78137350348adca52ce 100644
--- a/nars_core/nars/plugin/perception/SensoryChannel.java
+++ b/nars_core/nars/plugin/perception/SensoryChannel.java
@@ -17,6 +17,8 @@ public abstract class SensoryChannel implements Serializable {
     private Collection<SensoryChannel> reportResultsTo;
     public NAR nar; //for top-down influence of concept budgets
     public List<Task> results = new ArrayList<Task>();
+    public int height = 0; //1D channels have height 1
+    public int width = 0;
     public SensoryChannel(){}
     public SensoryChannel(NAR nar, Collection<SensoryChannel> reportResultsTo) {
         this.reportResultsTo = reportResultsTo;
diff --git a/nars_core/nars/plugin/perception/VisionChannel.java b/nars_core/nars/plugin/perception/VisionChannel.java
index 3c94ba0d4e3222067a6cbf5025e8c0cb0f164583..aa317564fdba3665a5fa5b383638c1fd8c2c3d2a 100644
--- a/nars_core/nars/plugin/perception/VisionChannel.java
+++ b/nars_core/nars/plugin/perception/VisionChannel.java
@@ -8,7 +8,6 @@ import nars.entity.Task;
 import nars.entity.TruthValue;
 import nars.inference.BudgetFunctions;
 import nars.io.Symbols;
-import nars.io.events.OutputHandler.IN;
 import nars.language.Inheritance;
 import nars.language.Term;
 import nars.main.Parameters;
@@ -17,8 +16,6 @@ public class VisionChannel extends SensoryChannel {
     double[][] inputs;
     boolean[][] updated;
     int cnt_updated = 0;
-    int height = 0;
-    int width = 0;
     int px = 0;
     int py = 0;
     Term label;
@@ -37,7 +34,6 @@ public class VisionChannel extends SensoryChannel {
     public boolean AddToMatrix(Task t) {
         Inheritance inh = (Inheritance) t.getTerm(); //channels receive inheritances
         String cur_subj = inh.getSubject().index_variable.toString();
-        nar.emit(IN.class, t);
         if(!cur_subj.equals(subj)) { //when subject changes, we start to collect from scratch,
             cnt_updated = 0; //this way multiple matrices can be processed by the same vision channel
             updated = new boolean[height][width];