set cut_paste_input [stack 0]
version 12.2 v5
push $cut_paste_input
Group {
 name BalanceGrade1
 tile_color 0xff
 label "\[value sequence]_\[value shot]"
 selected true
 xpos 1986
 ypos 327
 addUserKnob {20 BalanceGrade}
 addUserKnob {26 ColorMatrix_label l "@b;ColorMatrix" T " "}
 addUserKnob {41 matrix T ColorMatrix.matrix}
 addUserKnob {22 reset_mtx l Reset T "nuke.thisNode()\['matrix'].setValue(\[1,0,0,0,1,0,0,0,1])" +STARTLINE}
 addUserKnob {26 ""}
 addUserKnob {26 match_label l "@b;Match" T ""}
 addUserKnob {18 matchsrc l "src color"}
 matchsrc 0.18
 addUserKnob {6 matchsrc_panelDropped l "panel dropped state" -STARTLINE +HIDDEN}
 addUserKnob {18 matchdst l "dst color"}
 matchdst 0.18
 addUserKnob {6 matchdst_panelDropped l "panel dropped state" -STARTLINE +HIDDEN}
 addUserKnob {18 blackpoint t "this value will be subtracted from the offset"}
 blackpoint {0 0 0}
 addUserKnob {6 blackpoint_panelDropped l "panel dropped state" -STARTLINE +HIDDEN}
 addUserKnob {22 set_blackpoint l "Set Blackpoint" t "Set blackpoint based on selected region in the viewer. If preserve luminance is checked, the rgb will be balanced but the overall luminance will not be changed." T "node = nuke.thisNode()\nblackpoint_preserve_luminance = node\['blackpoint_preserve_luminance'].getValue()\nnuke.root().begin()\n\n# Get viewer and connected node to calculate format resolution\nviewer = nuke.activeViewer().node()\nif viewer.input(0):\n    viewed_node = viewer.input(0)\n    if not nuke.selectedNodes():\n        viewed_node.setSelected(1)\nelse:\n    viewed_node = nuke.activeViewer().node()\n\n# Get selected sample area\nbboxinfo = nuke.activeViewer().node()\['colour_sample_bbox'].value()\naspect = float(viewed_node.width() * viewed_node.pixelAspect()) / float(viewed_node.height())\ncornerA = \[(bboxinfo\[0]*0.5+0.5) * viewed_node.width(), (((bboxinfo\[1] * 0.5) + (0.5/aspect)) * aspect) * viewed_node.height()]\ncornerB = \[(bboxinfo\[2]*0.5+0.5) * viewed_node.width(), (((bboxinfo\[3] * 0.5) + (0.5/aspect)) * aspect) * viewed_node.height()]\narea = \[cornerB\[0] - cornerA\[0], cornerB\[1] - cornerA\[1]]\ncenter = \[cornerA\[0] + (area\[0]/2), cornerA\[1] + (area\[1] / 2)]\n\n# Reset blackpoint and add knob\nnode\['blackpoint'].setValue(\[0, 0, 0])\nadd_value = node\['add'].getValue()\nnode\['add'].setValue(\[0, 0, 0])\n\n# Sample input colors within box\ncolor_sample = \[node.sample('rgba.red', center\[0], center\[1], area\[0], area\[1]), node.sample('rgba.green', center\[0], center\[1], area\[0], area\[1]), node.sample('rgba.blue', center\[0], center\[1], area\[0], area\[1])]\n\nif blackpoint_preserve_luminance:\n    # calculate average luminance with rec709 weighting\n    average_luminance = color_sample\[0]*0.2126 + color_sample\[1]*0.7152 + color_sample\[2]*0.0722\n    color_sample = \[v - average_luminance for v in color_sample]\n\n# Set blackpoint to sampled value\nnode\['blackpoint'].setValue(color_sample)\nnode\['add'].setValue(add_value)\n" +STARTLINE}
 addUserKnob {6 blackpoint_preserve_luminance l "preserve luminance" t "Try not to shift luminance of the blackpoint when sampling, only shift the color to be neutral." -STARTLINE}
 blackpoint_preserve_luminance true
 addUserKnob {22 reset_match l Reset T "n = nuke.thisNode()\nn\['blackpoint'].setValue(\[0, 0, 0])\nn\['add'].setValue(\[0, 0, 0])\nn\['matchsrc'].setValue(0.18)\nn\['matchdst'].setValue(0.18)" +STARTLINE}
 addUserKnob {26 grade_label l "@b; Grade" T " "}
 addUserKnob {7 exposure t "Adjust exposure in stops" R -4 4}
 addUserKnob {6 exposure_panelDropped l "panel dropped state" -STARTLINE +HIDDEN}
 addUserKnob {18 multiply R 0 4}
 multiply {1 1 1}
 addUserKnob {6 multiply_panelDropped l "panel dropped state" -STARTLINE +HIDDEN}
 addUserKnob {18 add R -0.25 0.25}
 add {0 0 0}
 addUserKnob {6 add_panelDropped l "panel dropped state" -STARTLINE +HIDDEN}
 addUserKnob {22 reset_grade l Reset T "n = nuke.thisNode()\nn\['exposure'].setValue(0)\nn\['multiply'].setValue(\[1, 1, 1])\nn\['add'].setValue(\[0, 0, 0])" +STARTLINE}
 addUserKnob {26 ""}
 addUserKnob {6 invert t "Invert the color transform." +STARTLINE}
 addUserKnob {41 export_cc l "Export CC" T OCIOCDLTransform.export_cc}
 addUserKnob {1 sequence}
 sequence "\[value sceneCtrl.sequence]"
 addUserKnob {1 shot -STARTLINE}
 shot "\[value sceneCtrl.shot]"
 addUserKnob {2 spimtx_path l "spimtx path"}
 spimtx_path "\$env(PROJECT_ROOT_3D)/000_env/ocio/aces_1.2/luts/\$env(PROJECT)_\[value sequence]_\[value shot]_neutral.spimtx"
 addUserKnob {22 export_spimtx l "Export spimtx" t "Export spimtx format describing the balancegrade.\n\nSupports saturation, primaries multiply, offset." T "from __future__ import print_function\nfrom __future__ import with_statement\nimport nuke\n\ndef mtx_mult(a, b):\n    # multiply two 3x3 matrices and return the result\n    a = \[a\[0:3], a\[3:6], a\[6:9]]\n    b = \[b\[0:3], b\[3:6], b\[6:9]]\n    c = \[\[sum(a * b for a, b in zip(a_row, b_col)) for b_col in zip(*b)] for a_row in a]\n    return c\[0] + c\[1] + c\[2]\n\ndef export_spimtx(output_path=None):\n    # export an spimtx file given the color transformations specified on the balancegrade node.\n    node = nuke.thisNode()\n    nuke.root().begin()\n    spimtx_calibration_only = node\['spimtx_calibration_only'].getValue()\n\n    if not output_path:\n        output_path = nuke.getFilename('output_path')\n    if not output_path:\n        print('Error: no output path specified. Exiting...')\n        return\n\n    with node:\n        cdltransform = nuke.toNode('OCIOCDLTransform')\n    \n    mtx = node\['matrix'].getValue()\n\n    if spimtx_calibration_only:\n        dst_mtx = mtx\n        offset = \[0, 0, 0]\n        slope = \[1, 1, 1]\n    else:\n        offset = cdltransform\['offset'].getValue()\n        slope = cdltransform\['slope'].getValue()\n        mult_mtx = \[slope\[0], 0, 0, 0, slope\[1], 0, 0, 0, slope\[2]]\n        dst_mtx = mtx_mult(mult_mtx, mtx)\n\n    output_spimtx_string = '\{0\} \{1\} \{2\} \{3\} \{4\} \{5\} \{6\} \{7\} \{8\} \{9\} \{10\} \{11\}'.format(\n        dst_mtx\[0],\n        dst_mtx\[1],\n        dst_mtx\[2],\n        int(round(offset\[0] * 65535)),\n        dst_mtx\[3],\n        dst_mtx\[4],\n        dst_mtx\[5],\n        int(round(offset\[1] * 65535)),\n        dst_mtx\[6],\n        dst_mtx\[7],\n        dst_mtx\[8],\n        int(round(offset\[2] * 65535))\n        )\n\n    # Create spimtx file\n    spimtx_file = open(output_path, 'w+')\n    spimtx_file.write(output_spimtx_string)\n    spimtx_file.close()\n    print('Balance Grade: Done writing spimtx file.')\n\n\nif __name__=='__main__':\n    node = nuke.thisNode()\n    outputpath = node\['spimtx_path'].evaluate()\n    if outputpath != '':\n        export_spimtx(outputpath)\n    else:\n        export_spimtx()" +STARTLINE}
 addUserKnob {6 spimtx_calibration_only l "calibration only" t "only export the colormatrix calibration to the spimtx file. \n\notherwise export the entire balancegrade to the spimtx file." -STARTLINE}
}
 Input {
  inputs 0
  name Input
  xpos -370
  ypos -562
 }
 Dot {
  name Dot1
  label " "
  note_font "Helvetica Bold"
  note_font_size 24
  note_font_color 0xa5a5a501
  xpos -336
  ypos -486
 }
