def testShaderNameMatchesFileName(self): oslCode = GafferOSL.OSLCode() oslCode["out"]["o"] = Gaffer.Color3fPlug( direction=Gaffer.Plug.Direction.Out, flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) oslCode["code"].setValue("o = color( 0, 1, 0 );") info = subprocess.check_output( ["oslinfo", self.__osoFileName(oslCode)]) self.assertTrue( info.startswith("shader \"{0}\"".format( os.path.basename(self.__osoFileName(oslCode)))))
def testSource(self): # Make a shader using the OSLCode node. oslCode = GafferOSL.OSLCode() oslCode["parameters"]["i"] = Gaffer.Color3fPlug( flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) oslCode["out"]["o"] = Gaffer.Color3fPlug( direction=Gaffer.Plug.Direction.Out, flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) oslCode["code"].setValue("o = i * color( u, v, 0 );") # Export it to a .osl file and compile it. oslFileName = os.path.join(self.temporaryDirectory(), "test.osl") with open(oslFileName, "w") as f: f.write(oslCode.source("test")) shader = self.compileShader(oslFileName) # Load that onto an OSLShader and check that # it matches. oslShader = GafferOSL.OSLShader() oslShader.loadShader(shader) self.assertEqual(oslShader["parameters"].keys(), oslCode["parameters"].keys()) self.assertEqual(oslShader["out"].keys(), oslCode["out"].keys()) for p in oslShader["parameters"].children(): p.setFlags(Gaffer.Plug.Flags.Dynamic, True) self.assertEqual(repr(p), repr(oslCode["parameters"][p.getName()])) for p in oslShader["out"].children(): p.setFlags(Gaffer.Plug.Flags.Dynamic, True) self.assertEqual(repr(p), repr(oslCode["out"][p.getName()]))
def testSettable(self): n = Gaffer.Node() n["p1"] = Gaffer.Color3fPlug() n["p2"] = Gaffer.Color3fPlug() self.assertTrue(n["p1"].settable()) self.assertTrue(n["p2"].settable()) n["p2"].setInput(n["p1"]) self.assertTrue(n["p1"].settable()) self.assertFalse(n["p2"].settable()) # partially connected plugs should not be considered # settable, because all the children are not settable n["p2"]["r"].setInput(None) self.assertEqual(n["p2"]["r"].getInput(), None) self.assertEqual(n["p2"].getInput(), None) self.assertTrue(n["p1"].settable()) self.assertFalse(n["p2"].settable())
def testColor3fAcceptsColor4fInput(self): p4 = Gaffer.Color4fPlug(direction=Gaffer.Plug.Direction.Out) p3 = Gaffer.Color3fPlug() self.failUnless(p3.acceptsInput(p4)) p3.setInput(p4) self.failUnless(p3.getInput().isSame(p4)) self.failUnless(p3[0].getInput().isSame(p4[0])) self.failUnless(p3[1].getInput().isSame(p4[1])) self.failUnless(p3[2].getInput().isSame(p4[2])) self.assertEqual(p4[3].outputs(), ())
def testAddColumnUsingDynamicPlug( self ) : s = Gaffer.ScriptNode() s["s"] = Gaffer.Spreadsheet() s["s"]["rows"].addColumn( Gaffer.Color3fPlug( "c", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["s"]["rows"].addColumn( Gaffer.IntPlug( "i", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s2 = Gaffer.ScriptNode() s2.execute( s.serialise() ) self.assertEqual( s2["s"]["rows"][0]["cells"].keys(), s["s"]["rows"][0]["cells"].keys() ) self.assertEqual( s2["s"]["out"].keys(), s["s"]["out"].keys() ) self.assertEqual( s2.serialise(), s.serialise() )
def testContextTypes(self): s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["user"]["f"] = Gaffer.FloatPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) s["n"]["user"]["i"] = Gaffer.IntPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) s["n"]["user"]["c"] = Gaffer.Color3fPlug( flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) s["n"]["user"]["v"] = Gaffer.V3fPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) s["n"]["user"]["s"] = Gaffer.StringPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) s["e"] = Gaffer.Expression() s["e"].setExpression( inspect.cleandoc(""" parent.n.user.f = context( "f", 1 ); parent.n.user.i = context( "i", 1 ); parent.n.user.c = context( "c", color( 1, 2, 3 ) ); parent.n.user.v = context( "v", vector( 0, 1, 2 ) ); parent.n.user.s = context( "s", "default" ); """), "OSL") with Gaffer.Context() as c: self.assertEqual(s["n"]["user"]["f"].getValue(), 1) self.assertEqual(s["n"]["user"]["i"].getValue(), 1) self.assertEqual(s["n"]["user"]["c"].getValue(), IECore.Color3f(1, 2, 3)) self.assertEqual(s["n"]["user"]["v"].getValue(), IECore.V3f(0, 1, 2)) self.assertEqual(s["n"]["user"]["s"].getValue(), "default") c["f"] = 10 c["i"] = 11 c["c"] = IECore.Color3f(4, 5, 6) c["v"] = IECore.V3f(1, 2, 3) c["s"] = "non-default" self.assertEqual(s["n"]["user"]["f"].getValue(), 10) self.assertEqual(s["n"]["user"]["i"].getValue(), 11) self.assertEqual(s["n"]["user"]["c"].getValue(), IECore.Color3f(4, 5, 6)) self.assertEqual(s["n"]["user"]["v"].getValue(), IECore.V3f(1, 2, 3)) self.assertEqual(s["n"]["user"]["s"].getValue(), "non-default")
def testConnect(self): plane = GafferScene.Plane() shader = GafferSceneTest.TestShader("surface") shader["type"].setValue("surface") planeFilter = GafferScene.PathFilter() planeFilter["paths"].setValue(IECore.StringVectorData(["/plane"])) assignment = GafferScene.ShaderAssignment() assignment["in"].setInput(plane["out"]) assignment["filter"].setInput(planeFilter["out"]) assignment["shader"].setInput(shader["out"]) originalNetwork = assignment["out"].attributes("/plane")["surface"] self.assertEqual(len(originalNetwork), 1) textureShader = GafferSceneTest.TestShader("texture") tweaks = GafferScene.ShaderTweaks() tweaks["in"].setInput(assignment["out"]) tweaks["filter"].setInput(planeFilter["out"]) tweaks["shader"].setValue("surface") tweaks["tweaks"].addChild( GafferScene.TweakPlug("c", Gaffer.Color3fPlug())) tweaks["tweaks"][0]["value"].setInput(textureShader["out"]) tweakedNetwork = tweaks["out"].attributes("/plane")["surface"] self.assertEqual(len(tweakedNetwork), 2) self.assertEqual(tweakedNetwork.input(("surface", "c")), ("texture", "")) tweakedNetwork.removeShader("texture") self.assertEqual(tweakedNetwork, originalNetwork) textureShader["parameters"]["c"].setValue(imath.Color3f(1, 2, 3)) tweakedNetwork = tweaks["out"].attributes("/plane")["surface"] self.assertEqual( tweakedNetwork.getShader("texture").parameters["c"].value, imath.Color3f(1, 2, 3)) tweaks["tweaks"][0]["mode"].setValue( GafferScene.TweakPlug.Mode.Multiply) with self.assertRaisesRegexp( RuntimeError, "Mode must be \"Replace\" when inserting a connection"): tweaks["out"].attributes("/plane")
def testShaderTypesInAttributes(self): surface = GafferSceneTest.TestShader("surface") surface["name"].setValue("testSurface") surface["type"].setValue("test:surface") surface["parameters"]["t"] = Gaffer.Color3fPlug() texture = GafferSceneTest.TestShader("texture") texture["name"].setValue("testTexture") texture["type"].setValue("test:shader") surface["parameters"]["t"].setInput(texture["out"]) network = surface.attributes()["test:surface"] self.assertEqual(network[0].type, "test:shader") self.assertEqual(network[1].type, "test:surface")
def testPromoteDynamicColorPlugAndSerialise( self ) : s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["c"] = Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n"] ] ) ) b.promotePlug( b["n"]["c"] ) ss = s.serialise() s = Gaffer.ScriptNode() s.execute( ss ) self.assertTrue( isinstance( s["Box"]["c"], Gaffer.Color3fPlug ) ) self.assertTrue( s["Box"]["n"]["c"].getInput().isSame( s["Box"]["c"] ) )
def testPromoteDynamicColorPlugAndSerialise( self ) : s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["n"] = Gaffer.Node() s["b"]["n"]["c"] = Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) Gaffer.PlugAlgo.promote( s["b"]["n"]["c"] ) ss = s.serialise() s = Gaffer.ScriptNode() s.execute( ss ) self.assertTrue( isinstance( s["b"]["c"], Gaffer.Color3fPlug ) ) self.assertTrue( s["b"]["n"]["c"].getInput().isSame( s["b"]["c"] ) )
def testShaderTypesInState(self): surface = GafferSceneTest.TestShader("surface") surface["name"].setValue("testSurface") surface["type"].setValue("test:surface") surface["parameters"]["t"] = Gaffer.Color3fPlug() texture = GafferSceneTest.TestShader("texture") texture["name"].setValue("testTexture") texture["type"].setValue("test:shader") surface["parameters"]["t"].setInput(texture["out"]) state = surface.state() self.assertEqual(state[0].type, "test:shader") self.assertEqual(state[1].type, "test:surface")
def testReconnect(self): plane = GafferScene.Plane() shader = GafferSceneTest.TestShader("surface") shader["type"].setValue("surface") textureShader1 = GafferSceneTest.TestShader("texture1") shader["parameters"]["c"].setInput(textureShader1["out"]) planeFilter = GafferScene.PathFilter() planeFilter["paths"].setValue(IECore.StringVectorData(["/plane"])) assignment = GafferScene.ShaderAssignment() assignment["in"].setInput(plane["out"]) assignment["filter"].setInput(planeFilter["out"]) assignment["shader"].setInput(shader["out"]) originalNetwork = assignment["out"].attributes("/plane")["surface"] self.assertEqual(len(originalNetwork), 2) self.assertEqual(originalNetwork.input(("surface", "c")), ("texture1", "")) textureShader2 = GafferSceneTest.TestShader("texture2") tweaks = GafferScene.ShaderTweaks() tweaks["in"].setInput(assignment["out"]) tweaks["filter"].setInput(planeFilter["out"]) tweaks["shader"].setValue("surface") tweaks["tweaks"].addChild( GafferScene.TweakPlug("c", Gaffer.Color3fPlug())) tweaks["tweaks"][0]["value"].setInput(textureShader2["out"]) tweakedNetwork = tweaks["out"].attributes("/plane")["surface"] self.assertEqual(len(tweakedNetwork), 2) self.assertEqual(tweakedNetwork.input(("surface", "c")), ("texture2", "")) textureShader2["enabled"].setValue(False) tweakedNetwork = tweaks["out"].attributes("/plane")["surface"] self.assertEqual(len(tweakedNetwork), 1) self.assertFalse(tweakedNetwork.input(("surface", "c"))) textureShader2["enabled"].setValue(True) tweaks["tweaks"][0]["enabled"].setValue(False) self.assertEqual(tweaks["out"].attributes("/plane")["surface"], originalNetwork)
def testCommonAncestorType(self): s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["user"]["p1"] = Gaffer.IntPlug() s["n"]["user"]["p2"] = Gaffer.Color3fPlug() self.assertEqual( s["n"]["user"]["p1"].commonAncestor(s["n"]["user"]["p2"]["r"]), s["n"]["user"]) self.assertEqual( s["n"]["user"]["p1"].commonAncestor(s["n"]["user"]["p2"]["r"], Gaffer.Plug), s["n"]["user"]) self.assertEqual( s["n"]["user"]["p1"].commonAncestor(s["n"]["user"]["p2"]["r"], Gaffer.Node), s["n"])
def testPromoteCompoundPlugWithColorPlug(self): s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["n"] = Gaffer.Node() s["b"]["n"]["user"]["p"] = Gaffer.Plug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) s["b"]["n"]["user"]["p"]["c"] = Gaffer.Color3fPlug( flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) Gaffer.PlugAlgo.promote(s["b"]["n"]["user"]["p"]) s2 = Gaffer.ScriptNode() s2.execute(s.serialise()) self.assertEqual(len(s2["b"]["n"]["user"]["p"]["c"]), 3)
def testPromoteColor(self): s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["n"] = Gaffer.Node() s["b"]["n"]["c"] = Gaffer.Color3fPlug() s["b"]["n"]["c"].setValue(IECore.Color3f(1, 0, 1)) self.assertTrue(Gaffer.PlugAlgo.canPromote(s["b"]["n"]["c"])) self.assertFalse(Gaffer.PlugAlgo.isPromoted(s["b"]["n"]["c"])) p = Gaffer.PlugAlgo.promote(s["b"]["n"]["c"]) self.assertTrue(isinstance(p, Gaffer.Color3fPlug)) self.assertTrue(s["b"]["n"]["c"].getInput().isSame(p)) self.assertTrue(s["b"]["n"]["c"]["r"].getInput().isSame(p["r"])) self.assertTrue(s["b"]["n"]["c"]["g"].getInput().isSame(p["g"])) self.assertTrue(s["b"]["n"]["c"]["b"].getInput().isSame(p["b"])) self.assertEqual(p.getValue(), IECore.Color3f(1, 0, 1))
def testPromoteColor( self ) : s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["c"] = Gaffer.Color3fPlug() s["n"]["c"].setValue( IECore.Color3f( 1, 0, 1 ) ) b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n"] ] ) ) self.assertTrue( b.canPromotePlug( b["n"]["c"] ) ) self.assertFalse( b.plugIsPromoted( b["n"]["c"] ) ) p = b.promotePlug( b["n"]["c"] ) self.assertTrue( isinstance( p, Gaffer.Color3fPlug ) ) self.assertTrue( b["n"]["c"].getInput().isSame( p ) ) self.assertTrue( b["n"]["c"]["r"].getInput().isSame( p["r"] ) ) self.assertTrue( b["n"]["c"]["g"].getInput().isSame( p["g"] ) ) self.assertTrue( b["n"]["c"]["b"].getInput().isSame( p["b"] ) ) self.assertEqual( p.getValue(), IECore.Color3f( 1, 0, 1 ) )
def testReloadWithNestedOutputConnections(self): s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["color"] = Gaffer.Color3fPlug( direction=Gaffer.Plug.Direction.Out, flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic) s["b"].exportForReference(self.temporaryDirectory() + "/test.grf") s["a"] = GafferTest.AddNode() s["r"] = Gaffer.Reference() s["r"].load(self.temporaryDirectory() + "/test.grf") s["a"]["op1"].setInput(s["r"]["color"]["g"]) s["r"].load(self.temporaryDirectory() + "/test.grf") self.assertTrue(s["a"]["op1"].getInput().isSame(s["r"]["color"]["g"]))
def testMinimalPerf(self): constant = GafferImage.Constant() constant["format"].setValue(GafferImage.Format(4096, 4096)) floatToColor = GafferOSL.OSLShader() floatToColor.loadShader("Conversion/FloatToColor") oslImage = GafferOSL.OSLImage() oslImage["in"].setInput(constant["out"]) oslImage["channels"].addChild( Gaffer.NameValuePlug("", Gaffer.Color3fPlug("value"), True, "channel")) oslImage["channels"]["channel"]["value"].setInput( floatToColor["out"]["c"]) GafferImage.ImageAlgo.image(constant["out"]) # Run the fastest possible OSLImage on lots of tiles, to highlight any constant overhead with GafferTest.TestRunner.PerformanceScope(): GafferImage.ImageAlgo.image(oslImage["out"])
def testColorUnpromoting( self ) : s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["c"] = Gaffer.Color3fPlug() b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n"] ] ) ) p = b.promotePlug( b["n"]["c"] ) self.assertTrue( b.plugIsPromoted( b["n"]["c"] ) ) self.assertTrue( b.plugIsPromoted( b["n"]["c"]["r"] ) ) self.assertTrue( b.plugIsPromoted( b["n"]["c"]["g"] ) ) self.assertTrue( b.plugIsPromoted( b["n"]["c"]["b"] ) ) self.assertTrue( p.node().isSame( b ) ) b.unpromotePlug( b["n"]["c"] ) self.assertFalse( b.plugIsPromoted( b["n"]["c"] ) ) self.assertFalse( b.plugIsPromoted( b["n"]["c"]["r"] ) ) self.assertFalse( b.plugIsPromoted( b["n"]["c"]["g"] ) ) self.assertFalse( b.plugIsPromoted( b["n"]["c"]["b"] ) ) self.assertTrue( p.node() is None )
def testColorUnpromoting(self): s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["n"] = Gaffer.Node() s["b"]["n"]["c"] = Gaffer.Color3fPlug() p = Gaffer.PlugAlgo.promote(s["b"]["n"]["c"]) self.assertTrue(Gaffer.PlugAlgo.isPromoted(s["b"]["n"]["c"])) self.assertTrue(Gaffer.PlugAlgo.isPromoted(s["b"]["n"]["c"]["r"])) self.assertTrue(Gaffer.PlugAlgo.isPromoted(s["b"]["n"]["c"]["g"])) self.assertTrue(Gaffer.PlugAlgo.isPromoted(s["b"]["n"]["c"]["b"])) self.assertTrue(p.node().isSame(s["b"])) Gaffer.PlugAlgo.unpromote(s["b"]["n"]["c"]) self.assertFalse(Gaffer.PlugAlgo.isPromoted(s["b"]["n"]["c"])) self.assertFalse(Gaffer.PlugAlgo.isPromoted(s["b"]["n"]["c"]["r"])) self.assertFalse(Gaffer.PlugAlgo.isPromoted(s["b"]["n"]["c"]["g"])) self.assertFalse(Gaffer.PlugAlgo.isPromoted(s["b"]["n"]["c"]["b"])) self.assertTrue(p.node() is None)
def testVectorAndColourOutputs( self ) : s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["user"].addChild( Gaffer.V2fPlug( "v2f", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.V2iPlug( "v2i", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.V3fPlug( "v3f", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.V3iPlug( "v3i", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.Color3fPlug( "c3f", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.Color4fPlug( "c4f", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["e"] = Gaffer.Expression() s["e"]["engine"].setValue( "python" ) s["e"]["expression"].setValue( 'import IECore;' 'parent["n"]["user"]["v2f"] = IECore.V2f( 1, 2 );' 'parent["n"]["user"]["v2i"] = IECore.V2i( 3, 4 );' 'parent["n"]["user"]["v3f"] = IECore.V3f( 4, 5, 6 );' 'parent["n"]["user"]["v3i"] = IECore.V3i( 6, 7, 8 );' 'parent["n"]["user"]["c3f"] = IECore.Color3f( 9, 10, 11 );' 'parent["n"]["user"]["c4f"] = IECore.Color4f( 12, 13, 14, 15 );' ) def assertExpectedValues( script ) : self.assertEqual( script["n"]["user"]["v2f"].getValue(), IECore.V2f( 1, 2 ) ) self.assertEqual( script["n"]["user"]["v2i"].getValue(), IECore.V2i( 3, 4 ) ) self.assertEqual( script["n"]["user"]["v3f"].getValue(), IECore.V3f( 4, 5, 6 ) ) self.assertEqual( script["n"]["user"]["v3i"].getValue(), IECore.V3i( 6, 7, 8 ) ) self.assertEqual( script["n"]["user"]["c3f"].getValue(), IECore.Color3f( 9, 10, 11 ) ) self.assertEqual( script["n"]["user"]["c4f"].getValue(), IECore.Color4f( 12, 13, 14, 15 ) ) assertExpectedValues( s ) s2 = Gaffer.ScriptNode() s2.execute( s.serialise() ) assertExpectedValues( s2 )
def testReloadWithNestedInputConnections( self ) : s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["array"] = Gaffer.ArrayPlug( element = Gaffer.IntPlug(), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s["b"]["color"] = Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) s["a"] = GafferTest.AddNode() s["r"] = Gaffer.Reference() s["r"].load( self.temporaryDirectory() + "/test.grf" ) s["r"]["array"][0].setInput( s["a"]["sum"] ) s["r"]["array"][1].setInput( s["a"]["sum"] ) s["r"]["color"]["g"].setInput( s["a"]["sum"] ) s["r"].load( self.temporaryDirectory() + "/test.grf" ) self.assertTrue( s["r"]["array"][0].getInput().isSame( s["a"]["sum"] ) ) self.assertTrue( s["r"]["array"][1].getInput().isSame( s["a"]["sum"] ) ) self.assertTrue( s["r"]["color"]["g"].getInput().isSame( s["a"]["sum"] ) )
def testDynamicPlugSerialisation( self ) : s1 = Gaffer.ScriptNode() s1["n1"] = GafferTest.AddNode() s1["n2"] = GafferTest.AddNode() s1["n1"]["dynamicPlug"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s1["n1"]["dynamicPlug"].setInput( s1["n2"]["sum"] ) s1["n1"]["dynamicPlug2"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s1["n1"]["dynamicPlug2"].setValue( 100 ) s1["n1"]["dynamicStringPlug"] = Gaffer.StringPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s1["n1"]["dynamicStringPlug"].setValue( "hiThere" ) s1["n1"]["dynamicOutPlug"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, direction=Gaffer.Plug.Direction.Out ) s1["n1"]["dynamicColorOutPlug"] = Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, direction=Gaffer.Plug.Direction.Out ) s2 = Gaffer.ScriptNode() s2.execute( s1.serialise() ) self.assert_( s2["n1"]["dynamicPlug"].getInput().isSame( s2["n2"]["sum"] ) ) self.assertEqual( s2["n1"]["dynamicPlug2"].getValue(), 100 ) self.assertEqual( s2["n1"]["dynamicStringPlug"].getValue(), "hiThere" ) self.failUnless( isinstance( s2["n1"]["dynamicOutPlug"], Gaffer.IntPlug ) ) self.failUnless( isinstance( s2["n1"]["dynamicColorOutPlug"], Gaffer.Color3fPlug ) )
def testCantPromoteReadOnlyPlug(self): s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["n"] = Gaffer.Node() s["b"]["n"]["i"] = Gaffer.IntPlug() s["b"]["n"]["c"] = Gaffer.Color3fPlug() self.assertTrue(Gaffer.PlugAlgo.canPromote(s["b"]["n"]["i"])) self.assertTrue(Gaffer.PlugAlgo.canPromote(s["b"]["n"]["c"])) self.assertTrue(Gaffer.PlugAlgo.canPromote(s["b"]["n"]["c"]["r"])) s["b"]["n"]["i"].setFlags(Gaffer.Plug.Flags.ReadOnly, True) s["b"]["n"]["c"].setFlags(Gaffer.Plug.Flags.ReadOnly, True) s["b"]["n"]["c"]["r"].setFlags(Gaffer.Plug.Flags.ReadOnly, True) self.assertFalse(Gaffer.PlugAlgo.canPromote(s["b"]["n"]["i"])) self.assertFalse(Gaffer.PlugAlgo.canPromote(s["b"]["n"]["c"])) self.assertFalse(Gaffer.PlugAlgo.canPromote(s["b"]["n"]["c"]["r"])) self.assertRaises(RuntimeError, Gaffer.PlugAlgo.promote, s["b"]["n"]["i"]) self.assertRaises(RuntimeError, Gaffer.PlugAlgo.promote, s["b"]["n"]["c"]) self.assertRaises(RuntimeError, Gaffer.PlugAlgo.promote, s["b"]["n"]["c"]["r"]) k = s["b"].keys() uk = s["b"]["user"].keys() try: Gaffer.PlugAlgo.promote(s["b"]["n"]["i"]) except Exception, e: self.assertTrue("Cannot promote" in str(e)) self.assertTrue("read only" in str(e)) self.assertEqual(s["b"].keys(), k) self.assertEqual(s["b"]["user"].keys(), uk)
def testCantDoArithmeticOnConnection(self): plane = GafferScene.Plane() shader = GafferSceneTest.TestShader("surface") shader["type"].setValue("surface") textureShader = GafferSceneTest.TestShader("texture1") shader["parameters"]["c"].setInput(textureShader["out"]) planeFilter = GafferScene.PathFilter() planeFilter["paths"].setValue(IECore.StringVectorData(["/plane"])) assignment = GafferScene.ShaderAssignment() assignment["in"].setInput(plane["out"]) assignment["filter"].setInput(planeFilter["out"]) assignment["shader"].setInput(shader["out"]) tweaks = GafferScene.ShaderTweaks() tweaks["in"].setInput(assignment["out"]) tweaks["filter"].setInput(planeFilter["out"]) tweaks["shader"].setValue("surface") tweaks["tweaks"].addChild( GafferScene.TweakPlug("c", Gaffer.Color3fPlug())) for mode in GafferScene.TweakPlug.Mode.values: if mode == GafferScene.TweakPlug.Mode.Replace: continue tweaks["tweaks"][0]["mode"].setValue(mode) with self.assertRaisesRegexp( RuntimeError, "Mode must be \"Replace\" when a previous connection exists" ): tweaks["out"].attributes("/plane")
def testBadCachePolicyHang(self): # Using the legacy cache policy for OSLImage.shadingPlug creates a hang due to tbb task stealing, # though it's a bit hard to actually demonstrate constant = GafferImage.Constant() constant["format"].setValue(GafferImage.Format(128, 128, 1.000)) # Need a slow to compute OSL code in order to trigger hang mandelbrotCode = self.mandelbrotNode() # In order to trigger the hang, we need to mix threads which are stuck waiting for an expression which # uses the Standard policy with threads that are actually finishing, so that tbb tries to start up new # threads while we're waiting for the expression result. To do this, we use the "var" context variable # to create two versions of this OSLCode mandelbrotCode["varExpression"] = Gaffer.Expression() mandelbrotCode["varExpression"].setExpression( 'parent.parameters.iterations = 100000 + context( "var", 0 );', "OSL") oslImage = GafferOSL.OSLImage() oslImage["channels"].addChild( Gaffer.NameValuePlug( "", Gaffer.Color3fPlug( "value", defaultValue=imath.Color3f(1, 1, 1), flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ), True, "channel", Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) oslImage["in"].setInput(constant["out"]) oslImage["channels"]["channel"]["value"][0].setInput( mandelbrotCode["out"]["outFloat"]) oslImage["channels"]["channel"]["value"][1].setInput( mandelbrotCode["out"]["outFloat"]) oslImage["channels"]["channel"]["value"][2].setInput( mandelbrotCode["out"]["outFloat"]) # This imageStats is use to create non-blocking slow calculations imageStats = GafferImage.ImageStats() imageStats["in"].setInput(oslImage["out"]) imageStats["area"].setValue( imath.Box2i(imath.V2i(0, 0), imath.V2i(64, 64))) # This box does the non-blocking slow calculation, followed by a blocking slow calculation. # This ensures that tasks which do just the non-block calculation will start finishing while # the blocking slow calculation is still running, allowing tbb to try running more threads # on the blocking calcluation, realizing they can't run, and stealing tasks onto those threads # which can hit the Standard policy lock on the expression upstream and deadlock, unless the # OSLImage isolates its threads correctly expressionBox = Gaffer.Box() expressionBox.addChild( Gaffer.FloatVectorDataPlug("inChannelData", defaultValue=IECore.FloatVectorData( []))) expressionBox.addChild(Gaffer.FloatPlug("inStat")) expressionBox.addChild( Gaffer.FloatPlug("out", direction=Gaffer.Plug.Direction.Out)) expressionBox["inChannelData"].setInput(oslImage["out"]["channelData"]) expressionBox["inStat"].setInput(imageStats["average"]["r"]) expressionBox["contextVariables"] = Gaffer.ContextVariables() expressionBox["contextVariables"].setup( Gaffer.FloatVectorDataPlug("in", defaultValue=IECore.FloatVectorData( []))) expressionBox["contextVariables"]["variables"].addChild( Gaffer.NameValuePlug("image:tileOrigin", Gaffer.V2iPlug("value"), True, "member1")) expressionBox["contextVariables"]["variables"].addChild( Gaffer.NameValuePlug("image:channelName", Gaffer.StringPlug("value", defaultValue='R'), True, "member2")) expressionBox["contextVariables"]["variables"].addChild( Gaffer.NameValuePlug("var", Gaffer.IntPlug("value", defaultValue=1), True, "member3")) expressionBox["contextVariables"]["in"].setInput( expressionBox["inChannelData"]) expressionBox["expression"] = Gaffer.Expression() expressionBox["expression"].setExpression( inspect.cleandoc(""" d = parent["contextVariables"]["out"] parent["out"] = d[0] + parent["inStat"] """)) # Create a switch to mix which tasks perform the non-blocking or blocking calculation - we need a mixture # to trigger the hang switch = Gaffer.Switch() switch.setup(Gaffer.IntPlug( "in", defaultValue=0, )) switch["in"][0].setInput(expressionBox["out"]) switch["in"][1].setInput(imageStats["average"]["r"]) switch["switchExpression"] = Gaffer.Expression() switch["switchExpression"].setExpression( 'parent.index = ( stoi( context( "testContext", "0" ) ) % 10 ) > 5;', "OSL") # In order to evaluate this expression a bunch of times at once with different values of "testContext", # we set up a simple scene that can be evaluated with GafferSceneTest.traversScene. # In theory, we could use a simple function that used a parallel_for to evaluate switch["out"], but for # some reason we don't entirely understand, this does not trigger the hang import GafferSceneTest import GafferScene sphere = GafferScene.Sphere() pathFilter = GafferScene.PathFilter() pathFilter["paths"].setValue(IECore.StringVectorData(['/sphere'])) customAttributes = GafferScene.CustomAttributes() customAttributes["attributes"].addChild( Gaffer.NameValuePlug("foo", Gaffer.FloatPlug("value"), True, "member1")) customAttributes["attributes"]["member1"]["value"].setInput( switch["out"]) customAttributes["in"].setInput(sphere["out"]) customAttributes["filter"].setInput(pathFilter["out"]) collectScenes = GafferScene.CollectScenes() collectScenes["in"].setInput(customAttributes["out"]) collectScenes["rootNames"].setValue( IECore.StringVectorData([str(i) for i in range(1000)])) collectScenes["rootNameVariable"].setValue('testContext') # When OSLImage.shadingPlug is not correctly isolated, and grain size on ShadingEngine is smaller than the # image tile size, this fails about 50% of the time. Running it 5 times makes the failure pretty consistent. for i in range(5): Gaffer.ValuePlug.clearCache() Gaffer.ValuePlug.clearHashCache() GafferSceneTest.traverseScene(collectScenes["out"])
def testDefaultExpressionForSupportedPlugs(self): s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["user"].addChild( Gaffer.IntPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.FloatPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.StringPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.BoolPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.V2fPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.V2iPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.V3fPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.V3iPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.Color3fPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.Color4fPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.Box2fPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.Box2iPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.Box3fPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.Box3iPlug(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.IntVectorDataPlug(defaultValue=IECore.IntVectorData([0, 1]), flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.FloatVectorDataPlug( defaultValue=IECore.FloatVectorData([0, 1]), flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.StringVectorDataPlug( defaultValue=IECore.StringVectorData(["a", "b"]), flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["n"]["user"].addChild( Gaffer.V3fVectorDataPlug( defaultValue=IECore.V3fVectorData([IECore.V3f(1)]), flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) s["e"] = Gaffer.Expression() for plug in s["n"]["user"]: value = plug.getValue() s["e"].setExpression(s["e"].defaultExpression(plug, "python")) self.assertTrue(plug.getInput().node().isSame(s["e"])) self.assertEqual(plug.getValue(), value)
def colorSwitch(self): result = Gaffer.Switch() result.setup(Gaffer.Color3fPlug()) return result
import Gaffer import GafferOSL import GafferUI scriptWindow = GafferUI.ScriptWindow.acquire(script) script["OSLCode"] = GafferOSL.OSLCode() script.setFocus(script["OSLCode"]) oslEditor = GafferUI.NodeEditor.acquire(script["OSLCode"], floating=True) GafferUI.WidgetAlgo.grab(widget=oslEditor, imagePath="images/blank.png") script["OSLCode"]["parameters"]["width"] = Gaffer.FloatPlug(defaultValue=0.0) script["OSLCode"]["parameters"]["width"].setValue(0.025) script["OSLCode"]["out"]["stripes"] = Gaffer.Color3fPlug( direction=Gaffer.Plug.Direction.Out, defaultValue=imath.Color3f(0, 0, 0)) GafferUI.WidgetAlgo.grab(widget=oslEditor, imagePath="images/parameters.png") oslEditor.parent().setVisible(False) script["OSLCode"]["code"].setValue( "stripes = aastep( 0, sin( v * M_PI / width ) )") viewer = scriptWindow.getLayout().editors(GafferUI.Viewer)[0] # delay so it can render t = time.time() + 3 while time.time() < t: GafferUI.EventLoop.waitForIdle(1) GafferUI.WidgetAlgo.grab(widget=viewer, imagePath="images/shaderBallStripes.png") script["OSLCode"]["parameters"]["color1"] = Gaffer.Color3fPlug( defaultValue=imath.Color3f(0, 0, 0))
def testMerging(self): allFilter = GafferScene.PathFilter() allFilter["paths"].setValue(IECore.StringVectorData(['/...'])) plane = GafferScene.Plane() plane["divisions"].setValue(imath.V2i(20, 20)) # Assign a basic gradient shader uvGradientCode = GafferOSL.OSLCode() uvGradientCode["out"].addChild( Gaffer.Color3fPlug("out", direction=Gaffer.Plug.Direction.Out)) uvGradientCode["code"].setValue('out = color( u, v, 0.5 );') shaderAssignment = GafferScene.ShaderAssignment() shaderAssignment["in"].setInput(plane["out"]) shaderAssignment["filter"].setInput(allFilter["out"]) shaderAssignment["shader"].setInput(uvGradientCode["out"]["out"]) # Set up a random id from 0 - 3 on each face randomCode = GafferOSL.OSLCode() randomCode["out"].addChild( Gaffer.IntPlug("randomId", direction=Gaffer.Plug.Direction.Out)) randomCode["code"].setValue( 'randomId = int(cellnoise( P * 100 ) * 4);') outInt = GafferOSL.OSLShader() outInt.loadShader("ObjectProcessing/OutInt") outInt["parameters"]["name"].setValue('randomId') outInt["parameters"]["value"].setInput(randomCode["out"]["randomId"]) outObject = GafferOSL.OSLShader() outObject.loadShader("ObjectProcessing/OutObject") outObject["parameters"]["in0"].setInput( outInt["out"]["primitiveVariable"]) oSLObject = GafferOSL.OSLObject() oSLObject["in"].setInput(shaderAssignment["out"]) oSLObject["filter"].setInput(allFilter["out"]) oSLObject["shader"].setInput(outObject["out"]) oSLObject["interpolation"].setValue(2) # Create 4 meshes by picking each of the 4 ids deleteContextVariables = Gaffer.DeleteContextVariables() deleteContextVariables.setup(GafferScene.ScenePlug()) deleteContextVariables["variables"].setValue('collect:rootName') deleteContextVariables["in"].setInput(oSLObject["out"]) pickCode = GafferOSL.OSLCode() pickCode["parameters"].addChild(Gaffer.IntPlug("targetId")) pickCode["out"].addChild( Gaffer.IntPlug("cull", direction=Gaffer.Plug.Direction.Out)) pickCode["code"].setValue( 'int randomId; getattribute( "randomId", randomId ); cull = randomId != targetId;' ) expression = Gaffer.Expression() pickCode.addChild(expression) expression.setExpression( 'parent.parameters.targetId = stoi( context( "collect:rootName", "0" ) );', "OSL") outInt1 = GafferOSL.OSLShader() outInt1.loadShader("ObjectProcessing/OutInt") outInt1["parameters"]["name"].setValue('deleteFaces') outInt1["parameters"]["value"].setInput(pickCode["out"]["cull"]) outObject1 = GafferOSL.OSLShader() outObject1.loadShader("ObjectProcessing/OutObject") outObject1["parameters"]["in0"].setInput( outInt1["out"]["primitiveVariable"]) oSLObject1 = GafferOSL.OSLObject() oSLObject1["in"].setInput(deleteContextVariables["out"]) oSLObject1["filter"].setInput(allFilter["out"]) oSLObject1["shader"].setInput(outObject1["out"]) oSLObject1["interpolation"].setValue(2) deleteFaces = GafferScene.DeleteFaces() deleteFaces["in"].setInput(oSLObject1["out"]) deleteFaces["filter"].setInput(allFilter["out"]) collectScenes = GafferScene.CollectScenes() collectScenes["in"].setInput(deleteFaces["out"]) collectScenes["rootNames"].setValue( IECore.StringVectorData(['0', '1', '2', '3'])) collectScenes["sourceRoot"].setValue('/plane') # First variant: bake everything, covering the whole 1001 UDIM customAttributes1 = GafferScene.CustomAttributes() customAttributes1["attributes"].addMember( 'bake:fileName', IECore.StringData( '${bakeDirectory}/complete/<AOV>/<AOV>.<UDIM>.exr')) customAttributes1["in"].setInput(collectScenes["out"]) # Second vaiant: bake just 2 of the 4 meshes, leaving lots of holes that will need filling pruneFilter = GafferScene.PathFilter() pruneFilter["paths"].setValue(IECore.StringVectorData(['/2', '/3'])) prune = GafferScene.Prune() prune["in"].setInput(collectScenes["out"]) prune["filter"].setInput(pruneFilter["out"]) customAttributes2 = GafferScene.CustomAttributes() customAttributes2["attributes"].addMember( 'bake:fileName', IECore.StringData( '${bakeDirectory}/incomplete/<AOV>/<AOV>.<UDIM>.exr')) customAttributes2["in"].setInput(prune["out"]) # Third variant: bake everything, but with one mesh at a higher resolution customAttributes3 = GafferScene.CustomAttributes() customAttributes3["attributes"].addMember( 'bake:fileName', IECore.StringData( '${bakeDirectory}/mismatch/<AOV>/<AOV>.<UDIM>.exr')) customAttributes3["in"].setInput(collectScenes["out"]) pathFilter2 = GafferScene.PathFilter() pathFilter2["paths"].setValue(IECore.StringVectorData(['/2'])) customAttributes = GafferScene.CustomAttributes() customAttributes["attributes"].addMember('bake:resolution', IECore.IntData(200)) customAttributes["filter"].setInput(pathFilter2["out"]) customAttributes["in"].setInput(customAttributes3["out"]) # Merge the 3 variants mergeGroup = GafferScene.Group() mergeGroup["in"][-1].setInput(customAttributes["out"]) mergeGroup["in"][-1].setInput(customAttributes1["out"]) mergeGroup["in"][-1].setInput(customAttributes2["out"]) arnoldTextureBake = GafferArnold.ArnoldTextureBake() arnoldTextureBake["in"].setInput(mergeGroup["out"]) arnoldTextureBake["filter"].setInput(allFilter["out"]) arnoldTextureBake["bakeDirectory"].setValue(self.temporaryDirectory() + '/bakeMerge/') arnoldTextureBake["defaultResolution"].setValue(128) # We want to check the intermediate results arnoldTextureBake["cleanupIntermediateFiles"].setValue(False) # Dispatch the bake script = Gaffer.ScriptNode() script.addChild(arnoldTextureBake) dispatcher = GafferDispatch.LocalDispatcher() dispatcher["jobsDirectory"].setValue(self.temporaryDirectory()) dispatcher.dispatch([arnoldTextureBake]) # Check results imageReader = GafferImage.ImageReader() outLayer = GafferOSL.OSLShader() outLayer.loadShader("ImageProcessing/OutLayer") outLayer["parameters"]["layerColor"].setInput( uvGradientCode["out"]["out"]) outImage = GafferOSL.OSLShader() outImage.loadShader("ImageProcessing/OutImage") outImage["parameters"]["in0"].setInput(outLayer["out"]["layer"]) oSLImage = GafferOSL.OSLImage() oSLImage["in"].setInput(imageReader["out"]) oSLImage["shader"].setInput(outImage["out"]) merge3 = GafferImage.Merge() merge3["in"]["in0"].setInput(oSLImage["out"]) merge3["in"]["in1"].setInput(imageReader["out"]) merge3["operation"].setValue(10) edgeDetect = self.SimpleEdgeDetect() edgeDetect["in"].setInput(imageReader["out"]) edgeStats = GafferImage.ImageStats() edgeStats["in"].setInput(edgeDetect["out"]) refDiffStats = GafferImage.ImageStats() refDiffStats["in"].setInput(merge3["out"]) oneLayerReader = GafferImage.ImageReader() grade = GafferImage.Grade() grade["in"].setInput(oneLayerReader["out"]) grade["channels"].setValue('[A]') grade["blackPoint"].setValue(imath.Color4f(0, 0, 0, 0.999899983)) copyChannels = GafferImage.CopyChannels() copyChannels["in"]["in0"].setInput(merge3["out"]) copyChannels["in"]["in1"].setInput(grade["out"]) copyChannels["channels"].setValue('[A]') premultiply = GafferImage.Premultiply() premultiply["in"].setInput(copyChannels["out"]) refDiffCoveredStats = GafferImage.ImageStats() refDiffCoveredStats["in"].setInput(premultiply["out"]) # We are testing 3 different cases: # complete : Should be an exact match. # incomplete : Expect some mild variance of slopes and some error, because we have to # reconstruct a lot of missing data. # mismatch : We should get a larger image, sized to the highest override on any mesh. # Match won't be as perfect, because we're combining source images at # different resolutions for name, expectedSize, maxEdge, maxRefDiff, maxMaskedDiff in [ ("complete", 128, 0.01, 0.000001, 0.000001), ("incomplete", 128, 0.05, 0.15, 0.000001), ("mismatch", 200, 0.01, 0.01, 0.01) ]: imageReader["fileName"].setValue(self.temporaryDirectory() + "/bakeMerge/" + name + "/beauty/beauty.1001.tx") oneLayerReader["fileName"].setValue(self.temporaryDirectory() + "/bakeMerge/" + name + "/beauty/beauty.1001.exr") self.assertEqual(imageReader["out"]["format"].getValue().width(), expectedSize) self.assertEqual(imageReader["out"]["format"].getValue().height(), expectedSize) edgeStats["area"].setValue( imath.Box2i(imath.V2i(1), imath.V2i(expectedSize - 1))) refDiffStats["area"].setValue( imath.Box2i(imath.V2i(1), imath.V2i(expectedSize - 1))) refDiffCoveredStats["area"].setValue( imath.Box2i(imath.V2i(0), imath.V2i(expectedSize))) # Blue channel is constant, so everything should line up perfectly self.assertEqual(0, edgeStats["max"].getValue()[2]) self.assertEqual(0, refDiffStats["max"].getValue()[2]) self.assertEqual(0, refDiffCoveredStats["max"].getValue()[2]) for i in range(2): # Make sure we've got actual data, by checking that we have some error ( we're not expecting # to perfectly reconstruct the gradient when the input is incomplete ) self.assertGreater(edgeStats["max"].getValue()[i], 0.005) if name == "incomplete": self.assertGreater(edgeStats["max"].getValue()[i], 0.03) self.assertGreater(refDiffStats["max"].getValue()[i], 0.06) self.assertLess(edgeStats["max"].getValue()[i], maxEdge) self.assertLess(refDiffStats["max"].getValue()[i], maxRefDiff) self.assertLess(refDiffCoveredStats["max"].getValue()[i], maxMaskedDiff)