/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * media_device_link_test.cpp - Tests link handling on VIMC media device
 */

#include <iostream>

#include "media_device_test.h"

using namespace libcamera;
using namespace std;

/*
 * This link test requires a vimc device in order to exercise the
 * MediaObject link handling API on a graph with a predetermined topology.
 *
 * vimc is a Media Controller kernel driver that creates virtual devices.
 * From a userspace point of view they appear as normal media controller
 * devices, but are not backed by any particular piece of hardware. They can
 * thus be used for testing purpose without depending on a particular hardware
 * platform.
 *
 * If no vimc device is found (most likely because the vimc driver is not
 * loaded) the test is skipped.
 */

class MediaDeviceLinkTest : public MediaDeviceTest
{
	int init()
	{
		int ret = MediaDeviceTest::init();
		if (ret)
			return ret;

		if (!media_->acquire()) {
			cerr << "Unable to acquire media device "
			     << media_->deviceNode() << endl;
			return TestFail;
		}

		return TestPass;
	}

	int run()
	{
		/*
		 * First of all disable all links in the media graph to
		 * ensure we start from a known state.
		 */
		if (media_->disableLinks()) {
			cerr << "Failed to disable all links in the media graph";
			return TestFail;
		}

		/*
		 * Test if link can be consistently retrieved through the
		 * different functions the media device offers.
		 */
		string linkName("'Debayer A':[1] -> 'Scaler':[0]'");
		MediaLink *link = media_->link("Debayer A", 1, "Scaler", 0);
		if (!link) {
			cerr << "Unable to find link: " << linkName
			     << " using lookup by name" << endl;
			return TestFail;
		}

		MediaEntity *source = media_->getEntityByName("Debayer A");
		if (!source) {
			cerr << "Unable to find entity: 'Debayer A'" << endl;
			return TestFail;
		}

		MediaEntity *sink = media_->getEntityByName("Scaler");
		if (!sink) {
			cerr << "Unable to find entity: 'Scaler'" << endl;
			return TestFail;
		}

		MediaLink *link2 = media_->link(source, 1, sink, 0);
		if (!link2) {
			cerr << "Unable to find link: " << linkName
			     << " using lookup by entity" << endl;
			return TestFail;
		}

		if (link != link2) {
			cerr << "Link lookup by name and by entity don't match"
			     << endl;
			return TestFail;
		}

		link2 = media_->link(source->getPadByIndex(1),
				   sink->getPadByIndex(0));
		if (!link2) {
			cerr << "Unable to find link: " << linkName
			     << " using lookup by pad" << endl;
			return TestFail;
		}

		if (link != link2) {
			cerr << "Link lookup by name and by pad don't match"
			     << endl;
			return TestFail;
		}

		/* After reset the link shall not be enabled. */
		if (link->flags() & MEDIA_LNK_FL_ENABLED) {
			cerr << "Link " << linkName
			     << " should not be enabled after a device reset"
			     << endl;
			return TestFail;
		}

		/* Enable the link and test if enabling was successful. */
		if (link->setEnabled(true)) {
			cerr << "Failed to enable link: " << linkName
			     << endl;
			return TestFail;
		}

		if (!(link->flags() & MEDIA_LNK_FL_ENABLED)) {
			cerr << "Link " << linkName
			     << " was enabled but it is reported as disabled"
			     << endl;
			return TestFail;
		}

		/* Disable the link and test if disabling was successful. */
		if (link->setEnabled(false)) {
			cerr << "Failed to disable link: " << linkName
			     << endl;
			return TestFail;
		}

		if (link->flags() & MEDIA_LNK_FL_ENABLED) {
			cerr << "Link " << linkName
			     << " was disabled but it is reported as enabled"
			     << endl;
			return TestFail;
		}

		/* Try to get a non existing link. */
		linkName = "'Sensor A':[1] -> 'Scaler':[0]";
		link = media_->link("Sensor A", 1, "Scaler", 0);
		if (link) {
			cerr << "Link lookup for " << linkName
			     << " succeeded but link does not exist"
			     << endl;
			return TestFail;
		}

		/* Now get an immutable link and try to disable it. */
		linkName = "'Sensor A':[0] -> 'Raw Capture 0':[0]";
		link = media_->link("Sensor A", 0, "Raw Capture 0", 0);
		if (!link) {
			cerr << "Unable to find link: " << linkName
			     << " using lookup by name" << endl;
			return TestFail;
		}

		if (!(link->flags() & MEDIA_LNK_FL_IMMUTABLE)) {
			cerr << "Link " << linkName
			     << " should be 'IMMUTABLE'" << endl;
			return TestFail;
		}

		/* Disabling an immutable link shall fail. */
		if (!link->setEnabled(false)) {
			cerr << "Disabling immutable link " << linkName
			     << " succeeded but should have failed" << endl;
			return TestFail;
		}

		/*
		 * Enable an disabled link, and verify it is disabled again
		 * after disabling all links in the media graph.
		 */
		linkName = "'Debayer B':[1] -> 'Scaler':[0]'";
		link = media_->link("Debayer B", 1, "Scaler", 0);
		if (!link) {
			cerr << "Unable to find link: " << linkName
			     << " using lookup by name" << endl;
			return TestFail;
		}

		if (link->setEnabled(true)) {
			cerr << "Failed to enable link: " << linkName
			     << endl;
			return TestFail;
		}

		if (!(link->flags() & MEDIA_LNK_FL_ENABLED)) {
			cerr << "Link " << linkName
			     << " was enabled but it is reported as disabled"
			     << endl;
			return TestFail;
		}

		if (media_->disableLinks()) {
			cerr << "Failed to disable all links in the media graph";
			return TestFail;
		}

		if (link->flags() & MEDIA_LNK_FL_ENABLED) {
			cerr << "All links in the media graph have been disabled"
			     << " but link " << linkName
			     << " is still reported as enabled"  << endl;
			return TestFail;
		}

		return 0;
	}

	void cleanup()
	{
		media_->release();
	}
};

