From fc2891a2fe7340546f6620dbb7df86ca52b867e3 Mon Sep 17 00:00:00 2001 From: Chris Rorden Date: Fri, 11 May 2018 14:18:04 -0400 Subject: [PATCH] Python updates --- .DS_Store | Bin 32772 -> 32772 bytes COMMANDS.md | 129 +- PYTHON.md | 204 +++ UserNotification.pas | 232 ++++ _osx.command | 1 + commandsu.pas | 35 +- define_types.pas | 14 + mainunit.pas | 110 +- mesh.pas | 154 ++- opts.inc | 1 + optsCompat.inc | 1 + optsCompatGeom.inc | 1 + optsCore.inc | 1 + prefs.pas | 4 +- proc_py.pas | 90 ++ script/basic_paint_surface.gls | 25 +- script/create_atlas.gls | 16 +- script/fmri_mesh.gls | 17 +- script/frontal_atlas.gls | 18 +- script/hide_curves.gls | 18 +- script/mesh.gls | 18 +- script/newer_2017.gls | 44 +- script/node.gls | 39 +- script/shaders.gls | 66 +- script/track.gls | 26 +- scriptengine.lfm | 199 +-- scriptengine.pas | 1140 ++++++++++++++++- .../Resources/script/basic_paint_surface.gls | 24 +- .../Resources/script/create_atlas.gls | 16 +- .../Contents/Resources/script/fmri_mesh.gls | 18 +- .../Resources/script/frontal_atlas.gls | 18 +- .../Contents/Resources/script/hide_curves.gls | 18 +- .../Contents/Resources/script/mesh.gls | 18 +- .../Contents/Resources/script/newer_2017.gls | 44 +- .../Contents/Resources/script/node.gls | 39 +- .../Contents/Resources/script/shaders.gls | 66 +- .../Contents/Resources/script/track.gls | 26 +- surfice.lpi | 11 +- surfice.lps | 223 ++-- 39 files changed, 2486 insertions(+), 638 deletions(-) create mode 100644 PYTHON.md create mode 100755 UserNotification.pas create mode 100755 proc_py.pas diff --git a/.DS_Store b/.DS_Store index 8270165192b0ad2757b7f8173cd91c107176ed64..ff29eeb23e527a64a832285648fa0d9b38bb4291 100755 GIT binary patch delta 83 zcmZo^U}|Y#+7ReAd2^V^WNU}%qGHw6rj|Mi#)h>z3e{$o<~j;yhNhG4eZ?kshO2J& gbKlFcnKK}gf3icc+T '' then + begin + TmpNSStr := NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Sound, kCFStringEncodingUTF8)); + + try + Notification.setSoundName(TmpNSStr); + + finally + TmpNSStr.release; + end; + end; + + NSUserNotificationCenter.defaultUserNotificationCenter.deliverNotification(Notification); + + finally + Notification.release; + end; +end; + + + +initialization + UserNotificationCenterDelegate := NSUserNotificationCenterAlwaysShowDelegate.alloc.init; + NSUserNotificationCenter.defaultUserNotificationCenter.setDelegate(UserNotificationCenterDelegate); + + + +finalization + NSUserNotificationCenter.defaultUserNotificationCenter.setDelegate(nil); + UserNotificationCenterDelegate.release; + +{$endif} + + + +end. diff --git a/_osx.command b/_osx.command index e5a1153..df1b094 100755 --- a/_osx.command +++ b/_osx.command @@ -4,6 +4,7 @@ # make LCL_PLATFORM=cocoa CPU_TARGET=x86_64 clean bigide # lazbuild -B --ws=cocoa ./simplelaz.lpr # ./lazbuild --ws=carbon --compiler="/usr/local/lib/fpc/3.0.4/ppc386" --cpu=i386 --add-package lazopenglcontext --add-package pascalscript --build-ide= +# ./lazbuild --ws=cocoa --add-package lazopenglcontext --add-package pascalscript --build-ide= find /Users/rorden/Documents/osx -name ‘*.DS_Store’ -type f -delete diff --git a/commandsu.pas b/commandsu.pas index 4afc8fa..a5241cb 100755 --- a/commandsu.pas +++ b/commandsu.pas @@ -4,6 +4,7 @@ interface function EXISTS(lFilename: string): boolean; //function function ATLASMAXINDEX(OVERLAY: integer): integer; +function VERSION: string; procedure ATLASSTATMAP(ATLASNAME, STATNAME: string; const Indices: array of integer; const Intensities: array of single); procedure ATLASSATURATIONALPHA(lSaturation, lTransparency: single); procedure ATLASHIDE(OVERLAY: integer; const Filt: array of integer); @@ -24,11 +25,12 @@ procedure EDGESIZE(size: single; varies: boolean); procedure EDGETHRESH (LO, HI: single); procedure ELEVATION (DEG: integer); procedure FONTNAME(name: string); -procedure MESHLOAD(lFilename: string); procedure MESHCREATE(niiname, meshname: string; threshold, decimateFrac: single; minimumClusterVox, smoothStyle: integer); procedure MESHCURV; -procedure MESHREVERSEFACES; +procedure MESHLOAD(lFilename: string); procedure MESHOVERLAYORDER (FLIP: boolean); +procedure MESHREVERSEFACES; +procedure MESHSAVE(lFilename: string); procedure NODELOAD(lFilename: string); procedure MODALMESSAGE(STR: string); procedure MODELESSMESSAGE(STR: string); @@ -55,6 +57,7 @@ procedure OVERLAYSMOOTHVOXELWISEDATA (SMOOTH: boolean); procedure QUIT; procedure RESETDEFAULTS; procedure SAVEBMP(lFilename: string); +procedure SCRIPTFORMVISIBLE (VISIBLE: boolean); procedure SHADERADJUST(lProperty: string; lVal: single); procedure SHADERAMBIENTOCCLUSION(lVal: single); procedure SHADERFORBACKGROUNDONLY(BGONLY: boolean); @@ -74,13 +77,14 @@ procedure WAIT (MSEC: integer); Decl,Vars: string[255]; end; const - knFunc = 2; + knFunc = 3; kFuncRA : array [1..knFunc] of TScriptRec =( (Ptr:@ATLASMAXINDEX;Decl:'ATLASMAXINDEX';Vars:'(OVERLAY: integer): integer'), - (Ptr:@EXISTS;Decl:'EXISTS';Vars:'(lFilename: string): boolean') + (Ptr:@EXISTS;Decl:'EXISTS';Vars:'(lFilename: string): boolean'), + (Ptr:@VERSION;Decl:'VERSION';Vars:'(): string') ); -knProc = 63; +knProc = 65; kProcRA : array [1..knProc] of TScriptRec = ( (Ptr:@ATLASSTATMAP;Decl:'ATLASSTATMAP';Vars:'(ATLASNAME, STATNAME: string; const Intensities: array of integer; const Intensities: array of single)'), (Ptr:@ATLASSATURATIONALPHA;Decl:'ATLASSATURATIONALPHA';Vars:'(lSaturation, lTransparency: single)'), @@ -108,6 +112,7 @@ procedure WAIT (MSEC: integer); (Ptr:@MESHLOAD;Decl:'MESHLOAD';Vars:'(lFilename: string)'), (Ptr:@MESHCREATE;Decl:'MESHCREATE';Vars:'(niiname, meshname: string; threshold, decimateFrac: single; minimumClusterVox, smoothStyle: integer)'), (Ptr:@MESHOVERLAYORDER;Decl:'MESHOVERLAYORDER';Vars:'(FLIP: boolean)'), + (Ptr:@MESHSAVE;Decl:'MESHSAVE';Vars:'(lFilename: string)'), (Ptr:@NODELOAD;Decl:'NODELOAD';Vars:'(lFilename: string)'), (Ptr:@MODALMESSAGE;Decl:'MODALMESSAGE';Vars:'(STR: string)'), (Ptr:@MODELESSMESSAGE;Decl:'MODELESSMESSAGE';Vars:'(STR: string)'), @@ -133,6 +138,7 @@ procedure WAIT (MSEC: integer); (Ptr:@QUIT;Decl:'QUIT';Vars:''), (Ptr:@RESETDEFAULTS;Decl:'RESETDEFAULTS';Vars:''), (Ptr:@SAVEBMP;Decl:'SAVEBMP';Vars:'(lFilename: string)'), + (Ptr:@SCRIPTFORMVISIBLE;Decl:'SCRIPTFORMVISIBLE';Vars:'(VISIBLE: boolean)'), (Ptr:@SHADERADJUST;Decl:'SHADERADJUST';Vars:'(lProperty: string; lVal: single)'), (Ptr:@SHADERAMBIENTOCCLUSION;Decl:'SHADERAMBIENTOCCLUSION';Vars:'(lVal: single)'), (Ptr:@SHADERFORBACKGROUNDONLY;Decl:'SHADERFORBACKGROUNDONLY';Vars:'(BGONLY: boolean)'), @@ -152,6 +158,12 @@ implementation //{$IFDEF UNIX}fileutil,{$ENDIF} mainunit, define_types, shaderui, graphics, LCLintf, Forms, SysUtils, Dialogs, scriptengine, mesh, meshify; +procedure SCRIPTFORMVISIBLE (VISIBLE: boolean); +begin + GLForm1.ScriptMenuClick(nil); + ScriptForm.visible := VISIBLE; +end; + function ATLASMAXINDEX(OVERLAY: integer): integer; begin if (OVERLAY < 1) or (OVERLAY > kMaxOverlays) then @@ -337,6 +349,11 @@ procedure RESETDEFAULTS; GLForm1.ResetMenuClick(nil); end; +function VERSION(): string; +begin + result := kVers; +end; + function EXISTS(lFilename: string): boolean; begin result := FileExists(lFilename); @@ -456,6 +473,14 @@ procedure MESHLOAD(lFilename: string); end; end; +procedure MESHSAVE(lFilename: string); +begin + if not GLForm1.SaveMeshCore(lFilename) then begin + ScriptForm.Memo2.Lines.Add('Unable to save mesh named "'+lFilename+'"'); + end; +end; + + procedure MESHOVERLAYORDER (FLIP: boolean); begin gPrefs.isFlipMeshOverlay:= FLIP; diff --git a/define_types.pas b/define_types.pas index 726ca0a..47b721d 100755 --- a/define_types.pas +++ b/define_types.pas @@ -71,6 +71,7 @@ function asPt4f(x,y,z,w: single): TPoint4f; function asSingle(i : longint): single; overload; function asSingle(b0,b1,b2,b3: byte): single; overload; function asInt(s : single): longint; +function StrToFloatX(Const S : String) : Extended; function specialsingle (var s:single): boolean; //isFinite function ExtractFileExtGzUpper(FileName: string): string; function FileExistsF(fnm: string): boolean; //returns false if file exists but is directory @@ -95,6 +96,19 @@ implementation {$IFDEF UNIX} BaseUnix, {$ELSE} windows, shlobj, {$ENDIF} sysutils, math; +function StrToFloatX(Const S : String) : Extended; +//like StrToFloat but accepts either decimal separator: '1.23' or '1,23' +var + fmt: TFormatSettings; +begin + fmt := DefaultFormatSettings; + fmt.DecimalSeparator := '.'; + if TryStrToFloat(s, result, fmt) then + exit; + fmt.DecimalSeparator := ','; + result := StrToFloat(S,fmt); +end; + function FileExistsF(fnm: string): boolean; //returns false if file exists but is directory begin result := FileExists(fnm); diff --git a/mainunit.pas b/mainunit.pas index a018522..b3b0c02 100755 --- a/mainunit.pas +++ b/mainunit.pas @@ -287,6 +287,7 @@ TGLForm1 = class(TForm) procedure SaveMenuClick(Sender: TObject); procedure SaveMz3(var mesh: TMesh; isSaveOverlays: boolean); procedure SaveTrack (var lTrack: TTrack); + function SaveMeshCore(lFilename: string): boolean; procedure SaveMesh(var mesh: TMesh; isSaveOverlays: boolean); procedure SaveMeshMenuClick(Sender: TObject); procedure SaveTracksMenuClick(Sender: TObject); @@ -360,7 +361,7 @@ implementation {$R *.lfm} {$IFDEF LCLCocoa} uses - nsappkitext, glcocoanscontext; + UserNotification, nsappkitext, glcocoanscontext; {$ENDIF} var gNode: TMesh; @@ -2123,6 +2124,57 @@ procedure TGLForm1.RestrictMenuClick(Sender: TObject); GLBoxRequestUpdate(Sender); end; +function GetFloat(prompt: string; min,def,max: extended): extended; +var + PrefForm: TForm; + OkBtn: TButton; + promptLabel: TLabel; + valEdit: TEdit; +begin + PrefForm:=TForm.Create(nil); + PrefForm.SetBounds(100, 100, 640, 112); + PrefForm.Caption:='Value required'; + PrefForm.Position := poScreenCenter; + PrefForm.BorderStyle := bsDialog; + //label + promptLabel:=TLabel.create(PrefForm); + promptLabel.Caption:= prompt; + if (min < max) then + promptLabel.Caption:= format('%s (range %g..%g)', [prompt, min, max]); + promptLabel.Left := 8; + promptLabel.Top := 12; + promptLabel.Parent:=PrefForm; + //edit + valEdit:=TEdit.create(PrefForm); + valEdit.Caption := FloatToStrF(def, ffGeneral, 8, 4); + valEdit.Top := 42; + valEdit.Width := PrefForm.Width - 16; + valEdit.Left := 8; + valEdit.Parent:=PrefForm; + //OK button + OkBtn:=TButton.create(PrefForm); + OkBtn.Caption:='OK'; + OkBtn.Top := 78; + OkBtn.Width := 128; + OkBtn.Left := PrefForm.Width - OkBtn.Width - 8; + OkBtn.Parent:=PrefForm; + OkBtn.ModalResult:= mrOK; + {$IFNDEF Darwin} ScaleDPIX(PrefForm, 96);{$ENDIF} + {$IFDEF LCLCocoa} + if gPrefs.DarkMode then SetFormDarkMode(PrefForm); + {$ENDIF} + PrefForm.ShowModal; + result := def; + if (PrefForm.ModalResult = mrOK) then begin + result := StrToFloatDef(valEdit.Caption, def); + if (min < max) and (result < min) then + result := min; + if (min < max) and (result > max) then + result := max; + end; + FreeAndNil(PrefForm); +end; //GetFloat() + procedure TGLForm1.SimplifyMeshMenuClick(Sender: TObject); var @@ -2133,9 +2185,10 @@ procedure TGLForm1.SimplifyMeshMenuClick(Sender: TObject); begin msStart := gettickcount(); nTri := length(gMesh.Faces); - s := '.3'; - if not inputquery('Track simplify', 'Enter reduction factor (e.g. 0.2 will decimate 80% of all triangles)', s) then exit; - r := StrToFloatDef(s, 0.5); + r := GetFloat('Enter reduction factor (e.g. 0.2 will decimate 80% of all triangles)', 0.001,0.3,0.999); + //s := '.3'; + //if not inputquery('Track simplify', 'Enter reduction factor (e.g. 0.2 will decimate 80% of all triangles)', s) then exit; + //r := StrToFloatDef(s, 0.5); if (r <= 0.0) or (r > 1.0) then begin showmessage('Error: reduction factor should be BETWEEN 0 and 1'); exit; @@ -3019,7 +3072,6 @@ procedure TGLForm1.CurvMenuClick(Sender: TObject); showmessage('Unable to compute curvature: no mesh is loaded (use File/Open).'); exit; end; - //isTemp := (MessageDlg('Temporary CURV file?', mtConfirmation, [mbNo, mbYes], 0) = mrYes); isTemp := (Sender as TMenuItem).Tag = 1; fnm := changefileext(gPrefs.PrevFilename[1],'.curv'); if isTemp then begin @@ -3139,7 +3191,7 @@ procedure TGLForm1.AboutMenuClick(Sender: TObject); const kSamp = 36; var - isAtlasStr, TrackStr, MeshStr, str: string; + titleStr, isAtlasStr, TrackStr, MeshStr, str: string; s: dword; i: integer; scale: single; @@ -3174,11 +3226,15 @@ procedure TGLForm1.AboutMenuClick(Sender: TObject); {$IFDEF DGL} + ' DGL'{$ENDIF} {$IFNDEF COREGL}+' (Legacy OpenGL)'{$ENDIF} {$IFDEF Darwin} - + {$IFDEF LCLCocoa} + +''; titleStr := Str; str := ' '+GetHardwareVersion + +LineEnding+' '+ GetOSVersion + {$ELSE} +LineEnding+' @: '+ AppDir2 +LineEnding+' '+ isExeReadOnly +LineEnding+' '+GetHardwareVersion +LineEnding+' '+ GetOSVersion + {$ENDIF} {$ENDIF} +LineEnding+' www.mricro.com :: BSD 2-Clause License (opensource.org/licenses/BSD-2-Clause)' +LineEnding+' FPS ' +inttostr(round( (kSamp*1000)/(gettickcount-s))) @@ -3190,12 +3246,17 @@ procedure TGLForm1.AboutMenuClick(Sender: TObject); +LineEnding+' Track Vertices '+inttostr(gTrack.n_vertices)+' Faces '+ inttostr(gTrack.n_faces) +' Count ' +inttostr(gTrack.n_count) +TrackStr +LineEnding+' Node Vertices '+inttostr(length(gNode.vertices))+' Faces '+ inttostr(length(gNode.faces)) - +LineEnding+' GPU '+gShader.Vendor - +LineEnding+'Press "Abort" to quit and open settings '+ininame; - ClipBoard.AsText:= str; + +LineEnding+' GPU '+gShader.Vendor; //str := DefaultToHomeDir('mega'); - i := MessageDlg(str,mtInformation,[mbAbort, mbOK],0); - if i = mrAbort then Quit2TextEditor; + {$IFDEF LCLCocoa} + ClipBoard.AsText:= titleStr + LineEnding + str; + ShowAlertSheet(GLForm1.Handle,titleStr, str); + {$ELSE} + ClipBoard.AsText:= str; + MessageDlg(str,mtInformation,[mbOK],0); + {$ENDIF} + //i := MessageDlg(str,mtInformation,[mbAbort, mbOK],0); + //if i = mrAbort then Quit2TextEditor; end; procedure TGLForm1.AddNodesMenuClick(Sender: TObject); @@ -3703,6 +3764,31 @@ procedure TGLForm1.SaveMesh(var mesh: TMesh; isSaveOverlays: boolean); end; {$ENDIF} +function TGLForm1.SaveMeshCore(lFilename: string): boolean; +var + x: string; +begin + result := false; + if (lFilename = '') or (length(gMesh.Faces) < 1) then begin + exit; + end; + result := true; + x := UpperCase(ExtractFileExt(lFilename)); + if (x <> '.MZ3') and (x <> '.PLY') and (x <> '.OBJ') and (x <> '.GII') then begin + x := '.MZ3'; + lFilename := lFilename + x; + end; + if (x = '.MZ3') then + gMesh.SaveMz3(lFilename) + else if (x = '.GII') then + gMesh.SaveGii(lFilename) + else if (x = '.PLY') then + gMesh.SavePly(lFilename) + else + gMesh.SaveObj(lFilename); +end; + + procedure TGLForm1.SaveMeshMenuClick(Sender: TObject); begin SaveMesh(gMesh, true); diff --git a/mesh.pas b/mesh.pas index b729e88..b7483f4 100755 --- a/mesh.pas +++ b/mesh.pas @@ -4958,7 +4958,8 @@ procedure TMesh.LoadVtk(const FileName: string); f: TFByte;//TextFile; strlst: TStringList; str: string; - i, j, num_v, num_f, num_f_allocated, num_strip, cnt: integer; + strips: array of int32; + c, i, j, k, num_v, num_f, num_f_allocated, num_strip, cnt: integer; nV: LongInt; isBinary: boolean = true; begin @@ -5001,8 +5002,16 @@ procedure TMesh.LoadVtk(const FileName: string); goto 666; end; setlength(vertices, num_v); //vertices = zeros(num_f, 9); - if isBinary then - blockread(f, vertices[0], 3 * 4 * num_v) + if isBinary then begin + blockread(f, vertices[0], 3 * 4 * num_v); + {$IFDEF ENDIAN_LITTLE} // VTK is ALWAYS big endian! + for i := 0 to (num_v -1) do begin + SwapSingle(vertices[i].X); + SwapSingle(vertices[i].Y); + SwapSingle(vertices[i].Z); + end; + {$ENDIF} + end else begin //if binary else ASCII for i := 0 to (num_v-1) do begin //n.b. ParaView and Mango pack multiple vertices per line, so we can not use ReadLnBin(f, str); @@ -5023,49 +5032,110 @@ procedure TMesh.LoadVtk(const FileName: string); ReadLnBin(f, str); end; if pos('TRIANGLE_STRIPS', UpperCase(str)) = 1 then begin - if isBinary then begin - showmessage('Unable to read VTK binary "TRIANGLE_STRIPS"'); - goto 666; - end; strlst.DelimitedText := str; num_strip := StrToIntDef(strlst[1],0); cnt := StrToIntDef(strlst[2],0); num_f_allocated := cnt; + (*if isBinary then begin + showmessage(format('Unable to read VTK binary "TRIANGLE_STRIPS" %d %d', [num_strip, cnt])); + goto 666; + end;*) setlength(faces, num_f_allocated); //not sure how many triangles, lets guess num_f := 0; - for i := 0 to (num_strip -1) do begin - ReadLnBin(f, str); - strlst.DelimitedText := str; - cnt := StrToIntDef(strlst[0],0); - if (cnt < 3) then begin - setlength(faces,0); - num_f := 0; - goto 666; - end; - if ((num_f+cnt) > num_f_allocated) then begin //need to allocate more faces - num_f_allocated := num_f_allocated + cnt + kBlockSz; - setlength(faces, num_f_allocated); - end; - faces[num_f].Y := StrToIntDef(strlst[1],0); - faces[num_f].X := StrToIntDef(strlst[2],0); - faces[num_f].Z := StrToIntDef(strlst[3],0); - num_f := num_f + 1; - if (cnt > 3) then begin - for j := 4 to cnt do begin - //http://ogldev.atspace.co.uk/www/tutorial27/tutorial27.html - // winding order is reversed on the odd triangles - if odd(j) then begin //ITK snap triangle winding reverses with each new point - faces[num_f].X := StrToIntDef(strlst[j-1],0); - faces[num_f].Y := StrToIntDef(strlst[j-2],0); - end else begin - faces[num_f].X := StrToIntDef(strlst[j-2],0); - faces[num_f].Y := StrToIntDef(strlst[j-1],0); - end; - faces[num_f].Z := StrToIntDef(strlst[j],0); + if isBinary then begin + //Harvard Surgical Planning Laboratory MRB files are zip files with binary VTK Triangle_Strips + c := cnt; + setlength(strips, cnt); //vertices = zeros(num_f, 9); + blockread(f, strips[0], 4 * cnt); + {$IFDEF ENDIAN_LITTLE} // VTK is ALWAYS big endian! + for i := 0 to (cnt -1) do + SwapLongInt(strips[i]); + {$ENDIF} + k := 0; + for i := 0 to (num_strip -1) do begin + cnt := strips[k]; + k := k + 1; + if ((cnt < 3) or (k > c)) then begin + setlength(faces,0); + num_f := 0; + goto 666; + end; + if ((num_f+cnt) > num_f_allocated) then begin //need to allocate more faces + num_f_allocated := num_f_allocated + cnt + kBlockSz; + setlength(faces, num_f_allocated); + end; + faces[num_f].X := strips[k]; + faces[num_f].Y := strips[k+1]; + faces[num_f].Z := strips[k+2]; + k := k + 3; + num_f := num_f + 1; + if (cnt > 3) then begin + for j := 4 to cnt do begin + //http://ogldev.atspace.co.uk/www/tutorial27/tutorial27.html + // winding order is reversed on the odd triangles + if odd(j) then begin //ITK snap triangle winding reverses with each new point + faces[num_f].X := strips[k-2]; + faces[num_f].Y := strips[k-1]; + end else begin + faces[num_f].X := strips[k-1]; + faces[num_f].Y := strips[k-2]; + end; + faces[num_f].Z := strips[k]; + k := k + 1; num_f := num_f + 1; - end; //for j: each additional strip point - end; //cnt > 3 - end; //for i: each strip + end; //for j: each additional strip point + end; //cnt > 3 + end; //for i: each strip + (*k := faces[0].X; + c := faces[0].X; + for i := 0 to (num_f -1) do + if faces[i].X > k then k := faces[i].X; + for i := 0 to (num_f -1) do + if faces[i].X < c then c := faces[i].X; + for i := 0 to (num_f -1) do + if faces[i].Y > k then k := faces[i].Y; + for i := 0 to (num_f -1) do + if faces[i].Y < c then c := faces[i].Y; + for i := 0 to (num_f -1) do + if faces[i].Z > k then k := faces[i].Z; + for i := 0 to (num_f -1) do + if faces[i].Z < c then c := faces[i].Z; + showmessage(format('faces %d triangle indices %d..%d', [num_f,c,k])); *) + end else begin + for i := 0 to (num_strip -1) do begin + ReadLnBin(f, str); + strlst.DelimitedText := str; + cnt := StrToIntDef(strlst[0],0); + if (cnt < 3) then begin + setlength(faces,0); + num_f := 0; + goto 666; + end; + if ((num_f+cnt) > num_f_allocated) then begin //need to allocate more faces + num_f_allocated := num_f_allocated + cnt + kBlockSz; + setlength(faces, num_f_allocated); + end; + faces[num_f].Y := StrToIntDef(strlst[1],0); + faces[num_f].X := StrToIntDef(strlst[2],0); + faces[num_f].Z := StrToIntDef(strlst[3],0); + num_f := num_f + 1; + if (cnt > 3) then begin + for j := 4 to cnt do begin + //http://ogldev.atspace.co.uk/www/tutorial27/tutorial27.html + // winding order is reversed on the odd triangles + if odd(j) then begin //ITK snap triangle winding reverses with each new point + faces[num_f].X := StrToIntDef(strlst[j-1],0); + faces[num_f].Y := StrToIntDef(strlst[j-2],0); + end else begin + faces[num_f].X := StrToIntDef(strlst[j-2],0); + faces[num_f].Y := StrToIntDef(strlst[j-1],0); + end; + faces[num_f].Z := StrToIntDef(strlst[j],0); + num_f := num_f + 1; + end; //for j: each additional strip point + end; //cnt > 3 + end; //for i: each strip + end; //if binary else ASCII setlength(faces, num_f); goto 666; @@ -5100,11 +5170,11 @@ procedure TMesh.LoadVtk(const FileName: string); SwapLongInt(faces[i].Y); SwapLongInt(faces[i].Z); end; - for i := 0 to (num_v -1) do begin + (*for i := 0 to (num_v -1) do begin SwapSingle(vertices[i].X); SwapSingle(vertices[i].Y); SwapSingle(vertices[i].Z); - end; + end;*) {$ENDIF} end else begin //if binary else ASCII - indexed from 0 for i := 0 to (num_f -1) do begin @@ -5152,7 +5222,7 @@ function TMesh.CheckMesh: boolean; if specialsingle( vertices[i].X) or specialsingle( vertices[i].Y) or specialsingle( vertices[i].Z) then isNan := true; if isNan then begin - showmessage('Vertices are corrupted (infinity of NaN values)'); + showmessage('Vertices are corrupted (infinity of NaN values) '+inttostr(length(vertices))); result := false; end; if not result then diff --git a/opts.inc b/opts.inc index 8cdc2ad..f119e91 100755 --- a/opts.inc +++ b/opts.inc @@ -1,3 +1,4 @@ +{$DEFINE MYPY} //{$DEFINE DGL} //for DGL library, otherwise gl/glext //{$DEFINE COREGL} {$DEFINE GEOM_GLEXT} //if glext.pp defines diff --git a/optsCompat.inc b/optsCompat.inc index 8cdc2ad..f119e91 100755 --- a/optsCompat.inc +++ b/optsCompat.inc @@ -1,3 +1,4 @@ +{$DEFINE MYPY} //{$DEFINE DGL} //for DGL library, otherwise gl/glext //{$DEFINE COREGL} {$DEFINE GEOM_GLEXT} //if glext.pp defines diff --git a/optsCompatGeom.inc b/optsCompatGeom.inc index 8cdc2ad..f119e91 100755 --- a/optsCompatGeom.inc +++ b/optsCompatGeom.inc @@ -1,3 +1,4 @@ +{$DEFINE MYPY} //{$DEFINE DGL} //for DGL library, otherwise gl/glext //{$DEFINE COREGL} {$DEFINE GEOM_GLEXT} //if glext.pp defines diff --git a/optsCore.inc b/optsCore.inc index 5cdf744..2a64191 100755 --- a/optsCore.inc +++ b/optsCore.inc @@ -1,3 +1,4 @@ +{$DEFINE MYPY} //{$DEFINE DGL} //for DGL library, otherwise gl/glext {$DEFINE COREGL} //{$DEFINE HEMISSAO} //for hemispherical SSAO - requires shaders that save surface normal - see hemiAO3 and hemiAO diff --git a/prefs.pas b/prefs.pas index c84695c..9d20c5f 100755 --- a/prefs.pas +++ b/prefs.pas @@ -28,7 +28,7 @@ TPrefs = record ObjColor,BackColor: TColor; PrevFilename, PrevScriptName: TMRU; //{$IFDEF Darwin}BaseDirname, {$ENDIF} //OSX Sierra puts application in random directory, so 'Sample' 'BrainNet' folders will be in unknown locations - FontName, PrevTrackname, PrevNodename, PrevOverlayname,PrevScript, InitScript : string; + PyLib, FontName, PrevTrackname, PrevNodename, PrevOverlayname,PrevScript, InitScript : string; TextColor,TextBorder,GridAndBorder: TRGBA; ColorbarSize: single; //ColorBarPos: TUnitRect; @@ -312,6 +312,7 @@ procedure SetDefaultPrefs (var lPrefs: TPrefs; lEverything, askUserIfMissing: b for i := 1 to kNumDefaultMesh do PrevFilename[i] := DefaultMeshName(i, lPrefs, askUserIfMissing); FontName := ''; + PyLib := ''; end; end; with lPrefs do begin @@ -626,6 +627,7 @@ function IniFile(lRead: boolean; lFilename: string; var lPrefs: TPrefs): boolean IniStr(lRead, lIniFile, 'PrevOverlayname', lPrefs.PrevOverlayname); IniStr(lRead,lIniFile,'PrevScript',lPrefs.PrevScript); IniStrX(lRead,lIniFile,'FontName',lPrefs.FontName); + IniStrX(lRead,lIniFile,'PyLib',lPrefs.PyLib); IniMRU(lRead,lIniFile,'PrevFilename',lPrefs.PrevFilename, lPrefs); //IniMRU(lRead,lIniFile,'PrevScriptName',lPrefs.PrevScriptName); IniRGBA(lRead,lIniFile, 'TextColor',lPrefs.TextColor); diff --git a/proc_py.pas b/proc_py.pas new file mode 100755 index 0000000..9f01237 --- /dev/null +++ b/proc_py.pas @@ -0,0 +1,90 @@ +unit proc_py; + +{$mode objfpc}{$H+} + +interface + +uses + SysUtils, + PythonEngine; + +type + TStringDecodeRecW = record + SFrom, STo: WideString; + end; + +procedure Py_SetSysPath(const Dirs: array of string; DoAdd: boolean); + +function SBegin(const s, sub: string): boolean; +function SDecodeW(const S: WideString; const Decode: array of TStringDecodeRecW): WideString; +function SWideStringToPythonString(const Str: Widestring): string; + +const + cDefFixedFontName = {$ifdef windows} 'Consolas' {$else} {$ifdef linux} 'Ubuntu Mono' {$else} 'Monaco' {$endif} {$endif}; + cDefFixedFontSize = {$ifdef windows} 9 {$else} 11 {$endif}; + + cDefVarFontName = {$ifdef windows} 'Tahoma' {$else} {$ifdef linux} 'Ubuntu' {$else} 'default' {$endif} {$endif}; + cDefVarFontSize = {$ifdef windows} 9 {$else} 10 {$endif}; + + +implementation + +function SDecodeW(const S: WideString; const Decode: array of TStringDecodeRecW): WideString; +var + i, j: Integer; + DoDecode: Boolean; +begin + Result := ''; + i := 1; + repeat + if i > Length(S) then Break; + DoDecode := False; + for j := Low(Decode) to High(Decode) do + with Decode[j] do + if (SFrom <> '') and (SFrom = Copy(S, i, Length(SFrom))) then + begin + DoDecode := True; + Result := Result + STo; + Inc(i, Length(SFrom)); + Break + end; + if DoDecode then Continue; + Result := Result + S[i]; + Inc(i); + until False; +end; + +function SWideStringToPythonString(const Str: Widestring): string; +const + Decode: array[0..0] of TStringDecodeRecW = + ((SFrom: '"'; STo: '"+''"''+"')); +begin + Result:= UTF8Encode(SDecodeW(Str, Decode)); + Result:= 'r"'+Result+'"'; +end; + +function SBegin(const s, sub: string): boolean; +begin + Result:= Copy(s, 1, Length(sub))=sub; +end; + +procedure Py_SetSysPath(const Dirs: array of string; DoAdd: boolean); +var + Str, Sign: string; + i: Integer; +begin + Str:= ''; + for i:= 0 to Length(Dirs)-1 do + Str:= Str + 'r"' + Dirs[i] + '"' + ','; + if DoAdd then + Sign:= '+=' + else + Sign:= '='; + Str:= Format('sys.path %s [%s]', [Sign, Str]); + GetPythonEngine.ExecString(Str); +end; + + + +end. + diff --git a/script/basic_paint_surface.gls b/script/basic_paint_surface.gls index 1a429c1..ef71706 100755 --- a/script/basic_paint_surface.gls +++ b/script/basic_paint_surface.gls @@ -1,12 +1,13 @@ -BEGIN - RESETDEFAULTS; - AZIMUTHELEVATION(70, 15); - MESHLOAD('BrainMesh_ICBM152Right.mz3'); - OVERLAYLOAD('motor_4t95vol.nii.gz'); - OVERLAYMINMAX(1,2,12); - OVERLAYLOAD('motor_4t95vol.nii.gz'); - OVERLAYMINMAX(2,-1,-2); - COLORBARVISIBLE(true); - OVERLAYTRANSPARENCYONBACKGROUND(25); -END. - +begin + resetdefaults(); + azimuthelevation(70, 15); + meshload('BrainMesh_ICBM152Right.mz3'); + overlayload('motor_4t95vol.nii.gz'); + overlayminmax(1,2,12); + overlayload('motor_4t95vol.nii.gz'); + overlayminmax(2,-1,-2); + colorbarvisible(true); + overlaytransparencyonbackground(25); + meshcurv(); +end. + diff --git a/script/create_atlas.gls b/script/create_atlas.gls index 47b1836..d4a2256 100644 --- a/script/create_atlas.gls +++ b/script/create_atlas.gls @@ -1,17 +1,17 @@ var n,i,j: integer; msk: array of integer; -BEGIN - RESETDEFAULTS; - AZIMUTHELEVATION(240, 15); - MESHLOAD('AICHAhr_left.mz3'); - n := AtlasMaxIndex(0); +begin + resetdefaults(); + azimuthelevation(240, 15); + meshload('AICHAhr_left.mz3'); + n := atlasmaxindex(0); for i := n downto 1 do begin setlength(msk, i); for j := 1 to i do msk[j-1] := j; - ATLASHIDE(0,msk); + atlashide(0,msk); wait(30); end; - ATLASHIDE(0,[]); //show everything -END. \ No newline at end of file + atlashide(0,[]); //show everything +end. \ No newline at end of file diff --git a/script/fmri_mesh.gls b/script/fmri_mesh.gls index 0b904ae..0af2dde 100755 --- a/script/fmri_mesh.gls +++ b/script/fmri_mesh.gls @@ -1,9 +1,10 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('BrainMesh_ICBM152Right.mz3'); - OVERLAYLOAD('motor_4t95mesh.mz3'); - OVERLAYCOLORNAME(1, 'Red'); - SHADERXRAY(1.0, 0.3); - AZIMUTHELEVATION(110, 15); -END. +begin + resetdefaults(); + meshload('BrainMesh_ICBM152Right.mz3'); + overlayload('motor_4t95mesh.mz3'); + overlaycolorname(1, 'red'); + shaderxray(1.0, 0.3); + azimuthelevation(110, 15); + meshcurv(); +end. diff --git a/script/frontal_atlas.gls b/script/frontal_atlas.gls index 8205b74..097e971 100644 --- a/script/frontal_atlas.gls +++ b/script/frontal_atlas.gls @@ -1,10 +1,10 @@ -BEGIN - RESETDEFAULTS; - //assign intensities to superior frontal regions (AICHA regions 4..6) - // save as file named 'surficeTemp.mz3' in our home directory - ATLASSTATMAP('AICHAhr_left.mz3','surficeTemp.mz3',[4,5,6],[7,3,4]); - MESHLOAD('lh.pial'); - OVERLAYLOAD('surficeTemp.mz3'); - SHADERXRAY(1.0, 0.3); -END. +begin + resetdefaults(); + //assign intensities to superior frontal regions (aicha regions 4..6) + // save as file named 'surficetemp.mz3' in our home directory + atlasstatmap('AICHAhr_left.mz3','surficetemp.mz3',[4,5,6],[7,3,4]); + meshload('lh.pial'); + overlayload('surficetemp.mz3'); + shaderxray(1.0, 0.3); +end. diff --git a/script/hide_curves.gls b/script/hide_curves.gls index c6864c3..c695595 100644 --- a/script/hide_curves.gls +++ b/script/hide_curves.gls @@ -1,9 +1,9 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('BrainMesh_ICBM152Left_smoothed.mz3'); - MESHCURV; - SHADERNAME('HideCurves'); - OVERLAYLOAD('CIT168.mz3'); - SHADERFORBACKGROUNDONLY(true); - SHADERADJUST('CurvThreshHi', 0.44); -END. \ No newline at end of file +begin + resetdefaults(); + meshload('BrainMesh_ICBM152Left_smoothed.mz3'); + meshcurv(); + shadername('hidecurves'); + overlayload('CIT168.mz3'); + shaderforbackgroundonly(true); + shaderadjust('curvthreshhi', 0.44); +end. \ No newline at end of file diff --git a/script/mesh.gls b/script/mesh.gls index 61420a7..7e12389 100755 --- a/script/mesh.gls +++ b/script/mesh.gls @@ -1,10 +1,10 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('mni152_2009.mz3'); - OVERLAYLOAD('motor_4t95mesh.mz3'); - CLIPAZIMUTHELEVATION(0.37, 0, 140); - SHADERAMBIENTOCCLUSION(0.5); - AZIMUTHELEVATION(90, 20); - SHADERXRAY(1.0, 0.3); -END. +begin + resetdefaults(); + meshload('mni152_2009.mz3'); + overlayload('motor_4t95mesh.mz3'); + clipazimuthelevation(0.37, 0, 140); + shaderambientocclusion(0.5); + azimuthelevation(90, 20); + shaderxray(1.0, 0.3); +end. diff --git a/script/newer_2017.gls b/script/newer_2017.gls index 8a3fb79..37225a4 100644 --- a/script/newer_2017.gls +++ b/script/newer_2017.gls @@ -1,22 +1,22 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('BrainMesh_ICBM152Right.mz3'); - MESHCURV; - OVERLAYMINMAX(1,-1,1); - OVERLAYCOLORNAME(1,'Surface'); - //OVERLAYCOLORNAME(1,'Bone'); - OVERLAYINVERT(1,true); - //OVERLAYTRANSLUCENT(1, true); - OVERLAYLOAD('motor_4t95vol.nii.gz'); - OVERLAYCOLORNAME(2,'Kelvin') - OVERLAYMINMAX(2,2,7); - OVERLAYLOAD('scalp.mz3'); - OVERLAYCOLORNAME(3,'Gold'); - //SHADERNAME('Metal'); - SHADERXRAY(1.0, 0.9); - MESHOVERLAYORDER(true); - COLORBARVISIBLE(false); - SHADERAMBIENTOCCLUSION(0.05); - AZIMUTHELEVATION(90, 15); - CLIPAZIMUTHELEVATION(0.5, 0, 90); -END. +begin + resetdefaults(); + meshload('BrainMesh_ICBM152Right.mz3'); + meshcurv(); + overlayminmax(1,-1,1); + overlaycolorname(1,'surface'); + //overlaycolorname(1,'bone'); + overlayinvert(1,true); + //overlaytranslucent(1, true); + overlayload('motor_4t95vol.nii.gz'); + overlaycolorname(2,'kelvin') + overlayminmax(2,2,7); + overlayload('scalp.mz3'); + overlaycolorname(3,'gold'); + //shadername('metal'); + shaderxray(1.0, 0.9); + meshoverlayorder(true); + colorbarvisible(false); + shaderambientocclusion(0.05); + azimuthelevation(90, 15); + clipazimuthelevation(0.5, 0, 90); +end. diff --git a/script/node.gls b/script/node.gls index 7c03202..a0ff43b 100755 --- a/script/node.gls +++ b/script/node.gls @@ -1,20 +1,19 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('BrainMesh_ICBM152Left.mz3'); - EDGELOAD('LPBA40.edge'); - CLIPAZIMUTHELEVATION(0.3, 0, 130); - NODESIZE(6, true); - EDGESIZE(3,true); - NODEHEMISPHERE(-1); - AZIMUTHELEVATION(250, 35); - EDGECOLOR('ACTC',TRUE); - NODECOLOR('BLUE',TRUE); - NODETHRESH(1.0,1.0); - EDGETHRESH(0.5,1.0); - - MESHCURV; - OVERLAYMINMAX(1,-1,1); - OVERLAYCOLORNAME(1,'Surface'); - OVERLAYINVERT(1,true); - OVERLAYTRANSLUCENT(1, true); -END. +begin + resetdefaults(); + meshload('BrainMesh_ICBM152Left.mz3'); + edgeload('LPBA40.edge'); + clipazimuthelevation(0.3, 0, 130); + nodesize(6, true); + edgesize(3,true); + nodehemisphere(-1); + azimuthelevation(250, 35); + edgecolor('actc',true); + nodecolor('blue',true); + nodethresh(1.0,1.0); + edgethresh(0.5,1.0); + meshcurv(); + overlayminmax(1,-1,1); + overlaycolorname(1,'surface'); + overlayinvert(1,true); + overlaytranslucent(1, true); +end. diff --git a/script/shaders.gls b/script/shaders.gls index a705150..cab0ff9 100755 --- a/script/shaders.gls +++ b/script/shaders.gls @@ -1,43 +1,41 @@ const - kFramesPerRotation = 180; + kframesperrotation = 180; var i: integer; s: single; -BEGIN - RESETDEFAULTS; - MESHCOLOR(210, 148, 148); - MESHLOAD('BrainMesh_ICBM152Left.mz3'); - EDGELOAD('LPBA40.edge'); - CLIPAZIMUTHELEVATION(0.3, 0, 130); - NODESIZE(6, true); - EDGESIZE(3,true); - NODEHEMISPHERE(-1); - AZIMUTHELEVATION(250, 35); - EDGECOLOR('ACTC',TRUE); - NODECOLOR('RED',TRUE); - NODETHRESH(1.0,1.0); - EDGETHRESH(0.5,1.0); - FOR i := 1 to kFramesPerRotation * 5 DO BEGIN +begin + resetdefaults(); + meshcolor(210, 148, 148); + meshload('BrainMesh_ICBM152Left.mz3'); + edgeload('LPBA40.edge'); + clipazimuthelevation(0.3, 0, 130); + nodesize(6, true); + edgesize(3,true); + nodehemisphere(-1); + azimuthelevation(250, 35); + edgecolor('actc',true); + nodecolor('red',true); + nodethresh(1.0,1.0); + edgethresh(0.5,1.0); + for i := 1 to kframesperrotation * 5 do begin s := 0.5 + (i+0.0)/72; - IF s <= 1 THEN - CAMERADISTANCE(s); - IF (i MOD kFramesPerRotation) = 0 THEN BEGIN - CASE (i DIV kFramesPerRotation) OF - 1: SHADERNAME('metal'); - 2: SHADERNAME('wireframe'); + if s <= 1 then + cameradistance(s); + if (i mod kframesperrotation) = 0 then begin + case (i div kframesperrotation) of + 1: shadername('metal'); + 2: shadername('wireframe'); 3: begin - SHADERNAME('toon'); - SHADERAMBIENTOCCLUSION(0); + shadername('toon'); + shaderambientocclusion(0); end; 4: begin - SHADERNAME('wire'); - SHADERFORBACKGROUNDONLY(true); + shadername('wire'); + shaderforbackgroundonly(true); end; - END; - END; - AZIMUTH( round(360.0/kFramesPerRotation)); - WAIT(20); - END; -END. - - + end; + end; + azimuth( round(360.0/kframesperrotation)); + wait(20); + end; +end. \ No newline at end of file diff --git a/script/track.gls b/script/track.gls index 6638d81..178d605 100755 --- a/script/track.gls +++ b/script/track.gls @@ -1,15 +1,15 @@ -CONST - kSteps = 100; -VAR +const + ksteps = 100; +var i: integer; -BEGIN - RESETDEFAULTS; - MESHLOAD('stroke.mz3'); - TRACKLOAD('stroke.trk.gz'); - TRACKPREFS(15, 3, 0.5); - FOR i := 1 TO kSteps DO BEGIN - CLIPAZIMUTHELEVATION(( (0.8*i)/kSteps ), 0, 130); - WAIT(20); - END; -END. +begin + resetdefaults(); + meshload('stroke.mz3'); + trackload('stroke.trk.gz'); + trackprefs(15, 3, 0.5); + for i := 1 to ksteps do begin + clipazimuthelevation(( (0.8*i)/ksteps ), 0, 130); + wait(20); + end; +end. diff --git a/scriptengine.lfm b/scriptengine.lfm index 8d0b871..2759977 100755 --- a/scriptengine.lfm +++ b/scriptengine.lfm @@ -1,8 +1,8 @@ object ScriptForm: TScriptForm Tag = 2 - Left = 493 + Left = 451 Height = 380 - Top = 167 + Top = 74 Width = 420 ActiveControl = Memo1 Caption = 'ScriptForm' @@ -68,6 +68,11 @@ object ScriptForm: TScriptForm Caption = '&New' OnClick = New1Click end + object NewPython1: TMenuItem + Tag = 1 + Caption = 'New Python' + OnClick = New1Click + end object Open1: TMenuItem Caption = '&Open...' OnClick = Open1Click @@ -135,37 +140,48 @@ object ScriptForm: TScriptForm ShortCut = 16470 OnClick = Paste1Click end + object ListCommands1: TMenuItem + Caption = 'List all commands' + OnClick = ListCommands1Click + end end object Insert1: TMenuItem Caption = 'Insert' - OnClick = Insert1Click object MainImage1: TMenuItem Caption = 'Mesh' object meshload1: TMenuItem Tag = 4 Caption = 'meshload' - Hint = 'meshload(filename: string); Opens a mesh to view.' + Hint = 'meshload (filename: string) Opens a mesh to view.' OnClick = InsertCommand end object meshcolor1: TMenuItem Tag = 36 Caption = 'meshcolor' - Hint = 'meshcolor(R,G,B: byte); Set red/green/blue components of main image.' + Hint = 'meshcolor (r, g, b: integer) Set red/green/blue components of main image.' OnClick = InsertCommand end object meshcurv1: TMenuItem Caption = 'meshcurv' - Hint = 'meshcurv(); Displays mesh curvature, so crevices appear dark.' + Hint = 'meshcurv () Displays mesh curvature, so crevices appear dark.' OnClick = InsertCommand end - object meshreversefaces1: TMenuItem - Caption = 'meshreversefaces' - Hint = 'meshreversefaces(): reverse triangle winding to reverse front/back faces' - end object meshcreate1: TMenuItem Tag = 242322 Caption = 'meshcreate' - Hint = 'MESHCREATE(niiname, meshname: string; threshold, decimateFrac: single; minimumClusterVox, smoothStyle: integer); Convert a NIfTI voxel-based image into a mesh' + Hint = 'meshcreate (niiname, meshname: string; threshold, decimateFrac: float; minimumClusterVox, smoothStyle: integer) Convert a NIfTI voxel-based image into a mesh' + OnClick = InsertCommand + end + object meshreversefaces1: TMenuItem + Caption = 'meshreversefaces' + Hint = 'meshreversefaces() reverse triangle winding to reverse front/back faces' + OnClick = InsertCommand + end + object meshsave1: TMenuItem + Tag = 4 + Caption = 'meshsave' + Hint = 'meshsave (filename: string) Saves currently open mesh to disk.' + OnClick = InsertCommand end end object Overlays1: TMenuItem @@ -173,67 +189,73 @@ object ScriptForm: TScriptForm object overlayload1: TMenuItem Tag = 4 Caption = 'overlayload' - Hint = 'overlayload(filename: string): integer; Will add the overlay named filename and return the number of the overlay.' + Hint = 'overlayload (filename: string) integer; Will add the overlay named filename and return the number of the overlay.' OnClick = InsertCommand end object overlayadditive1: TMenuItem Tag = 1 Caption = 'overlayadditive' - Hint = 'overlayadditive(add: boolean); Determines whether overlay colors are combined by adding or mixing the colors. For example, overlap of red and green overlays will appear yellow if additive is true' + Hint = 'overlayadditive (add: boolean) Determines whether overlay colors are combined by adding or mixing the colors. For example, overlap of red and green overlays will appear yellow if additive is true' OnClick = InsertCommand end object overlaycloseall1: TMenuItem Caption = 'overlaycloseall' - Hint = 'overlaycloseall(); This function has no parameters. All open overlays will be closed.' + Hint = 'overlaycloseall () This function has no parameters. All open overlays will be closed.' OnClick = InsertCommand end object overlaycolorname1: TMenuItem Tag = 1214 Caption = 'overlaycolorname' - Hint = 'overlaycolorname(overlay: integer; filename: string); Set the colorscheme for the target overlay to a specified name.' + Hint = 'overlaycolorname (overlay: integer; filename: string) Set the colorscheme for the target overlay to a specified name.' OnClick = InsertCommand end object overlayminmax1: TMenuItem Tag = 1223 Caption = 'overlayminmax' - Hint = 'overlayminmax(overlay: integer; min, max: single); Sets the color range for the overlay.' + Hint = 'overlayminmax (overlay: integer; min, max: float) Sets the color range for the overlay.' OnClick = InsertCommand end object overlaytransparencyonbackground1: TMenuItem Tag = 2 Caption = 'overlaytransparencyonbackground' - Hint = 'overlaytransparencyonbackground(percent: integer); Controls the opacity of the overlays on the background.' + Hint = 'overlaytransparencyonbackground (percent: integer) Controls the opacity of the overlays on the background.' OnClick = InsertCommand end object overlaycolorfromzero1: TMenuItem Tag = 1 Caption = 'overlaycolorfromzero' - Hint = 'overlaycolorfromzero(fromzero: boolean); If set to false, then the full color range is used to show the overlay.' + Hint = 'overlaycolorfromzero (fromzero: boolean) If set to false, then the full color range is used to show the overlay.' Visible = False OnClick = InsertCommand end object overlayvisible1: TMenuItem Tag = 1211 Caption = 'overlayvisible' - Hint = 'overlayvisible(overlay: integer; visible: boolean); The feature allows you to make individual overlays visible or invisible.' + Hint = 'overlayvisible (overlay: integer; visible: boolean) This feature allows you to make individual overlays visible or invisible.' OnClick = InsertCommand end object overlaytranslucent1: TMenuItem Tag = 1211 Caption = 'overlaytranslucent' - Hint = 'overlaytranslucent(overlay: integer; translucent: boolean); The feature allows you to make individual overlays translucent or opaque.' + Hint = 'overlaytranslucent (overlay: integer; translucent: boolean) The feature allows you to make individual overlays translucent or opaque.' OnClick = InsertCommand end object overlayinvert1: TMenuItem Tag = 1211 Caption = 'overlayinvert' - Hint = 'overlayinvert(overlay: integer; invert: boolean); toggle whether overlay color scheme is inverted.' + Hint = 'overlayinvert (overlay: integer; invert: boolean) toggle whether overlay color scheme is inverted.' OnClick = InsertCommand end object overlaysmoothvoxelwisedata1: TMenuItem Tag = 1 Caption = 'overlaysmoothvoxelwisedata' - Hint = 'overlaysmoothvoxelwisedata(smooth: boolean); Determines if overlays are loaded using interpolation (smooth) or nearest neighbor (un-smoothed) interpolation.' + Hint = 'overlaysmoothvoxelwisedata (smooth: boolean) Determines if overlays are loaded using interpolation (smooth) or nearest neighbor (un-smoothed) interpolation.' + OnClick = InsertCommand + end + object meshoverlayorder1: TMenuItem + Tag = 1 + Caption = 'meshoverlayorder' + Hint = 'meshoverlayorder (flip: boolean) If true, the mesh will be drawn after the overlay, and xray sliders will influence overlay not mesh.' OnClick = InsertCommand end end @@ -242,79 +264,79 @@ object ScriptForm: TScriptForm object edgeload1: TMenuItem Tag = 4 Caption = 'edgeload' - Hint = 'edgeload(filename: string); Loads a BrainNet Viewer format Edge file, e.g. connectome map' + Hint = 'edgeload (filename: string) Loads a BrainNet Viewer format Edge file, e.g. connectome map' OnClick = InsertCommand end object edgecolor1: TMenuItem Tag = 1411 Caption = 'edgecolor' - Hint = 'edgecolor(name: string; varies: boolean); Select color scheme for connectome edge map' + Hint = 'edgecolor (name: string; varies: boolean) Select color scheme for connectome edge map' OnClick = InsertCommand end object edgecreate1: TMenuItem Tag = 1419 Caption = 'edgecreate' - Hint = 'createedge(filename: string; const mtx: array of single); Create a connectome edge map. For example, if you have 3 nodes, mtx should be an array with 9 values (3*3). For example, edgecreate('''',[1,2,3, 2,4,5, 3,5,6]) creates the links between 3 regions. Note the lower triangle and diagonal of this matrix is ignored.' + Hint = 'edgecreate (filename: string; const mtx: array of single) Create a connectome edge map. For example, if you have 3 nodes, mtx should be an array with 9 values (3*3). For example, edgecreate('''',[1,2,3, 2,4,5, 3,5,6]) creates the links between 3 regions. Note the lower triangle and diagonal of this matrix is ignored.' OnClick = InsertCommand end object edgesize1: TMenuItem Tag = 1311 Caption = 'edgesize' - Hint = 'edgesize(size: single; varies: boolean);' + Hint = 'edgesize (size: float; varies: boolean) Set the diameters of the cylinders of the connectome.' OnClick = InsertCommand end object edgethresh1: TMenuItem Tag = 23 Caption = 'edgethresh' - Hint = 'edgethresh(lo, hi: single); Set minimum and maximum values for connectome edge diameters.' + Hint = 'edgethresh (lo, hi: float) Set minimum and maximum values for connectome edge diameters.' OnClick = InsertCommand end object nodeload1: TMenuItem Tag = 4 Caption = 'nodeload' - Hint = 'nodeload(filename: string); Loads BrainNet viewer format node file.' + Hint = 'nodeload (filename: string) Loads BrainNet viewer format node file.' OnClick = InsertCommand end object nodecolor1: TMenuItem Tag = 1411 Caption = 'nodecolor' - Hint = 'nodecolor(name: string; varies: boolean); ' + Hint = 'nodecolor (name: string; varies: boolean) set colorscheme used for nodes.' OnClick = InsertCommand end object nodecreate1: TMenuItem Tag = 1459 Caption = 'nodecreate' - Hint = 'nodecreate(filename: string; const x, y, z, color, radius: array of single); Generates and displays a connectome hub map. The arrays x,y,z refer to the 3D spatial coordinates. The optional color and radius arrays allow you to specify the size. For example nodecreate(''mynode.node'',[0, 10, 8], [9, 0, 8], [0, 9, 0], [], []) creates three spheres with the default size and color. On the other hand, nodecreate(''mynode.node'',[0, 10, 8], [9, 0, 8], [0, 9, 0], [1, 2, 9], [5]) creates three spheres each with a unique color intensity and with a size of 5.' + Hint = 'nodecreate (filename: string; const x, y, z, color, radius: array of single) Generates and displays a connectome hub map. The arrays x,y,z refer to the 3D spatial coordinates. The optional color and radius arrays allow you to specify the size. For example nodecreate(''mynode.node'',[0, 10, 8], [9, 0, 8], [0, 9, 0], [], []) creates three spheres with the default size and color. On the other hand, nodecreate(''mynode.node'',[0, 10, 8], [9, 0, 8], [0, 9, 0], [1, 2, 9], [5]) creates three spheres each with a unique color intensity and with a size of 5.' OnClick = InsertCommand end object nodehemisphere1: TMenuItem Tag = 2 Caption = 'nodehemisphere' - Hint = 'nodehemisphere(val: integer); -1 for left hemipshere, 0 for both, 1 for right' + Hint = 'nodehemisphere (val: integer) Set -1 for left hemipshere, 0 for both, 1 for right' OnClick = InsertCommand end object ndepolarity1: TMenuItem Tag = 2 Caption = 'nodepolarity' - Hint = 'nodepolarity(val: integer); -1 for negative only, 0 for either, 1 for positive only' + Hint = 'nodepolarity (val: integer) Set -1 for negative only, 0 for either, 1 for positive only.' OnClick = InsertCommand end object nodesize1: TMenuItem Tag = 1311 Caption = 'nodesize' - Hint = 'nodesize(size: single; varies: boolean); Determine size scaling factor for nodes.' + Hint = 'nodesize (size: float; varies: boolean) Determine size scaling factor for nodes.' OnClick = InsertCommand end object nodethresh1: TMenuItem Tag = 23 Caption = 'nodethresh' - Hint = 'nodethresh (lo, hi: single); ' + Hint = 'nodethresh (lo, hi: float) Set the minimum and maximum range for nodes.' OnClick = InsertCommand end object nodethreshbysizenotcolor1: TMenuItem Tag = 1 Caption = 'nodethreshbysizenotcolor' - Hint = 'nodethreshbysizenotcolor(NodeThresholdBySize: boolean); If true then nodes will be hidden if they are smaller than the provided threshold. If false, they will be hidden if their color intensity is below the provided threshold.' + Hint = 'nodethreshbysizenotcolor (NodeThresholdBySize: boolean) If true then nodes will be hidden if they are smaller than the provided threshold. If false, they will be hidden if their color intensity is below the provided threshold.' OnClick = InsertCommand end end @@ -323,13 +345,13 @@ object ScriptForm: TScriptForm object trackload1: TMenuItem Tag = 4 Caption = 'trackload' - Hint = 'trackload(filename: string);' + Hint = 'trackload (filename: string) Load fiber steam lines from a file.' OnClick = InsertCommand end object trackprefs1: TMenuItem Tag = 33 Caption = 'trackprefs' - Hint = 'trackprefs(length, width, dither: single);' + Hint = 'trackprefs (length, width, dither: float) set the size and properties for streamlines' OnClick = InsertCommand end end @@ -338,31 +360,31 @@ object ScriptForm: TScriptForm object atlasgray1: TMenuItem Tag = 1218 Caption = 'atlasgray' - Hint = 'atlasgray(overlay: integer; const filt: array of integer); Gray atlas areas. For example atlasgray(0,[3,7]) will gray-out areas 3 and 7 of the background atlas. On the other hand, atlashide(1,[2,5]) will gray-out areas 2 and 5 of the first overlay image. For example atlashide(0,[3,7]) will gray the areas 3 and 7 of the background atlas. On the other hand, atlashide(1,[2,5]) will gray areas 2 and 5 of the first overlay image.' + Hint = 'atlasgray (overlay: integer; const filt: array of integer) Gray atlas areas. For example atlasgray(0,[3,7]) will gray-out areas 3 and 7 of the background atlas. On the other hand, atlashide(1,[2,5]) will gray-out areas 2 and 5 of the first overlay image. For example atlashide(0,[3,7]) will gray the areas 3 and 7 of the background atlas. On the other hand, atlashide(1,[2,5]) will gray areas 2 and 5 of the first overlay image.' OnClick = InsertCommand end object atlashide1: TMenuItem Tag = 1218 Caption = 'atlashide' - Hint = 'atlashide(overlay: integer; const filt: array of integer); Hide atlas areas. For example atlashide(0,[3,7]) will hide the areas 3 and 7 of the background atlas. On the other hand, atlashide(1,[2,5]) will hide areas 2 and 5 of the first overlay image.' + Hint = 'atlashide (overlay: integer; const filt: array of integer) Hide atlas areas. For example atlashide(0,[3,7]) will hide the areas 3 and 7 of the background atlas. On the other hand, atlashide(1,[2,5]) will hide areas 2 and 5 of the first overlay image.' OnClick = InsertCommand end object atlasmaxindex1: TMenuItem Tag = 2 Caption = 'atlasmaxindex' - Hint = 'atlasmaxindex(overlay: integer): integer; Reports maximum region humber in specified atlas. For example, if you load the CIT168 atlas (which has 15 regions) as your background image, then atlasmaxindex(0) will return 15.' + Hint = 'atlasmaxindex (overlay: integer): integer Reports maximum region humber in specified atlas. For example, if you load the CIT168 atlas (which has 15 regions) as your background image, then atlasmaxindex(0) will return 15.' OnClick = InsertCommand end object atlassaturationalpha1: TMenuItem Tag = 23 Caption = 'atlassaturationalpha' - Hint = 'atlassaturationalpha(saturation, transparency: single); Set saturation and transparency of atlas. A desaturated atlas will appear gray, a transparent atlas will reveal the background color.' + Hint = 'atlassaturationalpha (saturation, transparency: float) Set saturation and transparency of atlas. A desaturated atlas will appear gray, a transparent atlas will reveal the background color.' OnClick = InsertCommand end object atlasstatmap1: TMenuItem Tag = 241819 Caption = 'atlasstatmap' - Hint = 'atlasstatmap(atlasname, statname: string; const indices: array of integer; const intensities: array of single); This creates a new mesh, where indexed regions are saved having the corresponding brightness from the array ''indices''. For example atlasstatmap(''jhu.mz3'','''',[1,3,9],[1.1, 4.4, 2.4]) creates a mesh where regions 1, 3, and 9 are given values 1.1, 4.4 and 2.4. If statname is provided, a mesh will be saved to disk, e.g. atlasstatmap(''jhu.mz3'',''out.mz3'',[1,3,9],[1.1, 4.4, 2.4]). nb this function is for creating maps, you can load them with loadmesh() and loadoverlay(). ' + Hint = 'atlasstatmap (atlasname, statname: string; const indices: array of integer; const intensities: array of single) This creates a new mesh, where indexed regions are saved having the corresponding brightness from the array ''indices''. For example atlasstatmap(''jhu.mz3'','''',[1,3,9],[1.1, 4.4, 2.4]) creates a mesh where regions 1, 3, and 9 are given values 1.1, 4.4 and 2.4. If statname is provided, a mesh will be saved to disk, e.g. atlasstatmap(''jhu.mz3'',''out.mz3'',[1,3,9],[1.1, 4.4, 2.4]). nb this function is for creating maps, you can load them with loadmesh() and loadoverlay(). ' OnClick = InsertCommand end end @@ -371,13 +393,13 @@ object ScriptForm: TScriptForm object modalmessage1: TMenuItem Tag = 4 Caption = 'modalmessage' - Hint = 'modalmessage(str: string); Shows a modal dialog, script stops until user presses ''OK'' button to dismiss dialog.' + Hint = 'modalmessage (str: string) Shows a modal dialog, script stops until user presses ''OK'' button to dismiss dialog.' OnClick = InsertCommand end object modelessmessage1: TMenuItem Tag = 4 Caption = 'modelessmessage' - Hint = 'modelessmessage(str: string); Shows text in the rendering window. This text is displayed until the text is changed.' + Hint = 'modelessmessage (str: string) Shows text in the bottom status region of the scripting window.' OnClick = InsertCommand end end @@ -387,37 +409,37 @@ object ScriptForm: TScriptForm object shaderadjust1: TMenuItem Tag = 1413 Caption = 'shaderadjust' - Hint = 'shaderadjust(property: string; value: single); Sets one of the user-adjustable properties.' + Hint = 'shaderadjust (property: string; value: float) Sets one of the user-adjustable properties.' OnClick = InsertCommand end object shaderambientocclusion1: TMenuItem Tag = 3 Caption = 'shaderambientocclusion' - Hint = 'shaderambientocclusion(amount: single); range 0..1: strength of crevice shadows' + Hint = 'shaderambientocclusion (amount: float) Specify a value in the range 0..1 to set the strength of the crevice shadows' OnClick = InsertCommand end object shadername1: TMenuItem Tag = 4 Caption = 'shadername' - Hint = 'shadername(Filename: string); Loads the requested shader.' + Hint = 'shadername (Filename: string) Loads the requested shader.' OnClick = InsertCommand end object shaderlightazimuthelevation1: TMenuItem Tag = 22 Caption = 'shaderlightazimuthelevation' - Hint = 'shaderlightazimuthelevation(azimuth, elevation: integer); Changes location of light source.' + Hint = 'shaderlightazimuthelevation (azimuth, elevation: integer) Changes location of light source.' OnClick = InsertCommand end object shaderxray1: TMenuItem Tag = 23 Caption = 'shaderxray' - Hint = 'shaderxray(object, overlay: single); See occluded overlays/tracks/nodes by making either object transparent (0..1) or overlay/tracks/nodes emphasized (0..1)' + Hint = 'shaderxray (object, overlay: float) See occluded overlays/tracks/nodes by making either object transparent (0..1) or overlay/tracks/nodes emphasized (0..1)' OnClick = InsertCommand end object MenuItem1: TMenuItem Tag = 1 Caption = 'shaderforbackgroundonly' - Hint = 'shaderforbackgroundonly(onlybg: boolean); If true selected shader only influeces background image, otherwise shader influences background, overlays, tracks and nodes.' + Hint = 'shaderforbackgroundonly (onlybg: boolean) If true selected shader only influeces background image, otherwise shader influences background, overlays, tracks and nodes.' OnClick = InsertCommand end end @@ -426,114 +448,145 @@ object ScriptForm: TScriptForm object azimuth1: TMenuItem Tag = 2 Caption = 'azimuth' - Hint = 'azimuth(degrees: integer); This command rotates the rendering.' + Hint = 'azimuth (degrees: integer) This command rotates the rendering.' OnClick = InsertCommand end object azimuthelevation1: TMenuItem Tag = 22 Caption = 'azimuthelevation' - Hint = 'azimuthelevation(azi, elev: integer); Sets the viewer location.' + Hint = 'azimuthelevation (azi, elev: integer) Sets the viewer location.' OnClick = InsertCommand end object backcolor1: TMenuItem Tag = 36 Caption = 'backcolor' - Hint = 'backcolor(r,g,b: byte); Changes the background color, for example backcolor(255, 0, 0) will set a bright red background' + Hint = 'backcolor(r, g, b: integer) Changes the background color, for example backcolor(255, 0, 0) will set a bright red background' OnClick = InsertCommand end object cameradistance1: TMenuItem Tag = 3 Caption = 'cameradistance' - Hint = 'cameradistance(z: single); Sets the viewing distance from the object.' + Hint = 'cameradistance (z: float) Sets the viewing distance from the object.' OnClick = InsertCommand end object camerapan1: TMenuItem Tag = 23 Caption = 'camerapan' - Hint = 'camerapan(x, y: single); Translate image horizontally (x) and vertically (y). range -1..+1, where 0 is centered. ' + Hint = 'camerapan (x, y: float) Translate image horizontally (x) and vertically (y). range -1..+1, where 0 is centered. ' OnClick = InsertCommand end object MenuItem2: TMenuItem Tag = 2 Caption = 'colorbarposition' - Hint = 'colorbarposition(pos: integer); Sets the position of the colorbar: 1=bottom, 2=left, 3=top, 4=right.' + Hint = 'colorbarposition (pos: integer) Sets the position of the colorbar: 1=bottom, 2=left, 3=top, 4=right.' OnClick = InsertCommand end object colorbarvisible1: TMenuItem Tag = 1 Caption = 'colorbarvisible' - Hint = 'colorbarvisible(visible: boolean); Shows a colorbar on the main images.' + Hint = 'colorbarvisible (visible: boolean) Shows a colorbar on the main images.' OnClick = InsertCommand end object clip1: TMenuItem Tag = 3 Caption = 'clip' - Hint = 'clip(depth: single); Creates a clip plane that hides information close to the viewer.' + Hint = 'clip (depth: float) Creates a clip plane that hides information close to the viewer.' OnClick = InsertCommand end object clipazimuthelevation1: TMenuItem Tag = 33 Caption = 'clipazimuthelevation' - Hint = 'clipazimuthelevation(depth, azi, elev: single); Set a view-point independent clip plane.' + Hint = 'clipazimuthelevation (depth, azi, elev: float) Set a view-point independent clip plane.' OnClick = InsertCommand end object elevation1: TMenuItem Tag = 2 Caption = 'elevation' - Hint = 'elevation(degrees: integer); changes the render camera up or down.' + Hint = 'elevation (degrees: integer) Changes the render camera up or down.' OnClick = InsertCommand end object orientcubevisible1: TMenuItem Tag = 1 Caption = 'orientcubevisible' - Hint = 'orientcubevisible(visible: boolean); show or hide cube that indicates object rotation' + Hint = 'orientcubevisible (visible: boolean) Show or hide cube that indicates object rotation' OnClick = InsertCommand end object viewaxial1: TMenuItem Tag = 1 Caption = 'viewaxial' - Hint = 'viewaxial(std: boolean); creates rendering from an axial viewpoint.' + Hint = 'viewaxial (std: boolean) Creates rendering from an axial viewpoint.' OnClick = InsertCommand end object viewcoronal1: TMenuItem Tag = 1 Caption = 'viewcoronal' - Hint = 'viewcoronal(std: boolean); creates rendering from a coronal viewpoint.' + Hint = 'viewcoronal (std: boolean) Creates rendering from a coronal viewpoint.' OnClick = InsertCommand end object viewsagittal1: TMenuItem Tag = 1 Caption = 'viewsagittal' - Hint = 'viewsagittal(std: boolean); creates rendering from an sagittal viewpoint.' + Hint = 'viewsagittal (std: boolean) creates rendering from an sagittal viewpoint.' + OnClick = InsertCommand + end + end + object Advanced1: TMenuItem + Caption = 'Advanced' + object bmpzoom1: TMenuItem + Tag = 2 + Caption = 'bmpzoom' + Hint = 'bmpzoom (z: integer) copy and save bitmaps at higher resolution than screen. bmpzoom(2) will save images at twice the resolution.' + OnClick = InsertCommand + end + object exists1: TMenuItem + Tag = 4 + Caption = 'exists' + Hint = 'exists (filename: string): boolean Returns true if file exists on disk.' + OnClick = InsertCommand + end + object fontname1: TMenuItem + Tag = 4 + Caption = 'fontname' + Hint = 'fontname (filename) Changes font used for colorbar. For example, "fontname(''''ubuntu'''')" will use the Ubuntu font.' + OnClick = InsertCommand + end + object scriptformvisible1: TMenuItem + Tag = 1 + Caption = 'scriptformvisible' + Hint = 'scriptformvisible (visible: boolean) Shows/hides the scripting form.' + OnClick = InsertCommand + end + object version1: TMenuItem + Caption = 'version' + Hint = 'version (): string Returns software version name.' + end + object quit1: TMenuItem + Caption = 'quit' + Hint = 'quit () Terminate application. Useful if another program is controlling this software' OnClick = InsertCommand end end object Close1: TMenuItem Caption = 'closeall' - Hint = 'closeall(); Closes all open meshes, overlays, nodes and tracks' + Hint = 'closeall () Closes all open meshes, overlays, nodes and tracks' Visible = False OnClick = InsertCommand end - object quit1: TMenuItem - Caption = 'quit' - Hint = 'QUIT Terminate application. Useful if another program is controlling this software' - OnClick = InsertCommand - end object resetdefaults1: TMenuItem Caption = 'resetdefaults' - Hint = 'resetdefaults(); Sets all of the user adjustable settings to their default values.' + Hint = 'resetdefaults () Sets all of the user adjustable settings to their default values.' OnClick = InsertCommand end object savebmp1: TMenuItem Tag = 4 Caption = 'savebmp' - Hint = 'savebmp(filename: string); Saves the currently viewed image as a PNG format compressed bitmap image.' + Hint = 'savebmp (filename: string) Saves the currently viewed image as a PNG format compressed bitmap image.' OnClick = InsertCommand end object wait1: TMenuItem Tag = 2 Caption = 'wait' - Hint = 'wait(msec: integer); The program pauses for the specified duration. For example WAIT(1000) delays the script for one second.' + Hint = 'wait (msec: integer) The program pauses for the specified duration. For example WAIT(1000) delays the script for one second.' OnClick = InsertCommand end end diff --git a/scriptengine.pas b/scriptengine.pas index 000b168..bebd081 100755 --- a/scriptengine.pas +++ b/scriptengine.pas @@ -16,10 +16,10 @@ interface ClipBrd, {$endif} {$IFDEF Windows} uscaledpi,{$ENDIF} - //Messages, +{$IFDEF MYPY}PythonEngine, {$ENDIF} //{$IFNDEF USETRANSFERTEXTURE} scaleimageintensity,{$ENDIF} SysUtils, Classes, Graphics, Controls, Forms, Dialogs, - ExtCtrls, StdCtrls, define_types, Menus, + ExtCtrls, StdCtrls, define_types, Menus, strutils, uPSComponent,commandsu; (*OVERLAYLOADCLUSTER (lFilename: string; lThreshold, lClusterMM3: single; lSaveToDisk: boolean): integer; Will add the overlay named filename, only display voxels with intensity greater than threshold with a cluster volume greater than clusterMM and return the number of the overlay. @@ -48,6 +48,16 @@ TScriptForm = class(TForm) atlasgray1: TMenuItem; edgecreate1: TMenuItem; atlasmaxindex1: TMenuItem; + ListCommands1: TMenuItem; + bmpzoom1: TMenuItem; + fontname1: TMenuItem; + exists1: TMenuItem; + scriptformvisible1: TMenuItem; + version1: TMenuItem; + meshoverlayorder1: TMenuItem; + Advanced1: TMenuItem; + NewPython1: TMenuItem; + meshsave1: TMenuItem; meshcreate1: TMenuItem; meshreversefaces1: TMenuItem; nodethreshbysizenotcolor1: TMenuItem; @@ -144,7 +154,7 @@ TScriptForm = class(TForm) procedure FormDropFiles(Sender: TObject; const FileNames: array of String); procedure FormHide(Sender: TObject); procedure FormShow(Sender: TObject); - procedure Insert1Click(Sender: TObject); + procedure ListCommands1Click(Sender: TObject); procedure Memo1DragDrop(Sender, Source: TObject; X, Y: Integer); procedure ReportCaretPos; procedure FormCreate(Sender: TObject); @@ -171,9 +181,18 @@ TScriptForm = class(TForm) procedure Memo1Click(Sender: TObject); procedure Cut1Click(Sender: TObject); procedure Paste1Click(Sender: TObject); - procedure DemoProgram; + procedure DemoProgram (isPython: boolean = false); procedure ToPascal(s: string); procedure OpenStartupScript; + {$IFDEF MYPY} + function PyCreate: boolean; + function PyIsPythonScript(): boolean; + function PyExec(): boolean; + procedure PyEngineAfterInit(Sender: TObject); + procedure PyIOSendData(Sender: TObject; const Data: AnsiString); + procedure PyIOSendUniData(Sender: TObject; const Data: UnicodeString); + procedure PyModInitialization(Sender: TObject); + {$ENDIF} private fn: string; gchanged: Boolean; @@ -183,17 +202,1000 @@ TScriptForm = class(TForm) end; const kScriptExt = '.gls'; - kScriptFilter = 'NIfTI ('+kScriptExt+')|'+kScriptExt; + {$IFDEF MYPY} + kScriptFilter = 'Scripting ('+kScriptExt+')|*'+kScriptExt+'|Python|*.py'; + {$ELSE} + kScriptFilter = 'Scripting ('+kScriptExt+')|*'+kScriptExt; + {$ENDIF} var ScriptForm: TScriptForm; implementation -uses - mainunit,userdir, prefs ; + {$IFDEF FPC} {$R *.lfm} {$ENDIF} {$IFNDEF FPC} {$R *.DFM} {$ENDIF} +{$IFNDEF MYPY} +uses + mainunit,userdir, prefs; + +function ScriptDir: string; +begin + result := AppDir+'script'; + {$IFDEF UNIX} + if fileexists(result) then exit; + result := '/usr/share/mricrogl/script'; + if fileexists(result) then exit; + result := AppDir+'script' + {$ENDIF} +end; + +{$ELSE} +uses + mainunit,userdir, prefs, proc_py; + +function ScriptDir: string; +begin + result := AppDir+'script'; + {$IFDEF UNIX} + if fileexists(result) then exit; + result := '/usr/share/mricrogl/script'; + if fileexists(result) then exit; + result := AppDir+'script' + {$ENDIF} +end; + +var + PythonIO : TPythonInputOutput; + PyMod: TPythonModule; + PyEngine: TPythonEngine = nil; + {$IFDEF Darwin} + const + kBasePath = '/Library/Frameworks/Python.framework/Versions/'; + {$ENDIF} + + function findPythonLib(def: string): string; + {$IFDEF WINDOWS} + var + fnm: string; + begin + result := def; + if fileexists(def) then exit; + result :=''; //assume failure + fnm := ScriptDir + pathdelim + 'python35.dll'; + if not FileExists(fnm) then exit; + if not FileExists(changefileext(fnm,'.zip')) then exit; + result := fnm; + end; + + {$ELSE} + {$IFDEF Linux} + const + knPaths = 6; + kBasePaths : array [1..knPaths] of string = ('/lib64/','/usr/lib64/','/usr/lib/x86_64-linux-gnu/','/usr/lib/','/usr/local/lib/','/usr/lib/python2.7/config-x86_64-linux-gnu/'); + kBaseName = 'libpython'; + + {$ENDIF} + {$IFDEF Darwin} + const + knPaths = 2; + kBasePaths : array [1..knPaths] of string = (kBasePath, '/System'+kBasePath); + + {$ENDIF} + var + searchResult : TSearchRec; + pth, fnm: string; + vers : TStringList; + n: integer; + begin + result := def; + if fileexists(def) then exit; + result :=''; //assume failure + vers := TStringList.Create; + n := 1; + while (n <= knPaths) and (vers.Count < 1) do begin + pth := kBasePaths[n]; + n := n + 1; + if not DirectoryExists(pth) then continue; + if FindFirst(pth+'*', faDirectory, searchResult) = 0 then begin + repeat + //showmessage('?'+searchResult.Name); + if (length(searchResult.Name) < 1) or (searchResult.Name[1] = '.') then continue; + {$IFDEF LINUX} + if (pos(kBaseName,searchResult.Name) < 1) then continue; + {$ELSE} + if (not (searchResult.Name[1] in ['0'..'9'])) then continue; + {$ENDIF} + vers.Add(searchResult.Name); + until findnext(searchResult) <> 0; + end; + FindClose(searchResult); + end; + if vers.Count < 1 then begin + vers.Free; + exit; + end; + vers.Sort; + fnm := vers.Strings[vers.Count-1]; //newest version? what if 3.10 vs 3.9? + vers.Free; + {$IFDEF Darwin} + fnm := kBasePath+fnm+'/lib/libpython'+fnm+'.dylib'; + {$ENDIF} + {$IFDEF LINUX} + fnm := pth+ fnm; + {$ENDIF} + if fileexists(fnm) then + result := fnm; + end; + {$ENDIF} + +function TScriptForm.PyCreate: boolean; +//const +// cPyLibraryMac = '/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib'; +var + S: string; +begin + result := false; + S:= findPythonLib(gPrefs.PyLib); + if (S = '') then exit; + gPrefs.PyLib := S; + result := true; + PythonIO := TPythonInputOutput.Create(ScriptForm); + PyMod := TPythonModule.Create(ScriptForm); + PyEngine := TPythonEngine.Create(ScriptForm); + PyEngine.IO := PythonIO; + PyEngine.PyFlags:=[pfIgnoreEnvironmentFlag]; + PyEngine.UseLastKnownVersion:=false; + PyMod.Engine := PyEngine; + PyMod.ModuleName := 'gl'; + PyMod.OnInitialization:=PyModInitialization; + PythonIO.OnSendData := PyIOSendData; + PythonIO.OnSendUniData:= PyIOSendUniData; + PyEngine.DllPath:= ExtractFileDir(S); + PyEngine.DllName:= ExtractFileName(S); + PyEngine.LoadDll +end; +function TScriptForm.PyIsPythonScript(): boolean; +begin + result := ( Pos('import gl', Memo1.Text) > 0); //any python project must import gl +end; + +function TScriptForm.PyExec(): boolean; +begin + result := false; //assume code is not Python + if not (PyIsPythonScript) then exit; + Memo2.lines.Clear; + result := true; + if PyEngine = nil then begin + if not PyCreate then begin //do this the first time + {$IFDEF Darwin} + Memo2.lines.Add('Failed to launch Python [install Python in '+kBasePath+']'); + {$ENDIF} + {$IFDEF Windows} + Memo2.lines.Add('Failed to launch Python [place Python .dll and .zip in Script folder]'); + {$ENDIF} + {$IFDEF Linux} + Memo2.lines.Add('Unable to find Python library'); + Memo2.lines.Add(' run ''find -name "*libpython*"'' to find the library'); + Memo2.lines.Add(' if it does not exist, install it (''apt-get install libpython2.7'')'); + Memo2.lines.Add(' if it does exist, set use the Preferences/Advanced to set ''PyLib'''); + Memo2.lines.Add(' PyLib should be the complete path and filename of libpython*.so'); + {$ENDIF} + exit; + end; + end; + Memo2.lines.Add('Running Python script'); + try + PyEngine.ExecStrings(ScriptForm.Memo1.Lines); + except + caption := 'Python Engine Failed'; + end; + Memo2.lines.Add('Python Succesfully Executed'); + result := true; +end; + +procedure TScriptForm.PyIOSendData(Sender: TObject; + const Data: AnsiString); +begin + Memo2.Lines.Add(Data); +end; + +procedure TScriptForm.PyIOSendUniData(Sender: TObject; + const Data: UnicodeString); +begin + Memo2.Lines.Add(Data); +end; + +function PyVERSION(Self, Args : PPyObject): PPyObject; cdecl; +begin + with GetPythonEngine do + Result:= PyString_FromString(kVers); +end; + +function PyRESETDEFAULTS(Self, Args : PPyObject): PPyObject; cdecl; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + RESETDEFAULTS; +end; + +function PyMESHCURV(Self, Args : PPyObject): PPyObject; cdecl; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + MESHCURV; + //GLForm1.Caption := inttostr(random(888)); +end; + +function PyMESHREVERSEFACES(Self, Args : PPyObject): PPyObject; cdecl; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + MESHREVERSEFACES; +end; + + +function BOOL(i: integer): boolean; +begin + result := i <> 0; +end; + +function PySAVEBMP(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:savebmp', @PtrName)) then + begin + StrName:= string(PtrName); + SAVEBMP(StrName); + end; +end; + +function PyBACKCOLOR(Self, Args : PPyObject): PPyObject; cdecl; +var + R,G,B: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'iii:backcolor', @R,@G,@B)) then + BACKCOLOR(R,G,B); +end; + +function PyMESHCOLOR(Self, Args : PPyObject): PPyObject; cdecl; +var + R,G,B: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'iii:meshcolor', @R,@G,@B)) then + MESHCOLOR(R,G,B); +end; + +function PyATLASMAXINDEX(Self, Args : PPyObject): PPyObject; cdecl; +var + i: integer; +begin + Result:= GetPythonEngine.PyInt_FromLong(-1); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:atlasmaxindex', @I)) then + Result:= GetPythonEngine.PyInt_FromLong(ATLASMAXINDEX(I)); +end; + +function PyEXISTS(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:exists', @PtrName)) then + begin + StrName:= string(PtrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(EXISTS(StrName))); + end; +end; + +function PyAZIMUTH(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:azimuth', @A)) then + AZIMUTH(A); +end; + +function PyAZIMUTHELEVATION(Self, Args : PPyObject): PPyObject; cdecl; +var + A,E: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ii:azimuthelevation', @A, @E)) then + AZIMUTHELEVATION(A,E); +end; + +function PyBMPZOOM(Self, Args : PPyObject): PPyObject; cdecl; +var + Z: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:bmpzoom', @Z)) then + bmpzoom(Z); +end; + +function PyCAMERADISTANCE(Self, Args : PPyObject): PPyObject; cdecl; +var + Z: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'f:cameradistance', @Z)) then + CAMERADISTANCE(Z); +end; + +function PySHADERAMBIENTOCCLUSION(Self, Args : PPyObject): PPyObject; cdecl; +var + Z: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'f:shaderambientocclusion', @Z)) then + SHADERAMBIENTOCCLUSION(Z); +end; + +function PyCLIP(Self, Args : PPyObject): PPyObject; cdecl; +var + D: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'f:clip', @D)) then + CLIP(D); +end; + +function PyCLIPAZIMUTHELEVATION(Self, Args : PPyObject): PPyObject; cdecl; +var + D,A,E: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'fff:clipazimuthelevation', @D,@A,@E)) then + CLIPAZIMUTHELEVATION(D,A,E); +end; + +function PyTRACKPREFS(Self, Args : PPyObject): PPyObject; cdecl; +var + D,A,E: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'fff:trackprefs', @D,@A,@E)) then + TRACKPREFS(D,A,E); +end; + +function PyATLASSATURATIONALPHA(Self, Args : PPyObject): PPyObject; cdecl; +var + A,B: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ff:atlassaturationalpha', @A,@B)) then + ATLASSATURATIONALPHA(A,B); +end; + +function PyCAMERAPAN(Self, Args : PPyObject): PPyObject; cdecl; +var + A,B: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ff:camerapan', @A,@B)) then + CAMERAPAN(A,B); +end; + +function PyNODESIZE(Self, Args : PPyObject): PPyObject; cdecl; +var + A: single; + I: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'fi:nodesize', @A,@I)) then + NODESIZE(A,Bool(I)); +end; + +function PyEDGESIZE(Self, Args : PPyObject): PPyObject; cdecl; +var + A: single; + I: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'fi:edgesize', @A,@I)) then + EDGESIZE(A,Bool(I)); +end; + +function PyOVERLAYINVERT(Self, Args : PPyObject): PPyObject; cdecl; +var + B,I: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ii:overlayinvert', @I,@B)) then + OVERLAYINVERT(I,Bool(B)); +end; + +function PyOVERLAYTRANSLUCENT(Self, Args : PPyObject): PPyObject; cdecl; +var + B,I: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ii:overlaytranslucent', @I,@B)) then + OVERLAYTRANSLUCENT(I,Bool(B)); +end; + +function PyEDGETHRESH(Self, Args : PPyObject): PPyObject; cdecl; +var + A,B: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ff:edgethresh', @A,@B)) then + EDGETHRESH(A,B); +end; + +function PySHADERXRAY(Self, Args : PPyObject): PPyObject; cdecl; +var + A,B: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ff:shaderxray', @A,@B)) then + SHADERXRAY(A,B); +end; + +function PyNODETHRESH(Self, Args : PPyObject): PPyObject; cdecl; +var + A,B: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ff:nodethresh', @A,@B)) then + NODETHRESH(A,B); +end; + +function PyCOLORBARPOSITION(Self, Args : PPyObject): PPyObject; cdecl; +var + P: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:colorbarposition', @P)) then + COLORBARPOSITION (P); +end; + +function PyMESHOVERLAYORDER(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:meshoverlayorder', @A)) then + MESHOVERLAYORDER(BOOL(A)); +end; + +function PyORIENTCUBEVISIBLE(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:orientcubevisible', @A)) then + ORIENTCUBEVISIBLE(BOOL(A)); +end; + +function PyOVERLAYADDITIVE(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:overlayadditive', @A)) then + OVERLAYADDITIVE(BOOL(A)); +end; + +function PyOVERLAYSMOOTHVOXELWISEDATA(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:overlaysmoothvoxelwisedata', @A)) then + OVERLAYSMOOTHVOXELWISEDATA(BOOL(A)); +end; + +function PySHADERFORBACKGROUNDONLY(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:shaderforbackgroundonly', @A)) then + SHADERFORBACKGROUNDONLY(BOOL(A)); +end; + +function PyNODETHRESHBYSIZENOTCOLOR(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:nodethreshbysizenotcolor', @A)) then + NODETHRESHBYSIZENOTCOLOR(BOOL(A)); +end; + +function PyCOLORBARVISIBLE(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:colorbarvisible', @A)) then + COLORBARVISIBLE(BOOL(A)); +end; + +function PyFONTNAME(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:fontname', @PtrName)) then + begin + StrName:= string(PtrName); + FONTNAME(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyELEVATION(Self, Args : PPyObject): PPyObject; cdecl; +var + E: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:elevation', @E)) then + ELEVATION(E); +end; + +function PyNODEHEMISPHERE(Self, Args : PPyObject): PPyObject; cdecl; +var + E: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:nodehemisphere', @E)) then + NODEHEMISPHERE(E); +end; + +function PyNODEPOLARITY(Self, Args : PPyObject): PPyObject; cdecl; +var + E: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:nodepolarity', @E)) then + NODEPOLARITY(E); +end; + +function PyMESHLOAD(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:meshload', @PtrName)) then + begin + StrName:= string(PtrName); + MESHLOAD(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyTRACKLOAD(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:trackload', @PtrName)) then + begin + StrName:= string(PtrName); + TRACKLOAD(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyMESHSAVE(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:meshsave', @PtrName)) then + begin + StrName:= string(PtrName); + MESHSAVE(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyNODELOAD(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:nodeload', @PtrName)) then + begin + StrName:= string(PtrName); + NODELOAD(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyOVERLAYLOAD(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:overlayload', @PtrName)) then + begin + StrName:= string(PtrName); + OVERLAYLOAD(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyEDGELOAD(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:edgeload', @PtrName)) then + begin + StrName:= string(PtrName); + EDGELOAD(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyMODALMESSAGE(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:modalmessage', @PtrName)) then + begin + StrName:= string(PtrName); + MODALMESSAGE(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyMODELESSMESSAGE(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:modelessmessage', @PtrName)) then + begin + StrName:= string(PtrName); + MODELESSMESSAGE(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyOVERLAYCLOSEALL(Self, Args : PPyObject): PPyObject; cdecl; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(TRUE)); + OVERLAYCLOSEALL; +end; + +function PyQUIT(Self, Args : PPyObject): PPyObject; cdecl; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(TRUE)); + QUIT; +end; + +function PyOVERLAYCOLORNAME(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; + V: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'is:overlaycolorname', @V, @PtrName)) then + begin + StrName:= string(PtrName); + OVERLAYCOLORNAME(V, StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PySHADERNAME(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; + V: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 's:shadername', @PtrName)) then + begin + StrName:= string(PtrName); + SHADERNAME(StrName); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PySHADERADJUST(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; + f: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'sf:shaderadjust', @PtrName, @f)) then + begin + StrName:= string(PtrName); + SHADERADJUST(StrName, f); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyEDGECOLOR(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; + i: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'si:edgecolor', @PtrName, @i)) then + begin + StrName:= string(PtrName); + EDGECOLOR(StrName, bool(i)); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyNODECOLOR(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName: PChar; + StrName: string; + i: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'si:nodecolor', @PtrName, @i)) then + begin + StrName:= string(PtrName); + NODECOLOR(StrName, bool(i)); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PyMESHCREATE(Self, Args : PPyObject): PPyObject; cdecl; +var + PtrName,PtrName2: PChar; + StrName,StrName2: string; + f,f2: single; + i,i2: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(FALSE)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ssffii:meshcreate', @PtrName, @PtrName2, @f, @f2, @i, @i2)) then + begin + StrName:= string(PtrName); + StrName2:= string(PtrName2); + MESHCREATE(StrName, StrName2, f, f2, i, i2); + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + end; +end; + +function PySCRIPTFORMVISIBLE(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:scriptformvisible', @A)) then + SCRIPTFORMVISIBLE(BOOL(A)); +end; + +function PyVIEWAXIAL(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:viewaxial', @A)) then + VIEWAXIAL(BOOL(A)); +end; + +function PyVIEWCORONAL(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:viewcoronal', @A)) then + VIEWCORONAL(BOOL(A)); +end; + +function PyOVERLAYTRANSPARENCYONBACKGROUND(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:overlaytransparencyonbackground', @A)) then + OVERLAYTRANSPARENCYONBACKGROUND(A); +end; + +function PyWAIT(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:wait', @A)) then + WAIT(A); +end; + +function PySHADERLIGHTAZIMUTHELEVATION(Self, Args : PPyObject): PPyObject; cdecl; +var + A,B: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ii:shaderlightazimuthelevation', @A, @B)) then + SHADERLIGHTAZIMUTHELEVATION(A,B); +end; + +function PyOVERLAYMINMAX(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; + B,C: single; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'iff:overlayminmax', @A, @B, @C)) then + OVERLAYMINMAX(A,B,C); +end; + +function PyOVERLAYVISIBLE(Self, Args : PPyObject): PPyObject; cdecl; +var + A,B: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'ii:overlayvisible', @A, @B)) then + OVERLAYVISIBLE(A,BOOL(B)); +end; + + + +function PyVIEWSAGITTAL(Self, Args : PPyObject): PPyObject; cdecl; +var + A: integer; +begin + Result:= GetPythonEngine.PyBool_FromLong(Ord(True)); + with GetPythonEngine do + if Bool(PyArg_ParseTuple(Args, 'i:viewsagittal', @A)) then + VIEWSAGITTAL(BOOL(A)); +end; +procedure TScriptForm.PyModInitialization(Sender: TObject); +begin + with Sender as TPythonModule do begin + AddMethod('atlasmaxindex', @PyATLASMAXINDEX, ''); + AddMethod('atlassaturationalpha', @PyATLASSATURATIONALPHA, ''); + AddMethod('azimuth', @PyAZIMUTH, ''); + AddMethod('azimuthelevation', @PyAZIMUTHELEVATION, ''); + AddMethod('backcolor', @PyBACKCOLOR, ''); + AddMethod('bmpzoom', @PyBMPZOOM, ''); + AddMethod('cameradistance', @PyCAMERADISTANCE, ''); + AddMethod('camerapan', @PyCAMERAPAN, ''); + AddMethod('clip', @PyCLIP, ''); + AddMethod('clipazimuthelevation', @PyCLIPAZIMUTHELEVATION, ''); + AddMethod('colorbarposition', @PyCOLORBARPOSITION, ''); + AddMethod('colorbarvisible', @PyCOLORBARVISIBLE, ''); + AddMethod('edgecolor', @PyEDGECOLOR, ''); + AddMethod('edgeload', @PyEDGELOAD, ''); + AddMethod('edgesize', @PyEDGESIZE, ''); + AddMethod('edgethresh', @PyEDGETHRESH, ''); + AddMethod('elevation', @PyELEVATION, ''); + AddMethod('exists', @PyEXISTS, ''); + AddMethod('fontname', @PyFONTNAME, ''); + AddMethod('meshcolor', @PyMESHCOLOR, ''); + AddMethod('meshcreate', @PyMESHCREATE, ''); + AddMethod('meshcurv', @PyMESHCURV, ''); + AddMethod('meshload', @PyMESHLOAD, ''); + AddMethod('meshoverlayorder', @PyMESHOVERLAYORDER, ''); + AddMethod('meshreversefaces', @PyMESHREVERSEFACES, ''); + AddMethod('meshsave', @PyMESHSAVE, ''); + AddMethod('modalmessage', @PyMODALMESSAGE, ''); + AddMethod('modelessmessage', @PyMODELESSMESSAGE, ''); + AddMethod('nodecolor', @PyNODECOLOR, ''); + AddMethod('nodehemisphere', @PyNODEHEMISPHERE, ''); + AddMethod('nodeload', @PyNODELOAD, ''); + AddMethod('nodepolarity', @PyNODEPOLARITY, ''); + AddMethod('nodesize', @PyNODESIZE, ''); + AddMethod('nodethresh', @PyNODETHRESH, ''); + AddMethod('nodethreshbysizenotcolor', @PyNODETHRESHBYSIZENOTCOLOR, ''); + AddMethod('orientcubevisible', @PyORIENTCUBEVISIBLE, ''); + AddMethod('overlayadditive', @PyOVERLAYADDITIVE, ''); + AddMethod('overlaycloseall', @PyOVERLAYCLOSEALL, ''); + AddMethod('overlaycolorname', @PyOVERLAYCOLORNAME, ''); + AddMethod('overlayinvert', @PyOVERLAYINVERT, ''); + AddMethod('overlayload', @PyOVERLAYLOAD, ''); + AddMethod('overlayminmax', @PyOVERLAYMINMAX, ''); + AddMethod('overlaysmoothvoxelwisedata', @PyOVERLAYSMOOTHVOXELWISEDATA, ''); + AddMethod('overlaytranslucent', @PyOVERLAYTRANSLUCENT, ''); + AddMethod('overlaytransparencyonbackground', @PyOVERLAYTRANSPARENCYONBACKGROUND, ''); + AddMethod('overlayvisible', @PyOVERLAYVISIBLE, ''); + AddMethod('quit', @PyQUIT, ''); + AddMethod('resetdefaults', @PyRESETDEFAULTS, ''); + AddMethod('savebmp', @PySAVEBMP, ''); + AddMethod('scriptformvisible', @PySCRIPTFORMVISIBLE, ''); + AddMethod('shaderadjust', @PySHADERADJUST, ''); + AddMethod('shaderambientocclusion', @PySHADERAMBIENTOCCLUSION, ''); + AddMethod('shaderforbackgroundonly', @PySHADERFORBACKGROUNDONLY, ''); + AddMethod('shaderlightazimuthelevation', @PySHADERLIGHTAZIMUTHELEVATION, ''); + AddMethod('shadername', @PySHADERNAME, ''); + AddMethod('shaderxray', @PySHADERXRAY, ''); + AddMethod('trackload', @PyTRACKLOAD, ''); + AddMethod('trackprefs', @PyTRACKPREFS, ''); + AddMethod('version', @PyVERSION, ''); + AddMethod('viewaxial', @PyVIEWAXIAL, ''); + AddMethod('viewcoronal', @PyVIEWCORONAL, ''); + AddMethod('viewsagittal', @PyVIEWSAGITTAL, ''); + AddMethod('wait', @PyWAIT, ''); + end; +end; + +procedure TScriptForm.PyEngineAfterInit(Sender: TObject); +var + dir: string; +begin + dir:= ExtractFilePath(Application.ExeName); + {$ifdef windows} + Py_SetSysPath([dir+'DLLs', dir+cPyZipWindows], false); + {$endif} + Py_SetSysPath([dir+'Py'], true); +end; +{$ENDIF} //IFDEF MYPY + + procedure TScriptForm.OpenStartupScript; //do this after clrbar and gltext are created begin @@ -212,9 +1214,20 @@ procedure TScriptForm.OpenStartupScript; end; end; //RunStartUpScripts() -procedure TScriptForm.DemoProgram; +procedure TScriptForm.DemoProgram( isPython: boolean = false); begin Memo1.lines.clear; + if isPython then begin + Memo1.Lines.Add('import gl'); + Memo1.Lines.Add('import sys'); + Memo1.Lines.Add('print(sys.version)'); + Memo1.Lines.Add('print(gl.version())'); + Memo1.Lines.Add('# Note that resetdefaults() closes open meshes, overlays, track nodes'); + Memo1.Lines.Add('gl.resetdefaults()'); + Memo1.lines.Add(''); + Memo1.SelStart := maxint; + exit; + end; //Memo1.lines.Add('PROGRAM Demo;'); Memo1.lines.Add('BEGIN'); Memo1.lines.Add('//Insert commands here...'); @@ -236,19 +1249,6 @@ procedure MyWriteln(const s: string); ScriptForm.Memo2.lines.add(S); end; -function ScriptDir: string; -begin - result := AppDir+'script'; - {$IFDEF UNIX} - if fileexists(result) then exit; - result := '/usr/share/surfice/script'; - if fileexists(result) then exit; - result := AppDir+'script' - {$ENDIF} - //with latest versions of Darwin I store scripts in same folder - //result := ExeDir+'script' -end; - procedure TScriptForm.OpenSMRU(Sender: TObject);//open template or MRU //Templates have tag set to 0, Most-Recently-Used items have tag set to position in gMRUstr begin @@ -263,7 +1263,7 @@ procedure TScriptForm.OpenSMRU(Sender: TObject);//open template or MRU procedure TScriptForm.UpdateSMRU; const - kMenuItems = 6;//with OSX users quit from application menu + kMenuItems = 7;//with OSX users quit from application menu var lPos,lN,lM : integer; begin @@ -300,6 +1300,14 @@ procedure TScriptForm.Compile1Click(Sender: TObject); i: integer; compiled: boolean; begin + {$IFDEF MYPY} + if PyExec() then exit; + if (not (AnsiContainsText(Memo1.Text, 'begin'))) then begin + Memo2.Lines.Clear; + Memo2.Lines.Add('Error: script must contain "import gl" (for Python) or "begin" (for Pascal).'); + exit; + end; + {$ENDIF} Memo2.Lines.Clear; PSScript1.Script.Text := Memo1.Lines.Text; //PSScript1.Script.Text := Memo1.Lines.GetText; //<- this will leak! requires StrDispose @@ -358,9 +1366,61 @@ procedure TScriptForm.FormShow(Sender: TObject); {$ENDIF} end; -procedure TScriptForm.Insert1Click(Sender: TObject); +function IsPythonCompatible(lType: integer): boolean; +//current Python can not handle passing array types +var + lTstr: string; + i, len, n, t: integer; begin + result := true; + lTStr := inttostr(lType); + len := length(lTStr); + i := 1; + while i <= len do begin + if i = len then + n := 1 + else begin + n := strtoint(lTStr[i]); + inc(i); + end; + t := strtoint(lTStr[i]); + if (t = 8) or (t = 9) then + result := false; + inc(i); + end; +end; +procedure TScriptForm.ListCommands1Click(Sender: TObject); +var + i,j: integer; + M, M2: TMenuItem; + cmds: TStringList; +begin + cmds := TStringList.Create; + for i := 0 to (Insert1.Count -1) do begin + M := Insert1.Items[i]; + if (M.Visible) and (length(M.Hint) > 1) then begin + if (not IsPythonCompatible (M.Tag)) then + cmds.Add(M.Hint+' [Not compatible with Python]') + else + cmds.Add(M.Hint); + end; + if (M.Count > 1) then begin + for j := 0 to (M.Count -1) do begin + M2 := M.Items[j]; + if (M2.Visible) and (length(M2.Hint) > 1) then begin + if (not IsPythonCompatible (M2.Tag)) then + cmds.Add(M2.Hint+' [Not compatible with Python]') + else + cmds.Add(M2.Hint); + end; + end; + end; + end; + Memo2.Lines.Clear; + cmds.Sort; + Memo2.Lines.AddStrings(cmds); + cmds.Free; end; procedure TScriptForm.Memo1DragDrop(Sender, Source: TObject; X, Y: Integer); @@ -427,6 +1487,7 @@ procedure TScriptForm.FormCreate(Sender: TObject); fn := ''; gchanged := False; DemoProgram; + {$IFNDEF MYPY} NewPython1.Visible := false;{$ENDIF} FillMRU (gPrefs.PrevScriptName, ScriptDir+pathdelim,kScriptExt,True); //FillMRU (gPrefs.PrevScriptName, ScriptDir+pathdelim,kScriptExt,False); UpdateSMRU; @@ -589,11 +1650,11 @@ procedure TScriptForm.New1Click(Sender: TObject); exit; Memo2.Lines.Clear; fn := ''; - DemoProgram; + DemoProgram((Sender as TMenuItem).tag = 1 ); end; procedure CleanStr (var lStr: string); -//remove symbols, set upcase... +//remove symbols, set lower case... var lLen,lPos: integer; lS: string; @@ -604,16 +1665,18 @@ procedure CleanStr (var lStr: string); lS := ''; for lPos := 1 to lLen do if lStr[lPos] in ['0'..'9','a'..'z','A'..'Z'] then - lS := lS + upcase(lStr[lPos]); + lS := lS + AnsiLowerCase(lStr[lPos]); lStr := lS; end; -function TypeStr (lType: integer): string; +function TypeStr (lType: integer; isPy: boolean = false): string; var lTStr,lStr : string; i,n,len,lLoop,lT: integer;//1=boolean,2=integer,3=float,4=string[filename] begin result := ''; + if (lType = 0) and (isPy) then + result := '()'; if lType = 0 then exit; lTStr := inttostr(lType); @@ -631,7 +1694,13 @@ function TypeStr (lType: integer): string; inc(i); for lLoop := 1 to n do begin case lT of - 1: lStr := lStr +'true'; + 1: begin + if isPy then + lStr := lStr +'1' + else + lStr := lStr +'true'; + + end; 2: lStr := lStr +'1'; 3: begin if lLoop <= 3 then //for Cutout view, we need six values - make them different so this is a sensible cutout @@ -650,7 +1719,6 @@ function TypeStr (lType: integer): string; 7: lStr := lStr +'5';//kludge - make integer where 1 is not a good default, e.g. shaderquality 8: lStr := lStr +'[1, 2, 4]'; 9: lStr := lStr +'[1.1, 2.5, 4.2]'; - else lStr := lStr + '''?'''; end;//case if lLoop < n then @@ -666,7 +1734,13 @@ function TypeStr (lType: integer): string; procedure TScriptForm.InsertCommand(Sender: TObject); var lStr: string; + isPy: boolean; begin + {$IFDEF MYPY} + isPy := PyIsPythonScript(); + {$ELSE} + isPy := false; + {$ENDIF} lStr := (Sender as TMenuItem).Hint; if lStr <> '' then begin Memo2.Lines.Clear; @@ -674,7 +1748,13 @@ procedure TScriptForm.InsertCommand(Sender: TObject); end; lStr := (Sender as TMenuItem).Caption; CleanStr(lStr); - lStr := lStr+TypeStr((Sender as TMenuItem).Tag)+ ';'; + if isPy then begin + if IsPythonCompatible((Sender as TMenuItem).Tag) then + lStr := 'gl.'+lStr+TypeStr((Sender as TMenuItem).Tag, isPy) + else + lStr := '#not yet Python Compatible: gl.'+lStr+TypeStr((Sender as TMenuItem).Tag, isPy) + end else + lStr := lStr+TypeStr((Sender as TMenuItem).Tag)+ ';'; Clipboard.AsText := lStr; {$IFDEF UNIX} Memo1.SelText := (lStr)+ kUNIXeoln; diff --git a/surfice.app/Contents/Resources/script/basic_paint_surface.gls b/surfice.app/Contents/Resources/script/basic_paint_surface.gls index 8cd407d..ef71706 100755 --- a/surfice.app/Contents/Resources/script/basic_paint_surface.gls +++ b/surfice.app/Contents/Resources/script/basic_paint_surface.gls @@ -1,13 +1,13 @@ -BEGIN - RESETDEFAULTS; - AZIMUTHELEVATION(70, 15); - MESHLOAD('BrainMesh_ICBM152Right.mz3'); - OVERLAYLOAD('motor_4t95vol.nii.gz'); - OVERLAYMINMAX(1,2,12); - OVERLAYLOAD('motor_4t95vol.nii.gz'); - OVERLAYMINMAX(2,-1,-2); - COLORBARVISIBLE(true); - OVERLAYTRANSPARENCYONBACKGROUND(25); - MESHCURV; -END. +begin + resetdefaults(); + azimuthelevation(70, 15); + meshload('BrainMesh_ICBM152Right.mz3'); + overlayload('motor_4t95vol.nii.gz'); + overlayminmax(1,2,12); + overlayload('motor_4t95vol.nii.gz'); + overlayminmax(2,-1,-2); + colorbarvisible(true); + overlaytransparencyonbackground(25); + meshcurv(); +end. diff --git a/surfice.app/Contents/Resources/script/create_atlas.gls b/surfice.app/Contents/Resources/script/create_atlas.gls index 47b1836..d4a2256 100644 --- a/surfice.app/Contents/Resources/script/create_atlas.gls +++ b/surfice.app/Contents/Resources/script/create_atlas.gls @@ -1,17 +1,17 @@ var n,i,j: integer; msk: array of integer; -BEGIN - RESETDEFAULTS; - AZIMUTHELEVATION(240, 15); - MESHLOAD('AICHAhr_left.mz3'); - n := AtlasMaxIndex(0); +begin + resetdefaults(); + azimuthelevation(240, 15); + meshload('AICHAhr_left.mz3'); + n := atlasmaxindex(0); for i := n downto 1 do begin setlength(msk, i); for j := 1 to i do msk[j-1] := j; - ATLASHIDE(0,msk); + atlashide(0,msk); wait(30); end; - ATLASHIDE(0,[]); //show everything -END. \ No newline at end of file + atlashide(0,[]); //show everything +end. \ No newline at end of file diff --git a/surfice.app/Contents/Resources/script/fmri_mesh.gls b/surfice.app/Contents/Resources/script/fmri_mesh.gls index 221c273..0af2dde 100755 --- a/surfice.app/Contents/Resources/script/fmri_mesh.gls +++ b/surfice.app/Contents/Resources/script/fmri_mesh.gls @@ -1,10 +1,10 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('BrainMesh_ICBM152Right.mz3'); - OVERLAYLOAD('motor_4t95mesh.mz3'); - OVERLAYCOLORNAME(1, 'Red'); - SHADERXRAY(1.0, 0.3); - AZIMUTHELEVATION(110, 15); - MESHCURV; -END. +begin + resetdefaults(); + meshload('BrainMesh_ICBM152Right.mz3'); + overlayload('motor_4t95mesh.mz3'); + overlaycolorname(1, 'red'); + shaderxray(1.0, 0.3); + azimuthelevation(110, 15); + meshcurv(); +end. diff --git a/surfice.app/Contents/Resources/script/frontal_atlas.gls b/surfice.app/Contents/Resources/script/frontal_atlas.gls index 8205b74..097e971 100644 --- a/surfice.app/Contents/Resources/script/frontal_atlas.gls +++ b/surfice.app/Contents/Resources/script/frontal_atlas.gls @@ -1,10 +1,10 @@ -BEGIN - RESETDEFAULTS; - //assign intensities to superior frontal regions (AICHA regions 4..6) - // save as file named 'surficeTemp.mz3' in our home directory - ATLASSTATMAP('AICHAhr_left.mz3','surficeTemp.mz3',[4,5,6],[7,3,4]); - MESHLOAD('lh.pial'); - OVERLAYLOAD('surficeTemp.mz3'); - SHADERXRAY(1.0, 0.3); -END. +begin + resetdefaults(); + //assign intensities to superior frontal regions (aicha regions 4..6) + // save as file named 'surficetemp.mz3' in our home directory + atlasstatmap('AICHAhr_left.mz3','surficetemp.mz3',[4,5,6],[7,3,4]); + meshload('lh.pial'); + overlayload('surficetemp.mz3'); + shaderxray(1.0, 0.3); +end. diff --git a/surfice.app/Contents/Resources/script/hide_curves.gls b/surfice.app/Contents/Resources/script/hide_curves.gls index c6864c3..c695595 100644 --- a/surfice.app/Contents/Resources/script/hide_curves.gls +++ b/surfice.app/Contents/Resources/script/hide_curves.gls @@ -1,9 +1,9 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('BrainMesh_ICBM152Left_smoothed.mz3'); - MESHCURV; - SHADERNAME('HideCurves'); - OVERLAYLOAD('CIT168.mz3'); - SHADERFORBACKGROUNDONLY(true); - SHADERADJUST('CurvThreshHi', 0.44); -END. \ No newline at end of file +begin + resetdefaults(); + meshload('BrainMesh_ICBM152Left_smoothed.mz3'); + meshcurv(); + shadername('hidecurves'); + overlayload('CIT168.mz3'); + shaderforbackgroundonly(true); + shaderadjust('curvthreshhi', 0.44); +end. \ No newline at end of file diff --git a/surfice.app/Contents/Resources/script/mesh.gls b/surfice.app/Contents/Resources/script/mesh.gls index 61420a7..7e12389 100755 --- a/surfice.app/Contents/Resources/script/mesh.gls +++ b/surfice.app/Contents/Resources/script/mesh.gls @@ -1,10 +1,10 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('mni152_2009.mz3'); - OVERLAYLOAD('motor_4t95mesh.mz3'); - CLIPAZIMUTHELEVATION(0.37, 0, 140); - SHADERAMBIENTOCCLUSION(0.5); - AZIMUTHELEVATION(90, 20); - SHADERXRAY(1.0, 0.3); -END. +begin + resetdefaults(); + meshload('mni152_2009.mz3'); + overlayload('motor_4t95mesh.mz3'); + clipazimuthelevation(0.37, 0, 140); + shaderambientocclusion(0.5); + azimuthelevation(90, 20); + shaderxray(1.0, 0.3); +end. diff --git a/surfice.app/Contents/Resources/script/newer_2017.gls b/surfice.app/Contents/Resources/script/newer_2017.gls index 8a3fb79..37225a4 100644 --- a/surfice.app/Contents/Resources/script/newer_2017.gls +++ b/surfice.app/Contents/Resources/script/newer_2017.gls @@ -1,22 +1,22 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('BrainMesh_ICBM152Right.mz3'); - MESHCURV; - OVERLAYMINMAX(1,-1,1); - OVERLAYCOLORNAME(1,'Surface'); - //OVERLAYCOLORNAME(1,'Bone'); - OVERLAYINVERT(1,true); - //OVERLAYTRANSLUCENT(1, true); - OVERLAYLOAD('motor_4t95vol.nii.gz'); - OVERLAYCOLORNAME(2,'Kelvin') - OVERLAYMINMAX(2,2,7); - OVERLAYLOAD('scalp.mz3'); - OVERLAYCOLORNAME(3,'Gold'); - //SHADERNAME('Metal'); - SHADERXRAY(1.0, 0.9); - MESHOVERLAYORDER(true); - COLORBARVISIBLE(false); - SHADERAMBIENTOCCLUSION(0.05); - AZIMUTHELEVATION(90, 15); - CLIPAZIMUTHELEVATION(0.5, 0, 90); -END. +begin + resetdefaults(); + meshload('BrainMesh_ICBM152Right.mz3'); + meshcurv(); + overlayminmax(1,-1,1); + overlaycolorname(1,'surface'); + //overlaycolorname(1,'bone'); + overlayinvert(1,true); + //overlaytranslucent(1, true); + overlayload('motor_4t95vol.nii.gz'); + overlaycolorname(2,'kelvin') + overlayminmax(2,2,7); + overlayload('scalp.mz3'); + overlaycolorname(3,'gold'); + //shadername('metal'); + shaderxray(1.0, 0.9); + meshoverlayorder(true); + colorbarvisible(false); + shaderambientocclusion(0.05); + azimuthelevation(90, 15); + clipazimuthelevation(0.5, 0, 90); +end. diff --git a/surfice.app/Contents/Resources/script/node.gls b/surfice.app/Contents/Resources/script/node.gls index 7c03202..a0ff43b 100755 --- a/surfice.app/Contents/Resources/script/node.gls +++ b/surfice.app/Contents/Resources/script/node.gls @@ -1,20 +1,19 @@ -BEGIN - RESETDEFAULTS; - MESHLOAD('BrainMesh_ICBM152Left.mz3'); - EDGELOAD('LPBA40.edge'); - CLIPAZIMUTHELEVATION(0.3, 0, 130); - NODESIZE(6, true); - EDGESIZE(3,true); - NODEHEMISPHERE(-1); - AZIMUTHELEVATION(250, 35); - EDGECOLOR('ACTC',TRUE); - NODECOLOR('BLUE',TRUE); - NODETHRESH(1.0,1.0); - EDGETHRESH(0.5,1.0); - - MESHCURV; - OVERLAYMINMAX(1,-1,1); - OVERLAYCOLORNAME(1,'Surface'); - OVERLAYINVERT(1,true); - OVERLAYTRANSLUCENT(1, true); -END. +begin + resetdefaults(); + meshload('BrainMesh_ICBM152Left.mz3'); + edgeload('LPBA40.edge'); + clipazimuthelevation(0.3, 0, 130); + nodesize(6, true); + edgesize(3,true); + nodehemisphere(-1); + azimuthelevation(250, 35); + edgecolor('actc',true); + nodecolor('blue',true); + nodethresh(1.0,1.0); + edgethresh(0.5,1.0); + meshcurv(); + overlayminmax(1,-1,1); + overlaycolorname(1,'surface'); + overlayinvert(1,true); + overlaytranslucent(1, true); +end. diff --git a/surfice.app/Contents/Resources/script/shaders.gls b/surfice.app/Contents/Resources/script/shaders.gls index a705150..cab0ff9 100755 --- a/surfice.app/Contents/Resources/script/shaders.gls +++ b/surfice.app/Contents/Resources/script/shaders.gls @@ -1,43 +1,41 @@ const - kFramesPerRotation = 180; + kframesperrotation = 180; var i: integer; s: single; -BEGIN - RESETDEFAULTS; - MESHCOLOR(210, 148, 148); - MESHLOAD('BrainMesh_ICBM152Left.mz3'); - EDGELOAD('LPBA40.edge'); - CLIPAZIMUTHELEVATION(0.3, 0, 130); - NODESIZE(6, true); - EDGESIZE(3,true); - NODEHEMISPHERE(-1); - AZIMUTHELEVATION(250, 35); - EDGECOLOR('ACTC',TRUE); - NODECOLOR('RED',TRUE); - NODETHRESH(1.0,1.0); - EDGETHRESH(0.5,1.0); - FOR i := 1 to kFramesPerRotation * 5 DO BEGIN +begin + resetdefaults(); + meshcolor(210, 148, 148); + meshload('BrainMesh_ICBM152Left.mz3'); + edgeload('LPBA40.edge'); + clipazimuthelevation(0.3, 0, 130); + nodesize(6, true); + edgesize(3,true); + nodehemisphere(-1); + azimuthelevation(250, 35); + edgecolor('actc',true); + nodecolor('red',true); + nodethresh(1.0,1.0); + edgethresh(0.5,1.0); + for i := 1 to kframesperrotation * 5 do begin s := 0.5 + (i+0.0)/72; - IF s <= 1 THEN - CAMERADISTANCE(s); - IF (i MOD kFramesPerRotation) = 0 THEN BEGIN - CASE (i DIV kFramesPerRotation) OF - 1: SHADERNAME('metal'); - 2: SHADERNAME('wireframe'); + if s <= 1 then + cameradistance(s); + if (i mod kframesperrotation) = 0 then begin + case (i div kframesperrotation) of + 1: shadername('metal'); + 2: shadername('wireframe'); 3: begin - SHADERNAME('toon'); - SHADERAMBIENTOCCLUSION(0); + shadername('toon'); + shaderambientocclusion(0); end; 4: begin - SHADERNAME('wire'); - SHADERFORBACKGROUNDONLY(true); + shadername('wire'); + shaderforbackgroundonly(true); end; - END; - END; - AZIMUTH( round(360.0/kFramesPerRotation)); - WAIT(20); - END; -END. - - + end; + end; + azimuth( round(360.0/kframesperrotation)); + wait(20); + end; +end. \ No newline at end of file diff --git a/surfice.app/Contents/Resources/script/track.gls b/surfice.app/Contents/Resources/script/track.gls index 6638d81..178d605 100755 --- a/surfice.app/Contents/Resources/script/track.gls +++ b/surfice.app/Contents/Resources/script/track.gls @@ -1,15 +1,15 @@ -CONST - kSteps = 100; -VAR +const + ksteps = 100; +var i: integer; -BEGIN - RESETDEFAULTS; - MESHLOAD('stroke.mz3'); - TRACKLOAD('stroke.trk.gz'); - TRACKPREFS(15, 3, 0.5); - FOR i := 1 TO kSteps DO BEGIN - CLIPAZIMUTHELEVATION(( (0.8*i)/kSteps ), 0, 130); - WAIT(20); - END; -END. +begin + resetdefaults(); + meshload('stroke.mz3'); + trackload('stroke.trk.gz'); + trackprefs(15, 3, 0.5); + for i := 1 to ksteps do begin + clipazimuthelevation(( (0.8*i)/ksteps ), 0, 130); + wait(20); + end; +end. diff --git a/surfice.lpi b/surfice.lpi index 92b2eda..084abab 100644 --- a/surfice.lpi +++ b/surfice.lpi @@ -61,16 +61,19 @@ - + - + - + - + + + + diff --git a/surfice.lps b/surfice.lps index 6dd80dc..9e88b8a 100644 --- a/surfice.lps +++ b/surfice.lps @@ -3,14 +3,13 @@ - + - @@ -18,13 +17,10 @@ - - - + + - - @@ -32,28 +28,27 @@ - - - + + + + - - - + + + - - @@ -61,7 +56,6 @@ - @@ -69,7 +63,6 @@ - @@ -77,7 +70,6 @@ - @@ -85,7 +77,6 @@ - @@ -93,7 +84,6 @@ - @@ -101,7 +91,6 @@ - @@ -109,7 +98,6 @@ - @@ -117,16 +105,13 @@ - - - - + + + - - @@ -134,7 +119,6 @@ - @@ -142,7 +126,6 @@ - @@ -150,14 +133,13 @@ - - + + - @@ -165,7 +147,6 @@ - @@ -173,16 +154,13 @@ - - + - - - + @@ -191,14 +169,13 @@ - - - + + - + @@ -206,7 +183,6 @@ - @@ -214,7 +190,6 @@ - @@ -222,7 +197,6 @@ - @@ -230,14 +204,12 @@ - - @@ -245,7 +217,6 @@ - @@ -253,7 +224,6 @@ - @@ -267,8 +237,8 @@ - - + + @@ -276,18 +246,17 @@ - - + + - - - + + + - @@ -308,7 +277,6 @@ - @@ -323,7 +291,6 @@ - @@ -331,7 +298,6 @@ - @@ -353,7 +319,6 @@ - @@ -362,127 +327,143 @@ + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + +