Looking for a gmic + python scripter to help me out here.

I am working on trying to replicate this filter in gmic and I certainly do not understand python - https://github.com/weightan/SchrodingerWellPython

This is as far as I got
rep_hamiltonian:
skip ${2=1},${3=0}
#$1=sides#
#$2=radius#
#$3=rotation_ang#
#$4=translate_x#
#$5=translate_y#

sides={max(1,abs($1))}
ang={$3/180*pi}
one_segment={pi*2/$sides}
use_translate=0

#def polygon#

if [$4,$5]!=[0,0] use_translate=1 fi

$sides,1,1,2,"begin(
  const use_translate="$use_translate";
  const radius=$2;
  const ang="$ang";
  const os="$one_segment";
  translate_coords=[$4,$5];
  cv(n)=os*n+ang;
  use_translate?(
   vf(v)=[sin(v),cos(v)]*radius+translate_coords;
  ):(
   vf(v)=[sin(v),cos(v)]*radius;
  );
 );
 vf(cv(x));
"

How do they go all together?

On inpolygon, it seem to me that inpolygon process a vector. But, how is that translateable to gmic?

general_potential is the core part according to the author of the filter (yes, i chatted with him). So, it can’t be skipped. What does it do exactly?

EDIT: Now I remember @myselfhimself. Pinging him as he qualifies.

Hello,
gmic-py allows to convert GmicImage matrices from and to numpy.
The SchrodingerWellPython project has two python files, one for processing and dumping vectors to file, one for displaying a vector file using python matplot.
In the first python file, numpy is in used for manipulating pixel data.

The if __name__== "__main__" conditional block in python at the end of the Hamiltonian_solver.py file is what gets executed when the file is run directly (with python Hamiltonian_solver.py for example.

I do not know whether you want to get inspired by the project’s filter algorithm and write a pure-G’MIC filter version for it… or whether you are OK with cohabiting with the Python world.

If you want to cohabit with the Python world and use gmic-py along with this SchrodingerWellPython project’s source, what would need to be done is patch the latter’s aforementioned file’s end with something like (especially the part below the GMIC Python Import lines):

if __name__ == '__main__':


    mesh = makeCircleWellMatrix (N, inWell, outWell)
    
    e_values, e_vec = general_potential(mesh)   
    
    # GMIC Python Import lines
    import gmic
    gmic.run('display', gmic.GmicImage.from_numpy(e_values)) # or e_vec instead of e_values
    # Less important lines below if you prefer starting in gmic-py from now
    # END OF GMIC Python Import lines
    
    idx = e_values.argsort()[::-1]   
    e_values = e_values[idx]
    e_vec = e_vec[:,idx]

    print('vectors done')

    if 1:
        np.save('data_E_vectors_circle' + str(N) +'x'+ str(N) + 'e' + str(Elevels) , e_vec)


    print('save e_vec done')

    displayAndSaveIm(e_vec)
    
    print('****************************** all done *******************************')

If you want a pure G’MIC implementation and no Python at all… I do not know the G’MIC language enough for now… :confused:

This. He wants help understanding the python script.

1 Like

Yes, I want to understand the python script and what it does, and then convert it into the g’mic implementation. Even a pseudocode will do or a step by step description will do.

@Reptorian
step by step, looking at the if __name __ == "__main__": conditional block:

mesh = makeCircleWellMatrix (N, inWell, outWell) #globals: N=200,inWell=1,outWell=0

you want a makeCircleWellMatrix (N, inWell, outWell) Python to G’MIC reimplementation:

def makeCircleWellMatrix (n, inW, outW):
    well_matrix = np.empty((n, n))
    
    #00100
    #01110
    #00100
    
    for i in range(0, n):
        for j in range(0, n):
            if math.dist([i, j], [(n-1)/2, (n-1)/2]) <= (n-1)/2 :
                well_matrix[i][j] = inW
            else:
                well_matrix[i][j] = outW
                
    return well_matrix

Just looking at the 3 lines of comment + the if math.dist() statement seem to imply that the function creates a matrix of N x N zeros, with a 1.0 filled borderless circle that is N/2 diameter wide. Note that the for someVariable in range(min, max): loop header in Python can be understood as `for someVariable spanning from min to max with a step 1.

Here is a G’MIC command line reimplementation try for N=2:
gmic 200,200,1,1 circle 50\%,50\%,50,1,1.0

Here is a G’MIC file syntax variant with variables assignment:

N=100
inWell=1
outWell=0

makeCircleWellMatrix:
$1,$1,1,1 fill_color $3 circle 50%,50%,N/4,1,$2

rep_hamiltonian:
makeCircleWellMatrix $N,$inWell,$outWell

but I get an error but I do not know G’MIC’s syntax well…:
[gmic]-0./rep_hamiltonian/ *** Error (file 'aa.gmic', line #15) *** Command 'makeCircleWellMatrix': Undefined argument '$1', in expression '$1' (for 2 arguments specified).

@myselfhimself

I think I am understanding how it works now.

So to be clear, I don’t have to worry about general_potential()? That the part that gets me the most since the author said that it is the core part of the filter. Does it actually do anything to a existing matrix?

On def inPolygon(), it would seem to be a loop function that defines c, and then return c. A internal c.

makePolygonWellMatrix creates a matrix using a defined set of vector created from def_polygon.

Hey @Reptorian ,
it seems that everything is important to translate from that script file, except dead code if there were any…
The translation method would be: take each line / step in the Python script’s if name main condition, and try to convert it to G’MIC (which may imply converting dependent functions as well) and test it right away, then go next step. One call / function translated => one manual GMIC test => next call/function to translate etc…

What I showed before was for the makeCircleWellMatrix function, which ends up being translated from a dozen lines to 1 G’MIC line… and this can continue being translated for each line and depending function. If you manage to have the code I pasted fixed (there are some parameters / variables syntax error which I do not know how to solve), we can collaborate further to translate each algorithm step into the G’MIC language… with tiny solid hand-tested blocks, one at a time…

I have opened a Github issue related to your G’MIC translation endeavour

This is the work in progress G’MIC file. You are welcome to edit it with a pull-request or however you like.

@David_Tschumperle (or others)
what would be the G’MIC language equivalent for the numpy matrix flatten function used in position_mesh = np.matrix.flatten( matrixWell2D ), documented here ?.. OK G’MIC unroll x maybe!!

Definitely.

gmic -input '(1,2,3;4,5,6;7,8,9)' -name. 'threebythree' -display[threebythree]  \

pixelpost

-unroll[threebythree] x -display[threebythree] \

In Python with numpy:

gosgood@bertha ~/git_repositories/gmic-community/tutorial $ ipython
Python 3.9.2 (default, Feb 27 2021, 12:28:43) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.21.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import numpy as np

In [2]: threebythree = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]).reshape((3,3))

In [3]: threebythree
Out[3]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

In [4]: np.matrix.flatten(threebythree)
Out[4]: array([1, 2, 3, 4, 5, 6, 7, 8, 9])

Aside: -resize is a general purpose matrix/image reshaper. To undo -unroll:

-resize[threebythree] 3,3,1,1,0

Hope this helps.

1 Like

Thank you very much for this test! Nice to see a pythonist around in the G’MIC forums! Now let us continue with the numpy -> G’MIC conversion!

Now trying to translate the following to G’MIC where npis the numpy module:

No_points = N*N
x_intervals = np.linspace(0, 1, N)
increment = np.absolute(x_intervals[0] - x_intervals[1])
print ('increment ' + str(increment))

What happened to G’MIC’s lerp (linear interpolation)? I do not see it in the online G’MIC commands reference…

It’s still there.

  t=lerp(start,end,mixfactor);

where mixfactor of .5 means the average of start and end while 1 means end and 0 means start

1 Like

Tucked in the math parser.

lerp(a,b,t) returns 'a(1-t) + bt'.

Could pull it in as the fifth parameter to -fill or through -eval if you don’t want to peg your calculations to a specific image.

Here’s a tutorial that makes use of lerp: norm in the context of a math expression used as a parameter to -fill. Scroll down to the example of popping a color key of the rooster’s head.

1 Like

For translating

x_intervals = np.linspace(0, 1, N)

I had thought of

N=200
$N,1,1,1,x/$N display

ranging from 0 to … 0.95 only
hence the idea of lerp

Yep. That’s your G’MIC workalike of np.linspace.

Only looked at the python toy for a bit: looks like a visualization of Schrödinger’s Particle in a box, which can be quite compelling. Seems you all have it in hand. Looking forward to the filter. Have fun!

1 Like

Here is the linspace equivalent in G’MIC:
N=200
$N,1,1,1,x/($N-1) display

added it to the .gmic file

I am really stuck with parameters passing…

N=200

inWell=1
outWell=0

makeCircleWellMatrix :
$1,$1,1,1 fill_color $3 circle 50%,50%,$1/4,1,$2

rep_hamiltonian :
makeCircleWellMatrix $N,$inWell,$outWell unroll x

gmic bb.gmic rep_hamiltonian

[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Input custom command file 'bb.gmic' (3 new, total: 4410).
[gmic] *** Error in ./rep_hamiltonian/ (file 'bb.gmic', line #13) *** Command 'makeCircleWellMatrix': Undefined argument '$1', in expression '$1' (for 2 arguments specified).
[gmic] Command 'makeCircleWellMatrix' has the following description: 

[gmic] No help available for command 'makeCircleWellMatrix'. 
       Try 'gmic -h' for global help.

What is the proper syntax for command formatting in order to fix the parameters error? I had a brief look at documentation and gmic-community definitions already…

You could move N, Iwell, outWell to rep_hamiltonian. Without it, it does not know they exist. Command needs variables inside to know these variables exist.

I might look more tonight or tomorrow.