TEST_REGISTER(MediaDeviceLinkTest)
'n71' href='#n71'>71</a>
<a id='n72' href='#n72'>72</a>
<a id='n73' href='#n73'>73</a>
<a id='n74' href='#n74'>74</a>
<a id='n75' href='#n75'>75</a>
<a id='n76' href='#n76'>76</a>
<a id='n77' href='#n77'>77</a>
<a id='n78' href='#n78'>78</a>
<a id='n79' href='#n79'>79</a>
<a id='n80' href='#n80'>80</a>
<a id='n81' href='#n81'>81</a>
<a id='n82' href='#n82'>82</a>
<a id='n83' href='#n83'>83</a>
<a id='n84' href='#n84'>84</a>
<a id='n85' href='#n85'>85</a>
<a id='n86' href='#n86'>86</a>
<a id='n87' href='#n87'>87</a>
<a id='n88' href='#n88'>88</a>
<a id='n89' href='#n89'>89</a>
<a id='n90' href='#n90'>90</a>
<a id='n91' href='#n91'>91</a>
<a id='n92' href='#n92'>92</a>
<a id='n93' href='#n93'>93</a>
<a id='n94' href='#n94'>94</a>
<a id='n95' href='#n95'>95</a>
<a id='n96' href='#n96'>96</a>
<a id='n97' href='#n97'>97</a>
<a id='n98' href='#n98'>98</a>
<a id='n99' href='#n99'>99</a>
<a id='n100' href='#n100'>100</a>
<a id='n101' href='#n101'>101</a>
<a id='n102' href='#n102'>102</a>
<a id='n103' href='#n103'>103</a>
<a id='n104' href='#n104'>104</a>
<a id='n105' href='#n105'>105</a>
<a id='n106' href='#n106'>106</a>
<a id='n107' href='#n107'>107</a>
<a id='n108' href='#n108'>108</a>
<a id='n109' href='#n109'>109</a>
<a id='n110' href='#n110'>110</a>
<a id='n111' href='#n111'>111</a>
<a id='n112' href='#n112'>112</a>
<a id='n113' href='#n113'>113</a>
<a id='n114' href='#n114'>114</a>
<a id='n115' href='#n115'>115</a>
<a id='n116' href='#n116'>116</a>
<a id='n117' href='#n117'>117</a>
<a id='n118' href='#n118'>118</a>
<a id='n119' href='#n119'>119</a>
<a id='n120' href='#n120'>120</a>
<a id='n121' href='#n121'>121</a>
<a id='n122' href='#n122'>122</a>
<a id='n123' href='#n123'>123</a>
<a id='n124' href='#n124'>124</a>
<a id='n125' href='#n125'>125</a>
<a id='n126' href='#n126'>126</a>
<a id='n127' href='#n127'>127</a>
<a id='n128' href='#n128'>128</a>
<a id='n129' href='#n129'>129</a>
<a id='n130' href='#n130'>130</a>
<a id='n131' href='#n131'>131</a>
<a id='n132' href='#n132'>132</a>
<a id='n133' href='#n133'>133</a>
<a id='n134' href='#n134'>134</a>
<a id='n135' href='#n135'>135</a>
<a id='n136' href='#n136'>136</a>
<a id='n137' href='#n137'>137</a>
<a id='n138' href='#n138'>138</a>
<a id='n139' href='#n139'>139</a>
<a id='n140' href='#n140'>140</a>
<a id='n141' href='#n141'>141</a>
<a id='n142' href='#n142'>142</a>
<a id='n143' href='#n143'>143</a>
<a id='n144' href='#n144'>144</a>
<a id='n145' href='#n145'>145</a>
<a id='n146' href='#n146'>146</a>
<a id='n147' href='#n147'>147</a>
<a id='n148' href='#n148'>148</a>
<a id='n149' href='#n149'>149</a>
<a id='n150' href='#n150'>150</a>
<a id='n151' href='#n151'>151</a>
<a id='n152' href='#n152'>152</a>
<a id='n153' href='#n153'>153</a>
<a id='n154' href='#n154'>154</a>
<a id='n155' href='#n155'>155</a>
<a id='n156' href='#n156'>156</a>
<a id='n157' href='#n157'>157</a>
<a id='n158' href='#n158'>158</a>
<a id='n159' href='#n159'>159</a>
<a id='n160' href='#n160'>160</a>
<a id='n161' href='#n161'>161</a>
<a id='n162' href='#n162'>162</a>
<a id='n163' href='#n163'>163</a>
<a id='n164' href='#n164'>164</a>
<a id='n165' href='#n165'>165</a>
<a id='n166' href='#n166'>166</a>
<a id='n167' href='#n167'>167</a>
<a id='n168' href='#n168'>168</a>
<a id='n169' href='#n169'>169</a>
<a id='n170' href='#n170'>170</a>
<a id='n171' href='#n171'>171</a>
<a id='n172' href='#n172'>172</a>
<a id='n173' href='#n173'>173</a>
<a id='n174' href='#n174'>174</a>
<a id='n175' href='#n175'>175</a>
<a id='n176' href='#n176'>176</a>
<a id='n177' href='#n177'>177</a>
<a id='n178' href='#n178'>178</a>
<a id='n179' href='#n179'>179</a>
<a id='n180' href='#n180'>180</a>
<a id='n181' href='#n181'>181</a>
<a id='n182' href='#n182'>182</a>
<a id='n183' href='#n183'>183</a>
<a id='n184' href='#n184'>184</a>
<a id='n185' href='#n185'>185</a>
<a id='n186' href='#n186'>186</a>
<a id='n187' href='#n187'>187</a>
<a id='n188' href='#n188'>188</a>
<a id='n189' href='#n189'>189</a>
<a id='n190' href='#n190'>190</a>
<a id='n191' href='#n191'>191</a>
<a id='n192' href='#n192'>192</a>
<a id='n193' href='#n193'>193</a>
<a id='n194' href='#n194'>194</a>
<a id='n195' href='#n195'>195</a>
<a id='n196' href='#n196'>196</a>
<a id='n197' href='#n197'>197</a>
<a id='n198' href='#n198'>198</a>
<a id='n199' href='#n199'>199</a>
<a id='n200' href='#n200'>200</a>
<a id='n201' href='#n201'>201</a>
<a id='n202' href='#n202'>202</a>
<a id='n203' href='#n203'>203</a>
<a id='n204' href='#n204'>204</a>
<a id='n205' href='#n205'>205</a>
<a id='n206' href='#n206'>206</a>
<a id='n207' href='#n207'>207</a>
<a id='n208' href='#n208'>208</a>
<a id='n209' href='#n209'>209</a>
<a id='n210' href='#n210'>210</a>
<a id='n211' href='#n211'>211</a>
<a id='n212' href='#n212'>212</a>
<a id='n213' href='#n213'>213</a>
<a id='n214' href='#n214'>214</a>
<a id='n215' href='#n215'>215</a>
<a id='n216' href='#n216'>216</a>
<a id='n217' href='#n217'>217</a>
<a id='n218' href='#n218'>218</a>
<a id='n219' href='#n219'>219</a>
<a id='n220' href='#n220'>220</a>
<a id='n221' href='#n221'>221</a>
<a id='n222' href='#n222'>222</a>
<a id='n223' href='#n223'>223</a>
<a id='n224' href='#n224'>224</a>
<a id='n225' href='#n225'>225</a>
<a id='n226' href='#n226'>226</a>
<a id='n227' href='#n227'>227</a>
<a id='n228' href='#n228'>228</a>
<a id='n229' href='#n229'>229</a>
<a id='n230' href='#n230'>230</a>
<a id='n231' href='#n231'>231</a>
<a id='n232' href='#n232'>232</a>
<a id='n233' href='#n233'>233</a>
<a id='n234' href='#n234'>234</a>
<a id='n235' href='#n235'>235</a>
<a id='n236' href='#n236'>236</a>
<a id='n237' href='#n237'>237</a>
<a id='n238' href='#n238'>238</a>
<a id='n239' href='#n239'>239</a>
<a id='n240' href='#n240'>240</a>
<a id='n241' href='#n241'>241</a>
<a id='n242' href='#n242'>242</a>
<a id='n243' href='#n243'>243</a>
<a id='n244' href='#n244'>244</a>
<a id='n245' href='#n245'>245</a>
<a id='n246' href='#n246'>246</a>
<a id='n247' href='#n247'>247</a>
<a id='n248' href='#n248'>248</a>
<a id='n249' href='#n249'>249</a>
<a id='n250' href='#n250'>250</a>
<a id='n251' href='#n251'>251</a>
<a id='n252' href='#n252'>252</a>
<a id='n253' href='#n253'>253</a>
<a id='n254' href='#n254'>254</a>
<a id='n255' href='#n255'>255</a>
<a id='n256' href='#n256'>256</a>
<a id='n257' href='#n257'>257</a>
<a id='n258' href='#n258'>258</a>
<a id='n259' href='#n259'>259</a>
<a id='n260' href='#n260'>260</a>
<a id='n261' href='#n261'>261</a>
<a id='n262' href='#n262'>262</a>
<a id='n263' href='#n263'>263</a>
<a id='n264' href='#n264'>264</a>
<a id='n265' href='#n265'>265</a>
<a id='n266' href='#n266'>266</a>
<a id='n267' href='#n267'>267</a>
<a id='n268' href='#n268'>268</a>
<a id='n269' href='#n269'>269</a>
<a id='n270' href='#n270'>270</a>
<a id='n271' href='#n271'>271</a>
<a id='n272' href='#n272'>272</a>
<a id='n273' href='#n273'>273</a>
<a id='n274' href='#n274'>274</a>
<a id='n275' href='#n275'>275</a>
<a id='n276' href='#n276'>276</a>
<a id='n277' href='#n277'>277</a>
<a id='n278' href='#n278'>278</a>
<a id='n279' href='#n279'>279</a>
<a id='n280' href='#n280'>280</a>
<a id='n281' href='#n281'>281</a>
<a id='n282' href='#n282'>282</a>
<a id='n283' href='#n283'>283</a>
<a id='n284' href='#n284'>284</a>
<a id='n285' href='#n285'>285</a>
<a id='n286' href='#n286'>286</a>
<a id='n287' href='#n287'>287</a>
<a id='n288' href='#n288'>288</a>
<a id='n289' href='#n289'>289</a>
<a id='n290' href='#n290'>290</a>
<a id='n291' href='#n291'>291</a>
<a id='n292' href='#n292'>292</a>
<a id='n293' href='#n293'>293</a>
<a id='n294' href='#n294'>294</a>
<a id='n295' href='#n295'>295</a>
<a id='n296' href='#n296'>296</a>
<a id='n297' href='#n297'>297</a>
<a id='n298' href='#n298'>298</a>
<a id='n299' href='#n299'>299</a>
</pre></td>
<td class='lines'><pre><code><span class="hl slc"># SPDX-License-Identifier: BSD-2-Clause</span>
<span class="hl slc">#</span>
<span class="hl slc"># Copyright (C) 2019, Raspberry Pi (Trading) Limited</span>
<span class="hl slc">#</span>
<span class="hl slc"># ctt_alsc.py - camera tuning tool for ALSC (auto lens shading correction)</span>