set N787cd800 [stack 0]
 OCIOCDLTransform {
  slope {{parent.OCIOCDLTransform.slope} {parent.OCIOCDLTransform.slope} {parent.OCIOCDLTransform.slope}}
  offset {{parent.OCIOCDLTransform.offset} {parent.OCIOCDLTransform.offset} {parent.OCIOCDLTransform.offset}}
  direction inverse
  working_space scene_linear
  name OCIOCDLTransform_inverse
  xpos -260
  ypos -442
 }
 ColorMatrix {
  matrix {
      {{parent.ColorMatrix.matrix} {parent.ColorMatrix.matrix} {parent.ColorMatrix.matrix}}
      {{parent.ColorMatrix.matrix} {parent.ColorMatrix.matrix} {parent.ColorMatrix.matrix}}
      {{parent.ColorMatrix.matrix} {parent.ColorMatrix.matrix} {parent.ColorMatrix.matrix}}
    }
  invert true
  name ColorMatrix_invert
  xpos -260
  ypos -370
 }
push $N787cd800
 ColorMatrix {
  matrix {
      {1 0 0}
      {0 1 0}
      {0 0 1}
    }
  name ColorMatrix
  xpos -370
  ypos -442
 }
 OCIOCDLTransform {
  slope {{"matchdst/matchsrc*pow(2, exposure)*multiply"} {"matchdst/matchsrc*pow(2, exposure)*multiply"} {"matchdst/matchsrc*pow(2, exposure)*multiply"}}
  offset {{"parent.add - parent.blackpoint"} {"parent.add - parent.blackpoint"} {"parent.add - parent.blackpoint"}}
  working_space scene_linear
  name OCIOCDLTransform
  xpos -370
  ypos -370
 }
 Switch {
  inputs 2
  which {{parent.invert}}
  name Switch_inverse
  xpos -370
  ypos -274
 }
 Output {
  name Output
  xpos -370
  ypos -202
 }
end_group
# Creation Time=Thu Jul  8 16:36:34 2021
# Creator=Martin