<span class="hl kwa">from</span> ctt_image_load <span class="hl kwa">import</span> <span class="hl opt">*</span>
<span class="hl kwa">import</span> matplotlib<span class="hl opt">.</span>pyplot <span class="hl kwa">as</span> plt
<span class="hl kwa">from</span> matplotlib <span class="hl kwa">import</span> cm
<span class="hl kwa">from</span> mpl_toolkits<span class="hl opt">.</span>mplot3d <span class="hl kwa">import</span> Axes3D


<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">preform alsc calibration on a set of images</span>
<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl kwa">def</span> <span class="hl kwd">alsc_all</span><span class="hl opt">(</span>Cam<span class="hl opt">,</span> do_alsc_colour<span class="hl opt">,</span> plot<span class="hl opt">):</span>
    imgs_alsc <span class="hl opt">=</span> Cam<span class="hl opt">.</span>imgs_alsc
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    create list of colour temperatures and associated calibration tables</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    list_col <span class="hl opt">= []</span>
    list_cr <span class="hl opt">= []</span>
    list_cb <span class="hl opt">= []</span>
    list_cg <span class="hl opt">= []</span>
    <span class="hl kwa">for</span> Img <span class="hl kwa">in</span> imgs_alsc<span class="hl opt">:</span>
        col<span class="hl opt">,</span> cr<span class="hl opt">,</span> cb<span class="hl opt">,</span> cg<span class="hl opt">,</span> size <span class="hl opt">=</span> <span class="hl kwd">alsc</span><span class="hl opt">(</span>Cam<span class="hl opt">,</span> Img<span class="hl opt">,</span> do_alsc_colour<span class="hl opt">,</span> plot<span class="hl opt">)</span>
        list_col<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>col<span class="hl opt">)</span>
        list_cr<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>cr<span class="hl opt">)</span>
        list_cb<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>cb<span class="hl opt">)</span>
        list_cg<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>cg<span class="hl opt">)</span>
        Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">&apos;</span>
    Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Finished processing images&apos;</span>
    w<span class="hl opt">,</span> h<span class="hl opt">,</span> dx<span class="hl opt">,</span> dy <span class="hl opt">=</span> size
    Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Channel dimensions: w = {}  h = {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span><span class="hl kwb">int</span><span class="hl opt">(</span>w<span class="hl opt">),</span> <span class="hl kwb">int</span><span class="hl opt">(</span>h<span class="hl opt">))</span>
    Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">16x12 grid rectangle size: w = {} h = {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>dx<span class="hl opt">,</span> dy<span class="hl opt">)</span>

    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    convert to numpy array for data manipulation</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    list_col <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">array</span><span class="hl opt">(</span>list_col<span class="hl opt">)</span>
    list_cr <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">array</span><span class="hl opt">(</span>list_cr<span class="hl opt">)</span>
    list_cb <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">array</span><span class="hl opt">(</span>list_cb<span class="hl opt">)</span>
    list_cg <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">array</span><span class="hl opt">(</span>list_cg<span class="hl opt">)</span>

    cal_cr_list <span class="hl opt">= []</span>
    cal_cb_list <span class="hl opt">= []</span>

    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    only do colour calculations if required</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    <span class="hl kwa">if</span> do_alsc_colour<span class="hl opt">:</span>
        Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">ALSC colour tables&apos;</span>
        <span class="hl kwa">for</span> ct <span class="hl kwa">in</span> <span class="hl kwb">sorted</span><span class="hl opt">(</span><span class="hl kwb">set</span><span class="hl opt">(</span>list_col<span class="hl opt">)):</span>
            Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Colour temperature: {} K&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>ct<span class="hl opt">)</span>
            <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">            average tables for the same colour temperature</span>
<span class="hl str">            &quot;&quot;&quot;</span>
            indices <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">where</span><span class="hl opt">(</span>list_col <span class="hl opt">==</span> ct<span class="hl opt">)</span>
            ct <span class="hl opt">=</span> <span class="hl kwb">int</span><span class="hl opt">(</span>ct<span class="hl opt">)</span>
            t_r <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">(</span>list_cr<span class="hl opt">[</span>indices<span class="hl opt">],</span> axis<span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">)</span>
            t_b <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">(</span>list_cb<span class="hl opt">[</span>indices<span class="hl opt">],</span> axis<span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">)</span>
            <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">            force numbers to be stored to 3dp.... :(</span>
<span class="hl str">            &quot;&quot;&quot;</span>
            t_r <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">where</span><span class="hl opt">((</span><span class="hl num">100</span><span class="hl opt">*</span>t_r<span class="hl opt">) %</span> <span class="hl num">1</span> <span class="hl opt">&lt;=</span> <span class="hl num">0.05</span><span class="hl opt">,</span> t_r<span class="hl opt">+</span><span class="hl num">0.001</span><span class="hl opt">,</span> t_r<span class="hl opt">)</span>
            t_b <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">where</span><span class="hl opt">((</span><span class="hl num">100</span><span class="hl opt">*</span>t_b<span class="hl opt">) %</span> <span class="hl num">1</span> <span class="hl opt">&lt;=</span> <span class="hl num">0.05</span><span class="hl opt">,</span> t_b<span class="hl opt">+</span><span class="hl num">0.001</span><span class="hl opt">,</span> t_b<span class="hl opt">)</span>
            t_r <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">where</span><span class="hl opt">((</span><span class="hl num">100</span><span class="hl opt">*</span>t_r<span class="hl opt">) %</span> <span class="hl num">1</span> <span class="hl opt">&gt;=</span> <span class="hl num">0.95</span><span class="hl opt">,</span> t_r<span class="hl opt">-</span><span class="hl num">0.001</span><span class="hl opt">,</span> t_r<span class="hl opt">)</span>
            t_b <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">where</span><span class="hl opt">((</span><span class="hl num">100</span><span class="hl opt">*</span>t_b<span class="hl opt">) %</span> <span class="hl num">1</span> <span class="hl opt">&gt;=</span> <span class="hl num">0.95</span><span class="hl opt">,</span> t_b<span class="hl opt">-</span><span class="hl num">0.001</span><span class="hl opt">,</span> t_b<span class="hl opt">)</span>
            t_r <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwb">round</span><span class="hl opt">(</span>t_r<span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">)</span>
            t_b <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwb">round</span><span class="hl opt">(</span>t_b<span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">)</span>
            r_corners <span class="hl opt">= (</span>t_r<span class="hl opt">[</span><span class="hl num">0</span><span class="hl opt">],</span> t_r<span class="hl opt">[</span><span class="hl num">15</span><span class="hl opt">],</span> t_r<span class="hl opt">[-</span><span class="hl num">1</span><span class="hl opt">],</span> t_r<span class="hl opt">[-</span><span class="hl num">16</span><span class="hl opt">])</span>
            b_corners <span class="hl opt">= (</span>t_b<span class="hl opt">[</span><span class="hl num">0</span><span class="hl opt">],</span> t_b<span class="hl opt">[</span><span class="hl num">15</span><span class="hl opt">],</span> t_b<span class="hl opt">[-</span><span class="hl num">1</span><span class="hl opt">],</span> t_b<span class="hl opt">[-</span><span class="hl num">16</span><span class="hl opt">])</span>
            r_cen <span class="hl opt">=</span> t_r<span class="hl opt">[</span><span class="hl num">5</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">7</span><span class="hl opt">]+</span>t_r<span class="hl opt">[</span><span class="hl num">5</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">8</span><span class="hl opt">]+</span>t_r<span class="hl opt">[</span><span class="hl num">6</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">7</span><span class="hl opt">]+</span>t_r<span class="hl opt">[</span><span class="hl num">6</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">8</span><span class="hl opt">]</span>
            r_cen <span class="hl opt">=</span> <span class="hl kwb">round</span><span class="hl opt">(</span>r_cen<span class="hl opt">/</span><span class="hl num">4</span><span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">)</span>
            b_cen <span class="hl opt">=</span> t_b<span class="hl opt">[</span><span class="hl num">5</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">7</span><span class="hl opt">]+</span>t_b<span class="hl opt">[</span><span class="hl num">5</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">8</span><span class="hl opt">]+</span>t_b<span class="hl opt">[</span><span class="hl num">6</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">7</span><span class="hl opt">]+</span>t_b<span class="hl opt">[</span><span class="hl num">6</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">8</span><span class="hl opt">]</span>
            b_cen <span class="hl opt">=</span> <span class="hl kwb">round</span><span class="hl opt">(</span>b_cen<span class="hl opt">/</span><span class="hl num">4</span><span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">)</span>
            Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Red table corners: {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>r_corners<span class="hl opt">)</span>
            Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Red table centre: {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>r_cen<span class="hl opt">)</span>
            Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Blue table corners: {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>b_corners<span class="hl opt">)</span>
            Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Blue table centre: {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>b_cen<span class="hl opt">)</span>
            cr_dict <span class="hl opt">= {</span>
                <span class="hl str">&apos;ct&apos;</span><span class="hl opt">:</span> ct<span class="hl opt">,</span>
                <span class="hl str">&apos;table&apos;</span><span class="hl opt">:</span> <span class="hl kwb">list</span><span class="hl opt">(</span>t_r<span class="hl opt">)</span>
            <span class="hl opt">}</span>
            cb_dict <span class="hl opt">= {</span>
                <span class="hl str">&apos;ct&apos;</span><span class="hl opt">:</span> ct<span class="hl opt">,</span>
                <span class="hl str">&apos;table&apos;</span><span class="hl opt">:</span> <span class="hl kwb">list</span><span class="hl opt">(</span>t_b<span class="hl opt">)</span>
            <span class="hl opt">}</span>
            cal_cr_list<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>cr_dict<span class="hl opt">)</span>
            cal_cb_list<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>cb_dict<span class="hl opt">)</span>
            Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">&apos;</span>
    <span class="hl kwa">else</span><span class="hl opt">:</span>
        cal_cr_list<span class="hl opt">,</span> cal_cb_list <span class="hl opt">=</span> <span class="hl kwa">None</span><span class="hl opt">,</span> <span class="hl kwa">None</span>

    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    average all values for luminance shading and return one table for all temperatures</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    lum_lut <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">(</span>list_cg<span class="hl opt">,</span> axis<span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">)</span>
    lum_lut <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">where</span><span class="hl opt">((</span><span class="hl num">100</span><span class="hl opt">*</span>lum_lut<span class="hl opt">) %</span> <span class="hl num">1</span> <span class="hl opt">&lt;=</span> <span class="hl num">0.05</span><span class="hl opt">,</span> lum_lut<span class="hl opt">+</span><span class="hl num">0.001</span><span class="hl opt">,</span> lum_lut<span class="hl opt">)</span>
    lum_lut <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">where</span><span class="hl opt">((</span><span class="hl num">100</span><span class="hl opt">*</span>lum_lut<span class="hl opt">) %</span> <span class="hl num">1</span> <span class="hl opt">&gt;=</span> <span class="hl num">0.95</span><span class="hl opt">,</span> lum_lut<span class="hl opt">-</span><span class="hl num">0.001</span><span class="hl opt">,</span> lum_lut<span class="hl opt">)</span>
    lum_lut <span class="hl opt">=</span> <span class="hl kwb">list</span><span class="hl opt">(</span>np<span class="hl opt">.</span><span class="hl kwb">round</span><span class="hl opt">(</span>lum_lut<span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">))</span>

    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    calculate average corner for lsc gain calculation further on</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    corners <span class="hl opt">= (</span>lum_lut<span class="hl opt">[</span><span class="hl num">0</span><span class="hl opt">],</span> lum_lut<span class="hl opt">[</span><span class="hl num">15</span><span class="hl opt">],</span> lum_lut<span class="hl opt">[-</span><span class="hl num">1</span><span class="hl opt">],</span> lum_lut<span class="hl opt">[-</span><span class="hl num">16</span><span class="hl opt">])</span>
    Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Luminance table corners: {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>corners<span class="hl opt">)</span>
    l_cen <span class="hl opt">=</span> lum_lut<span class="hl opt">[</span><span class="hl num">5</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">7</span><span class="hl opt">]+</span>lum_lut<span class="hl opt">[</span><span class="hl num">5</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">8</span><span class="hl opt">]+</span>lum_lut<span class="hl opt">[</span><span class="hl num">6</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">7</span><span class="hl opt">]+</span>lum_lut<span class="hl opt">[</span><span class="hl num">6</span><span class="hl opt">*</span><span class="hl num">16</span><span class="hl opt">+</span><span class="hl num">8</span><span class="hl opt">]</span>
    l_cen <span class="hl opt">=</span> <span class="hl kwb">round</span><span class="hl opt">(</span>l_cen<span class="hl opt">/</span><span class="hl num">4</span><span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">)</span>
    Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Luminance table centre: {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>l_cen<span class="hl opt">)</span>
    av_corn <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwb">sum</span><span class="hl opt">(</span>corners<span class="hl opt">)/</span><span class="hl num">4</span>

    <span class="hl kwa">return</span> cal_cr_list<span class="hl opt">,</span> cal_cb_list<span class="hl opt">,</span> lum_lut<span class="hl opt">,</span> av_corn


<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">calculate g/r and g/b for 32x32 points arranged in a grid for a single image</span>
<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl kwa">def</span> <span class="hl kwd">alsc</span><span class="hl opt">(</span>Cam<span class="hl opt">,</span> Img<span class="hl opt">,</span> do_alsc_colour<span class="hl opt">,</span> plot<span class="hl opt">=</span><span class="hl kwa">False</span><span class="hl opt">):</span>
    Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Processing image: &apos;</span> <span class="hl opt">+</span> Img<span class="hl opt">.</span>name
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    get channel in correct order</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    channels <span class="hl opt">= [</span>Img<span class="hl opt">.</span>channels<span class="hl opt">[</span>i<span class="hl opt">]</span> <span class="hl kwa">for</span> i <span class="hl kwa">in</span> Img<span class="hl opt">.</span>order<span class="hl opt">]</span>
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    calculate size of single rectangle.</span>
<span class="hl str">    -(-(w-1)//32) is a ceiling division. w-1 is to deal robustly with the case</span>
<span class="hl str">    where w is a multiple of 32.</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    w<span class="hl opt">,</span> h <span class="hl opt">=</span> Img<span class="hl opt">.</span>w<span class="hl opt">/</span><span class="hl num">2</span><span class="hl opt">,</span> Img<span class="hl opt">.</span>h<span class="hl opt">/</span><span class="hl num">2</span>
    dx<span class="hl opt">,</span> dy <span class="hl opt">=</span> <span class="hl kwb">int</span><span class="hl opt">(-(-(</span>w<span class="hl opt">-</span><span class="hl num">1</span><span class="hl opt">)//</span><span class="hl num">16</span><span class="hl opt">)),</span> <span class="hl kwb">int</span><span class="hl opt">(-(-(</span>h<span class="hl opt">-</span><span class="hl num">1</span><span class="hl opt">)//</span><span class="hl num">12</span><span class="hl opt">))</span>
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    average the green channels into one</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    av_ch_g <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">((</span>channels<span class="hl opt">[</span><span class="hl num">1</span><span class="hl opt">:</span><span class="hl num">2</span><span class="hl opt">]),</span> axis<span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">)</span>
    <span class="hl kwa">if</span> do_alsc_colour<span class="hl opt">:</span>
        <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">        obtain 16x12 grid of intensities for each channel and subtract black level</span>
<span class="hl str">        &quot;&quot;&quot;</span>
        g <span class="hl opt">=</span> <span class="hl kwd">get_16x12_grid</span><span class="hl opt">(</span>av_ch_g<span class="hl opt">,</span> dx<span class="hl opt">,</span> dy<span class="hl opt">) -</span> Img<span class="hl opt">.</span>blacklevel_16
        r <span class="hl opt">=</span> <span class="hl kwd">get_16x12_grid</span><span class="hl opt">(</span>channels<span class="hl opt">[</span><span class="hl num">0</span><span class="hl opt">],</span> dx<span class="hl opt">,</span> dy<span class="hl opt">) -</span> Img<span class="hl opt">.</span>blacklevel_16
        b <span class="hl opt">=</span> <span class="hl kwd">get_16x12_grid</span><span class="hl opt">(</span>channels<span class="hl opt">[</span><span class="hl num">3</span><span class="hl opt">],</span> dx<span class="hl opt">,</span> dy<span class="hl opt">) -</span> Img<span class="hl opt">.</span>blacklevel_16
        <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">        calculate ratios as 32 bit in order to be supported by medianBlur function</span>
<span class="hl str">        &quot;&quot;&quot;</span>
        cr <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">reshape</span><span class="hl opt">(</span>g<span class="hl opt">/</span>r<span class="hl opt">, (</span><span class="hl num">12</span><span class="hl opt">,</span> <span class="hl num">16</span><span class="hl opt">)).</span><span class="hl kwd">astype</span><span class="hl opt">(</span><span class="hl str">&apos;float32&apos;</span><span class="hl opt">)</span>
        cb <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">reshape</span><span class="hl opt">(</span>g<span class="hl opt">/</span>b<span class="hl opt">, (</span><span class="hl num">12</span><span class="hl opt">,</span> <span class="hl num">16</span><span class="hl opt">)).</span><span class="hl kwd">astype</span><span class="hl opt">(</span><span class="hl str">&apos;float32&apos;</span><span class="hl opt">)</span>
        cg <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">reshape</span><span class="hl opt">(</span><span class="hl num">1</span><span class="hl opt">/</span>g<span class="hl opt">, (</span><span class="hl num">12</span><span class="hl opt">,</span> <span class="hl num">16</span><span class="hl opt">)).</span><span class="hl kwd">astype</span><span class="hl opt">(</span><span class="hl str">&apos;float32&apos;</span><span class="hl opt">)</span>
        <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">        median blur to remove peaks and save as float 64</span>
<span class="hl str">        &quot;&quot;&quot;</span>
        cr <span class="hl opt">=</span> cv2<span class="hl opt">.</span><span class="hl kwd">medianBlur</span><span class="hl opt">(</span>cr<span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">).</span><span class="hl kwd">astype</span><span class="hl opt">(</span><span class="hl str">&apos;float64&apos;</span><span class="hl opt">)</span>
        cb <span class="hl opt">=</span> cv2<span class="hl opt">.</span><span class="hl kwd">medianBlur</span><span class="hl opt">(</span>cb<span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">).</span><span class="hl kwd">astype</span><span class="hl opt">(</span><span class="hl str">&apos;float64&apos;</span><span class="hl opt">)</span>
        cg <span class="hl opt">=</span> cv2<span class="hl opt">.</span><span class="hl kwd">medianBlur</span><span class="hl opt">(</span>cg<span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">).</span><span class="hl kwd">astype</span><span class="hl opt">(</span><span class="hl str">&apos;float64&apos;</span><span class="hl opt">)</span>
        cg <span class="hl opt">=</span> cg<span class="hl opt">/</span>np<span class="hl opt">.</span><span class="hl kwb">min</span><span class="hl opt">(</span>cg<span class="hl opt">)</span>

        <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">        debugging code showing 2D surface plot of vignetting. Quite useful for</span>
<span class="hl str">        for sanity check</span>
<span class="hl str">        &quot;&quot;&quot;</span>
        <span class="hl kwa">if</span> plot<span class="hl opt">:</span>
            hf <span class="hl opt">=</span> plt<span class="hl opt">.</span><span class="hl kwd">figure</span><span class="hl opt">(</span>figsize<span class="hl opt">=(</span><span class="hl num">8</span><span class="hl opt">,</span> <span class="hl num">8</span><span class="hl opt">))</span>
            ha <span class="hl opt">=</span> hf<span class="hl opt">.</span><span class="hl kwd">add_subplot</span><span class="hl opt">(</span><span class="hl num">311</span><span class="hl opt">,</span> projection<span class="hl opt">=</span><span class="hl str">&apos;3d&apos;</span><span class="hl opt">)</span>
            <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">            note Y is plotted as -Y so plot has same axes as image</span>
<span class="hl str">            &quot;&quot;&quot;</span>
            X<span class="hl opt">,</span> Y <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">meshgrid</span><span class="hl opt">(</span><span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl num">16</span><span class="hl opt">),</span> <span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl num">12</span><span class="hl opt">))</span>
            ha<span class="hl opt">.</span><span class="hl kwd">plot_surface</span><span class="hl opt">(</span>X<span class="hl opt">, -</span>Y<span class="hl opt">,</span> cr<span class="hl opt">,</span> cmap<span class="hl opt">=</span>cm<span class="hl opt">.</span>coolwarm<span class="hl opt">,</span> linewidth<span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">)</span>
            ha<span class="hl opt">.</span><span class="hl kwd">set_title</span><span class="hl opt">(</span><span class="hl str">&apos;ALSC Plot</span><span class="hl esc">\n</span><span class="hl str">Img: {}</span><span class="hl esc">\n\n</span><span class="hl str">cr&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>Img<span class="hl opt">.</span><span class="hl kwb">str</span><span class="hl opt">))</span>
            hb <span class="hl opt">=</span> hf<span class="hl opt">.</span><span class="hl kwd">add_subplot</span><span class="hl opt">(</span><span class="hl num">312</span><span class="hl opt">,</span> projection<span class="hl opt">=</span><span class="hl str">&apos;3d&apos;</span><span class="hl opt">)</span>
            hb<span class="hl opt">.</span><span class="hl kwd">plot_surface</span><span class="hl opt">(</span>X<span class="hl opt">, -</span>Y<span class="hl opt">,</span> cb<span class="hl opt">,</span> cmap<span class="hl opt">=</span>cm<span class="hl opt">.</span>coolwarm<span class="hl opt">,</span> linewidth<span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">)</span>
            hb<span class="hl opt">.</span><span class="hl kwd">set_title</span><span class="hl opt">(</span><span class="hl str">&apos;cb&apos;</span><span class="hl opt">)</span>
            hc <span class="hl opt">=</span> hf<span class="hl opt">.</span><span class="hl kwd">add_subplot</span><span class="hl opt">(</span><span class="hl num">313</span><span class="hl opt">,</span> projection<span class="hl opt">=</span><span class="hl str">&apos;3d&apos;</span><span class="hl opt">)</span>
            hc<span class="hl opt">.</span><span class="hl kwd">plot_surface</span><span class="hl opt">(</span>X<span class="hl opt">, -</span>Y<span class="hl opt">,</span> cg<span class="hl opt">,</span> cmap<span class="hl opt">=</span>cm<span class="hl opt">.</span>coolwarm<span class="hl opt">,</span> linewidth<span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">)</span>
            hc<span class="hl opt">.</span><span class="hl kwd">set_title</span><span class="hl opt">(</span><span class="hl str">&apos;g&apos;</span><span class="hl opt">)</span>
            <span class="hl slc"># print(Img.str)</span>
            plt<span class="hl opt">.</span><span class="hl kwd">show</span><span class="hl opt">()</span>

        <span class="hl kwa">return</span> Img<span class="hl opt">.</span>col<span class="hl opt">,</span> cr<span class="hl opt">.</span><span class="hl kwd">flatten</span><span class="hl opt">(),</span> cb<span class="hl opt">.</span><span class="hl kwd">flatten</span><span class="hl opt">(),</span> cg<span class="hl opt">.</span><span class="hl kwd">flatten</span><span class="hl opt">(), (</span>w<span class="hl opt">,</span> h<span class="hl opt">,</span> dx<span class="hl opt">,</span> dy<span class="hl opt">)</span>

    <span class="hl kwa">else</span><span class="hl opt">:</span>
        <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">        only perform calculations for luminance shading</span>
<span class="hl str">        &quot;&quot;&quot;</span>
        g <span class="hl opt">=</span> <span class="hl kwd">get_16x12_grid</span><span class="hl opt">(</span>av_ch_g<span class="hl opt">,</span> dx<span class="hl opt">,</span> dy<span class="hl opt">) -</span> Img<span class="hl opt">.</span>blacklevel_16
        cg <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">reshape</span><span class="hl opt">(</span><span class="hl num">1</span><span class="hl opt">/</span>g<span class="hl opt">, (</span><span class="hl num">12</span><span class="hl opt">,</span> <span class="hl num">16</span><span class="hl opt">)).</span><span class="hl kwd">astype</span><span class="hl opt">(</span><span class="hl str">&apos;float32&apos;</span><span class="hl opt">)</span>
        cg <span class="hl opt">=</span> cv2<span class="hl opt">.</span><span class="hl kwd">medianBlur</span><span class="hl opt">(</span>cg<span class="hl opt">,</span> <span class="hl num">3</span><span class="hl opt">).</span><span class="hl kwd">astype</span><span class="hl opt">(</span><span class="hl str">&apos;float64&apos;</span><span class="hl opt">)</span>
        cg <span class="hl opt">=</span> cg<span class="hl opt">/</span>np<span class="hl opt">.</span><span class="hl kwb">min</span><span class="hl opt">(</span>cg<span class="hl opt">)</span>

        <span class="hl kwa">if</span> plot<span class="hl opt">:</span>
            hf <span class="hl opt">=</span> plt<span class="hl opt">.</span><span class="hl kwd">figure</span><span class="hl opt">(</span>figssize<span class="hl opt">=(</span><span class="hl num">8</span><span class="hl opt">,</span> <span class="hl num">8</span><span class="hl opt">))</span>
            ha <span class="hl opt">=</span> hf<span class="hl opt">.</span><span class="hl kwd">add_subplot</span><span class="hl opt">(</span><span class="hl num">1</span><span class="hl opt">,</span> <span class="hl num">1</span><span class="hl opt">,</span> <span class="hl num">1</span><span class="hl opt">,</span> projection<span class="hl opt">=</span><span class="hl str">&apos;3d&apos;</span><span class="hl opt">)</span>
            X<span class="hl opt">,</span> Y <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">meashgrid</span><span class="hl opt">(</span><span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl num">16</span><span class="hl opt">),</span> <span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl num">12</span><span class="hl opt">))</span>
            ha<span class="hl opt">.</span><span class="hl kwd">plot_surface</span><span class="hl opt">(</span>X<span class="hl opt">, -</span>Y<span class="hl opt">,</span> cg<span class="hl opt">,</span> cmap<span class="hl opt">=</span>cm<span class="hl opt">.</span>coolwarm<span class="hl opt">,</span> linewidth<span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">)</span>
            ha<span class="hl opt">.</span><span class="hl kwd">set_title</span><span class="hl opt">(</span><span class="hl str">&apos;ALSC Plot (Luminance only!)</span><span class="hl esc">\n</span><span class="hl str">Img: {}</span><span class="hl esc">\n\n</span><span class="hl str">cg&apos;</span><span class="hl opt">).</span><span class="hl kwd">format</span><span class="hl opt">(</span>Img<span class="hl opt">.</span><span class="hl kwb">str</span><span class="hl opt">)</span>
            plt<span class="hl opt">.</span><span class="hl kwd">show</span><span class="hl opt">()</span>

        <span class="hl kwa">return</span> Img<span class="hl opt">.</span>col<span class="hl opt">,</span> <span class="hl kwa">None</span><span class="hl opt">,</span> <span class="hl kwa">None</span><span class="hl opt">,</span> cg<span class="hl opt">.</span><span class="hl kwd">flatten</span><span class="hl opt">(), (</span>w<span class="hl opt">,</span> h<span class="hl opt">,</span> dx<span class="hl opt">,</span> dy<span class="hl opt">)</span>


<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">Compresses channel down to a 16x12 grid</span>
<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl kwa">def</span> <span class="hl kwd">get_16x12_grid</span><span class="hl opt">(</span>chan<span class="hl opt">,</span> dx<span class="hl opt">,</span> dy<span class="hl opt">):</span>
    grid <span class="hl opt">= []</span>
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    since left and bottom border will not necessarily have rectangles of</span>
<span class="hl str">    dimension dx x dy, the 32nd iteration has to be handled separately.</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    <span class="hl kwa">for</span> i <span class="hl kwa">in</span> <span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl num">11</span><span class="hl opt">):</span>
        <span class="hl kwa">for</span> j <span class="hl kwa">in</span> <span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl num">15</span><span class="hl opt">):</span>
            grid<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">(</span>chan<span class="hl opt">[</span>dy<span class="hl opt">*</span>i<span class="hl opt">:</span>dy<span class="hl opt">*(</span><span class="hl num">1</span><span class="hl opt">+</span>i<span class="hl opt">),</span> dx<span class="hl opt">*</span>j<span class="hl opt">:</span>dx<span class="hl opt">*(</span><span class="hl num">1</span><span class="hl opt">+</span>j<span class="hl opt">)]))</span>
        grid<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">(</span>chan<span class="hl opt">[</span>dy<span class="hl opt">*</span>i<span class="hl opt">:</span>dy<span class="hl opt">*(</span><span class="hl num">1</span><span class="hl opt">+</span>i<span class="hl opt">),</span> <span class="hl num">15</span><span class="hl opt">*</span>dx<span class="hl opt">:]))</span>
    <span class="hl kwa">for</span> j <span class="hl kwa">in</span> <span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl num">15</span><span class="hl opt">):</span>
        grid<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">(</span>chan<span class="hl opt">[</span><span class="hl num">11</span><span class="hl opt">*</span>dy<span class="hl opt">:,</span> dx<span class="hl opt">*</span>j<span class="hl opt">:</span>dx<span class="hl opt">*(</span><span class="hl num">1</span><span class="hl opt">+</span>j<span class="hl opt">)]))</span>
    grid<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">(</span>chan<span class="hl opt">[</span><span class="hl num">11</span><span class="hl opt">*</span>dy<span class="hl opt">:,</span> <span class="hl num">15</span><span class="hl opt">*</span>dx<span class="hl opt">:]))</span>
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    return as np.array, ready for further manipulation</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    <span class="hl kwa">return</span> np<span class="hl opt">.</span><span class="hl kwd">array</span><span class="hl opt">(</span>grid<span class="hl opt">)</span>


<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">obtains sigmas for red and blue, effectively a measure of the &apos;error&apos;</span>
<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl kwa">def</span> <span class="hl kwd">get_sigma</span><span class="hl opt">(</span>Cam<span class="hl opt">,</span> cal_cr_list<span class="hl opt">,</span> cal_cb_list<span class="hl opt">):</span>
    Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Calculating sigmas&apos;</span>
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    provided colour alsc tables were generated for two different colour</span>
<span class="hl str">    temperatures sigma is calculated by comparing two calibration temperatures</span>
<span class="hl str">    adjacent in colour space</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    create list of colour temperatures</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    cts <span class="hl opt">= [</span>cal<span class="hl opt">[</span><span class="hl str">&apos;ct&apos;</span><span class="hl opt">]</span> <span class="hl kwa">for</span> cal <span class="hl kwa">in</span> cal_cr_list<span class="hl opt">]</span>
    <span class="hl slc"># print(cts)</span>
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    calculate sigmas for each adjacent cts and return worst one</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    sigma_rs <span class="hl opt">= []</span>
    sigma_bs <span class="hl opt">= []</span>
    <span class="hl kwa">for</span> i <span class="hl kwa">in</span> <span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl kwb">len</span><span class="hl opt">(</span>cts<span class="hl opt">)-</span><span class="hl num">1</span><span class="hl opt">):</span>
        sigma_rs<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span><span class="hl kwd">calc_sigma</span><span class="hl opt">(</span>cal_cr_list<span class="hl opt">[</span>i<span class="hl opt">][</span><span class="hl str">&apos;table&apos;</span><span class="hl opt">],</span> cal_cr_list<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">][</span><span class="hl str">&apos;table&apos;</span><span class="hl opt">]))</span>
        sigma_bs<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span><span class="hl kwd">calc_sigma</span><span class="hl opt">(</span>cal_cb_list<span class="hl opt">[</span>i<span class="hl opt">][</span><span class="hl str">&apos;table&apos;</span><span class="hl opt">],</span> cal_cb_list<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">][</span><span class="hl str">&apos;table&apos;</span><span class="hl opt">]))</span>
        Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Colour temperature interval {} - {} K&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>cts<span class="hl opt">[</span>i<span class="hl opt">],</span> cts<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">])</span>
        Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Sigma red: {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>sigma_rs<span class="hl opt">[-</span><span class="hl num">1</span><span class="hl opt">])</span>
        Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Sigma blue: {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>sigma_bs<span class="hl opt">[-</span><span class="hl num">1</span><span class="hl opt">])</span>

    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    return maximum sigmas, not necessarily from the same colour temperature</span>
<span class="hl str">    interval</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    sigma_r <span class="hl opt">=</span> <span class="hl kwb">max</span><span class="hl opt">(</span>sigma_rs<span class="hl opt">)</span> <span class="hl kwa">if</span> sigma_rs <span class="hl kwa">else</span> <span class="hl num">0.005</span>
    sigma_b <span class="hl opt">=</span> <span class="hl kwb">max</span><span class="hl opt">(</span>sigma_bs<span class="hl opt">)</span> <span class="hl kwa">if</span> sigma_bs <span class="hl kwa">else</span> <span class="hl num">0.005</span>
    Cam<span class="hl opt">.</span>log <span class="hl opt">+=</span> <span class="hl str">&apos;</span><span class="hl esc">\n</span><span class="hl str">Maximum sigmas: Red = {} Blue = {}&apos;</span><span class="hl opt">.</span><span class="hl kwd">format</span><span class="hl opt">(</span>sigma_r<span class="hl opt">,</span> sigma_b<span class="hl opt">)</span>

    <span class="hl slc"># print(sigma_rs, sigma_bs)</span>
    <span class="hl slc"># print(sigma_r, sigma_b)</span>
    <span class="hl kwa">return</span> sigma_r<span class="hl opt">,</span> sigma_b


<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">calculate sigma from two adjacent gain tables</span>
<span class="hl str">&quot;&quot;&quot;</span>
<span class="hl kwa">def</span> <span class="hl kwd">calc_sigma</span><span class="hl opt">(</span>g1<span class="hl opt">,</span> g2<span class="hl opt">):</span>
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    reshape into 16x12 matrix</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    g1 <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">reshape</span><span class="hl opt">(</span>g1<span class="hl opt">, (</span><span class="hl num">12</span><span class="hl opt">,</span> <span class="hl num">16</span><span class="hl opt">))</span>
    g2 <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">reshape</span><span class="hl opt">(</span>g2<span class="hl opt">, (</span><span class="hl num">12</span><span class="hl opt">,</span> <span class="hl num">16</span><span class="hl opt">))</span>
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    apply gains to gain table</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    gg <span class="hl opt">=</span> g1<span class="hl opt">/</span>g2
    <span class="hl kwa">if</span> np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">(</span>gg<span class="hl opt">) &lt;</span> <span class="hl num">1</span><span class="hl opt">:</span>
        gg <span class="hl opt">=</span> <span class="hl num">1</span><span class="hl opt">/</span>gg
    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    for each internal patch, compute average difference between it and its 4</span>
<span class="hl str">    neighbours, then append to list</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    diffs <span class="hl opt">= []</span>
    <span class="hl kwa">for</span> i <span class="hl kwa">in</span> <span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl num">10</span><span class="hl opt">):</span>
        <span class="hl kwa">for</span> j <span class="hl kwa">in</span> <span class="hl kwb">range</span><span class="hl opt">(</span><span class="hl num">14</span><span class="hl opt">):</span>
            <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">            note indexing is incremented by 1 since all patches on borders are</span>
<span class="hl str">            not counted</span>
<span class="hl str">            &quot;&quot;&quot;</span>
            diff <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwb">abs</span><span class="hl opt">(</span>gg<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">][</span>j<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">]-</span>gg<span class="hl opt">[</span>i<span class="hl opt">][</span>j<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">])</span>
            diff <span class="hl opt">+=</span> np<span class="hl opt">.</span><span class="hl kwb">abs</span><span class="hl opt">(</span>gg<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">][</span>j<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">]-</span>gg<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">2</span><span class="hl opt">][</span>j<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">])</span>
            diff <span class="hl opt">+=</span> np<span class="hl opt">.</span><span class="hl kwb">abs</span><span class="hl opt">(</span>gg<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">][</span>j<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">]-</span>gg<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">][</span>j<span class="hl opt">])</span>
            diff <span class="hl opt">+=</span> np<span class="hl opt">.</span><span class="hl kwb">abs</span><span class="hl opt">(</span>gg<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">][</span>j<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">]-</span>gg<span class="hl opt">[</span>i<span class="hl opt">+</span><span class="hl num">1</span><span class="hl opt">][</span>j<span class="hl opt">+</span><span class="hl num">2</span><span class="hl opt">])</span>
            diffs<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span>diff<span class="hl opt">/</span><span class="hl num">4</span><span class="hl opt">)</span>

    <span class="hl str">&quot;&quot;&quot;</span>
<span class="hl str">    return mean difference</span>
<span class="hl str">    &quot;&quot;&quot;</span>
    mean_diff <span class="hl opt">=</span> np<span class="hl opt">.</span><span class="hl kwd">mean</span><span class="hl opt">(</span>diffs<span class="hl opt">)</span>
    <span class="hl kwa">return</span><span class="hl opt">(</span>np<span class="hl opt">.</span><span class="hl kwb">round</span><span class="hl opt">(</span>mean_diff<span class="hl opt">,</span> <span class="hl num">5</span><span class="hl opt">))</span>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.1</a> (<a href='https://git-scm.com/'>git 2.18.0</a>) at 2025-02-22 23:33:03 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>