├── Images ├── MNIST.jpg ├── nn.jpg └── xor.jpg ├── LICENSE ├── README.md ├── Samples ├── Keras4Delphi.dpr ├── untMain.dfm └── untMain.pas └── src ├── Keras.Layers.pas ├── Keras.Models.pas ├── Keras.PreProcessing.pas ├── Keras.pas ├── NumPy ├── NDArray.Api.pas ├── np.Api.pas ├── np.Base.pas ├── np.Models.pas └── np.Utils.pas └── Python.Utils.pas /Images/MNIST.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pigrecos/Keras4Delphi/3e2658d8b9fe2916672ed78d94fbf80f96a7e3ba/Images/MNIST.jpg -------------------------------------------------------------------------------- /Images/nn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pigrecos/Keras4Delphi/3e2658d8b9fe2916672ed78d94fbf80f96a7e3ba/Images/nn.jpg -------------------------------------------------------------------------------- /Images/xor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pigrecos/Keras4Delphi/3e2658d8b9fe2916672ed78d94fbf80f96a7e3ba/Images/xor.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Max 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Keras4Delphi** is a high-level neural networks API, written in Pascal(Delphi Rio 10.3) with Python Binding and capable of running on top of TensorFlow, CNTK, or Theano. Based on [Keras.NET](https://github.com/SciSharp/Keras.NET) and [Keras](https://github.com/keras-team/keras) 2 | 3 | Use Keras if you need a deep learning library that: 4 | 5 | Allows for easy and fast prototyping (through user friendliness, modularity, and extensibility). 6 | Supports both convolutional networks and recurrent networks, as well as combinations of the two. 7 | Runs seamlessly on CPU and GPU. 8 | 9 | ## Keras4Delphi is using: 10 | 11 | * [python4delphi](https://github.com/pyscripter/python4delphi) (thanks [@pyscripter](https://github.com/pyscripter) to the great work) 12 | * [NumPy4Delphi](https://github.com/Pigrecos/Keras4Delphi/tree/master/src/NumPy) (Partial conversion) 13 | 14 | ## Prerequisite 15 | * Python 2.7 - 3.7, Link: https://www.python.org/downloads/ 16 | * Install keras, numpy and one of the backend (Tensorflow/CNTK/Theano). Please see on how to configure: https://keras.io/backend/ 17 | 18 | ## Example with XOR sample 19 | 20 | ```pascal 21 | //Load train data 22 | var x : TNDarray := TNumPy.npArray( [ [ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1 ] ] ); 23 | var y : TNDarray := TNumPy.npArray( [ 0, 1, 1, 0 ] ); 24 | 25 | //Build functional model 26 | var input : TKInput := TKInput.Create(tnp_shape.Create([2])); 27 | var hidden1: TBaseLayer := TDense.Create(32, 'relu').&Set([input]); 28 | var hidden2: TBaseLayer := TDense.Create(64, 'relu').&Set([hidden1]); 29 | var output : TBaseLayer := TDense.Create(1, 'sigmoid').&Set([hidden2]); 30 | 31 | var model : TModel := TModel.Create ( [ input ] , [ output ]); 32 | 33 | //Compile and train 34 | model.Compile(TStringOrInstance.Create( TAdam.Create ), 'binary_crossentropy',['accuracy']); 35 | 36 | var batch_size : Integer := 2; 37 | var history: THistory := model.Fit(x, y, @batch_size, 10,1); 38 | 39 | model.Summary; 40 | 41 | var logs := history.HistoryLogs; 42 | 43 | //Save model and weights 44 | var json : string := model.ToJson; 45 | TFile.WriteAllText('model.json', json); 46 | model.SaveWeight('model.h5'); 47 | 48 | //Load model and weight 49 | var loaded_model : TBaseModel := TSequential.ModelFromJson(TFile.ReadAllText('model.json')); 50 | loaded_model.LoadWeight('model.h5'); 51 | ``` 52 | 53 | **Output:** 54 | 55 | ![](https://github.com/Pigrecos/Keras4Delphi/blob/master/Images/xor.jpg) 56 | 57 | ## MNIST CNN Example 58 | 59 | Python example taken from: https://keras.io/examples/mnist_cnn/ 60 | 61 | ```pascal 62 | var 63 | res : TArray; 64 | begin 65 | var batch_size : Integer := 128; //Training batch size 66 | var num_classes: Integer := 10; //No. of classes 67 | var epochs : Integer := 12; //No. of epoches we will train 68 | 69 | // input image dimensions 70 | var img_rows: Integer := 28; 71 | var img_cols: Integer := 28; 72 | 73 | // Declare the input shape for the network 74 | var input_shape : Tnp_shape := default(Tnp_shape); 75 | 76 | // Load the MNIST dataset into Numpy array 77 | res := TMNIST.load_data; 78 | var x_train, y_train ,x_test, y_test : TNDArray; 79 | 80 | x_train := res[0]; 81 | y_train := res[1]; 82 | x_test := res[2]; 83 | y_test := res[3]; 84 | 85 | //Check if its channel fist or last and rearrange the dataset accordingly 86 | var K: TBackend := TBackend.Create; 87 | if(K.ImageDataFormat = 'channels_first') then 88 | begin 89 | x_train := x_train.reshape([x_train.shape[0], 1, img_rows, img_cols]); 90 | x_test := x_test.reshape ([x_test.shape[0] , 1, img_rows, img_cols]); 91 | input_shape := Tnp_shape.Create([1, img_rows, img_cols]); 92 | end else 93 | begin 94 | x_train := x_train.reshape([x_train.shape[0], img_rows, img_cols, 1]); 95 | x_test := x_test.reshape ([x_test.shape[0] , img_rows, img_cols, 1]); 96 | input_shape := Tnp_shape.Create([img_rows, img_cols, 1]); 97 | end; 98 | 99 | //Normalize the input data 100 | x_train := x_train.astype(vNumpy.float32_); 101 | x_test := x_test.astype(vNumpy.float32_); 102 | x_train := TNDArray.opDiv(x_train, 255); 103 | x_test := TNDArray.opDiv(x_test, 255); 104 | 105 | redtOutput.Lines.Add('x_train shape: ' + x_train.shape.ToString); 106 | redtOutput.Lines.Add( IntToStr(x_train.shape[0]) + ' train samples'); 107 | redtOutput.Lines.Add( IntToStr(x_test.shape[0]) + ' test samples'); 108 | 109 | // Convert class vectors to binary class matrices 110 | var Util : TUtil := TUtil.Create; 111 | y_train := Util.ToCategorical(y_train, @num_classes); 112 | y_test := Util.ToCategorical(y_test, @num_classes); 113 | 114 | // Build CNN model 115 | var model : TSequential := TSequential.Create; 116 | 117 | model.Add( TConv2D.Create(32, [3, 3],'relu', @input_shape) ); 118 | model.Add( TConv2D.Create(64, [3, 3],'relu')); 119 | model.Add( TMaxPooling2D.Create([2, 2])); 120 | model.Add( TDropout.Create(0.25)); 121 | model.Add( TFlatten.Create); 122 | model.Add( TDense.Create(128, 'relu')); 123 | model.Add( TDropout.Create(0.5)); 124 | model.Add( TDense.Create(num_classes, 'softmax')); 125 | 126 | //Compile with loss, metrics and optimizer 127 | model.Compile(TStringOrInstance.Create(TAdadelta.Create), 'categorical_crossentropy', [ 'accuracy' ]); 128 | 129 | //Train the model 130 | model.Fit(x_train, y_train, @batch_size, epochs, 1,nil,0,[ x_test, y_test ]); 131 | 132 | //Score the model for performance 133 | var score : TArray := model.Evaluate(x_test, y_test, nil, 0); 134 | 135 | redtOutput.Lines.Add('Test loss: ' + FloatToStr(score[0])); 136 | redtOutput.Lines.Add('Test accuracy:'+ FloatToStr(score[1])); 137 | 138 | // Save the model to HDF5 format which can be loaded later or ported to other application 139 | model.Save('model.h5'); 140 | // Save it to Tensorflow JS format and we will test it in browser. 141 | model.SaveTensorflowJSFormat('./'); 142 | ``` 143 | 144 | **Output** 145 | 146 | Reached 98% accuracy within 3 epoches. 147 | 148 | ![](https://github.com/Pigrecos/Keras4Delphi/blob/master/Images/MNIST.jpg) 149 | 150 | 151 | ## Sentiment classification LSTM 152 | 153 | Python example taken from: //https://keras.io/examples/imdb_lstm/ 154 | 155 | ```pascal 156 | var 157 | res : TArray; 158 | begin 159 | var max_features: Integer := 20000; 160 | // cut texts after this number of words (among top max_features most common words) 161 | var maxlen : Integer := 80; 162 | var batch_size : Integer := 32; 163 | 164 | redtOutput.Lines.Add('Loading data...'); 165 | res := TIMDB.load_data(@max_features); 166 | var x_train, y_train ,x_test, y_test,X,Y,tmp : TNDArray; 167 | 168 | x_train := res[0]; 169 | y_train := res[1]; 170 | x_test := res[2]; 171 | y_test := res[3]; 172 | 173 | redtOutput.Lines.Add('train sequences: ' + x_train.shape.ToString); 174 | redtOutput.Lines.Add('test sequences: ' + x_test.shape.ToString); 175 | 176 | redtOutput.Lines.Add('Pad sequences (samples x time)'); 177 | var tseq : TSequenceUtil := TSequenceUtil.Create; 178 | x_train := tseq.PadSequences(x_train, @maxlen); 179 | x_test := tseq.PadSequences(x_test, @maxlen); 180 | redtOutput.Lines.Add('x_train shape: ' + x_train.shape.ToString); 181 | redtOutput.Lines.Add('x_test shape: ' + x_test.shape.ToString); 182 | 183 | redtOutput.Lines.Add('Build model...'); 184 | var model : TSequential := TSequential.Create; 185 | model.Add( TEmbedding.Create(max_features, 128)); 186 | model.Add( TLSTM.Create(128, 0.2, 0.2)); 187 | model.Add( TDense.Create(1, 'sigmoid')); 188 | 189 | //try using different optimizers and different optimizer configs 190 | model.Compile(TStringOrInstance.Create('adam'), 'binary_crossentropy', [ 'accuracy' ]); 191 | model.Summary; 192 | 193 | redtOutput.Lines.Add('Train...'); 194 | model.Fit(x_train, y_train, @batch_size, 15, 1,[ x_test, y_test ]); 195 | 196 | //Score the model for performance 197 | var score : TArray := model.Evaluate(x_test, y_test, @batch_size); 198 | 199 | redtOutput.Lines.Add('Test score: ' + FloatToStr(score[0])); 200 | redtOutput.Lines.Add('Test accuracy:'+ FloatToStr(score[1])); 201 | 202 | // Save the model to HDF5 format which can be loaded later or ported to other application 203 | model.Save('model.h5'); 204 | ``` 205 | 206 | # Notes 207 | welcome collaborative testing and improvement of source code. I have little free time 208 | 209 | ### TODO List ### 210 | * Test code 211 | * and Much more 212 | -------------------------------------------------------------------------------- /Samples/Keras4Delphi.dpr: -------------------------------------------------------------------------------- 1 | program Keras4Delphi; 2 | 3 | uses 4 | Vcl.Forms, 5 | untMain in 'untMain.pas' {frmMain}, 6 | np.Base in '..\src\NumPy\np.Base.pas', 7 | Python.Utils in '..\src\Python.Utils.pas', 8 | NDArray.Api in '..\src\NumPy\NDArray.Api.pas', 9 | np.Api in '..\src\NumPy\np.Api.pas', 10 | np.Models in '..\src\NumPy\np.Models.pas', 11 | Keras in '..\src\Keras.pas', 12 | Keras.Models in '..\src\Keras.Models.pas', 13 | np.Utils in '..\src\NumPy\np.Utils.pas', 14 | Keras.Layers in '..\src\Keras.Layers.pas', 15 | Keras.PreProcessing in '..\src\Keras.PreProcessing.pas'; 16 | 17 | {$R *.res} 18 | 19 | begin 20 | Application.Initialize; 21 | Application.MainFormOnTaskbar := True; 22 | Application.CreateForm(TfrmMain, frmMain); 23 | Application.Run; 24 | end. 25 | -------------------------------------------------------------------------------- /Samples/untMain.dfm: -------------------------------------------------------------------------------- 1 | object frmMain: TfrmMain 2 | Left = 0 3 | Top = 0 4 | Caption = '[Demo test] Keras for Delphi' 5 | ClientHeight = 554 6 | ClientWidth = 804 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | OnShow = FormShow 15 | PixelsPerInch = 96 16 | TextHeight = 13 17 | object spl1: TSplitter 18 | Left = 241 19 | Top = 43 20 | Width = 5 21 | Height = 258 22 | ExplicitLeft = 497 23 | ExplicitTop = 42 24 | end 25 | object spl2: TSplitter 26 | Left = 0 27 | Top = 301 28 | Width = 804 29 | Height = 5 30 | Cursor = crVSplit 31 | Align = alBottom 32 | ExplicitTop = 309 33 | end 34 | object pnlTop: TPanel 35 | Left = 0 36 | Top = 0 37 | Width = 804 38 | Height = 43 39 | Align = alTop 40 | TabOrder = 0 41 | object btn1: TButton 42 | Left = 16 43 | Top = 12 44 | Width = 75 45 | Height = 25 46 | Caption = 'keras' 47 | TabOrder = 0 48 | OnClick = btn1Click 49 | end 50 | end 51 | object pnl1: TPanel 52 | Left = 0 53 | Top = 43 54 | Width = 241 55 | Height = 258 56 | Align = alLeft 57 | Caption = 'pnl1' 58 | TabOrder = 1 59 | object img1: TImage 60 | Left = 1 61 | Top = 1 62 | Width = 239 63 | Height = 256 64 | Align = alClient 65 | Stretch = True 66 | ExplicitWidth = 232 67 | end 68 | end 69 | object redtOutput: TRichEdit 70 | Left = 0 71 | Top = 306 72 | Width = 804 73 | Height = 248 74 | Align = alBottom 75 | Color = clInfoBk 76 | Font.Charset = ANSI_CHARSET 77 | Font.Color = clWindowText 78 | Font.Height = -11 79 | Font.Name = 'MS Sans Serif' 80 | Font.Style = [] 81 | ParentFont = False 82 | ScrollBars = ssVertical 83 | TabOrder = 2 84 | WordWrap = False 85 | Zoom = 100 86 | OnChange = redtOutputChange 87 | end 88 | object pnl2: TPanel 89 | Left = 246 90 | Top = 43 91 | Width = 558 92 | Height = 258 93 | Align = alClient 94 | Caption = 'pnl2' 95 | TabOrder = 3 96 | object cht1: TChart 97 | Left = 1 98 | Top = 1 99 | Width = 556 100 | Height = 256 101 | Legend.LegendStyle = lsSeries 102 | Legend.TextStyle = ltsPlain 103 | Title.Text.Strings = ( 104 | 'Training and Validation Accuracy') 105 | BottomAxis.Title.Caption = 'Epoch' 106 | LeftAxis.Title.Caption = 'Loss' 107 | Align = alClient 108 | TabOrder = 0 109 | DefaultCanvas = 'TGDIPlusCanvas' 110 | PrintMargins = ( 111 | 15 112 | 19 113 | 15 114 | 19) 115 | ColorPaletteIndex = 18 116 | object srsTraining_Loss: TLineSeries 117 | Legend.Text = 'Training loss' 118 | LegendTitle = 'Training loss' 119 | Brush.BackColor = clDefault 120 | Pointer.InflateMargins = True 121 | Pointer.Style = psRectangle 122 | XValues.Name = 'X' 123 | XValues.Order = loAscending 124 | YValues.Name = 'Y' 125 | YValues.Order = loNone 126 | end 127 | object srsValidation_loss: TLineSeries 128 | Legend.Text = 'Validation accuracy' 129 | LegendTitle = 'Validation accuracy' 130 | Brush.BackColor = clDefault 131 | Pointer.InflateMargins = True 132 | Pointer.Style = psRectangle 133 | XValues.Name = 'X' 134 | XValues.Order = loAscending 135 | YValues.Name = 'Y' 136 | YValues.Order = loNone 137 | end 138 | end 139 | end 140 | object PyIOCom: TPythonGUIInputOutput 141 | UnicodeIO = True 142 | RawOutput = False 143 | Output = redtOutput 144 | Left = 544 145 | Top = 3 146 | end 147 | end 148 | -------------------------------------------------------------------------------- /Samples/untMain.pas: -------------------------------------------------------------------------------- 1 | unit untMain; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.ComCtrls, 8 | System.TypInfo, System.Rtti,PythonEngine, PythonGUIInputOutput, 9 | Python.Utils, 10 | 11 | Keras.Layers, 12 | Keras.Models, 13 | Keras, 14 | 15 | np.Base, 16 | np.Api, 17 | 18 | np.Models, 19 | NDArray.Api, VclTee.TeeGDIPlus, VCLTee.TeEngine, VCLTee.Series, VCLTee.TeeProcs, VCLTee.Chart, Vcl.Buttons; 20 | 21 | type 22 | TArray2D = array of TArray; 23 | TfrmMain = class(TForm) 24 | pnlTop: TPanel; 25 | pnl1: TPanel; 26 | redtOutput: TRichEdit; 27 | PyIOCom: TPythonGUIInputOutput; 28 | btn1: TButton; 29 | img1: TImage; 30 | pnl2: TPanel; 31 | spl1: TSplitter; 32 | spl2: TSplitter; 33 | cht1: TChart; 34 | srsTraining_Loss: TLineSeries; 35 | srsValidation_loss: TLineSeries; 36 | procedure FormShow(Sender: TObject); 37 | procedure btn1Click(Sender: TObject); 38 | procedure redtOutputChange(Sender: TObject); 39 | private 40 | procedure TestVarios; 41 | procedure esempio_XOR; 42 | procedure MergeExample; 43 | procedure ImplementCallback; 44 | procedure NumPyTest; 45 | procedure Test1; 46 | procedure MNIST_CNN; 47 | procedure SentimentClassification; 48 | procedure SentimentClassificationLSTM; 49 | procedure Predict(text: string); 50 | procedure TextGen; 51 | function LoadTxt(fileName: string; lenSeq:Integer; step: Integer; var rawTxt: TArray; var DataX: TArray2D; var DataY: TArray):Integer; 52 | procedure TextGen_predict(model : TSequential; seqLen, Step: Integer); 53 | { Private declarations } 54 | public 55 | { Public declarations } 56 | end; 57 | 58 | var 59 | frmMain: TfrmMain; 60 | vNumpy : TNumPy; 61 | 62 | 63 | implementation 64 | uses System.Generics.Collections, System.Diagnostics, System.IOUtils, Jpeg,MethodCallBack,System.Math, 65 | np.Utils, 66 | 67 | Keras.PreProcessing; 68 | 69 | {$R *.dfm} 70 | 71 | procedure TfrmMain.TestVarios; 72 | var 73 | shape,shape1 : Tnp_Shape; 74 | TestArray : TNDArray; 75 | TestArray1 : TNDArray; 76 | aN1,aN2 : TNDArray; 77 | s1 : string; 78 | i : Integer; 79 | begin 80 | 81 | TestArray := vNumpy.npArray( [1,2,3]) ; 82 | s1 := TestArray.repr ; 83 | redtOutput.Lines.Add(s1) ; 84 | redtOutput.Lines.Add('=========='); 85 | 86 | TestArray := vNumpy.npArray( [ [1,2,3], [1,2,3] ]) ; 87 | s1 := TestArray.repr ; 88 | redtOutput.Lines.Add(s1) ; 89 | redtOutput.Lines.Add('=========='); 90 | 91 | TestArray := vNumpy.npArray([ [ [2,4,5], [7,8,9] ], 92 | [ [6,3,2], [8,2,1] ] 93 | ] ) ; 94 | 95 | TestArray.data; 96 | TestArray.ndim; 97 | TestArray.itemsize; 98 | TestArray.len; 99 | TestArray.item([4]); 100 | 101 | 102 | var a : TArray2D := [ [1,2,3], [4,5,6] ] ; 103 | var given: TNDArray := vNumpy.empty_like(a); 104 | var sh : Tnp_Shape := given.shape; 105 | var dt : TDtype := given.dtype; 106 | redtOutput.Lines.Add(dt.ToString); 107 | 108 | s1 := TestArray.repr ; 109 | redtOutput.Lines.Add(s1) ; 110 | redtOutput.Lines.Add('=========='); 111 | 112 | TestArray1 := vNumpy.npArray(['uno','due','tre','quattro','cinque'] ) ; 113 | s1 := TestArray1.repr ; 114 | redtOutput.Lines.Add(s1) ; 115 | redtOutput.Lines.Add('=========='); 116 | 117 | shape := Tnp_Shape.Create([1,2,3]); 118 | shape1:= Tnp_Shape.Create([7,4,5]); 119 | 120 | aN1 := TNDArray.Create(TNumPy.ToPython( TValue.FromShape(shape1))); 121 | aN2 := TNDArray.Create(TNumPy.ToPython( TValue.FromShape(shape))); 122 | TestArray1 := vNumpy.npArray([aN1,aN2] ) ; 123 | s1 := TestArray1.repr ; 124 | redtOutput.Lines.Add(s1) ; 125 | redtOutput.Lines.Add('=========='); 126 | 127 | 128 | TestArray1 := vNumpy.npArray([24]); 129 | i :=vNumpy.asscalar(TestArray1); 130 | redtOutput.Lines.Add( IntToStr(i) ) 131 | 132 | end; 133 | 134 | function log(epochidx: Integer): Double; 135 | begin 136 | Result := 0.0; 137 | frmMain.redtOutput.Lines.Add('test callback :' + IntToStr(epochidx)); 138 | end; 139 | 140 | function pylog(self, args : PPyObject): PPyObject;cdecl; 141 | var 142 | epochidx: Integer ; 143 | d : Double; 144 | begin 145 | Result := nil; 146 | if g_MyPyEngine.PyArg_ParseTuple( args, 'if:logFunction',@epochidx,@d) <> 0 then 147 | begin 148 | log(epochidx) ; 149 | d := 7.0; 150 | Result := g_MyPyEngine.VariantAsPyObject(d) ; 151 | end; 152 | end; 153 | 154 | procedure TfrmMain.btn1Click(Sender: TObject); 155 | begin 156 | //============== Esempi ======================// 157 | 158 | // ====NumPy basic test 159 | (*NumPyTest; 160 | 161 | // ====keras test 162 | Test1; 163 | // 164 | esempio_XOR; 165 | // 166 | MergeExample ; 167 | // 168 | ImplementCallback; 169 | // 170 | MNIST_CNN ; 171 | // 172 | SentimentClassification; 173 | Predict('I hate you'); 174 | Predict('I care about you'); 175 | // 176 | SentimentClassificationLSTM; *) 177 | // 178 | TextGen ; 179 | var filemodel : string :='TextGen.h5'; 180 | var model : TSequential := TSequential(TSequential.LoadModel(filemodel)); 181 | TextGen_predict(model,40,3); 182 | // 183 | end; 184 | 185 | procedure TfrmMain.NumPyTest; 186 | var 187 | stopwatch : TStopwatch ; 188 | N, D_in, HH, D_out : Integer; 189 | x,y,w1,w2 : TNDArray; 190 | learning_rate, 191 | loss : Double; 192 | t : Integer; 193 | begin 194 | TestVarios; 195 | 196 | N := 64; D_in := 1000; HH := 100; D_out := 10; 197 | 198 | // Create random input and output data 199 | redtOutput.Lines.Add(' creating random data'); 200 | x := vNumpy.randn([N, D_in]); 201 | y := vNumpy.randn([N, D_out]); 202 | 203 | y.item([1,2]); 204 | 205 | redtOutput.Lines.Add(' learning'); 206 | stopwatch := TStopwatch.StartNew; 207 | // Randomly initialize weights 208 | w1 := vNumpy.randn([D_in, HH]); 209 | w2 := vNumpy.randn([HH, D_out]); 210 | 211 | learning_rate := 1.0E-06; 212 | 213 | var h : TNDArray; 214 | var h_relu : TNDArray; 215 | var y_pred : TNDArray; 216 | var grad_y_pred : TNDArray; 217 | var grad_w2 : TNDArray; 218 | var grad_h_relu : TNDArray; 219 | var grad_h : TNDArray; 220 | var grad_w1 : TNDArray; 221 | for t := 0 to 500 do 222 | begin 223 | // Forward pass: compute predicted y 224 | h := x.dot(w1); 225 | h_relu := vNumpy.maximum(h, vNumpy.asarray(0)); 226 | y_pred := h_relu.dot(w2); 227 | 228 | // Compute and print loss 229 | loss := vNumpy.asscalar( vNumpy.square(TNDArray.opSub(y_pred, y)).sum); 230 | if (t mod 20) = 0 then 231 | redtOutput.Lines.Add( Format('step: %d loss: %e ',[t,loss])); 232 | 233 | // Backprop to compute gradients of w1 and w2 with respect to loss 234 | grad_y_pred := TNDArray.opMul(2.0, (TNDArray.opSub(y_pred, y))); 235 | grad_w2 := h_relu.T.dot(grad_y_pred); 236 | grad_h_relu := grad_y_pred.dot(w2.T); 237 | grad_h := grad_h_relu.copy(); 238 | TPythonObject(grad_h)[TNDArray.opLess(h, 0)] := vNumpy.asarray(0); 239 | grad_w1 := x.T.dot(grad_h); 240 | 241 | // Update weights 242 | w1.opISub( TNDArray.opMul(learning_rate , grad_w1)); // inplace substraction is faster than -= 243 | w2.opISub( TNDArray.opMul(learning_rate , grad_w2)); 244 | end; 245 | stopwatch.Stop; 246 | stopwatch.ElapsedMilliseconds; 247 | redtOutput.Lines.Add( Format('step: 500, final loss: %e , elapsed time: %s',[loss,formatdatetime('hh:nn:ss.zzz', stopwatch.ElapsedMilliseconds)])); 248 | 249 | end; 250 | 251 | procedure TfrmMain.redtOutputChange(Sender: TObject); 252 | begin 253 | SendMessage(redtOutput.handle, WM_VSCROLL, SB_BOTTOM, 0); 254 | end; 255 | 256 | procedure TfrmMain.Test1; 257 | var 258 | res : tarray; 259 | 260 | begin 261 | 262 | 263 | res := TCifar100.load_data; 264 | var x_train, y_train ,x_test, y_test : TNDArray; 265 | 266 | x_train := res[0]; 267 | y_train := res[1]; 268 | x_test := res[2]; 269 | y_test := res[3]; 270 | 271 | redtOutput.Lines.Add('x_train shape: ' + x_train.shape.ToString); 272 | redtOutput.Lines.Add( IntToStr(x_train.shape[0]) + ' train samples'); 273 | redtOutput.Lines.Add( IntToStr(x_test.shape[0]) + ' test samples'); 274 | 275 | redtOutput.Lines.Add('y_train shape: ' + y_train.shape.ToString); 276 | redtOutput.Lines.Add( IntToStr(y_train.shape[0]) + ' train samples'); 277 | redtOutput.Lines.Add( IntToStr(y_test.shape[0]) + ' test samples'); 278 | 279 | TEarlyStopping.Create ('val_loss', 3) ; 280 | 281 | TLearningRateScheduler.Create (pylog) ; 282 | end; 283 | 284 | procedure TfrmMain.esempio_XOR; 285 | begin 286 | //Load train data 287 | var x : TNDarray := TNumPy.npArray( [ [ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1 ] ] ); 288 | var y : TNDarray := TNumPy.npArray( [ 0, 1, 1, 0 ] ); 289 | 290 | //Build functional model 291 | var input : TKInput := TKInput.Create(tnp_shape.Create([2])); 292 | var hidden1: TBaseLayer := TDense.Create(32, 'relu').&Set([input]); 293 | var hidden2: TBaseLayer := TDense.Create(64, 'relu').&Set([hidden1]); 294 | var output : TBaseLayer := TDense.Create(1, 'sigmoid').&Set([hidden2]); 295 | 296 | var model : TModel := TModel.Create ( [ input ] , [ output ]); 297 | model.Summary; 298 | 299 | //Compile and train 300 | model.Compile(TAdam.Create , 'binary_crossentropy',['accuracy']); 301 | 302 | var batch_size : Integer := 2; 303 | var history: THistory := model.Fit(x, y, @batch_size, 10,1); 304 | 305 | srsTraining_Loss.Clear; 306 | srsTraining_Loss.AddArray(history.HistoryLogs['loss']) ; 307 | srsValidation_loss.Clear; 308 | srsValidation_loss.AddArray(history.HistoryLogs['accuracy']); 309 | 310 | history.HistoryLogs; 311 | 312 | //Save model and weights 313 | var json : string := model.ToJson; 314 | TFile.WriteAllText('model.json', json); 315 | model.SaveWeight('model.h5'); 316 | 317 | //Load model and weight 318 | var loaded_model : TBaseModel := TSequential.ModelFromJson(TFile.ReadAllText('model.json')); 319 | loaded_model.LoadWeight('model.h5'); 320 | end; 321 | 322 | procedure TfrmMain.MergeExample; 323 | begin 324 | var input : TKInput := TKInput.Create(tnp_shape.Create([32, 32])); 325 | var a : TBaseLayer := TDense.Create(32, 'sigmoid').&Set([input]); 326 | var output : TBaseLayer := TDense.Create(1, 'sigmoid').&Set([a]); 327 | 328 | TModel.Create ( [ input ] , [ output ]); 329 | 330 | //Load train data 331 | var x : TNDarray := TNumPy.npArray( [ [ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1 ] ] ); 332 | redtOutput.Lines.Add('x :' + x.shape.ToString); 333 | TNumPy.npArray( [ 0, 1, 1, 0 ] ); 334 | 335 | var input1 : TKInput := TKInput.Create(tnp_shape.Create([32, 32,3])); 336 | var conv1 : TBaseLayer := TConv2D.Create(32, [4, 4], 'relu').&Set([input1]); 337 | var pool1 : TBaseLayer := TMaxPooling2D.Create([2, 2]).&Set([conv1]); 338 | var flatten1: TBaseLayer := TFlatten.Create.&Set([pool1]); 339 | 340 | var input2 : TKInput := TKInput.Create(tnp_shape.Create([32, 32,3])); 341 | var conv2 : TBaseLayer := TConv2D.Create(16, [8, 8], 'relu').&Set([input2]); 342 | var pool2 : TBaseLayer := TMaxPooling2D.Create([2, 2]).&Set([conv2]); 343 | var flatten2: TBaseLayer := TFlatten.Create.&Set([pool2]); 344 | 345 | TConcatenate.Create([flatten1, flatten2]); 346 | 347 | end; 348 | 349 | procedure TfrmMain.ImplementCallback; 350 | begin 351 | 352 | //Load train data 353 | var x : TNDarray := TNumPy.npArray( [ [ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1 ] ] ); 354 | var y : TNDarray := TNumPy.npArray( [ 0, 1, 1, 0 ] ); 355 | 356 | //Build sequential model 357 | var model : TSequential := TSequential.Create; 358 | 359 | var inp : Tnp_shape := Tnp_shape.Create([2]); 360 | model.Add( TDense.Create(32, 'relu', @inp) ); 361 | model.Add( TDense.Create(64, 'relu')); 362 | model.Add( TDense.Create(1, 'sigmoid')); 363 | 364 | var callback : keras.TCallback := TLearningRateScheduler.Create (pylog) ; 365 | 366 | var lossHistory : keras.TCallback := keras.TCallback.Custom('LossHistory', 'LossHistory.py'); 367 | 368 | 369 | //Compile and train 370 | model.Compile(TAdam.Create, 'binary_crossentropy', [ 'accuracy' ]); 371 | var batch_size: Integer := 2; 372 | model.Fit(x, y, @batch_size, 10, 1, [ callback,lossHistory ]); 373 | 374 | var customLosses: TArray := lossHistory.GetDoubleArray('losses'); 375 | 376 | end; 377 | 378 | procedure TfrmMain.MNIST_CNN; 379 | var 380 | res : TArray; 381 | begin 382 | var batch_size : Integer := 128; //Training batch size 383 | var num_classes: Integer := 10; //No. of classes 384 | var epochs : Integer := 12; //No. of epoches we will train 385 | 386 | // input image dimensions 387 | var img_rows: Integer := 28; 388 | var img_cols: Integer := 28; 389 | 390 | // Declare the input shape for the network 391 | var input_shape : Tnp_shape := default(Tnp_shape); 392 | 393 | // Load the MNIST dataset into Numpy array 394 | res := TMNIST.load_data; 395 | var x_train, y_train ,x_test, y_test : TNDArray; 396 | 397 | x_train := res[0]; 398 | y_train := res[1]; 399 | x_test := res[2]; 400 | y_test := res[3]; 401 | redtOutput.Lines.Add('y_train shape: ' + y_train.shape.ToString); 402 | redtOutput.Repaint; 403 | //Check if its channel fist or last and rearrange the dataset accordingly 404 | var K: TBackend := TBackend.Create; 405 | if(K.ImageDataFormat = 'channels_first') then 406 | begin 407 | x_train := x_train.reshape([x_train.shape[0], 1, img_rows, img_cols]); 408 | x_test := x_test.reshape ([x_test.shape[0] , 1, img_rows, img_cols]); 409 | input_shape := Tnp_shape.Create([1, img_rows, img_cols]); 410 | end else 411 | begin 412 | x_train := x_train.reshape([x_train.shape[0], img_rows, img_cols, 1]); 413 | x_test := x_test.reshape ([x_test.shape[0] , img_rows, img_cols, 1]); 414 | input_shape := Tnp_shape.Create([img_rows, img_cols, 1]); 415 | end; 416 | 417 | //Normalize the input data 418 | x_train := x_train.astype(vNumpy.float32_); 419 | x_test := x_test.astype(vNumpy.float32_); 420 | x_train := TNDArray.opDiv(x_train, 255); 421 | x_test := TNDArray.opDiv(x_test, 255); 422 | 423 | redtOutput.Lines.Add('x_train shape: ' + x_train.shape.ToString); 424 | redtOutput.Lines.Add('y_train shape: ' + y_train.shape.ToString); 425 | redtOutput.Lines.Add( IntToStr(x_train.shape[0]) + ' train samples'); 426 | redtOutput.Lines.Add( IntToStr(x_test.shape[0]) + ' test samples'); 427 | redtOutput.Repaint; 428 | 429 | // Convert class vectors to binary class matrices 430 | var Util : TUtil := TUtil.Create; 431 | y_train := Util.ToCategorical(y_train, @num_classes); 432 | y_test := Util.ToCategorical(y_test, @num_classes); 433 | redtOutput.Lines.Add('y_train shape: ' + y_train.shape.ToString) ; 434 | redtOutput.Repaint; 435 | 436 | // Build CNN model 437 | var model : TSequential := TSequential.Create; 438 | 439 | model.Add( TConv2D.Create(32, [3, 3],'relu', @input_shape) ); 440 | model.Add( TConv2D.Create(64, [3, 3],'relu')); 441 | model.Add( TMaxPooling2D.Create([2, 2])); 442 | model.Add( TDropout.Create(0.25)); 443 | model.Add( TFlatten.Create); 444 | model.Add( TDense.Create(128, 'relu')); 445 | model.Add( TDropout.Create(0.5)); 446 | model.Add( TDense.Create(num_classes, 'softmax')); 447 | model.Summary; 448 | 449 | //Compile with loss, metrics and optimizer 450 | model.Compile(TAdadelta.Create, 'categorical_crossentropy', [ 'accuracy' ]); 451 | 452 | //Train the model 453 | var history: THistory := model.Fit(x_train, y_train, @batch_size, epochs, 1,nil,0,[ x_test, y_test ]); 454 | 455 | srsTraining_Loss.Clear; 456 | srsTraining_Loss.AddArray(history.HistoryLogs['loss']) ; 457 | srsValidation_loss.Clear; 458 | srsValidation_loss.AddArray(history.HistoryLogs['accuracy']); 459 | 460 | //Score the model for performance 461 | var score : TArray := model.Evaluate(x_test, y_test, nil, 0); 462 | 463 | redtOutput.Lines.Add('Test loss: ' + FloatToStr(score[0])); 464 | redtOutput.Lines.Add('Test accuracy:'+ FloatToStr(score[1])); 465 | 466 | // Save the model to HDF5 format which can be loaded later or ported to other application 467 | model.Save('model.h5'); 468 | // Save it to Tensorflow JS format and we will test it in browser. 469 | model.SaveTensorflowJSFormat('./'); 470 | end; 471 | 472 | //https://keras.io/examples/imdb_lstm/ 473 | procedure TfrmMain.SentimentClassificationLSTM; 474 | var 475 | res : TArray; 476 | begin 477 | var max_features: Integer := 20000; 478 | // cut texts after this number of words (among top max_features most common words) 479 | var maxlen : Integer := 80; 480 | var batch_size : Integer := 32; 481 | var EpochNum : Integer := 15; 482 | 483 | redtOutput.Lines.Add('Loading data...'); 484 | res := TIMDB.load_data(@max_features); 485 | var x_train, y_train ,x_test, y_test : TNDArray; 486 | 487 | x_train := res[0]; 488 | y_train := res[1]; 489 | x_test := res[2]; 490 | y_test := res[3]; 491 | 492 | redtOutput.Lines.Add('train sequences: ' + x_train.shape.ToString); 493 | redtOutput.Lines.Add('test sequences: ' + x_test.shape.ToString); 494 | 495 | redtOutput.Lines.Add('Pad sequences (samples x time)'); 496 | var tseq : TSequenceUtil := TSequenceUtil.Create; 497 | x_train := tseq.PadSequences(x_train, @maxlen); 498 | x_test := tseq.PadSequences(x_test, @maxlen); 499 | redtOutput.Lines.Add('x_train shape: ' + x_train.shape.ToString); 500 | redtOutput.Lines.Add('x_test shape: ' + x_test.shape.ToString); 501 | 502 | redtOutput.Lines.Add('Build model...'); 503 | var model : TSequential := TSequential.Create; 504 | model.Add( TEmbedding.Create(max_features, 128)); 505 | model.Add( TLSTM.Create(128, 0.2, 0.2)); 506 | model.Add( TDense.Create(1, 'sigmoid')); 507 | 508 | //try using different optimizers and different optimizer configs 509 | model.Compile('rmsprop', 'binary_crossentropy', [ 'accuracy' ]); 510 | model.Summary; 511 | 512 | redtOutput.Lines.Add('Train...'); 513 | var history: THistory := model.Fit(x_train, y_train, @batch_size, EpochNum, 1,[ x_test, y_test ]); 514 | 515 | srsTraining_Loss.Clear; 516 | srsTraining_Loss.AddArray(history.HistoryLogs['loss']) ; 517 | srsValidation_loss.Clear; 518 | srsValidation_loss.AddArray(history.HistoryLogs['accuracy']); 519 | 520 | //Score the model for performance 521 | var score : TArray := model.Evaluate(x_test, y_test, @batch_size); 522 | 523 | redtOutput.Lines.Add('Test score: ' + FloatToStr(score[0])); 524 | redtOutput.Lines.Add('Test accuracy:'+ FloatToStr(score[1])); 525 | 526 | // Save the model to HDF5 format which can be loaded later or ported to other application 527 | model.Save('model.h5'); 528 | 529 | end; 530 | 531 | procedure TfrmMain.SentimentClassification; 532 | var 533 | res : TArray; 534 | 535 | begin 536 | // Embedding 537 | var max_features := 20000; 538 | var maxlen := 500; 539 | var embedding_size:= 32; 540 | 541 | // Convolution 542 | var filters := 32; 543 | var kernel_size := 3; 544 | var pool_size := 2; 545 | 546 | // Load the dataset but only keep the top n words, zero the rest 547 | res := TIMDB.load_data(@max_features); 548 | 549 | var x_train, y_train ,x_test, y_test: TNDArray; 550 | x_train := res[0]; 551 | y_train := res[1]; 552 | x_test := res[2]; 553 | y_test := res[3]; 554 | redtOutput.Lines.Add('x_train shape: ' + x_train.shape.ToString); 555 | redtOutput.Lines.Add('x_test shape: ' + x_test.shape.ToString); 556 | 557 | var tseq : TSequenceUtil := TSequenceUtil.Create; 558 | x_train := tseq.PadSequences(x_train, @maxlen); 559 | x_test := tseq.PadSequences(x_test, @maxlen); 560 | redtOutput.Lines.Add('x_train shape: ' + x_train.shape.ToString); 561 | redtOutput.Lines.Add('x_test shape: ' + x_test.shape.ToString); 562 | 563 | // Create model 564 | var model : TSequential := TSequential.Create; 565 | 566 | model.Add( TEmbedding.Create(max_features, embedding_size, @maxlen)); 567 | model.Add( TConv1D.Create(filters, kernel_size, 'same', 'relu',nil)); 568 | model.Add( TMaxPooling1D.Create(pool_size)); 569 | model.Add( TFlatten.Create); 570 | model.Add( TDense.Create(250, 'relu')); 571 | model.Add( TDense.Create(1, 'sigmoid')); 572 | 573 | //Compile with loss, metrics and optimizer 574 | model.Compile('sgd', 'categorical_crossentropy', [ 'accuracy' ]); 575 | model.Summary; 576 | 577 | //Train the model 578 | var history : THistory := model.Fit(x_train, y_train, @embedding_size, 10, 2,[ x_test, y_test ]); 579 | 580 | srsTraining_Loss.Clear; 581 | srsTraining_Loss.AddArray(history.HistoryLogs['loss']) ; 582 | srsValidation_loss.Clear; 583 | srsValidation_loss.AddArray(history.HistoryLogs['accuracy']); 584 | 585 | //Score the model for performance 586 | var score : TArray := model.Evaluate(x_test, y_test, nil, 0); 587 | 588 | redtOutput.Lines.Add('Test loss: ' + FloatToStr(score[0])); 589 | redtOutput.Lines.Add('Test accuracy:'+ FloatToStr(score[1]*100)); 590 | 591 | // Save the model to HDF5 format which can be loaded later or ported to other application 592 | model.Save('model.h5'); 593 | // Save it to Tensorflow JS format and we will test it in browser. 594 | model.SaveTensorflowJSFormat('./'); 595 | end; 596 | 597 | procedure TfrmMain.Predict(text: string); 598 | var 599 | model : TBaseModel; 600 | indexes : TDictionary; 601 | words : TArray; 602 | w,res : string; 603 | tokens : TArray; 604 | TextUtil: TTextUtil; 605 | begin 606 | model := TSequential.LoadModel('model.h5') ; 607 | 608 | indexes := TIMDB.GetWordIndex; 609 | 610 | TextUtil := TTextUtil.Create; 611 | Words := TextUtil.TextToWordSequence(text); 612 | for w in words do 613 | tokens := tokens + [ indexes[w] ]; 614 | 615 | var x : TNDArray := TNumPy.npArray(tokens); 616 | x := x.reshape([1,x.shape[0]]); 617 | var tseq : TSequenceUtil := TSequenceUtil.Create; 618 | var maxlen : Integer := 500; 619 | x := tseq.PadSequences(x, @maxlen); 620 | var y : TNDArray := model.Predict(x); 621 | 622 | var binary := Round(y.asscalar); 623 | 624 | if binary = 0 then res := 'Negative' 625 | else res := 'Positive' ; 626 | 627 | redtOutput.Lines.Add(Format('Sentiment for "{%s} : {%s}"',[ text, res])); 628 | 629 | end; 630 | 631 | procedure OnEpochEnd(epochidx: Integer;log:string); 632 | begin 633 | frmMain.redtOutput.Lines.Add('test callback :' + IntToStr(epochidx)); 634 | end; 635 | 636 | function pyOnEpochEnd(self, args : PPyObject): PPyObject;cdecl; far; 637 | var 638 | epochidx,i: Integer ; 639 | dLogs : PPyObject; 640 | 641 | begin 642 | Result := nil; 643 | if g_MyPyEngine.PyArg_ParseTuple( args, 'iO:OnEpochEnd', @epochidx,@dLogs ) <> 0 then 644 | begin 645 | OnEpochEnd(epochidx,'') ; 646 | 647 | Result := g_MyPyEngine.VariantAsPyObject(epochidx) ; 648 | end; 649 | end; 650 | 651 | function TfrmMain.LoadTxt(fileName: string; lenSeq:Integer; step: Integer; var rawTxt: TArray; var DataX: TArray2D; var DataY: TArray):Integer; 652 | var 653 | i,n,n_chars, 654 | seq_length : Integer; 655 | s : AnsiString; 656 | c : AnsiChar; 657 | ss : TStringStream; 658 | seq_in, 659 | seq_out : TArray; 660 | char_to_int : TDictionary; 661 | 662 | begin 663 | Result := 0; 664 | 665 | ss := TStringStream.Create; 666 | try 667 | ss.LoadFromFile(fileName); 668 | SetLength(rawTxt,ss.Size); 669 | 670 | ss.Position := 0; 671 | i := ss.Read(rawTxt[0],ss.Size) ; 672 | 673 | if i <1 then Exit; 674 | 675 | SetString(s,PAnsiChar(@rawTxt[0]), Length(rawTxt)); 676 | s := AnsiLowerCase(s); 677 | 678 | ZeroMemory(@rawTxt[0],Length(rawTxt)); 679 | CopyMemory(@rawTxt[0],@s[1],Length(s)); 680 | s := ''; 681 | 682 | char_to_int := TDictionary.Create; 683 | try 684 | n := 0; 685 | for i := 0 to Length(rawTxt)-1 do 686 | begin 687 | if not char_to_int.ContainsKey( rawTxt[i] ) then 688 | begin 689 | char_to_int.Add(rawTxt[i],n); 690 | inc(n); 691 | end; 692 | end; 693 | Result := char_to_int.Count; 694 | 695 | n_chars := Length(rawTxt); 696 | // # prepare the dataset of input to output pairs encoded as integers 697 | seq_length := lenSeq; 698 | SetLength(seq_in,seq_length) ; 699 | SetLength(seq_out,1); 700 | i := 0; 701 | repeat 702 | ZeroMemory(seq_in,Length(seq_in)); 703 | ZeroMemory(seq_out,Length(seq_out)); 704 | TArray.Copy(rawTxt,seq_in,i,0, seq_length); 705 | TArray.Copy(rawTxt,seq_out,i+seq_length,0, 1); 706 | 707 | SetLength(dataX,Length(dataX)+1); 708 | for c in seq_in do 709 | dataX[ High(dataX) ] := dataX[ High(dataX) ] + [ char_to_int[c] ] ; 710 | 711 | dataY := dataY + [ char_to_int[seq_out[0]] ] ; 712 | 713 | inc(i,Step); 714 | until i >= ((n_chars - seq_length)-1); 715 | 716 | finally 717 | char_to_int.Free; 718 | end; 719 | 720 | finally 721 | ss.Free 722 | end; 723 | end; 724 | 725 | // https://machinelearningmastery.com/text-generation-lstm-recurrent-neural-networks-python-keras/ 726 | // text file - http://www.gutenberg.org/ebooks/28371 727 | procedure TfrmMain.TextGen; 728 | var 729 | n_chars,i,t, 730 | n_vocab, 731 | seq_length, 732 | n_patterns, 733 | step : Integer; 734 | raw_text : TArray; 735 | dataX : TArray2D; 736 | dataY, 737 | sentence : TArray; 738 | item : TArray; 739 | X,Y : TNDArray; 740 | input_shape : Tnp_Shape; 741 | checkpoint, 742 | early_stop, 743 | logEpoch : keras.TCallback ; 744 | batch_size : Integer; 745 | epochs : Integer; 746 | begin 747 | seq_length := 40; 748 | batch_size := 64; 749 | epochs := 20; 750 | step := 3; 751 | 752 | n_vocab := LoadTxt('Alice.txt', seq_length, step,raw_text, dataX,dataY); 753 | n_chars := Length(raw_text); 754 | n_patterns := Length(dataX); 755 | 756 | redtOutput.Lines.Add('Total Characters: ' + IntToStr(n_chars)); 757 | redtOutput.Lines.Add('Total Vocab: ' + IntToStr(n_vocab)); 758 | redtOutput.Lines.Add('Total Patterns: ' + IntToStr(n_patterns)); 759 | 760 | //# reshape X to be [samples, time steps, features] 761 | X := TNumPy.zeros(Tnp_Shape.Create([n_patterns,seq_length,n_vocab]), vNumpy.int32_ ) ; 762 | Y := TNumPy.zeros(Tnp_Shape.Create([n_patterns,n_vocab]), vNumpy.int32_) ; 763 | 764 | //# one hot encode the input/output variable 765 | for i := 0 to n_patterns -1 do 766 | begin 767 | sentence := dataX[i]; 768 | for t := 0 to High(sentence) do 769 | begin 770 | item := [i,t, sentence[t] ]; 771 | X[ item ] := TNumPy.asarray(1); 772 | end; 773 | item := [i, dataY[i]]; 774 | Y[ item ] := TNumPy.asarray(1); 775 | end; 776 | 777 | input_shape := tnp_shape.Create([X.shape[1], X.shape[2]]); 778 | //# define the LSTM model 779 | var model : TSequential := TSequential.Create; 780 | var filepath : string :='weights-improvement-{epoch:02d}-{loss:.4f}.hdf5'; 781 | model.Add( TBidirectional.Create( TGRU.Create(256),@input_shape )); 782 | model.Add( TDropout.Create(0.2)); 783 | model.Add( TDense.Create(y.shape[1])); 784 | model.Add( TActivation.Create('softmax') ); 785 | 786 | model.Compile('adam' ,'categorical_crossentropy', [ 'accuracy' ]); 787 | model.Summary; 788 | 789 | checkpoint := TModelCheckpoint.Create(filepath,'loss',1,True,False,'min'); 790 | early_stop := TEarlyStopping.Create('val_acc',0,20); 791 | logEpoch := TLambdaCallback.Create(pyOnEpochEnd); 792 | 793 | model.Fit(X,Y,@batch_size,epochs,1,[checkpoint,early_stop,logEpoch]) ; 794 | 795 | model.Save('TextGen.h5'); 796 | 797 | end; 798 | 799 | procedure TfrmMain.TextGen_predict(model : TSequential; seqLen, Step: Integer); 800 | var 801 | n,i,start, 802 | n_vocab, 803 | maxlen,t : Integer; 804 | raw_text : TArray; 805 | char_to_int : TDictionary; 806 | int_to_char : TDictionary; 807 | dataX : TArray2D; 808 | dataY : TArray; 809 | pattern,item : TArray; 810 | s : AnsiString; 811 | x,prediction, 812 | tmp : TNDArray; 813 | index : Integer; 814 | begin 815 | tmp := nil; 816 | n_vocab := LoadTxt('Alice.txt', seqLen,Step,raw_text, dataX,dataY); 817 | maxlen := Length (dataX[0]); 818 | 819 | char_to_int := TDictionary.Create; 820 | int_to_char := TDictionary.Create; 821 | try 822 | n := 0; 823 | for i := 0 to Length(raw_text)-1 do 824 | begin 825 | if not char_to_int.ContainsKey( raw_text[i] ) then 826 | begin 827 | char_to_int.Add(raw_text[i],n); 828 | int_to_char.Add(n,raw_text[i]); 829 | inc(n); 830 | end; 831 | end; 832 | //# pick a random seed 833 | start := Random(Length(dataX)-1); 834 | pattern := dataX[start]; 835 | 836 | s:= ''; 837 | for i := 0 to High(pattern) do 838 | s := s + int_to_char[ pattern[i] ]; 839 | 840 | redtOutput.Lines.Add('Seed: '); 841 | redtOutput.Lines.Add(s); 842 | redtOutput.Repaint; 843 | 844 | //# generate characters 845 | for i := 0 to 1000 do 846 | begin 847 | X := TNumPy.zeros(Tnp_Shape.Create([1,maxlen,n_vocab]), vNumpy.bool_ ) ; 848 | //# one hot encode the input/output variable 849 | for t := 0 to High(pattern) do 850 | begin 851 | item := [0,t, pattern[t]]; 852 | X[ item ] := TNumPy.asarray(1); 853 | end; 854 | 855 | prediction := model.Predict(X,nil,0); 856 | index := vNumpy.argmax(prediction,nil,tmp).asscalar; 857 | pattern := pattern + [ index ]; 858 | Delete(pattern,0,1); 859 | 860 | s := s + int_to_char[ index ]; 861 | end; 862 | redtOutput.Lines.Add('Output: '); 863 | redtOutput.Lines.Add(s); 864 | redtOutput.Refresh; 865 | finally 866 | char_to_int.Free; 867 | int_to_char.Free; 868 | end; 869 | end; 870 | 871 | procedure TfrmMain.FormShow(Sender: TObject); 872 | var 873 | jpg: TJpegImage; 874 | 875 | begin 876 | // inizialige python engine with gui input/output 877 | InitGlobal(PyIOCom); 878 | 879 | vNumpy := TNumPy.Init(True); 880 | 881 | jpg := TJpegImage.Create; 882 | jpg.LoadFromFile('nn.jpg'); 883 | img1.Picture.Assign(jpg); 884 | end; 885 | 886 | end. 887 | -------------------------------------------------------------------------------- /src/Keras.Models.pas: -------------------------------------------------------------------------------- 1 | {*******************************************************} 2 | { } 3 | { Keras Wrapper for Delphi } 4 | { } 5 | { Copyright (C) 2020 Pigrecos(Max) } 6 | { } 7 | {*******************************************************} 8 | 9 | unit Keras.Models; 10 | 11 | interface 12 | uses System.SysUtils, System.Generics.Collections, 13 | PythonEngine, Keras,np.Models,Python.Utils, 14 | Keras.Layers; 15 | 16 | type 17 | 18 | // BaseModel 19 | 20 | TBaseModel = class(TBase) 21 | public 22 | constructor Create; 23 | procedure Compile(optimizer : TStringOrInstance; 24 | loss : string; 25 | metrics : TArray= nil; 26 | loss_weights : TArray = nil; 27 | sample_weight_mode : PChar = nil; 28 | weighted_metrics : TArray = nil; 29 | target_tensors : TArray= nil); 30 | function Fit(x : TNDarray; 31 | y : TNDarray; 32 | batch_size : PInteger = nil; 33 | epochs : Integer = 1; 34 | verbose : Integer= 1; 35 | callbacks : TArray = nil; 36 | validation_split : Double = 0.0; 37 | validation_data : TArray = nil; 38 | shuffle : Boolean = true; 39 | class_weight : TDictionary = nil; 40 | sample_weight : TNDarray = nil; 41 | initial_epoch : Integer = 0; 42 | steps_per_epoch : PInteger = nil; 43 | validation_steps : PInteger= nil):THistory;overload; 44 | function Fit(x : TNDarray; 45 | y : TNDarray; 46 | batch_size : PInteger ; 47 | epochs : Integer; 48 | verbose : Integer; 49 | validation_data : TArray ):THistory;overload; 50 | function Evaluate(x : TNDarray; 51 | y : TNDarray; 52 | batch_size : PInteger = nil; 53 | verbose : Integer= 1; 54 | sample_weight : TNDarray = nil; 55 | steps : PInteger= nil; 56 | callbacks : TArray = nil): TArray; 57 | function Predict(x : TNDarray; 58 | batch_size : PInteger = nil; 59 | verbose : Integer= 1; 60 | steps : PInteger= nil; 61 | callbacks : TArray = nil):TNDarray; overload; 62 | function Predict(x : TArray; // List 63 | batch_size : PInteger = nil; 64 | verbose : Integer= 1; 65 | steps : PInteger= nil; 66 | callbacks : TArray = nil):TNDarray;overload; 67 | function TrainOnBatch(x : TNDarray; 68 | y : TNDarray; 69 | sample_weight : TNDarray = nil; 70 | class_weight : TDictionary = nil): TArray; 71 | function TestOnBatch(x : TNDarray; 72 | y : TNDarray; 73 | sample_weight : TNDarray = nil): TArray; 74 | function PredictOnBatch(x: TNDarray):TNDarray; 75 | function FitGenerator(generator : TSequence; 76 | steps_per_epoch : PInteger = nil; 77 | epochs : Integer = 1; 78 | verbose : Integer= 1; 79 | callbacks : TArray = nil; 80 | validation_data : TSequence = nil; 81 | validation_steps : PInteger = nil; 82 | validation_freq : Integer = 1; 83 | class_weight : TDictionary = nil; 84 | max_queue_size : Integer= 10; 85 | workers : Integer = 1; 86 | use_multiprocessing : Boolean = false; 87 | shuffle : Boolean= true; 88 | initial_epoch : Integer= 0):THistory; 89 | function EvaluateGenerator(generator : TSequence; 90 | steps : PInteger= nil; 91 | callbacks : TArray = nil; 92 | max_queue_size : Integer = 10; 93 | workers : Integer = 1; 94 | use_multiprocessing : Boolean = false; 95 | verbose : Integer = 0): TArray; 96 | function PredictGenerator(generator : TSequence; 97 | steps : PInteger= nil; 98 | callbacks : TArray = nil; 99 | max_queue_size : Integer = 10; 100 | workers : Integer = 1; 101 | use_multiprocessing : Boolean = false; 102 | verbose : Integer = 0):TNDarray; 103 | function ToJson: string; 104 | procedure SaveWeight(path: string); 105 | procedure Save(filepath: string; overwrite : Boolean= true; include_optimizer: Boolean = true) ; 106 | function GetWeights: TArray; 107 | procedure SetWeights(weights: TArray); 108 | procedure LoadWeight(path: string); 109 | procedure Summary(line_length: PInteger = nil; positions : TArray= nil) ; 110 | function ModelFromYaml(Yaml_string:string): TBaseModel; 111 | procedure SaveOnnx(filePath: string); 112 | procedure SaveTensorflowJSFormat(artifacts_dir: string; quantize : Boolean= false); 113 | 114 | class function LoadModel(filepath: string; custom_objects: TDictionary = nil; compile : Boolean = true): TBaseModel; 115 | class function ModelFromJson(json_string: string): TBaseModel; 116 | end; 117 | 118 | TModel = class(TBaseModel) 119 | public 120 | constructor Create; overload; 121 | constructor Create(py: PPyObject); overload; 122 | constructor Create(py: TPythonObject); overload; 123 | constructor Create(input,output: TArray); overload; 124 | constructor Create(input: TArray); overload; 125 | end; 126 | 127 | TSequential = class(TBaseModel) 128 | public 129 | constructor Create; overload; 130 | constructor Create(py: PPyObject); overload; 131 | constructor Create(py: TPythonObject); overload; 132 | constructor Create(input: TArray); overload; 133 | 134 | procedure Add(layer: TBaseLayer); 135 | end; 136 | 137 | // Utils 138 | TUtil = class(TBase) 139 | public 140 | caller : TPythonObject; 141 | constructor Create; 142 | function MultiGPUModel(model: TBaseModel; gpus: TArray; cpu_merge: Boolean = true; cpu_relocation: Boolean = false): TBaseModel;overload; 143 | function MultiGPUModel(model: TBaseModel; gpus: Integer; cpu_merge: Boolean = true; cpu_relocation: Boolean = false):TBaseModel; overload; 144 | function ToCategorical(y: TNDarray; num_classes : PInteger= nil; dtype: string = 'float32'):TNDarray; 145 | function Normalize(y: TNDarray; axis: Integer = -1; order: Integer = 2): TNDarray; 146 | procedure PlotModel(model: TBaseModel; to_file: string = 'model.png'; show_shapes: Boolean = false; show_layer_names: Boolean = true; rankdir: string = 'TB'; expand_nested: Boolean = false; dpi: Integer = 96) ; 147 | procedure ConfigTensorFlowBackend(intra_op_parallelism_threads: Integer; inter_op_parallelism_threads: Integer; allow_soft_placement: Boolean; cpu_device_count: Integer;gpu_device_count: Integer ); 148 | procedure device( device_name: string ); 149 | end; 150 | 151 | implementation 152 | uses Winapi.Windows, System.IOUtils, System.Rtti,np.Utils,np.Base, np.Api; 153 | 154 | { TUtil } 155 | 156 | constructor TUtil.Create; 157 | begin 158 | inherited create; 159 | 160 | caller := GetKerasClassIstance('utils'); 161 | end; 162 | 163 | function TUtil.MultiGPUModel(model: TBaseModel; gpus: TArray; cpu_merge: Boolean = true; cpu_relocation: Boolean = false): TBaseModel; 164 | begin 165 | Result := TBaseModel.Create; 166 | 167 | Parameters.Clear; 168 | Parameters.Add( TPair.Create('model',model) ); 169 | Parameters.Add( TPair.Create('gpus', TValue.FromArray(gpus)) ); 170 | Parameters.Add( TPair.Create('cpu_merge',cpu_merge) ); 171 | Parameters.Add( TPair.Create('cpu_relocation',cpu_relocation) ); 172 | 173 | Result.PyInstance := InvokeStaticMethod(caller,'multi_gpu_model',Parameters) 174 | end; 175 | 176 | function TUtil.MultiGPUModel(model: TBaseModel; gpus: Integer;cpu_merge: Boolean = true; cpu_relocation: Boolean = false):TBaseModel; 177 | begin 178 | Result := TBaseModel.Create; 179 | 180 | Parameters.Clear; 181 | Parameters.Add( TPair.Create('model',model) ); 182 | Parameters.Add( TPair.Create('gpus',gpus) ); 183 | Parameters.Add( TPair.Create('cpu_merge',cpu_merge) ); 184 | Parameters.Add( TPair.Create('cpu_relocation',cpu_relocation) ); 185 | 186 | Result.PyInstance := InvokeStaticMethod(caller,'multi_gpu_model',Parameters) 187 | end; 188 | 189 | function TUtil.ToCategorical(y: TNDarray; num_classes : PInteger= nil; dtype: string = 'float32'):TNDarray; 190 | begin 191 | Parameters.Clear; 192 | Parameters.Add( TPair.Create('y',y) ); 193 | 194 | if num_classes <> nil then Parameters.Add( TPair.Create('num_classes',num_classes^)) 195 | else Parameters.Add( TPair.Create('num_classes', TPythonObject.None )); 196 | 197 | Parameters.Add( TPair.Create('dtype',dtype) ); 198 | 199 | Result := TNDArray.Create( InvokeStaticMethod(caller,'to_categorical',Parameters) ) 200 | 201 | end; 202 | 203 | function TUtil.Normalize(y: TNDarray; axis: Integer = -1; order: Integer = 2): TNDarray; 204 | begin 205 | Parameters.Clear; 206 | Parameters.Add( TPair.Create('y',y) ); 207 | Parameters.Add( TPair.Create('axis',axis) ); 208 | Parameters.Add( TPair.Create('order',order) ); 209 | 210 | Result := TNDArray.Create( InvokeStaticMethod(caller,'normalize',Parameters) ) 211 | end; 212 | 213 | procedure TUtil.PlotModel(model: TBaseModel; to_file: string = 'model.png'; show_shapes: Boolean = false; show_layer_names: Boolean = true; rankdir: string = 'TB'; expand_nested: Boolean = false; dpi: Integer = 96) ; 214 | begin 215 | Parameters.Clear; 216 | Parameters.Add( TPair.Create('model',model) ); 217 | Parameters.Add( TPair.Create('to_file',to_file) ); 218 | Parameters.Add( TPair.Create('show_shapes',show_shapes) ); 219 | Parameters.Add( TPair.Create('show_layer_names',show_layer_names) ); 220 | Parameters.Add( TPair.Create('rankdir',rankdir) ); 221 | Parameters.Add( TPair.Create('expand_nested',expand_nested) ); 222 | Parameters.Add( TPair.Create('dpi',dpi) ); 223 | 224 | InvokeStaticMethod(caller,'plot_model',Parameters) 225 | end; 226 | 227 | procedure TUtil.ConfigTensorFlowBackend(intra_op_parallelism_threads: Integer; inter_op_parallelism_threads: Integer; allow_soft_placement: Boolean; cpu_device_count: Integer;gpu_device_count: Integer ); 228 | var 229 | tf,conf,kb,config,session : TPythonObject; 230 | deviceCount : TPyDict; 231 | begin 232 | tf := TPythonObject.Create(ImportModule('tensorflow')); 233 | conf := TPythonObject.Create(ImportModule('tensorflow.compat.v1')); 234 | kb := TPythonObject.Create(ImportModule('tensorflow.compat.v1.keras.backend')); 235 | 236 | deviceCount := TPyDict.Create; 237 | deviceCount['CPU'] := TPyInt.Create( cpu_device_count ); 238 | deviceCount['GPU'] := TPyInt.Create( gpu_device_count ); 239 | 240 | Parameters.Clear; 241 | Parameters.Add( TPair.Create('intra_op_parallelism_threads',intra_op_parallelism_threads) ); 242 | Parameters.Add( TPair.Create('inter_op_parallelism_threads',inter_op_parallelism_threads) ); 243 | Parameters.Add( TPair.Create('allow_soft_placement',allow_soft_placement) ); 244 | Parameters.Add( TPair.Create('device_count',deviceCount) ); 245 | config := InvokeStaticMethod(conf,'ConfigProto',Parameters,False) ; 246 | 247 | Parameters.Clear; 248 | Parameters.Add( TPair.Create('config',config) ); 249 | session := InvokeStaticMethod(conf,'Session',Parameters,False); 250 | 251 | Parameters.Clear; 252 | Parameters.Add( TPair.Create('session',session) ); 253 | InvokeStaticMethod(kb,'set_session',Parameters) 254 | end; 255 | 256 | procedure TUtil.device( device_name: string ); 257 | var 258 | tf : TPythonObject; 259 | 260 | begin 261 | tf := TPythonObject.Create(ImportModule('tensorflow')); 262 | 263 | Parameters.Clear; 264 | Parameters.Add( TPair.Create('device_name',device_name) ); 265 | 266 | InvokeStaticMethod(tf,'device',Parameters) 267 | end; 268 | 269 | { TBaseModel } 270 | 271 | constructor TBaseModel.Create; 272 | begin 273 | inherited Create; 274 | end; 275 | 276 | procedure TBaseModel.Compile(optimizer: TStringOrInstance; loss: string; metrics: TArray; 277 | loss_weights: TArray; sample_weight_mode: PChar; weighted_metrics: TArray; 278 | target_tensors: TArray); 279 | begin 280 | Parameters.Clear; 281 | 282 | Parameters.Add( TPair.Create('optimizer',optimizer.PyObject)); 283 | Parameters.Add( TPair.Create('loss',loss)); 284 | Parameters.Add( TPair.Create('metrics',TValue.FromArray(metrics))); 285 | Parameters.Add( TPair.Create('loss_weights',TValue.FromArray(loss_weights))); 286 | Parameters.Add( TPair.Create('sample_weight_mode',sample_weight_mode)); 287 | Parameters.Add( TPair.Create('weighted_metrics',TValue.FromArray(weighted_metrics))); 288 | Parameters.Add( TPair.Create('target_tensors',TValue.FromArray(target_tensors))); 289 | 290 | g_MyPyEngine.Py_XDecRef(InvokeMethod('compile',Parameters).Handle) 291 | end; 292 | 293 | function TBaseModel.Evaluate(x, y: TNDarray; batch_size: PInteger; verbose: Integer; sample_weight: TNDarray; 294 | steps: PInteger; callbacks: TArray): TArray; 295 | begin 296 | Parameters.Clear; 297 | 298 | Parameters.Add( TPair.Create('x', x)); 299 | Parameters.Add( TPair.Create('y',y)); 300 | 301 | if batch_size <> nil then 302 | Parameters.Add( TPair.Create('batch_size',batch_size^)); 303 | 304 | Parameters.Add( TPair.Create('verbose',verbose)); 305 | Parameters.Add( TPair.Create('sample_weight',sample_weight)); 306 | 307 | if steps <> nil then 308 | Parameters.Add( TPair.Create('steps',steps^)); 309 | 310 | if callbacks <> nil then 311 | Parameters.Add( TPair.Create('callbacks',TValue.FromArray(callbacks))); 312 | 313 | Result := InvokeMethod('evaluate',Parameters).AsArrayofDouble; 314 | end; 315 | 316 | function TBaseModel.EvaluateGenerator(generator: TSequence; steps: PInteger; callbacks: TArray; 317 | max_queue_size, workers: Integer; use_multiprocessing: Boolean; verbose: Integer): TArray; 318 | var 319 | pyresult : TPythonObject; 320 | begin 321 | Parameters.Clear; 322 | 323 | Parameters.Add( TPair.Create('generator',generator)); 324 | 325 | if steps <> nil then 326 | Parameters.Add( TPair.Create('steps',steps^)); 327 | 328 | if callbacks <> nil then 329 | Parameters.Add( TPair.Create('callbacks',TValue.FromArray(callbacks))); 330 | 331 | Parameters.Add( TPair.Create('max_queue_size',max_queue_size)); 332 | Parameters.Add( TPair.Create('workers',workers)); 333 | Parameters.Add( TPair.Create('use_multiprocessing',use_multiprocessing)); 334 | Parameters.Add( TPair.Create('verbose',verbose)); 335 | 336 | pyresult := InvokeMethod('evaluate_generator',Parameters); 337 | 338 | Result := []; 339 | if pyresult = nil then Exit(Result); 340 | 341 | if not g_MyPyEngine.PyIter_Check(pyresult.Handle) then 342 | begin 343 | Result := Result + [ pyresult.AsDouble ]; 344 | Exit; 345 | end; 346 | 347 | result := pyresult.AsArrayofDouble; 348 | 349 | g_MyPyEngine.Py_XDecRef(pyresult.handle); 350 | 351 | end; 352 | 353 | function TBaseModel.Fit(x, y: TNDarray; batch_size: PInteger; epochs, verbose: Integer; callbacks: TArray; 354 | validation_split: Double; validation_data: TArray; shuffle: Boolean; 355 | class_weight: TDictionary; sample_weight: TNDarray; initial_epoch: Integer; steps_per_epoch, 356 | validation_steps: PInteger): THistory; 357 | var 358 | py : TPythonObject; 359 | begin 360 | Parameters.Clear; 361 | 362 | Parameters.Add( TPair.Create('x',x)); 363 | Parameters.Add( TPair.Create('y',y)); 364 | 365 | if batch_size <> nil then Parameters.Add( TPair.Create('batch_size',batch_size^)) 366 | else Parameters.Add( TPair.Create('batch_size', TPythonObject.None )); 367 | 368 | Parameters.Add( TPair.Create('epochs',epochs)); 369 | Parameters.Add( TPair.Create('verbose',verbose)); 370 | 371 | if callbacks <> nil then Parameters.Add( TPair.Create('callbacks',TValue.FromArray(callbacks))) 372 | else Parameters.Add( TPair.Create('callbacks', TPythonObject.None )); 373 | 374 | Parameters.Add( TPair.Create('validation_split',validation_split)); 375 | 376 | if (validation_data <> nil) then Parameters.Add( TPair.Create('validation_data', TValue.FromArray(validation_data))) 377 | else Parameters.Add( TPair.Create('validation_data', TPythonObject.None )); 378 | 379 | Parameters.Add( TPair.Create('shuffle',shuffle)); 380 | 381 | if (class_weight <> nil) then Parameters.Add( TPair.Create('class_weight',ToDict(class_weight))) 382 | else Parameters.Add( TPair.Create('class_weight', TPythonObject.None )); 383 | 384 | Parameters.Add( TPair.Create('sample_weight',sample_weight)); 385 | Parameters.Add( TPair.Create('initial_epoch',initial_epoch)); 386 | 387 | if steps_per_epoch <> nil then Parameters.Add( TPair.Create('steps_per_epoch',steps_per_epoch^)) 388 | else Parameters.Add( TPair.Create('steps_per_epoch', TPythonObject.None )); 389 | 390 | if validation_steps <> nil then Parameters.Add( TPair.Create('validation_steps',validation_steps^)) 391 | else Parameters.Add( TPair.Create('validation_steps', TPythonObject.None )); 392 | 393 | py := InvokeMethod('fit', Parameters); 394 | 395 | Result := THistory.Create(py); 396 | 397 | 398 | end; 399 | 400 | function TBaseModel.Fit(x, y: TNDarray; batch_size: PInteger; epochs, verbose: Integer; validation_data: TArray): THistory; 401 | var 402 | py : TPythonObject; 403 | begin 404 | Parameters.Clear; 405 | 406 | Parameters.Add( TPair.Create('x',x)); 407 | Parameters.Add( TPair.Create('y',y)); 408 | 409 | if batch_size <> nil then Parameters.Add( TPair.Create('batch_size',batch_size^)) 410 | else Parameters.Add( TPair.Create('batch_size', TPythonObject.None )); 411 | 412 | Parameters.Add( TPair.Create('epochs',epochs)); 413 | Parameters.Add( TPair.Create('verbose',verbose)); 414 | 415 | 416 | if (validation_data <> nil) then Parameters.Add( TPair.Create('validation_data', TValue.FromArray(validation_data))) 417 | else Parameters.Add( TPair.Create('validation_data', TPythonObject.None )); 418 | 419 | py := InvokeMethod('fit', Parameters); 420 | 421 | Result := THistory.Create(py); 422 | end; 423 | 424 | function TBaseModel.FitGenerator(generator: TSequence; steps_per_epoch: PInteger; epochs, verbose: Integer; 425 | callbacks: TArray; validation_data: TSequence; validation_steps: PInteger; validation_freq: Integer; 426 | class_weight: TDictionary; max_queue_size, workers: Integer; use_multiprocessing, shuffle: Boolean; 427 | initial_epoch: Integer): THistory; 428 | begin 429 | Parameters.Clear; 430 | 431 | Parameters.Add( TPair.Create('generator',generator)); 432 | if steps_per_epoch <> nil then 433 | Parameters.Add( TPair.Create('steps_per_epoch',steps_per_epoch^)); 434 | 435 | Parameters.Add( TPair.Create('epochs',epochs)); 436 | Parameters.Add( TPair.Create('verbose',verbose)); 437 | 438 | if callbacks <> nil then 439 | Parameters.Add( TPair.Create('callbacks',TValue.FromArray(callbacks))); 440 | 441 | if (validation_data <> nil) then 442 | Parameters.Add( TPair.Create('validation_data',validation_data)); 443 | 444 | if validation_steps <> nil then 445 | Parameters.Add( TPair.Create('validation_steps',validation_steps^)); 446 | //Parameters.Add( TPair.Create('validation_freq',validation_freq)); 447 | Parameters.Add( TPair.Create('class_weight',class_weight)); 448 | Parameters.Add( TPair.Create('max_queue_size',max_queue_size)); 449 | Parameters.Add( TPair.Create('workers',workers)); 450 | Parameters.Add( TPair.Create('use_multiprocessing',use_multiprocessing)); 451 | Parameters.Add( TPair.Create('shuffle',shuffle)); 452 | Parameters.Add( TPair.Create('initial_epoch',initial_epoch)); 453 | 454 | var py := InvokeMethod('fit_generator', Parameters); 455 | 456 | Result := THistory.Create(py); 457 | end; 458 | 459 | class function TBaseModel.LoadModel(filepath: string; custom_objects: TDictionary; compile: Boolean): TBaseModel; 460 | var 461 | model: TBaseModel; 462 | dict : TPyDict; 463 | item : TPair; 464 | args : TList< TPair > ; 465 | begin 466 | model := TBaseModel.Create; 467 | 468 | if custom_objects <> nil then 469 | begin 470 | dict := TPyDict.Create; 471 | for item in custom_objects do 472 | dict[item.Key] := ToPython(Item.Value) ; 473 | end; 474 | 475 | args := TList< TPair >.Create; 476 | 477 | args.Add( TPair.Create('filepath',filepath)); 478 | 479 | if custom_objects <> nil then args.Add( TPair.Create('custom_objects',ToDict(custom_objects))) 480 | else args.Add( TPair.Create('custom_objects', TPythonObject.None )); 481 | 482 | model.PyInstance := GetKerasClassIstance('models'); 483 | model.PyInstance := InvokeStaticMethod(model.PyInstance,'load_model',args) ; 484 | 485 | Result := model; 486 | 487 | end; 488 | 489 | class function TBaseModel.ModelFromJson(json_string: string): TBaseModel; 490 | var 491 | model: TBaseModel; 492 | args : TList< TPair > ; 493 | begin 494 | model := TBaseModel.Create; 495 | 496 | args := TList< TPair >.Create; 497 | 498 | args.Add( TPair.Create('json_string',json_string)); 499 | 500 | model.PyInstance := GetKerasClassIstance('models'); 501 | model.PyInstance := InvokeStaticMethod(model.PyInstance,'model_from_json',args) ; 502 | 503 | Result := model; 504 | end; 505 | 506 | function TBaseModel.ModelFromYaml(Yaml_string: string): TBaseModel; 507 | var 508 | model: TBaseModel; 509 | begin 510 | model := TBaseModel.Create; 511 | 512 | Parameters.Clear; 513 | Parameters.Add( TPair.Create('Yaml_string',Yaml_string)); 514 | 515 | model.PyInstance := GetKerasClassIstance('models'); 516 | model.PyInstance := InvokeStaticMethod(model.PyInstance,'model_from_yaml',Parameters) ; 517 | 518 | Result := model; 519 | end; 520 | 521 | function TBaseModel.GetWeights: TArray; 522 | var 523 | pyWeights : TPythonObject; 524 | weights : TArray; 525 | i : Integer; 526 | weightsArray: PPyObject; 527 | begin 528 | Parameters.Clear; 529 | 530 | pyWeights := InvokeMethod('get_weights',Parameters) ; 531 | 532 | for i := 0 to g_MyPyEngine.PySequence_Length( pyWeights.Handle )-1 do 533 | begin 534 | weightsArray := g_MyPyEngine.PySequence_GetItem( pyWeights.Handle, i ) ; 535 | 536 | var n : TNDarray := TNumPy.npArray( TNDarray.Create(weightsArray) ); 537 | weights := weights + [ n ]; 538 | end; 539 | 540 | Result := weights; 541 | end; 542 | 543 | procedure TBaseModel.SetWeights(weights: TArray); 544 | var 545 | list : TPyList; 546 | i : Integer; 547 | begin 548 | list := TPyList.Create; 549 | 550 | for i := 0 to High(weights) do 551 | list.Append(weights[i]); 552 | 553 | Parameters.Clear; 554 | 555 | Parameters.Add( TPair.Create('list', list)); 556 | 557 | g_MyPyEngine.Py_XDecRef(InvokeMethod('set_weights',Parameters).Handle) 558 | end; 559 | 560 | procedure TBaseModel.SaveWeight(path: string); 561 | begin 562 | Parameters.Clear; 563 | 564 | Parameters.Add( TPair.Create('path', path)); 565 | 566 | g_MyPyEngine.Py_XDecRef(InvokeMethod('save_weights',Parameters).Handle) 567 | end; 568 | 569 | procedure TBaseModel.LoadWeight(path: string); 570 | begin 571 | Parameters.Clear; 572 | 573 | Parameters.Add( TPair.Create('path', path)); 574 | 575 | g_MyPyEngine.Py_XDecRef(InvokeMethod('load_weights',Parameters).Handle) 576 | end; 577 | 578 | procedure TBaseModel.Save(filepath: string; overwrite, include_optimizer: Boolean); 579 | begin 580 | Parameters.Clear; 581 | 582 | Parameters.Add( TPair.Create('filepath', filepath)); 583 | Parameters.Add( TPair.Create('overwrite', overwrite)); 584 | Parameters.Add( TPair.Create('include_optimizer', include_optimizer)); 585 | 586 | g_MyPyEngine.Py_XDecRef(InvokeMethod('save',Parameters).Handle) 587 | end; 588 | 589 | procedure TBaseModel.Summary(line_length: PInteger; positions: TArray); 590 | begin 591 | Parameters.Clear; 592 | 593 | if line_length <> nil then Parameters.Add( TPair.Create('line_length', line_length^)) 594 | else Parameters.Add( TPair.Create('line_length', TPythonObject.None )); 595 | 596 | if positions <> nil then Parameters.Add( TPair.Create('positions', TValue.FromArray(positions))) 597 | else Parameters.Add( TPair.Create('positions', TPythonObject.None )); 598 | 599 | g_MyPyEngine.Py_XDecRef(InvokeMethod('summary',Parameters).Handle ); 600 | 601 | end; 602 | 603 | function TBaseModel.ToJson: string; 604 | begin 605 | Parameters.Clear; 606 | 607 | Result := InvokeMethod('to_json',Parameters).ToString; 608 | end; 609 | 610 | function TBaseModel.Predict(x: TArray; batch_size: PInteger; verbose: Integer; steps: PInteger; 611 | callbacks: TArray): TNDarray; 612 | var 613 | items : TArray; 614 | x_tuple: TPyTuple; 615 | n : Integer; 616 | begin 617 | Parameters.Clear; 618 | 619 | for n := 0 to Length(x) - 1 do 620 | items := items + [ x[n].Handle ]; 621 | 622 | x_tuple := TPyTuple.Create(items); 623 | 624 | Parameters.Add( TPair.Create('x',x_tuple)); 625 | if batch_size <> nil then 626 | Parameters.Add( TPair.Create('batch_size',batch_size^)); 627 | Parameters.Add( TPair.Create('verbose',verbose)); 628 | if steps <> nil then 629 | Parameters.Add( TPair.Create('steps',steps^)); 630 | if callbacks <> nil then 631 | Parameters.Add( TPair.Create('callbacks',TValue.FromArray(callbacks))); 632 | 633 | Result := TNDarray.Create(InvokeMethod('predict', Parameters)); 634 | end; 635 | 636 | function TBaseModel.Predict(x: TNDarray; batch_size: PInteger; verbose: Integer; steps: PInteger; 637 | callbacks: TArray): TNDarray; 638 | begin 639 | Parameters.Clear; 640 | 641 | Parameters.Add( TPair.Create('x',x)); 642 | if batch_size <> nil then 643 | Parameters.Add( TPair.Create('batch_size',batch_size^)); 644 | Parameters.Add( TPair.Create('verbose',verbose)); 645 | if steps <> nil then 646 | Parameters.Add( TPair.Create('steps',steps^)); 647 | if callbacks <> nil then 648 | Parameters.Add( TPair.Create('callbacks',TValue.FromArray(callbacks))); 649 | 650 | Result := TNDarray.Create(InvokeMethod('predict', Parameters)); 651 | end; 652 | 653 | function TBaseModel.PredictGenerator(generator: TSequence; steps: PInteger; callbacks: TArray; 654 | max_queue_size, workers: Integer; use_multiprocessing: Boolean; verbose: Integer): TNDarray; 655 | var 656 | py : TPythonObject; 657 | begin 658 | Parameters.Clear; 659 | 660 | Parameters.Add( TPair.Create('generator',generator)); 661 | if steps <> nil then 662 | Parameters.Add( TPair.Create('steps',steps^)); 663 | if callbacks <> nil then 664 | Parameters.Add( TPair.Create('callbacks',TValue.FromArray(callbacks))); 665 | Parameters.Add( TPair.Create('max_queue_size',max_queue_size)); 666 | Parameters.Add( TPair.Create('workers',workers)); 667 | Parameters.Add( TPair.Create('use_multiprocessing',use_multiprocessing)); 668 | Parameters.Add( TPair.Create('verbose',verbose)); 669 | 670 | py := InvokeMethod('predict_generator', Parameters); 671 | 672 | Result := TNDarray.Create(py); 673 | end; 674 | 675 | function TBaseModel.PredictOnBatch(x: TNDarray): TNDarray; 676 | begin 677 | Parameters.Clear; 678 | 679 | Parameters.Add( TPair.Create('x',x)); 680 | 681 | Result := TNDarray.Create(InvokeMethod('predict_on_batch', Parameters)); 682 | end; 683 | 684 | function TBaseModel.TrainOnBatch(x, y, sample_weight: TNDarray; class_weight: TDictionary): TArray; 685 | var 686 | pyresult : TPythonObject; 687 | begin 688 | Parameters.Clear; 689 | 690 | Parameters.Add( TPair.Create('x',x)); 691 | Parameters.Add( TPair.Create('y',y)); 692 | Parameters.Add( TPair.Create('sample_weight',sample_weight)); 693 | Parameters.Add( TPair.Create('class_weight',class_weight)); 694 | 695 | pyresult := InvokeMethod('train_on_batch', Parameters); 696 | 697 | Result := []; 698 | if pyresult = nil then Exit(Result); 699 | 700 | if not g_MyPyEngine.PyIter_Check(pyresult.Handle) then 701 | begin 702 | Result := Result + [ pyresult.AsDouble ]; 703 | Exit; 704 | end; 705 | 706 | result := pyresult.AsArrayofDouble; 707 | end; 708 | 709 | function TBaseModel.TestOnBatch(x, y, sample_weight: TNDarray): TArray; 710 | var 711 | pyresult : TPythonObject; 712 | begin 713 | Parameters.Clear; 714 | 715 | Parameters.Add( TPair.Create('x',x)); 716 | Parameters.Add( TPair.Create('y',y)); 717 | Parameters.Add( TPair.Create('sample_weight',sample_weight)); 718 | 719 | pyresult := InvokeMethod('test_on_batch', Parameters); 720 | 721 | Result := []; 722 | if pyresult = nil then Exit(Result); 723 | 724 | if not g_MyPyEngine.PyIter_Check(pyresult.Handle) then 725 | begin 726 | Result := Result + [ pyresult.AsDouble ]; 727 | Exit; 728 | end; 729 | 730 | result := pyresult.AsArrayofDouble; 731 | g_MyPyEngine.Py_XDecRef(pyresult.Handle); 732 | end; 733 | 734 | procedure TBaseModel.SaveOnnx(filePath: string); 735 | begin 736 | Parameters.Clear; 737 | 738 | Parameters.Add( TPair.Create('filePath',filePath)); 739 | 740 | InvokeStaticMethod(hkeras2onnxMod,'convert_keras',Parameters) ; 741 | TFile.WriteAllText(filePath, hkeras2onnxMod.ToString); 742 | end; 743 | 744 | procedure TBaseModel.SaveTensorflowJSFormat(artifacts_dir: string; quantize: Boolean); 745 | var 746 | htf : TPythonObject; 747 | begin 748 | Parameters.Clear; 749 | 750 | htf := GetTFJSClassIstance('converters'); 751 | 752 | if htf = nil then 753 | begin 754 | MessageBoxA(0,'tensorflowjs not installated!','Info',MB_OK); 755 | Exit; 756 | end; 757 | 758 | Parameters.Add( TPair.Create('model',PyInstance)); 759 | Parameters.Add( TPair.Create('artifacts_dir',artifacts_dir)); 760 | Parameters.Add( TPair.Create('quantize',quantize)); 761 | 762 | InvokeStaticMethod(htf,'save_keras_model',Parameters) ; 763 | 764 | end; 765 | 766 | { TModel } 767 | 768 | constructor TModel.Create; 769 | begin 770 | inherited Create; 771 | end; 772 | 773 | 774 | constructor TModel.Create(py: TPythonObject); 775 | begin 776 | Create; 777 | PyInstance := py; 778 | end; 779 | 780 | constructor TModel.Create(py: PPyObject); 781 | begin 782 | Create; 783 | PyInstance := TPythonObject.Create( py ); 784 | end; 785 | 786 | constructor TModel.Create(input: TArray); 787 | begin 788 | inherited Create; 789 | 790 | Parameters.Add( TPair.Create('input', TValue.FromArray(input)) ); 791 | 792 | PyInstance := GetKerasClassIstance('models.Model'); 793 | init(); 794 | end; 795 | 796 | constructor TModel.Create(input, output: TArray); 797 | begin 798 | inherited Create; 799 | 800 | Parameters.Add( TPair.Create('inputs', TValue.FromArray(input)) ); 801 | Parameters.Add( TPair.Create('outputs', TValue.FromArray(output)) ); 802 | 803 | PyInstance := GetKerasClassIstance('models.Model'); 804 | init(); 805 | end; 806 | 807 | { TSequential } 808 | 809 | constructor TSequential.Create; 810 | begin 811 | inherited Create; 812 | 813 | PyInstance := GetKerasClassIstance('models.Sequential'); 814 | init; 815 | end; 816 | 817 | constructor TSequential.Create(py: PPyObject); 818 | begin 819 | Create; 820 | PyInstance := TPythonObject.Create( py ); 821 | end; 822 | 823 | constructor TSequential.Create(py: TPythonObject); 824 | begin 825 | Create; 826 | PyInstance := py ; 827 | end; 828 | 829 | constructor TSequential.Create(input: TArray); 830 | var 831 | i : Integer; 832 | begin 833 | for i := 0 to Length(input)-1 do 834 | Add( input[i]); 835 | end; 836 | 837 | procedure TSequential.Add(layer: TBaseLayer); 838 | begin 839 | Parameters.Clear; 840 | 841 | Parameters.Add( TPair.Create('layers', layer )); 842 | 843 | g_MyPyEngine.Py_XDecRef ( InvokeMethod('add',Parameters).Handle ) ; 844 | end; 845 | 846 | end. 847 | -------------------------------------------------------------------------------- /src/Keras.PreProcessing.pas: -------------------------------------------------------------------------------- 1 | unit Keras.PreProcessing; 2 | 3 | interface 4 | uses System.SysUtils, System.Generics.Collections, 5 | PythonEngine, Keras,np.Models ,Python.Utils, 6 | Keras.Layers, 7 | np.Utils; 8 | 9 | type 10 | // Sequence 11 | TSequenceUtil = class(TBase) 12 | public 13 | caller : TPythonObject; 14 | constructor Create; 15 | function PadSequences(sequences : TNDarray ; 16 | maxlen : PInteger = nil; 17 | dtype : string = 'int32'; 18 | padding : string = 'pre'; 19 | truncating: string = 'pre'; 20 | value : Double= 0.0): TNDArray; 21 | 22 | function SkipGrams(sequence : TNDarray; 23 | vocabulary_size : Integer; 24 | window_size : Integer= 4; 25 | negative_samples: Double= 1.0; 26 | shuffle : Boolean= true; 27 | categorical : Boolean= false; 28 | sampling_table : TNDArray= nil; 29 | seed : PInteger= nil): TNDArray; 30 | 31 | function MakeSamplingTable(size: Integer; sampling_factor : Double= 1e-05) : TNDArray; 32 | end; 33 | 34 | //TextProcessing 35 | TTokenizer = class(TBase) 36 | public 37 | caller : TPythonObject; 38 | constructor Create; overload; 39 | constructor Create(num_words : PInteger = nil; 40 | filters : string = '!\"#$%&()*+,-./:;<=>?@[\\]^_`{|}~'+#9#13#10; 41 | lower : Boolean = true; 42 | split : string= ' '; 43 | char_level : Boolean= false; 44 | oov_token : PInteger= nil; 45 | document_count : Integer= 0);overload; 46 | 47 | procedure FitOnTexts(texts: TArray); 48 | procedure FitOnSequences(sequences: TArray); 49 | function TextsToSequences(texts: TArray):TArray; 50 | function SequencesToTexts(sequences: TArray):TArray; 51 | function TextsToMatrix(texts: TArray; mode: string = 'binary'):TMatrix; 52 | end; 53 | 54 | TTextUtil = class(TBase) 55 | public 56 | caller : TPythonObject; 57 | constructor Create; overload; 58 | function HashingTrick(text : string ; 59 | n : Integer; 60 | hash_function : string = ''; 61 | filters : string = '!\"#$%&()*+,-./:;<=>?@[\\]^_`{|}~'+#9#13#10; 62 | lower : Boolean= true; 63 | split : string= ' '): TArray; 64 | 65 | function OneHot(text : string ; 66 | n : Integer; 67 | filters: string = '!\"#$%&()*+,-./:;<=>?@[\\]^_`{|}~'+#9#13#10; 68 | lower : Boolean= true; 69 | split : string= ' '): TArray2D; 70 | 71 | function TextToWordSequence(text : String ; 72 | filters : String = '!\"#$%&()*+,-./:;<=>?@[\\]^_`{|}~'+#9#13#10; 73 | lower : Boolean= true; 74 | split : String= ' '): TArray; 75 | end; 76 | 77 | // SequenceProcessing 78 | TTimeseriesGenerator = class(TBase) 79 | public 80 | constructor Create(data : TNDArray; 81 | targets : TNDArray; 82 | length : Integer; 83 | sampling_rate : Integer= 1; 84 | stride : Integer = 1; 85 | start_index : Integer= 0; 86 | end_index : PInteger= nil; 87 | shuffle : Boolean= false; 88 | reverse : Boolean= false; 89 | batch_size : Integer= 128); 90 | 91 | end; 92 | 93 | implementation 94 | uses System.Rtti; 95 | { TSequenceUtil } 96 | 97 | constructor TSequenceUtil.Create; 98 | begin 99 | inherited create; 100 | 101 | caller := GetKerasClassIstance('preprocessing.sequence'); 102 | end; 103 | 104 | function TSequenceUtil.MakeSamplingTable(size: Integer; sampling_factor: Double): TNDArray; 105 | begin 106 | Parameters.Clear; 107 | Parameters.Add( TPair.Create('size',size) ); 108 | Parameters.Add( TPair.Create('sampling_factor',sampling_factor) ); 109 | 110 | 111 | Result := TNDArray.Create( InvokeStaticMethod(caller,'make_sampling_table',Parameters) ) 112 | end; 113 | 114 | function TSequenceUtil.PadSequences(sequences: TNDarray; maxlen: PInteger; dtype, padding, truncating: string; value: Double): TNDArray; 115 | begin 116 | Parameters.Clear; 117 | Parameters.Add( TPair.Create('sequences',sequences) ); 118 | 119 | if maxlen <> nil then Parameters.Add( TPair.Create('maxlen',maxlen^)) 120 | else Parameters.Add( TPair.Create('maxlen', TPythonObject.None )); 121 | 122 | Parameters.Add( TPair.Create('dtype',dtype) ); 123 | Parameters.Add( TPair.Create('padding',padding) ); 124 | Parameters.Add( TPair.Create('truncating',truncating) ); 125 | Parameters.Add( TPair.Create('value',value) ); 126 | 127 | Result := TNDArray.Create( InvokeStaticMethod(caller,'pad_sequences',Parameters) ) 128 | end; 129 | 130 | function TSequenceUtil.SkipGrams(sequence: TNDarray; vocabulary_size, window_size: Integer; negative_samples: Double; 131 | shuffle, categorical: Boolean; sampling_table: TNDArray; seed: PInteger): TNDArray; 132 | begin 133 | Parameters.Clear; 134 | Parameters.Add( TPair.Create('sequences',sequence) ); 135 | Parameters.Add( TPair.Create('vocabulary_size',vocabulary_size) ); 136 | Parameters.Add( TPair.Create('window_size',window_size) ); 137 | Parameters.Add( TPair.Create('negative_samples',negative_samples) ); 138 | Parameters.Add( TPair.Create('shuffle',shuffle) ); 139 | Parameters.Add( TPair.Create('categorical',categorical) ); 140 | 141 | if sampling_table <> nil then Parameters.Add( TPair.Create('sampling_table',sampling_table)) 142 | else Parameters.Add( TPair.Create('sampling_table', TPythonObject.None )); 143 | 144 | if sampling_table <> nil then Parameters.Add( TPair.Create('seed',seed^)) 145 | else Parameters.Add( TPair.Create('seed', TPythonObject.None )); 146 | 147 | Result := TNDArray.Create( InvokeStaticMethod(caller,'skipgrams',Parameters) ) 148 | end; 149 | 150 | { TTokenizer } 151 | 152 | constructor TTokenizer.Create; 153 | begin 154 | inherited create; 155 | 156 | caller := GetKerasClassIstance('preprocessing.text'); 157 | end; 158 | 159 | constructor TTokenizer.Create(num_words: PInteger; filters: string; lower: Boolean; split: string; char_level: Boolean; 160 | oov_token: PInteger; document_count: Integer); 161 | begin 162 | Parameters.Clear; 163 | 164 | if num_words <> nil then Parameters.Add( TPair.Create('num_words',num_words^)) 165 | else Parameters.Add( TPair.Create('num_words', TPythonObject.None )); 166 | 167 | Parameters.Add( TPair.Create('filters',filters) ); 168 | Parameters.Add( TPair.Create('lower',lower) ); 169 | Parameters.Add( TPair.Create('split',split) ); 170 | Parameters.Add( TPair.Create('char_level',char_level) ); 171 | 172 | if oov_token <> nil then Parameters.Add( TPair.Create('oov_token',oov_token^)) 173 | else Parameters.Add( TPair.Create('oov_token', TPythonObject.None )); 174 | 175 | Parameters.Add( TPair.Create('document_count',document_count) ); 176 | 177 | PyInstance := InvokeStaticMethod(caller,'Tokenizer',Parameters) 178 | end; 179 | 180 | procedure TTokenizer.FitOnSequences(sequences: TArray); 181 | begin 182 | Parameters.Clear; 183 | 184 | Parameters.Add( TPair.Create('sequences',TValue.FromArray(sequences)) ); 185 | 186 | InvokeStaticMethod(caller,'fit_on_sequences',Parameters) 187 | end; 188 | 189 | procedure TTokenizer.FitOnTexts(texts: TArray); 190 | begin 191 | Parameters.Clear; 192 | 193 | Parameters.Add( TPair.Create('texts',TValue.FromArray(texts)) ); 194 | 195 | InvokeStaticMethod(caller,'fit_on_texts',Parameters) 196 | end; 197 | 198 | function TTokenizer.SequencesToTexts(sequences: TArray): TArray; 199 | begin 200 | Parameters.Clear; 201 | 202 | Parameters.Add( TPair.Create('sequences',TValue.FromArray(sequences)) ); 203 | 204 | Result := InvokeStaticMethod(caller,'sequences_to_texts',Parameters).AsArrayofString; 205 | end; 206 | 207 | function TTokenizer.TextsToMatrix(texts: TArray; mode: string): TMatrix; 208 | var 209 | atmp: TPythonObject; 210 | begin 211 | Parameters.Clear; 212 | 213 | Parameters.Add( TPair.Create('texts',TValue.FromArray(texts)) ); 214 | Parameters.Add( TPair.Create('mode',mode) ); 215 | 216 | atmp := InvokeStaticMethod(caller,'texts_to_matrix',Parameters) ; 217 | 218 | Result := TMatrix.Create( atmp.Handle ); 219 | 220 | end; 221 | 222 | function TTokenizer.TextsToSequences(texts: TArray): TArray; 223 | var 224 | atmp: TArray; 225 | i : Integer; 226 | begin 227 | Parameters.Clear; 228 | 229 | Parameters.Add( TPair.Create('texts',TValue.FromArray(texts)) ); 230 | 231 | atmp := InvokeStaticMethod(caller,'texts_to_sequences',Parameters).AsArrayofPyObj ; 232 | 233 | for i := 0 to High(atmp) do 234 | Result := Result + [ TSequence.Create( atmp[i].Handle ) ]; 235 | end; 236 | 237 | { TTextUtil } 238 | 239 | constructor TTextUtil.Create; 240 | begin 241 | inherited create; 242 | 243 | caller := GetKerasClassIstance('preprocessing.text'); 244 | end; 245 | 246 | function TTextUtil.HashingTrick(text: string; n: Integer; hash_function, filters: string; lower: Boolean; 247 | split: string): TArray; 248 | begin 249 | Parameters.Clear; 250 | 251 | Parameters.Add( TPair.Create('text',text) ); 252 | Parameters.Add( TPair.Create('n',n) ); 253 | Parameters.Add( TPair.Create('hash_function',hash_function) ); 254 | Parameters.Add( TPair.Create('filters',filters) ); 255 | Parameters.Add( TPair.Create('lower',lower) ); 256 | Parameters.Add( TPair.Create('split',split) ); 257 | 258 | Result := InvokeStaticMethod(caller,'hashing_trick',Parameters).AsArrayofInt; 259 | end; 260 | 261 | function TTextUtil.OneHot(text: string; n: Integer; filters: string; lower: Boolean; split: string): TArray2D; 262 | begin 263 | Parameters.Clear; 264 | 265 | Parameters.Add( TPair.Create('text',text) ); 266 | Parameters.Add( TPair.Create('n',n) ); 267 | Parameters.Add( TPair.Create('filters',filters) ); 268 | Parameters.Add( TPair.Create('lower',lower) ); 269 | Parameters.Add( TPair.Create('split',split) ); 270 | 271 | InvokeStaticMethod(caller,'one_hot',Parameters); 272 | end; 273 | 274 | function TTextUtil.TextToWordSequence(text: String; filters: String; lower: Boolean; split: String): TArray; 275 | begin 276 | Parameters.Clear; 277 | Result := []; 278 | Parameters.Add( TPair.Create('text',AnsiString( text )) ); 279 | Parameters.Add( TPair.Create('filters',filters) ); 280 | Parameters.Add( TPair.Create('lower',lower) ); 281 | Parameters.Add( TPair.Create('split',split) ); 282 | 283 | Result := InvokeStaticMethod(caller,'text_to_word_sequence',Parameters).AsArrayofString; 284 | end; 285 | 286 | { TTimeseriesGenerator } 287 | 288 | constructor TTimeseriesGenerator.Create(data, targets: TNDArray; length, sampling_rate, stride, start_index: Integer; 289 | end_index: PInteger; shuffle, reverse: Boolean; batch_size: Integer); 290 | begin 291 | inherited Create; 292 | 293 | Parameters.Add( TPair.Create('data',data) ); 294 | Parameters.Add( TPair.Create('targets',targets) ); 295 | Parameters.Add( TPair.Create('length',length) ); 296 | Parameters.Add( TPair.Create('sampling_rate',sampling_rate) ); 297 | Parameters.Add( TPair.Create('stride',stride) ); 298 | Parameters.Add( TPair.Create('start_index',start_index) ); 299 | 300 | if end_index <> nil then Parameters.Add( TPair.Create('end_index',end_index^)) 301 | else Parameters.Add( TPair.Create('end_index', TPythonObject.None )); 302 | 303 | Parameters.Add( TPair.Create('shuffle',shuffle) ); 304 | Parameters.Add( TPair.Create('reverse',reverse) ); 305 | Parameters.Add( TPair.Create('batch_size',batch_size) ); 306 | 307 | PyInstance := GetKerasClassIstance('preprocessing.sequence.TimeseriesGenerator'); 308 | Init; 309 | end; 310 | 311 | end. 312 | -------------------------------------------------------------------------------- /src/NumPy/np.Base.pas: -------------------------------------------------------------------------------- 1 | {*******************************************************} 2 | { } 3 | { Numpy Wrapper for Delphi } 4 | { } 5 | { Copyright (C) 2020 Pigrecos(Max) } 6 | { } 7 | {*******************************************************} 8 | unit np.Base; 9 | 10 | // np.dtype.gen.cs 11 | // np.module.gen.cs 12 | // TDtypeExtensions -----> for circular reference error 13 | 14 | interface 15 | uses Winapi.Windows, System.SysUtils,System.Rtti, 16 | PythonEngine, 17 | Python.Utils, 18 | 19 | np.Utils, 20 | np.Models; 21 | 22 | type 23 | Constants = (inf, neg_inf) ; 24 | 25 | PTPythonObject = ^TPythonObject; 26 | PTNDarray = TArray ; 27 | PPTNDarray = ^PTNDarray; 28 | 29 | TNumPy = class; 30 | 31 | 32 | 33 | TDtypeExtensions = class 34 | public 35 | class function GetDtype(pObj:T):TDtype; 36 | end; 37 | 38 | TNumPy = class 39 | private 40 | class function Getbool_: TDtype; 41 | class function Getbool8: TDtype; 42 | class function Getbyte: TDtype; 43 | class function Getbytes_: TDtype; 44 | class function Getclongfloat: TDtype; 45 | class function Getcomplex_: TDtype; 46 | class function Getcomplex128: TDtype; 47 | class function Getcomplex192: TDtype; 48 | class function Getcomplex256: TDtype; 49 | class function Getcomplex64: TDtype; 50 | class function Getcsingle: TDtype; 51 | class function Getdouble: TDtype; 52 | class function Getfloat_: TDtype; 53 | class function Getfloat128: TDtype; 54 | class function Getfloat16: TDtype; 55 | class function Getfloat32: TDtype; 56 | class function Getfloat64: TDtype; 57 | class function Getfloat96: TDtype; 58 | class function Gethalf: TDtype; 59 | class function Getint_: TDtype; 60 | class function Getint16: TDtype; 61 | class function Getint32: TDtype; 62 | class function Getint64: TDtype; 63 | class function Getint8: TDtype; 64 | class function Getintc: TDtype; 65 | class function Getintp: TDtype; 66 | class function Getlongfloat: TDtype; 67 | class function Getlonglong: TDtype; 68 | class function Getobject_: TDtype; 69 | class function Getshort: TDtype; 70 | class function Getsingle: TDtype; 71 | class function Getubyte: TDtype; 72 | class function Getuint: TDtype; 73 | class function Getuint16: TDtype; 74 | class function Getuint32: TDtype; 75 | class function Getuint64: TDtype; 76 | class function Getuint8: TDtype; 77 | class function Getuintc: TDtype; 78 | class function Getuintp: TDtype; 79 | class function Getulonglong: TDtype; 80 | class function Getunicode_: TDtype; 81 | class function Getushort: TDtype; 82 | class function Getvoid: TDtype; 83 | procedure Setbool_(const Value: TDtype); 84 | procedure Setbool8(const Value: TDtype); 85 | procedure Setbyte(const Value: TDtype); 86 | procedure Setbytes_(const Value: TDtype); 87 | procedure Setclongfloat(const Value: TDtype); 88 | procedure Setcomplex_(const Value: TDtype); 89 | procedure Setcomplex128(const Value: TDtype); 90 | procedure Setcomplex192(const Value: TDtype); 91 | procedure Setcomplex256(const Value: TDtype); 92 | procedure Setcomplex64(const Value: TDtype); 93 | procedure Setcsingle(const Value: TDtype); 94 | procedure Setdouble(const Value: TDtype); 95 | procedure Setfloat_(const Value: TDtype); 96 | procedure Setfloat128(const Value: TDtype); 97 | procedure Setfloat16(const Value: TDtype); 98 | procedure Setfloat32(const Value: TDtype); 99 | procedure Setfloat64(const Value: TDtype); 100 | procedure Setfloat96(const Value: TDtype); 101 | procedure Sethalf(const Value: TDtype); 102 | procedure Setint_(const Value: TDtype); 103 | procedure Setint16(const Value: TDtype); 104 | procedure Setint32(const Value: TDtype); 105 | procedure Setint64(const Value: TDtype); 106 | procedure Setint8(const Value: TDtype); 107 | procedure Setintc(const Value: TDtype); 108 | procedure Setintp(const Value: TDtype); 109 | procedure Setlongfloat(const Value: TDtype); 110 | procedure Setlonglong(const Value: TDtype); 111 | procedure Setobject_(const Value: TDtype); 112 | procedure Setshort(const Value: TDtype); 113 | procedure Setsingle(const Value: TDtype); 114 | procedure Setubyte(const Value: TDtype); 115 | procedure Setuint(const Value: TDtype); 116 | procedure Setuint16(const Value: TDtype); 117 | procedure Setuint32(const Value: TDtype); 118 | procedure Setuint64(const Value: TDtype); 119 | procedure Setuint8(const Value: TDtype); 120 | procedure Setuintc(const Value: TDtype); 121 | procedure Setuintp(const Value: TDtype); 122 | procedure Setulonglong(const Value: TDtype); 123 | procedure Setunicode_(const Value: TDtype); 124 | procedure Setushort(const Value: TDtype); 125 | procedure Setvoid(const Value: TDtype); 126 | // np.module.gen.cs 127 | public 128 | class var FhModuleNumPy : TPythonObject; 129 | 130 | constructor Init(inizialize: Boolean); 131 | 132 | class function ToTuple: TPyTuple;overload; static; 133 | class function ToTuple(input: TArray): TPyTuple; overload; static; 134 | class function ToPython(value:TValue): TPythonObject;overload; static; 135 | class function ToCsharp(pyobj:TPythonObject): T; static; 136 | class function ConvertArrayToNDarray(a: TArray): TNDarray; overload; 137 | class function ConvertArrayToNDarray(a: TArray2D): TNDarray; overload; 138 | 139 | function inf : Double; 140 | function Infinity : Double; 141 | function PINF : Double; 142 | function infty : Double; 143 | function NINF : Double; 144 | function nan : Double; 145 | function NZERO : Double; 146 | function PZERO : Double; 147 | function e : Double; 148 | function euler_gamma : Double; 149 | function newaxis : Double; 150 | function pi : Double; 151 | 152 | property bool_ : TDtype read Getbool_ write Setbool_; 153 | property bool8_: TDtype read Getbool8 write Setbool8; 154 | property byte_ : TDtype read Getbyte write Setbyte; 155 | property short_: TDtype read Getshort write Setshort; 156 | property intc_: TDtype read Getintc write Setintc; 157 | property int_ : TDtype read Getint_ write Setint_; 158 | property longlong_: TDtype read Getlonglong write Setlonglong; 159 | property intp_: TDtype read Getintp write Setintp; 160 | property int8_: TDtype read Getint8 write Setint8; 161 | property int16_: TDtype read Getint16 write Setint16; 162 | property int32_: TDtype read Getint32 write Setint32; 163 | property int64_: TDtype read Getint64 write Setint64; 164 | property ubyte_: TDtype read Getubyte write Setubyte; 165 | property ushort_: TDtype read Getushort write Setushort; 166 | property uintc_: TDtype read Getuintc write Setuintc; 167 | property uint_: TDtype read Getuint write Setuint; 168 | property ulonglong_: TDtype read Getulonglong write Setulonglong; 169 | property uintp_: TDtype read Getuintp write Setuintp; 170 | property uint8_: TDtype read Getuint8 write Setuint8; 171 | property uint16_: TDtype read Getuint16 write Setuint16; 172 | property uint32_: TDtype read Getuint32 write Setuint32; 173 | property uint64_: TDtype read Getuint64 write Setuint64; 174 | property half_: TDtype read Gethalf write Sethalf; 175 | property single_: TDtype read Getsingle write Setsingle; 176 | property double_: TDtype read Getdouble write Setdouble; 177 | property float_ : TDtype read Getfloat_ write Setfloat_; 178 | property longfloat_: TDtype read Getlongfloat write Setlongfloat; 179 | property float16_: TDtype read Getfloat16 write Setfloat16; 180 | property float32_: TDtype read Getfloat32 write Setfloat32; 181 | property float64_: TDtype read Getfloat64 write Setfloat64; 182 | property float96_: TDtype read Getfloat96 write Setfloat96; 183 | property float128_: TDtype read Getfloat128 write Setfloat128; 184 | property csingle_: TDtype read Getcsingle write Setcsingle; 185 | property complex_ : TDtype read Getcomplex_ write Setcomplex_; 186 | property clongfloat_:TDtype read Getclongfloat write Setclongfloat; 187 | property complex64_: TDtype read Getcomplex64 write Setcomplex64; 188 | property complex128_:TDtype read Getcomplex128 write Setcomplex128; 189 | property complex192_:TDtype read Getcomplex192 write Setcomplex192; 190 | property complex256_:TDtype read Getcomplex256 write Setcomplex256; 191 | property object_ : TDtype read Getobject_ write Setobject_; 192 | property bytes_ : TDtype read Getbytes_ write Setbytes_; 193 | property unicode_ : TDtype read Getunicode_ write Setunicode_; 194 | property void_ : TDtype read Getvoid write Setvoid; 195 | 196 | //property hModuleNumPy : TPythonObject read FhModuleNumPy; 197 | 198 | 199 | end; 200 | 201 | implementation 202 | uses 203 | System.Generics.Collections, 204 | System.TypInfo, 205 | np.Api; 206 | 207 | function ImportModule(Name: string): PPyObject; 208 | var 209 | res : PPyObject; 210 | begin 211 | res := g_MyPyEngine.PyImport_ImportModule(PAnsiChar(AnsiString(Name)) ) ; 212 | 213 | if g_MyPyEngine.PyErr_Occurred <> nil then 214 | begin 215 | g_MyPyEngine.PyErr_Clear; 216 | Exit(nil); 217 | end; 218 | Result := res; 219 | end; 220 | 221 | { TDtypeExtensions } 222 | 223 | class function TDtypeExtensions.GetDtype(pObj: T): TDtype; 224 | var 225 | Info : PTypeInfo; 226 | res : TPythonObject; 227 | rtti : TRttiType; 228 | begin 229 | 230 | { Get type info for the "yet unknown type" } 231 | Info := TypeInfo(T); 232 | 233 | if System.TypeInfo(T) = System.TypeInfo(boolean) then Result := TNumPy.Getbool8 234 | 235 | else if System.TypeInfo(T) = System.TypeInfo(int8) then Result := TNumPy.Getint8 236 | else if System.TypeInfo(T) = System.TypeInfo(UInt8) then Result := TNumPy.Getuint8 237 | else if System.TypeInfo(T) = System.TypeInfo(Byte) then Result := TNumPy.Getuint8 238 | 239 | else if System.TypeInfo(T) = System.TypeInfo(int16) then Result := TNumPy.Getint16 240 | else if System.TypeInfo(T) = System.TypeInfo(Word) then Result := TNumPy.Getuint16 241 | else if System.TypeInfo(T) = System.TypeInfo(UInt16) then Result := TNumPy.Getuint16 242 | 243 | else if System.TypeInfo(T) = System.TypeInfo(Int32) then Result := TNumPy.Getint32 244 | else if System.TypeInfo(T) = System.TypeInfo(Cardinal) then Result := TNumPy.Getuint32 245 | else if System.TypeInfo(T) = System.TypeInfo(Uint32) then Result := TNumPy.Getuint32 246 | 247 | else if System.TypeInfo(T) = System.TypeInfo(Int64) then Result := TNumPy.Getint64 248 | else if System.TypeInfo(T) = System.TypeInfo(uint64) then Result := TNumPy.Getuint64 249 | 250 | else if System.TypeInfo(T) = System.TypeInfo(Single) then Result := TNumPy.Getfloat32 251 | else if System.TypeInfo(T) = System.TypeInfo(double) then Result := TNumPy.Getfloat64 252 | 253 | else if System.TypeInfo(T) = System.TypeInfo(string) then Result := TNumPy.Getunicode_ 254 | else if System.TypeInfo(T) = System.TypeInfo(char) then Result := TNumPy.Getunicode_ 255 | 256 | else if (Info.Kind = tkArray) then 257 | begin 258 | rtti := TRttiContext.Create.GetType(TypeInfo(T)); 259 | 260 | if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getbool8 261 | 262 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getint8 263 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint8 264 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint8 265 | 266 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getint16 267 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint16 268 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint16 269 | 270 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getint32 271 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint32 272 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint32 273 | 274 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getint64 275 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint64 276 | 277 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getfloat32 278 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getfloat64 279 | 280 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getunicode_ 281 | else if TRttiArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getunicode_ 282 | end 283 | else if (Info.Kind = tkDynArray) then 284 | begin 285 | rtti := TRttiContext.Create.GetType(TypeInfo(T)); 286 | 287 | if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getbool8 288 | 289 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getint8 290 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint8 291 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint8 292 | 293 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getint16 294 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint16 295 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint16 296 | 297 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getint32 298 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint32 299 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint32 300 | 301 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getint64 302 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getuint64 303 | 304 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getfloat32 305 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getfloat64 306 | 307 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getunicode_ 308 | else if TRttiDynamicArrayType(rtti).Handle = System.TypeInfo(TArray) then Result := TNumPy.Getunicode_ 309 | end 310 | 311 | else 312 | raise EPythonError.Create('Can not convert type of given object to dtype: " '); 313 | 314 | end; 315 | 316 | { TNumPy } 317 | 318 | constructor TNumPy.Init(inizialize: Boolean); 319 | begin 320 | //Self := default(TNumPy) ; 321 | if g_MyPyEngine = nil then 322 | InitGlobal; 323 | 324 | MaskFPUExceptions(True); 325 | if FhModuleNumPy = nil then 326 | FhModuleNumPy := TPythonObject.Create( ImportModule('numpy') ); 327 | 328 | end; 329 | 330 | class function TNumPy.ToCsharp(pyobj:TPythonObject): T; 331 | var 332 | Info : PTypeInfo; 333 | Data : PTypeData; 334 | 335 | p : PPyObject; 336 | rv : TArray; 337 | Name : string; 338 | seq_length, i: Integer; 339 | begin 340 | { Get type info for the "yet unknown type" } 341 | Info := System.TypeInfo(T); 342 | Data := GetTypeData(Info); 343 | 344 | if info^.Kind = tkClass then 345 | begin 346 | Name := string(Info^.Name); 347 | // types from 'ToCsharpConversions' 348 | if LowerCase(Name) = 'tdtype' then PTPythonObject(@Result)^ := TDtype.Create(pyobj.Handle) 349 | else if LowerCase(Name) = 'tndarray' then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 350 | else if LowerCase(Name) = 'tmatrix' then PTPythonObject(@Result)^ := TMatrix.Create(pyobj.Handle) 351 | else if LowerCase(Name).Contains('tndarray<') then 352 | begin 353 | if LowerCase(Name).Contains('byte') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 354 | else if LowerCase(Name).Contains('word') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 355 | else if LowerCase(Name).Contains('boolean') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 356 | else if (LowerCase(Name).Contains('int32')) or 357 | (LowerCase(Name).Contains('integer')) then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 358 | else if LowerCase(Name).Contains('int64') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 359 | else if (LowerCase(Name).Contains('single')) or 360 | (LowerCase(Name).Contains('float32')) then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 361 | else if LowerCase(Name).Contains('double') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 362 | else 363 | raise Exception.Create('Type ' + Name + 'missing. Add it to "ToCsharpConversions"'); 364 | end; 365 | end 366 | else if info^.Kind = tkRecord then 367 | begin 368 | Name := string(Info^.Name); 369 | // types from 'ToCsharpConversions' 370 | if LowerCase(Name) = 'tndarray' then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 371 | else if LowerCase(Name).Contains('tndarray<') then 372 | begin 373 | if LowerCase(Name).Contains('byte') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 374 | else if LowerCase(Name).Contains('word') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 375 | else if LowerCase(Name).Contains('boolean') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 376 | else if (LowerCase(Name).Contains('int32')) or 377 | (LowerCase(Name).Contains('integer')) then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 378 | else if LowerCase(Name).Contains('int64') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 379 | else if (LowerCase(Name).Contains('single')) or 380 | (LowerCase(Name).Contains('float32')) then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 381 | else if LowerCase(Name).Contains('double') then PTPythonObject(@Result)^ := TNDArray.Create(pyobj) 382 | else 383 | raise Exception.Create('Type ' + Name + 'missing. Add it to "ToCsharpConversions"'); 384 | end; 385 | end 386 | else if (Info^.Kind = tkArray) or (Info^.Kind = tkDynArray) then 387 | begin 388 | if g_MyPyEngine.PySequence_Check( pyobj.Handle ) = 1 then 389 | begin 390 | seq_length := g_MyPyEngine.PySequence_Length( pyobj.Handle ); 391 | // if we have at least one object in the sequence, 392 | if seq_length > 0 then 393 | // we try to get the first one, simply to test if the sequence API is really implemented. 394 | g_MyPyEngine.Py_XDecRef( g_MyPyEngine.PySequence_GetItem( pyobj.Handle, 0 ) ); 395 | if g_MyPyEngine.PyErr_Occurred = nil then 396 | begin 397 | for i := 0 to g_MyPyEngine.PySequence_Length( pyobj.Handle ) -1 do 398 | begin 399 | p := g_MyPyEngine.PySequence_GetItem( pyobj.Handle, i ); 400 | rv := rv + [ ToCsharp( TPythonObject.Create(p) ) ]; 401 | end; 402 | 403 | PPTNDarray(@Result)^ := rv; 404 | end else 405 | begin 406 | g_MyPyEngine.PyErr_Clear; 407 | PTPythonObject(@Result)^ := nil; 408 | end; 409 | end; 410 | end else 411 | begin 412 | if (Info^.Kind = tkInteger) then 413 | begin 414 | case data^.OrdType of 415 | otUByte,otSByte: PByte(@Result)^ := g_MyPyEngine.PyObjectAsVariant(pyobj.Handle); 416 | otUWord,otSWord: PWord(@Result)^ := g_MyPyEngine.PyObjectAsVariant(pyobj.Handle); 417 | otULong,otSLong: PInteger(@Result)^ := g_MyPyEngine.PyObjectAsVariant(pyobj.Handle); 418 | end; 419 | end 420 | else if (Info^.Kind = tkInt64) then PInt64(@Result)^ := g_MyPyEngine.PyObjectAsVariant(pyobj.Handle) 421 | else if (Info^.Kind = tkFloat) then PFloat(@Result)^ := g_MyPyEngine.PyObjectAsVariant(pyobj.Handle) 422 | else if (Info^.Kind = tkUnicodeString) then PUnicodeString(@Result)^ := g_MyPyEngine.PyObjectAsVariant(pyobj.Handle) 423 | else if (Info^.Kind = tkWideString) then PWideString(@Result)^ := g_MyPyEngine.PyObjectAsVariant(pyobj.Handle) 424 | else if (Info^.Kind = tkAnsiString ) then PAnsiString(@Result)^ := g_MyPyEngine.PyObjectAsVariant(pyobj.Handle) 425 | else if (Info = System.TypeInfo(boolean))then PBoolean(@Result)^ := g_MyPyEngine.PyObjectAsVariant(pyobj.Handle) 426 | end; 427 | end; 428 | 429 | class function TNumPy.ToPython(value: TValue): TPythonObject; 430 | var 431 | Info : PTypeInfo; 432 | data : PTypeData; 433 | aTmp : TArray; 434 | begin 435 | Result := nil; 436 | 437 | Info := value.TypeInfo; 438 | data := value.TypeData; 439 | 440 | //PPyObject type 441 | if Info.Kind = tkPointer then 442 | begin 443 | var pp : PPyObject; 444 | if info.Name = 'PPyObject' then 445 | begin 446 | pp := value.AsType ; 447 | Result := TPythonObject.Create(pp); 448 | end; 449 | 450 | end 451 | //TPythonObject type 452 | else if Info.Kind = tkClass then 453 | begin 454 | if (data.ParentInfo^.Name = 'TPythonObject') or (data.ParentInfo^.Name = 'TNDArray') then 455 | Result := value.AsType 456 | // TList 457 | else if Info.Name = 'TList' then 458 | begin 459 | var aTmpStr : TArray; 460 | var i : Integer; 461 | 462 | aTmpStr := TList(value.AsObject).ToArray; 463 | for i := 0 to High(aTmpStr) do 464 | aTmp := aTmp + [ aTmpStr[i] ]; 465 | 466 | Result := TPythonObject.Create( g_MyPyEngine.ArrayToPyList( TValueArrayToArrayOfConst( aTmp ) ) ); 467 | end; 468 | end 469 | // array type 470 | else if (Info.Kind = tkDynArray) or (Info.Kind = tkArray) then 471 | begin 472 | Result := ToTuple( value.AsArray ); 473 | end 474 | // tnp_slice type 475 | else if Info = System.TypeInfo(Tnp_Slice) then 476 | begin 477 | Result := value.AsType.ToPython ; 478 | end 479 | // tnp_shape type 480 | else if Info = System.TypeInfo(Tnp_Shape) then 481 | begin 482 | Result := ToTuple ( TValue.ArrayOfToValueArray( value.AsType.Dimensions) ); 483 | end 484 | // double type 485 | else if (Info = System.TypeInfo(Double)) or (Info^.Kind = tkFloat) then 486 | begin 487 | Result := TPyFloat.Create(value.AsType); 488 | end 489 | // int64 type 490 | else if Info = System.TypeInfo(Int64) then 491 | begin 492 | Result := TPyLong.Create(value.AsInt64); 493 | end 494 | // integer type 495 | else if Info = System.TypeInfo(integer) then 496 | begin 497 | Result := TPyInt.Create(value.AsInteger); 498 | end 499 | else if Info = System.TypeInfo(Byte) then 500 | begin 501 | Result := TPyInt.Create(value.AsInteger); 502 | end 503 | else if Info = System.TypeInfo(Word) then 504 | begin 505 | Result := TPyInt.Create(value.AsInteger); 506 | end 507 | // string type 508 | else if Info = System.TypeInfo(string) then 509 | begin 510 | Result := TPyString.Create(value.AsString); 511 | end 512 | //ansistring type 513 | else if Info = System.TypeInfo(AnsiString) then 514 | begin 515 | Result := TPyString.Create(value.AsString); 516 | end 517 | else if Info = System.TypeInfo(Boolean) then 518 | begin 519 | if value.AsBoolean = true then 520 | Result := TPythonObject.Create(PPyObject(g_MyPyEngine.Py_True) ) 521 | else 522 | Result := TPythonObject.Create(PPyObject(g_MyPyEngine.Py_False) ); 523 | g_MyPyEngine.Py_XIncRef(Result.Handle); 524 | end; 525 | 526 | if Result = nil then 527 | raise Exception.Create('Error in ToPython conversion function'); 528 | end; 529 | 530 | class function TNumPy.ConvertArrayToNDarray(a: TArray): TNDarray; 531 | begin 532 | Result := npArray(a); 533 | end; 534 | 535 | class function TNumPy.ConvertArrayToNDarray(a: TArray2D): TNDarray; 536 | begin 537 | Result := npArray(a).reshape( [ Length(a), Length(a[0]) ]) 538 | end; 539 | 540 | class function TNumPy.ToTuple(): TPyTuple; 541 | var 542 | aArray : TArray; 543 | 544 | begin 545 | SetLength(aArray,0) ; 546 | 547 | Result := TPyTuple.Create(aArray); 548 | end; 549 | 550 | class function TNumPy.ToTuple(input: TArray): TPyTuple; 551 | var 552 | aArray : TArray; 553 | i : Integer; 554 | begin 555 | SetLength(aArray,Length(input)) ; 556 | for i := 0 to Length(input) - 1 do 557 | aArray[i] := ToPython(input[i]); 558 | 559 | Result := TPyTuple.Create(aArray); 560 | end; 561 | 562 | class function TNumPy.Getbool8: TDtype; 563 | begin 564 | Result := ToCsharp( FhModuleNumPy.GetAttr('bool8')) 565 | end; 566 | 567 | class function TNumPy.Getbool_: TDtype; 568 | begin 569 | Result := ToCsharp( FhModuleNumPy.GetAttr('bool_')) 570 | end; 571 | 572 | class function TNumPy.Getbyte: TDtype; 573 | begin 574 | Result := ToCsharp( FhModuleNumPy.GetAttr('byte')) 575 | end; 576 | 577 | class function TNumPy.Getbytes_: TDtype; 578 | begin 579 | Result := ToCsharp( FhModuleNumPy.GetAttr('bytes_')) 580 | end; 581 | 582 | class function TNumPy.Getclongfloat: TDtype; 583 | begin 584 | Result := ToCsharp( FhModuleNumPy.GetAttr('clongfloat')) 585 | end; 586 | 587 | class function TNumPy.Getcomplex128: TDtype; 588 | begin 589 | Result := ToCsharp( FhModuleNumPy.GetAttr('complex128')) 590 | end; 591 | 592 | class function TNumPy.Getcomplex192: TDtype; 593 | begin 594 | Result := ToCsharp( FhModuleNumPy.GetAttr('complex192')) 595 | end; 596 | 597 | class function TNumPy.Getcomplex256: TDtype; 598 | begin 599 | Result := ToCsharp( FhModuleNumPy.GetAttr('complex256')) 600 | end; 601 | 602 | class function TNumPy.Getcomplex64: TDtype; 603 | begin 604 | Result := ToCsharp( FhModuleNumPy.GetAttr('complex64')) 605 | end; 606 | 607 | class function TNumPy.Getcomplex_: TDtype; 608 | begin 609 | Result := ToCsharp( FhModuleNumPy.GetAttr('complex_')) 610 | end; 611 | 612 | class function TNumPy.Getcsingle: TDtype; 613 | begin 614 | Result := ToCsharp( FhModuleNumPy.GetAttr('csingle')) 615 | end; 616 | 617 | class function TNumPy.Getdouble: TDtype; 618 | begin 619 | Result := ToCsharp( FhModuleNumPy.GetAttr('double')) 620 | end; 621 | 622 | class function TNumPy.Getfloat128: TDtype; 623 | begin 624 | Result := ToCsharp( FhModuleNumPy.GetAttr('loat128')) 625 | end; 626 | 627 | class function TNumPy.Getfloat16: TDtype; 628 | begin 629 | Result := ToCsharp( FhModuleNumPy.GetAttr('float16')) 630 | end; 631 | 632 | class function TNumPy.Getfloat32: TDtype; 633 | begin 634 | Result := ToCsharp( FhModuleNumPy.GetAttr('float32')) 635 | end; 636 | 637 | class function TNumPy.Getfloat64: TDtype; 638 | begin 639 | Result := ToCsharp( FhModuleNumPy.GetAttr('float64')) 640 | end; 641 | 642 | class function TNumPy.Getfloat96: TDtype; 643 | begin 644 | Result := ToCsharp( FhModuleNumPy.GetAttr('float96')) 645 | end; 646 | 647 | class function TNumPy.Getfloat_: TDtype; 648 | begin 649 | Result := ToCsharp( FhModuleNumPy.GetAttr('float_')) 650 | end; 651 | 652 | class function TNumPy.Gethalf: TDtype; 653 | begin 654 | Result := ToCsharp( FhModuleNumPy.GetAttr('half')) 655 | end; 656 | 657 | class function TNumPy.Getint16: TDtype; 658 | begin 659 | Result := ToCsharp( FhModuleNumPy.GetAttr('int16')) 660 | end; 661 | 662 | class function TNumPy.Getint32: TDtype; 663 | begin 664 | Result := ToCsharp( FhModuleNumPy.GetAttr('int32')) 665 | end; 666 | 667 | class function TNumPy.Getint64: TDtype; 668 | begin 669 | Result := ToCsharp( FhModuleNumPy.GetAttr('int64')) 670 | end; 671 | 672 | class function TNumPy.Getint8: TDtype; 673 | begin 674 | Result := ToCsharp( FhModuleNumPy.GetAttr('int8')) 675 | end; 676 | 677 | class function TNumPy.Getintc: TDtype; 678 | begin 679 | Result := ToCsharp( FhModuleNumPy.GetAttr('intc')) 680 | end; 681 | 682 | class function TNumPy.Getintp: TDtype; 683 | begin 684 | Result := ToCsharp( FhModuleNumPy.GetAttr('intp')) 685 | end; 686 | 687 | class function TNumPy.Getint_: TDtype; 688 | begin 689 | Result := ToCsharp( FhModuleNumPy.GetAttr('int_')) 690 | end; 691 | 692 | class function TNumPy.Getlongfloat: TDtype; 693 | begin 694 | Result := ToCsharp( FhModuleNumPy.GetAttr('longfloat')) 695 | end; 696 | 697 | class function TNumPy.Getlonglong: TDtype; 698 | begin 699 | Result := ToCsharp( FhModuleNumPy.GetAttr('longlong')) 700 | end; 701 | 702 | class function TNumPy.Getobject_: TDtype; 703 | begin 704 | Result := ToCsharp( FhModuleNumPy.GetAttr('object_')) 705 | end; 706 | 707 | class function TNumPy.Getshort: TDtype; 708 | begin 709 | Result := ToCsharp( FhModuleNumPy.GetAttr('short')) 710 | end; 711 | 712 | class function TNumPy.Getsingle: TDtype; 713 | begin 714 | Result := ToCsharp( FhModuleNumPy.GetAttr('single')) 715 | end; 716 | 717 | class function TNumPy.Getubyte: TDtype; 718 | begin 719 | Result := ToCsharp( FhModuleNumPy.GetAttr('ubyte')) 720 | end; 721 | 722 | class function TNumPy.Getuint: TDtype; 723 | begin 724 | Result := ToCsharp( FhModuleNumPy.GetAttr('uint')) 725 | end; 726 | 727 | class function TNumPy.Getuint16: TDtype; 728 | begin 729 | Result := ToCsharp( FhModuleNumPy.GetAttr('uint16')) 730 | end; 731 | 732 | class function TNumPy.Getuint32: TDtype; 733 | begin 734 | Result := ToCsharp( FhModuleNumPy.GetAttr('uint32')) 735 | end; 736 | 737 | class function TNumPy.Getuint64: TDtype; 738 | begin 739 | Result := ToCsharp( FhModuleNumPy.GetAttr('uint64')) 740 | end; 741 | 742 | class function TNumPy.Getuint8: TDtype; 743 | begin 744 | Result := ToCsharp( FhModuleNumPy.GetAttr('uint8')) 745 | end; 746 | 747 | class function TNumPy.Getuintc: TDtype; 748 | begin 749 | Result := ToCsharp( FhModuleNumPy.GetAttr('uintc')) 750 | end; 751 | 752 | class function TNumPy.Getuintp: TDtype; 753 | begin 754 | Result := ToCsharp( FhModuleNumPy.GetAttr('uintp')) 755 | end; 756 | 757 | class function TNumPy.Getulonglong: TDtype; 758 | begin 759 | Result := ToCsharp( FhModuleNumPy.GetAttr('ulonglong')) 760 | end; 761 | 762 | class function TNumPy.Getunicode_: TDtype; 763 | begin 764 | Result := ToCsharp( FhModuleNumPy.GetAttr('unicode_')) 765 | end; 766 | 767 | class function TNumPy.Getushort: TDtype; 768 | begin 769 | Result := ToCsharp( FhModuleNumPy.GetAttr('ushort')) 770 | end; 771 | 772 | class function TNumPy.Getvoid: TDtype; 773 | begin 774 | Result := ToCsharp( FhModuleNumPy.GetAttr('void')) 775 | end; 776 | 777 | procedure TNumPy.Setbool8(const Value: TDtype); 778 | begin 779 | FhModuleNumPy.SetAttr('bool8', ToPython(value)); 780 | end; 781 | 782 | procedure TNumPy.Setbool_(const Value: TDtype); 783 | begin 784 | FhModuleNumPy.SetAttr('bool_', ToPython(value)); 785 | end; 786 | 787 | procedure TNumPy.Setbyte(const Value: TDtype); 788 | begin 789 | FhModuleNumPy.SetAttr('byte', ToPython(value)); 790 | end; 791 | 792 | procedure TNumPy.Setbytes_(const Value: TDtype); 793 | begin 794 | FhModuleNumPy.SetAttr('bytes_', ToPython(value)); 795 | end; 796 | 797 | procedure TNumPy.Setclongfloat(const Value: TDtype); 798 | begin 799 | FhModuleNumPy.SetAttr('clongfloat', ToPython(value)); 800 | end; 801 | 802 | procedure TNumPy.Setcomplex128(const Value: TDtype); 803 | begin 804 | FhModuleNumPy.SetAttr('complex128', ToPython(value)); 805 | end; 806 | 807 | procedure TNumPy.Setcomplex192(const Value: TDtype); 808 | begin 809 | FhModuleNumPy.SetAttr('complex192', ToPython(value)); 810 | end; 811 | 812 | procedure TNumPy.Setcomplex256(const Value: TDtype); 813 | begin 814 | FhModuleNumPy.SetAttr('complex256', ToPython(value)); 815 | end; 816 | 817 | procedure TNumPy.Setcomplex64(const Value: TDtype); 818 | begin 819 | FhModuleNumPy.SetAttr('complex64', ToPython(value)); 820 | end; 821 | 822 | procedure TNumPy.Setcomplex_(const Value: TDtype); 823 | begin 824 | FhModuleNumPy.SetAttr('complex_', ToPython(value)); 825 | end; 826 | 827 | procedure TNumPy.Setcsingle(const Value: TDtype); 828 | begin 829 | FhModuleNumPy.SetAttr('csingle', ToPython(value)); 830 | end; 831 | 832 | procedure TNumPy.Setdouble(const Value: TDtype); 833 | begin 834 | FhModuleNumPy.SetAttr('double', ToPython(value)); 835 | end; 836 | 837 | procedure TNumPy.Setfloat128(const Value: TDtype); 838 | begin 839 | FhModuleNumPy.SetAttr('float128', ToPython(value)); 840 | end; 841 | 842 | procedure TNumPy.Setfloat16(const Value: TDtype); 843 | begin 844 | FhModuleNumPy.SetAttr('float16', ToPython(value)); 845 | end; 846 | 847 | procedure TNumPy.Setfloat32(const Value: TDtype); 848 | begin 849 | FhModuleNumPy.SetAttr('float32', ToPython(value)); 850 | end; 851 | 852 | procedure TNumPy.Setfloat64(const Value: TDtype); 853 | begin 854 | FhModuleNumPy.SetAttr('float64', ToPython(value)); 855 | end; 856 | 857 | procedure TNumPy.Setfloat96(const Value: TDtype); 858 | begin 859 | FhModuleNumPy.SetAttr('float96', ToPython(value)); 860 | end; 861 | 862 | procedure TNumPy.Setfloat_(const Value: TDtype); 863 | begin 864 | FhModuleNumPy.SetAttr('float_', ToPython(value)); 865 | end; 866 | 867 | procedure TNumPy.Sethalf(const Value: TDtype); 868 | begin 869 | FhModuleNumPy.SetAttr('half', ToPython(value)); 870 | end; 871 | 872 | procedure TNumPy.Setint16(const Value: TDtype); 873 | begin 874 | FhModuleNumPy.SetAttr('int16', ToPython(value)); 875 | end; 876 | 877 | procedure TNumPy.Setint32(const Value: TDtype); 878 | begin 879 | FhModuleNumPy.SetAttr('int32', ToPython(value)); 880 | end; 881 | 882 | procedure TNumPy.Setint64(const Value: TDtype); 883 | begin 884 | FhModuleNumPy.SetAttr('int64', ToPython(value)); 885 | end; 886 | 887 | procedure TNumPy.Setint8(const Value: TDtype); 888 | begin 889 | FhModuleNumPy.SetAttr('int8', ToPython(value)); 890 | end; 891 | 892 | procedure TNumPy.Setintc(const Value: TDtype); 893 | begin 894 | FhModuleNumPy.SetAttr('intc', ToPython(value)); 895 | end; 896 | 897 | procedure TNumPy.Setintp(const Value: TDtype); 898 | begin 899 | FhModuleNumPy.SetAttr('intp', ToPython(value)); 900 | end; 901 | 902 | procedure TNumPy.Setint_(const Value: TDtype); 903 | begin 904 | FhModuleNumPy.SetAttr('int_', ToPython(value)); 905 | end; 906 | 907 | procedure TNumPy.Setlongfloat(const Value: TDtype); 908 | begin 909 | FhModuleNumPy.SetAttr('longfloat', ToPython(value)); 910 | end; 911 | 912 | procedure TNumPy.Setlonglong(const Value: TDtype); 913 | begin 914 | FhModuleNumPy.SetAttr('longlong', ToPython(value)); 915 | end; 916 | 917 | procedure TNumPy.Setobject_(const Value: TDtype); 918 | begin 919 | FhModuleNumPy.SetAttr('object_', ToPython(value)); 920 | end; 921 | 922 | procedure TNumPy.Setshort(const Value: TDtype); 923 | begin 924 | FhModuleNumPy.SetAttr('short', ToPython(value)); 925 | end; 926 | 927 | procedure TNumPy.Setsingle(const Value: TDtype); 928 | begin 929 | FhModuleNumPy.SetAttr('single', ToPython(value)); 930 | end; 931 | 932 | procedure TNumPy.Setubyte(const Value: TDtype); 933 | begin 934 | FhModuleNumPy.SetAttr('ubyte', ToPython(value)); 935 | end; 936 | 937 | procedure TNumPy.Setuint(const Value: TDtype); 938 | begin 939 | FhModuleNumPy.SetAttr('uint', ToPython(value)); 940 | end; 941 | 942 | procedure TNumPy.Setuint16(const Value: TDtype); 943 | begin 944 | FhModuleNumPy.SetAttr('uint16', ToPython(value)); 945 | end; 946 | 947 | procedure TNumPy.Setuint32(const Value: TDtype); 948 | begin 949 | FhModuleNumPy.SetAttr('uint32', ToPython(value)); 950 | end; 951 | 952 | procedure TNumPy.Setuint64(const Value: TDtype); 953 | begin 954 | FhModuleNumPy.SetAttr('uint64', ToPython(value)); 955 | end; 956 | 957 | procedure TNumPy.Setuint8(const Value: TDtype); 958 | begin 959 | FhModuleNumPy.SetAttr('uint8', ToPython(value)); 960 | end; 961 | 962 | procedure TNumPy.Setuintc(const Value: TDtype); 963 | begin 964 | FhModuleNumPy.SetAttr('uintc', ToPython(value)); 965 | end; 966 | 967 | procedure TNumPy.Setuintp(const Value: TDtype); 968 | begin 969 | FhModuleNumPy.SetAttr('uintp', ToPython(value)); 970 | end; 971 | 972 | procedure TNumPy.Setulonglong(const Value: TDtype); 973 | begin 974 | FhModuleNumPy.SetAttr('ulonglong', ToPython(value)); 975 | end; 976 | 977 | procedure TNumPy.Setunicode_(const Value: TDtype); 978 | begin 979 | FhModuleNumPy.SetAttr('unicode_', ToPython(value)); 980 | end; 981 | 982 | procedure TNumPy.Setushort(const Value: TDtype); 983 | begin 984 | FhModuleNumPy.SetAttr('ushort', ToPython(value)); 985 | end; 986 | 987 | procedure TNumPy.Setvoid(const Value: TDtype); 988 | begin 989 | FhModuleNumPy.SetAttr('void', ToPython(value)); 990 | end; 991 | 992 | { TNumPy_Constant } 993 | 994 | /// 995 | /// IEEE 754 floating point representation of (positive) infinity. 996 | /// 997 | function TNumPy.inf: Double; 998 | begin 999 | Result := FhModuleNumPy.GetAttr('inf').AsDouble; 1000 | end; 1001 | 1002 | /// 1003 | /// IEEE 754 floating point representation of (positive) infinity. 1004 | /// 1005 | /// Use np.inf because Inf, Infinity, PINF and infty are aliases for inf.For more details, see inf. 1006 | /// 1007 | function TNumPy.Infinity: Double; 1008 | begin 1009 | Result := FhModuleNumPy.GetAttr('inf').AsDouble; 1010 | end; 1011 | 1012 | /// 1013 | /// IEEE 754 floating point representation of (positive) infinity. 1014 | /// 1015 | /// Use np.inf because Inf, Infinity, PINF and infty are aliases for inf.For more details, see inf. 1016 | /// 1017 | function TNumPy.PINF: Double; 1018 | begin 1019 | Result := FhModuleNumPy.GetAttr('inf').AsDouble; 1020 | end; 1021 | 1022 | /// 1023 | /// IEEE 754 floating point representation of (positive) infinity. 1024 | /// 1025 | /// Use np.inf because Inf, Infinity, PINF and infty are aliases for inf.For more details, see inf. 1026 | /// 1027 | function TNumPy.infty: Double; 1028 | begin 1029 | Result := FhModuleNumPy.GetAttr('inf').AsDouble; 1030 | end; 1031 | 1032 | /// 1033 | /// IEEE 754 floating point representation of (positive) infinity. 1034 | /// 1035 | function TNumPy.NINF: Double; 1036 | begin 1037 | Result := FhModuleNumPy.GetAttr('NINF').AsDouble; 1038 | end; 1039 | 1040 | /// 1041 | /// IEEE 754 floating point representation of Not a Number(NaN). 1042 | /// 1043 | function TNumPy.nan: Double; 1044 | begin 1045 | Result := FhModuleNumPy.GetAttr('nan').AsDouble; 1046 | end; 1047 | 1048 | /// 1049 | /// IEEE 754 floating point representation of negative zero. 1050 | /// 1051 | function TNumPy.NZERO: Double; 1052 | begin 1053 | Result := FhModuleNumPy.GetAttr('NZERO').AsDouble; 1054 | end; 1055 | 1056 | /// 1057 | /// IEEE 754 floating point representation of negative zero. 1058 | /// 1059 | function TNumPy.PZERO: Double; 1060 | begin 1061 | Result := FhModuleNumPy.GetAttr('PZERO').AsDouble; 1062 | end; 1063 | 1064 | /// 1065 | /// Euler’s constant, base of natural logarithms, Napier’s constant. 1066 | /// 1067 | function TNumPy.e: Double; 1068 | begin 1069 | Result := FhModuleNumPy.GetAttr('e').AsDouble; 1070 | end; 1071 | 1072 | /// 1073 | /// γ = 0.5772156649015328606065120900824024310421... 1074 | /// https://en.wikipedia.org/wiki/Euler-Mascheroni_constant 1075 | /// 1076 | function TNumPy.euler_gamma: Double; 1077 | begin 1078 | Result := FhModuleNumPy.GetAttr('e').AsDouble; 1079 | end; 1080 | 1081 | /// 1082 | /// A convenient alias for None, useful for indexing arrays. 1083 | /// 1084 | function TNumPy.newaxis: Double; 1085 | begin 1086 | Result := FhModuleNumPy.GetAttr('newaxis').AsDouble; 1087 | end; 1088 | 1089 | /// 1090 | /// pi = 3.1415926535897932384626433... 1091 | /// 1092 | function TNumPy.pi: Double; 1093 | begin 1094 | Result := FhModuleNumPy.GetAttr('e').AsDouble; 1095 | end; 1096 | 1097 | end. 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | -------------------------------------------------------------------------------- /src/NumPy/np.Models.pas: -------------------------------------------------------------------------------- 1 | {*******************************************************} 2 | { } 3 | { Numpy Wrapper for Delphi } 4 | { } 5 | { Copyright (C) 2020 Pigrecos(Max) } 6 | { } 7 | {*******************************************************} 8 | unit np.Models; 9 | 10 | 11 | 12 | interface 13 | uses System.SysUtils, System.Rtti,System.Generics.Collections, 14 | PythonEngine, 15 | Python.Utils; 16 | 17 | const 18 | NULL_ : Integer = $CC; 19 | 20 | type 21 | 22 | TDtype = class(TPythonObject) 23 | public 24 | constructor Create(t: TDtype); overload; 25 | constructor Create(_pyobject: PPyObject);overload; 26 | end; 27 | 28 | TFlags = class(TPythonObject) 29 | public 30 | constructor Create(_pyobject: PPyObject); 31 | end; 32 | 33 | TMatrix = class(TPythonObject) 34 | public 35 | constructor Create(_pyobject: PPyObject); 36 | end; 37 | 38 | TMemMapMode = class(TPythonObject) 39 | public 40 | constructor Create(_pyobject: PPyObject); 41 | end; 42 | 43 | PTnp_Shape = ^Tnp_Shape; 44 | Tnp_Shape = record 45 | private 46 | function GetItem(index:Integer): Integer; 47 | public 48 | Dimensions : TArray; 49 | 50 | constructor Create(shape : TArray); 51 | function ToString: string; 52 | 53 | class operator Equal (a,b: Tnp_Shape): Boolean; 54 | class operator NotEqual(a,b: Tnp_Shape): Boolean; 55 | 56 | property Item[index: Integer]: Integer read GetItem;default; 57 | end; 58 | 59 | /// 60 | /// NDArray can be indexed using slicing 61 | /// A slice is constructed by start:stop:step notation 62 | /// 63 | /// Examples: 64 | /// 65 | /// a[start:stop] # items start through stop-1 66 | /// a[start:] # items start through the rest of the array 67 | /// a[:stop] # items from the beginning through stop-1 68 | /// 69 | /// The key point to remember is that the :stop value represents the first value that is not 70 | /// in the selected slice. So, the difference between stop and start is the number of elements 71 | /// selected (if step is 1, the default). 72 | /// 73 | /// There is also the step value, which can be used with any of the above: 74 | /// a[:] # a copy of the whole array 75 | /// a[start:stop:step] # start through not past stop, by step 76 | /// 77 | /// The other feature is that start or stop may be a negative number, which means it counts 78 | /// from the end of the array instead of the beginning. So: 79 | /// a[-1] # last item in the array 80 | /// a[-2:] # last two items in the array 81 | /// a[:-2] # everything except the last two items 82 | /// Similarly, step may be a negative number: 83 | /// 84 | /// a[::- 1] # all items in the array, reversed 85 | /// a[1::- 1] # the first two items, reversed 86 | /// a[:-3:-1] # the last two items, reversed 87 | /// a[-3::- 1] # everything except the last two items, reversed 88 | /// 89 | /// NumSharp is kind to the programmer if there are fewer items than 90 | /// you ask for. For example, if you ask for a[:-2] and a only contains one element, you get an 91 | /// empty list instead of an error.Sometimes you would prefer the error, so you have to be aware 92 | /// that this may happen. 93 | /// 94 | /// Adapted from Greg Hewgill's answer on Stackoverflow: https://stackoverflow.com/questions/509211/understanding-slice-notation 95 | /// 96 | /// Note: special IsIndex == true 97 | /// It will pick only a single value at Start in this dimension effectively reducing the Shape of the sliced matrix by 1 dimension. 98 | /// It can be used to reduce an N-dimensional array/matrix to a (N-1)-dimensional array/matrix 99 | /// 100 | /// Example: 101 | /// a=[[1, 2], [3, 4]] 102 | /// a[:, 1] returns the second column of that 2x2 matrix as a 1-D vector 103 | /// 104 | Tnp_Slice = record 105 | public 106 | Start : Integer; 107 | Stop : Integer; 108 | Step : Integer; 109 | IsIndex : Boolean; 110 | 111 | len : Integer; 112 | 113 | function Create(_Start: Integer =$CC; _Stop: Integer = $CC; _Step: Integer = 1 ):Tnp_Slice; overload; 114 | function Create(slice_notation : string ):Tnp_Slice; overload; 115 | function ParseSlices(multi_slice_notation : string ):TArray; 116 | function FormatSlices(slices : TArray): string ; 117 | procedure Parse(slice_notation : string ); 118 | function All: Tnp_Slice; 119 | function Index(index: Integer): Tnp_Slice; 120 | function ToString:string; 121 | function GetSize(dim: Integer):Integer; 122 | function GetAbsStep: Integer; 123 | function GetAbsStart(dim: Integer): Integer; 124 | function GetAbsStop(dim: Integer): Integer; 125 | function ToPython: TPythonObject; 126 | function FormatNullableIntForPython(i : Integer=0): string; 127 | 128 | class operator Equal (a,b: Tnp_Slice): Boolean; 129 | class operator NotEqual(a,b: Tnp_Slice): Boolean; 130 | end; 131 | 132 | TNDArray = class; 133 | 134 | TNDArray = class(TPythonObject) 135 | private 136 | 137 | function Getitem(index: string): TNDarray; overload; 138 | procedure SetItem(index: string; const Value: TNDarray); overload; 139 | 140 | function Getitem(index: TArray): TNDarray; overload; 141 | procedure SetItem(index: TArray; const Value: TNDarray); overload; 142 | 143 | function Getitem(index: TArray): TNDarray; overload; 144 | procedure SetItem(index:TArray; const Value: TNDarray); overload; 145 | 146 | function Getitem(index: TArray): TNDarray; overload; 147 | procedure SetItem(index: TArray; const Value: TNDarray); overload; 148 | 149 | public 150 | constructor Create(t: TNDArray); overload; 151 | constructor Create(_pyobject: PPyObject);overload; 152 | 153 | function flags : TFlags ; // TODO: implement Flags 154 | function shape : Tnp_Shape ; 155 | function strides : TArray; 156 | function ndim : Integer; 157 | function data : PPyObject; 158 | function size : Integer; 159 | function itemsize : Integer; 160 | function nbytes: Integer; 161 | function base : TNDArray; 162 | function dtype : TDtype; 163 | function T : TNDArray; 164 | //public NDarray real => new NDarray(self.GetAttr("real")); 165 | //public NDarray imag => new NDarray(self.GetAttr("imag")); 166 | function flat : PPyObject; // todo: wrap and support usecases 167 | function ctypes : PPyObject; // TODO: wrap ctypes 168 | function len : Integer; 169 | procedure itemset(args: TArray); 170 | function ToString(order: PChar): TArray; overload; 171 | function ToBytes(order : PChar = nil): TArray; 172 | procedure view(dtype : TDtype ; tipo : Variant) ; 173 | procedure resize(new_shape : Tnp_Shape; refcheck : PBoolean = nil) ; 174 | function reshape(newshape: TArray): TNDarray ; overload; 175 | function repr : string; 176 | function str: string; 177 | function asscalar: T; 178 | 179 | //------------------------------ 180 | // Comparison operators: 181 | //------------------------------ 182 | function equal (obj: TValue): TNDarray ; 183 | function not_equals(obj: TValue): TNDarray; 184 | 185 | class function opLess (a: TNDarray; obj: TValue) : TNDArray; 186 | class function opLessEq (a: TNDarray; obj: TValue) : TNDArray; 187 | class function opGreat (a: TNDarray; obj: TValue) : TNDArray; 188 | class function opGreatEq(a: TNDarray; obj: TValue) : TNDArray; 189 | 190 | //------------------------------ 191 | // Truth value of an array(bool) : 192 | //------------------------------ 193 | class function nonzero(a: TNDarray): TNDarray; 194 | 195 | //------------------------------ 196 | // Unary operations: 197 | //------------------------------ 198 | class function opNeg(a: TNDarray): TNDarray; 199 | class function opPos(a: TNDarray): TNDarray; 200 | class function opNot(a: TNDarray): TNDarray; 201 | 202 | //------------------------------ 203 | // Arithmetic operators: 204 | //------------------------------ 205 | Class Function opAdd(a : TNDarray ; obj: TValue) : TNDarray ; overload; 206 | Class Function opAdd(obj: TValue; a : TNDarray ): TNDarray ; overload; 207 | Class Function opAdd(a : TNDarray ; obj: TNDarray ): TNDarray ; overload; 208 | Class Function opSub(a : TNDarray ; obj: TValue) : TNDarray ; overload; 209 | Class Function opSub(a : TNDarray ; obj: TNDarray ): TNDarray ; overload; 210 | Class Function opMul(a : TNDarray ; obj: TValue) : TNDarray ; overload; 211 | Class Function opMul(obj: TValue; a : TNDarray ): TNDarray ; overload; 212 | Class Function opMul(a : TNDarray ; obj: TNDarray ): TNDarray ; overload; 213 | Class Function opDiv(a : TNDarray ; obj: TValue) : TNDarray ; overload; 214 | Class Function opDiv(a : TNDarray ; obj: TNDarray ): TNDarray ; overload; 215 | 216 | Function opDivMod (obj: TValue): TNDarray ; 217 | Function opPow (obj: TValue): TNDarray ; 218 | 219 | Class Function floordiv (a : TNDarray ; obj: TValue) : TNDarray ; 220 | Class Function opMod (a : TNDarray ; obj: TValue) : TNDarray ; 221 | Class Function opSLeft (a : TNDarray ; obj: integer): TNDarray ; 222 | Class Function opSRight (a : TNDarray ; obj: integer): TNDarray ; 223 | Class Function opAnd (a : TNDarray ; obj: integer): TNDarray ; 224 | Class Function opOr (a : TNDarray ; obj: integer): TNDarray ; 225 | Class Function opXor (a : TNDarray ; obj: integer): TNDarray ; 226 | 227 | //------------------------------ 228 | // Arithmetic, in-place: 229 | //------------------------------ 230 | Function opIAdd(obj: TValue) : TNDarray ; 231 | Function opISub(obj: TValue) : TNDarray ; 232 | Function opIMul(obj: TValue) : TNDarray ; 233 | Function opIDiv(obj: TValue) : TNDarray ; 234 | 235 | Function opITrueDiv(obj: TValue ): TNDarray ; 236 | Function IFloorDiv (obj: TValue) : TNDarray ; 237 | 238 | Function opIMod(obj: TValue) : TNDarray ; 239 | Function opIPow(obj: TValue) : TNDarray ; 240 | 241 | Function IopSLeft (obj: TValue): TNDarray ; 242 | Function IopSRight (obj: TValue): TNDarray ; 243 | 244 | Function IopAnd (obj: TValue): TNDarray ; 245 | Function IopOr (obj: TValue): TNDarray ; 246 | Function IopXor ( obj:TValue): TNDarray ; 247 | 248 | property Items[index: string]:TNDarray read Getitem write SetItem; default; 249 | property Items[index: TArray] :TNDarray read Getitem write SetItem ;default; 250 | property Items[index: TArray]:TNDarray read Getitem write SetItem ;default; 251 | property Items[index: TArray] :TNDarray read Getitem write SetItem ;default; 252 | end; 253 | 254 | TNDArray = class (TNDArray) 255 | public 256 | constructor Create(Value: TNDarray); overload; 257 | constructor Create(_pyobject: PPyObject);overload; 258 | 259 | end; 260 | 261 | implementation 262 | uses System.RegularExpressions,System.Variants, 263 | np.Base, np.Api,np.Utils; 264 | 265 | { TDtype } 266 | 267 | constructor TDtype.Create(_pyobject: PPyObject); 268 | begin 269 | inherited Create(_pyobject); 270 | end; 271 | 272 | constructor TDtype.Create(t: TDtype); 273 | begin 274 | inherited Create(t.Handle); 275 | end; 276 | 277 | { TFlags } 278 | 279 | constructor TFlags.Create(_pyobject: PPyObject); 280 | begin 281 | inherited Create(_pyobject) ; 282 | end; 283 | 284 | { TMatrix } 285 | 286 | constructor TMatrix.Create(_pyobject: PPyObject); 287 | begin 288 | inherited Create(_pyobject) ; 289 | end; 290 | 291 | { TMemMapMode } 292 | 293 | constructor TMemMapMode.Create(_pyobject: PPyObject); 294 | begin 295 | inherited Create(_pyobject) ; 296 | end; 297 | 298 | { Tnp_Shape } 299 | 300 | constructor Tnp_Shape.Create(shape: TArray); 301 | begin 302 | Self := default(Tnp_Shape); 303 | Dimensions := shape; 304 | end; 305 | 306 | class operator Tnp_Shape.Equal(a, b: Tnp_Shape): Boolean; 307 | var 308 | i : Integer; 309 | begin 310 | if Length(a.Dimensions) <> Length(b.Dimensions) then Exit(False); 311 | 312 | for i := 0 to Length(a.Dimensions) do 313 | if a.Dimensions[i] <> b.Dimensions[i] then Exit(False) ; 314 | 315 | Result:= True; 316 | end; 317 | 318 | class operator Tnp_Shape.NotEqual(a, b: Tnp_Shape): Boolean; 319 | begin 320 | Result := not (a = b); 321 | end; 322 | 323 | function Tnp_Shape.GetItem(index:Integer): Integer; 324 | begin 325 | Result := Dimensions[index]; 326 | end; 327 | 328 | function Tnp_Shape.ToString: string; 329 | var 330 | i : Integer; 331 | begin 332 | Result := ''; 333 | for i := 0 to Length(Dimensions)-1 do 334 | Result := Result + IntToStr(Dimensions[i]) + ','; 335 | 336 | if Length(Result) > 1 then 337 | begin 338 | Result := '(' +Result ; 339 | Result[Length(Result)] := ')' 340 | end; 341 | 342 | end; 343 | 344 | { Tnp_Slice } 345 | 346 | function Tnp_Slice.Create(slice_notation: string): Tnp_Slice; 347 | begin 348 | Result := default(Tnp_Slice); 349 | Parse(slice_notation); 350 | end; 351 | 352 | function Tnp_Slice.Create(_Start, _Stop, _Step: Integer): Tnp_Slice; 353 | begin 354 | Result := default(Tnp_Slice); 355 | Result.Start := _start; 356 | Result.Stop := _stop; 357 | Result.Step := _step; 358 | end; 359 | 360 | function Tnp_Slice.All: Tnp_Slice; 361 | begin 362 | Result := default(Tnp_Slice); 363 | Result := Create() 364 | end; 365 | 366 | function Tnp_Slice.ParseSlices(multi_slice_notation: string): TArray; 367 | var 368 | regEx : TRegEx; 369 | res : TArray; 370 | i : Integer; 371 | begin 372 | regEx := TRegEx.Create(',\s*'); 373 | res := regEx.Split(multi_slice_notation) ; 374 | 375 | Result := []; 376 | for i := 0 to High(res) do 377 | begin 378 | if (res[i] <> '') and (res[i] <> ' ') then 379 | begin 380 | Result := Result + [ Create( res[i] ) ] 381 | end; 382 | end; 383 | end; 384 | 385 | procedure Tnp_Slice.Parse(slice_notation: string); 386 | var 387 | regEx : TRegEx; 388 | match : TMatch; 389 | iStart, 390 | iStop, 391 | iStep : Integer; 392 | start_string, 393 | stop_string, 394 | step_string, 395 | single_pick_string : string; 396 | begin 397 | if slice_notation.IsNullOrWhiteSpace(slice_notation) then 398 | raise Exception.Create('Slice notation expected, got empty string or null'); 399 | 400 | regEx := TRegEx.Create('^\s*([+-]?\s*\d+)?\s*:\s*([+-]?\s*\d+)?\s*(:\s*([+-]?\s*\d+)?)?\s*$|^\s*([+-]?\s*\d+)\s*$'); 401 | 402 | match := regEx.Match(slice_notation); 403 | if not match.Success then 404 | raise Exception.Create('Invalid slice notation'); 405 | 406 | start_string := regEx.Replace(match.Groups[1].Value,'\s+','') ; 407 | stop_string := regEx.Replace(match.Groups[2].Value,'\s+','') ; 408 | step_string := regEx.Replace(match.Groups[4].Value,'\s+','') ; 409 | 410 | single_pick_string :=regEx.Replace(match.Groups[5].Value,'\s+','') ; 411 | 412 | if not slice_notation.IsNullOrWhiteSpace(single_pick_string) then 413 | begin 414 | if not Integer.TryParse(single_pick_string,iStart) then 415 | raise Exception.Create('Invalid value for start: '+ start_string); 416 | 417 | Start := iStart; 418 | Stop := Start + 1; 419 | Step := 1; 420 | IsIndex := True; 421 | Exit; 422 | end; 423 | 424 | if start_string.IsNullOrWhiteSpace(start_string) then 425 | Start := null_ 426 | else begin 427 | if not Integer.TryParse(start_string,iStart) then 428 | raise Exception.Create('Invalid value for start: '+ start_string); 429 | 430 | Start := iStart; 431 | end; 432 | if stop_string.IsNullOrWhiteSpace(stop_string) then 433 | Stop := null_ 434 | else begin 435 | if not Integer.TryParse(stop_string,iStop) then 436 | raise Exception.Create('Invalid value for stop: '+ stop_string); 437 | 438 | Start := iStop; 439 | end; 440 | if step_string.IsNullOrWhiteSpace(step_string) then 441 | Step := 1 442 | else begin 443 | if not Integer.TryParse(step_string,iStep) then 444 | raise Exception.Create('Invalid value for step: '+ step_string); 445 | 446 | Step := iStep; 447 | end; 448 | end; 449 | 450 | function Tnp_Slice.FormatSlices(slices: TArray): string; 451 | var 452 | i : Integer; 453 | begin 454 | Result := ''; 455 | for i := 0 to High(slices) do 456 | Result := Result + slices[i].ToString + ','; 457 | 458 | Result := Copy(Result ,1,Length(Result)-1); 459 | 460 | end; 461 | 462 | function Tnp_Slice.GetAbsStart(dim: Integer): Integer; 463 | var 464 | absStartN, absStart : Integer; 465 | begin 466 | if Start < 0 then absStartN := dim + Start 467 | else absStartN := Start; 468 | 469 | if Step < 0 then 470 | begin 471 | if absStartN = NULL_ then absStart := dim 472 | else absStart := absStartN; 473 | end else 474 | begin 475 | if absStartN = NULL_ then absStart := 0 476 | else absStart := absStartN; 477 | end; 478 | 479 | Result := absStart; 480 | end; 481 | 482 | function Tnp_Slice.GetAbsStep: Integer; 483 | begin 484 | Result := Abs(Step); 485 | end; 486 | 487 | function Tnp_Slice.GetAbsStop(dim: Integer): Integer; 488 | var 489 | absStopN, absStop : Integer; 490 | begin 491 | if Stop < 0 then absStopN := dim + Stop 492 | else absStopN := Stop; 493 | 494 | if Step < 0 then 495 | begin 496 | if absStopN = NULL_ then absStop := 0 497 | else absStop := absStopN; 498 | end else 499 | begin 500 | if absStopN = NULL_ then absStop := dim 501 | else absStop := absStopN; 502 | end; 503 | 504 | Result := absStop; 505 | 506 | end; 507 | 508 | function Tnp_Slice.GetSize(dim: Integer): Integer; 509 | var 510 | absStart, absStop,absStep : Integer; 511 | begin 512 | absStart := GetAbsStart(dim); 513 | absStop := GetAbsStop(dim); 514 | absStep := GetAbsStep; 515 | 516 | Result := ((absStop - absStart)+(absStep-1)) div absStep; 517 | end; 518 | 519 | function Tnp_Slice.Index(index: Integer): Tnp_Slice; 520 | begin 521 | Create(index,index+1); 522 | IsIndex := True; 523 | end; 524 | 525 | class operator Tnp_Slice.NotEqual(a, b: Tnp_Slice): Boolean; 526 | begin 527 | Result := not(a = b) 528 | end; 529 | 530 | class operator Tnp_Slice.Equal(a, b: Tnp_Slice): Boolean; 531 | begin 532 | Result := (a.Start = b.Start) and (a.Stop = b.Stop) and (a.Step = b.Step) 533 | end; 534 | 535 | function Tnp_Slice.ToPython: TPythonObject; 536 | var 537 | sEval : string; 538 | 539 | begin 540 | { TODO -oMax -c : modificare call python engine 26/01/2020 16:59:16 } 541 | sEval := Format('slice(%s,%s,%s)',[FormatNullableIntForPython(Start),FormatNullableIntForPython(Stop),FormatNullableIntForPython(Step)]); 542 | 543 | Result := TPythonObject.Create( g_MyPyEngine.EvalString(sEval) ); 544 | end; 545 | 546 | function Tnp_Slice.FormatNullableIntForPython(i: Integer): string; 547 | begin 548 | if i = null_ then 549 | Result := 'None' 550 | else 551 | Result := IntToStr(i) 552 | end; 553 | 554 | function Tnp_Slice.ToString: string; 555 | var 556 | sStart, 557 | sStop : string; 558 | opt_step : string; 559 | begin 560 | if IsIndex then 561 | begin 562 | if Start = NULL_ then Start := 0; 563 | Exit(IntToStr(Start)); 564 | end; 565 | if Step = 1 then opt_step := '' 566 | else opt_step := ':'+ IntToStr(Step) ; 567 | 568 | if Start = 0 then sStart := '' 569 | else sStart := IntToStr(Start) ; 570 | 571 | if Stop = NULL_ then sStop := '' 572 | else sStop := IntToStr(Stop); 573 | 574 | Result := sStart +':'+ sStop + opt_step; 575 | end; 576 | 577 | { TNDArray } 578 | 579 | constructor TNDArray.Create(_pyobject: PPyObject); 580 | begin 581 | inherited Create(_pyobject); 582 | end; 583 | 584 | constructor TNDArray.Create(t: TNDArray); 585 | begin 586 | inherited Create(t.Handle); 587 | end; 588 | 589 | //------------------------------ 590 | // Comparison operators: 591 | //------------------------------ 592 | function TNDArray.equal(obj: TValue): TNDarray; 593 | begin 594 | Result := TNDarray.Create( InvokeMethod('__eq__', [TNumPy.ToPython(obj)] ) ); 595 | end; 596 | 597 | function TNDArray.not_equals(obj: TValue): TNDarray; 598 | begin 599 | Result := TNDarray.Create( InvokeMethod('__ne__', [TNumPy.ToPython(obj)] ) ); 600 | end; 601 | 602 | class function TNDArray.opLess(a: TNDarray; obj: TValue): TNDArray; 603 | begin 604 | Result := TNDarray.Create( a.InvokeMethod('__lt__', [TNumPy.ToPython(obj)] ) ); 605 | end; 606 | 607 | class function TNDArray.opLessEq(a: TNDarray; obj: TValue): TNDArray; 608 | begin 609 | Result := TNDarray.Create( a.InvokeMethod('__le__', [TNumPy.ToPython(obj)] ) ); 610 | end; 611 | 612 | class function TNDArray.opGreat(a: TNDarray; obj: TValue): TNDArray; 613 | begin 614 | Result := TNDarray.Create( a.InvokeMethod('__gt__', [TNumPy.ToPython(obj)] ) ); 615 | end; 616 | 617 | class function TNDArray.opGreatEq(a: TNDarray; obj: TValue): TNDArray; 618 | begin 619 | Result := TNDarray.Create( a.InvokeMethod('__ge__', [TNumPy.ToPython(obj)] ) ); 620 | end; 621 | 622 | //------------------------------ 623 | // Truth value of an array(bool) : 624 | //------------------------------ 625 | class function TNDArray.nonzero(a: TNDarray): TNDarray; 626 | begin 627 | Result := TNDarray.Create( a.InvokeMethod('__nonzero__',[]) ); 628 | end; 629 | 630 | 631 | //------------------------------ 632 | // Unary operations: 633 | //------------------------------ 634 | class function TNDArray.opNeg(a: TNDarray): TNDarray; 635 | begin 636 | Result := TNDarray.Create( a.InvokeMethod('__neg__',[]) ); 637 | end; 638 | 639 | class function TNDArray.opNot(a: TNDarray): TNDarray; 640 | begin 641 | Result := TNDarray.Create( a.InvokeMethod('__invert__',[]) ); 642 | end; 643 | 644 | class function TNDArray.opPos(a: TNDarray): TNDarray; 645 | begin 646 | Result := TNDarray.Create( a.InvokeMethod('__pos__',[]) ); 647 | end; 648 | 649 | //------------------------------ 650 | // Arithmetic operators: 651 | //------------------------------ 652 | class function TNDArray.opSLeft(a: TNDarray; obj: integer): TNDarray; 653 | begin 654 | Result := TNDarray.Create( a.InvokeMethod('__lshift__', [TNumPy.ToPython(obj)] ) ); 655 | end; 656 | 657 | class function TNDArray.opSRight(a: TNDarray; obj: integer): TNDarray; 658 | begin 659 | Result := TNDarray.Create( a.InvokeMethod('__rshift__', [TNumPy.ToPython(obj)] ) ); 660 | end; 661 | 662 | class function TNDArray.opOr(a: TNDarray; obj: integer): TNDarray; 663 | begin 664 | Result := TNDarray.Create( a.InvokeMethod('__or__', [TNumPy.ToPython(obj)] ) ); 665 | end; 666 | 667 | class function TNDArray.opXor(a: TNDarray; obj: integer): TNDarray; 668 | begin 669 | Result := TNDarray.Create( a.InvokeMethod('__xor__', [TNumPy.ToPython(obj)] ) ); 670 | end; 671 | 672 | function TNDArray.opDivMod(obj: TValue): TNDarray; 673 | begin 674 | Result := TNDarray.Create( InvokeMethod('__divmod__', [TNumPy.ToPython(obj)] ) ); 675 | end; 676 | 677 | function TNDArray.opPow(obj: TValue): TNDarray; 678 | begin 679 | Result := TNDarray.Create( InvokeMethod('__pow__', [TNumPy.ToPython(obj)] ) ); 680 | end; 681 | 682 | class function TNDArray.opSub(a: TNDarray; obj: TValue): TNDarray; 683 | begin 684 | Result := TNDarray.Create( a.InvokeMethod('__sub__', [TNumPy.ToPython(obj)] ) ); 685 | end; 686 | 687 | class function TNDArray.opSub(a, obj: TNDarray): TNDarray; 688 | begin 689 | Result := TNDarray.Create( a.InvokeMethod('__sub__', [TNumPy.ToPython(obj)] ) ); 690 | end; 691 | 692 | class function TNDArray.opAdd(a: TNDarray; obj: TValue): TNDarray; 693 | begin 694 | Result := TNDarray.Create( a.InvokeMethod('__add__', [TNumPy.ToPython(obj)] ) ); 695 | end; 696 | 697 | class function TNDArray.opAdd(obj: TValue; a: TNDarray): TNDarray; 698 | begin 699 | Result := TNDarray.Create( a.InvokeMethod('__add__', [TNumPy.ToPython(obj)] ) ); 700 | end; 701 | 702 | class function TNDArray.opAdd(a, obj: TNDarray): TNDarray; 703 | begin 704 | Result := TNDarray.Create( a.InvokeMethod('__add__', [TNumPy.ToPython(obj)] ) ); 705 | end; 706 | 707 | class function TNDArray.opAnd(a: TNDarray; obj: integer): TNDarray; 708 | begin 709 | Result := TNDarray.Create( a.InvokeMethod('__and__', [TNumPy.ToPython(obj)] ) ); 710 | end; 711 | 712 | class function TNDArray.opDiv(a: TNDarray; obj: TValue): TNDarray; 713 | begin 714 | Result := TNDarray.Create( a.InvokeMethod('__truediv__', [TNumPy.ToPython(obj)] ) ); 715 | end; 716 | 717 | class function TNDArray.opDiv(a, obj: TNDarray): TNDarray; 718 | begin 719 | Result := TNDarray.Create( a.InvokeMethod('__truediv__', [TNumPy.ToPython(obj)] ) ); 720 | end; 721 | 722 | class function TNDArray.floordiv(a: TNDarray; obj: TValue): TNDarray; 723 | begin 724 | Result := TNDarray.Create( a.InvokeMethod('__floordiv__', [TNumPy.ToPython(obj)] ) ); 725 | end; 726 | 727 | class function TNDArray.opMod(a: TNDarray; obj: TValue): TNDarray; 728 | begin 729 | Result := TNDarray.Create( a.InvokeMethod('__mod__', [TNumPy.ToPython(obj)] ) ); 730 | end; 731 | 732 | class function TNDArray.opMul(a, obj: TNDarray): TNDarray; 733 | begin 734 | Result := TNDarray.Create( a.InvokeMethod('__mul__', [TNumPy.ToPython(obj)] ) ); 735 | end; 736 | 737 | class function TNDArray.opMul(a: TNDarray; obj: TValue): TNDarray; 738 | begin 739 | Result := TNDarray.Create( a.InvokeMethod('__mul__', [TNumPy.ToPython(obj)] ) ); 740 | end; 741 | 742 | class function TNDArray.opMul(obj: TValue; a: TNDarray): TNDarray; 743 | begin 744 | Result := TNDarray.Create( a.InvokeMethod('__mul__', [TNumPy.ToPython(obj)] ) ); 745 | end; 746 | 747 | //------------------------------ 748 | // Arithmetic, in-place: 749 | //------------------------------ 750 | function TNDArray.opIAdd(obj: TValue): TNDarray; 751 | begin 752 | Result := TNDarray.Create( InvokeMethod('__iadd__', [TNumPy.ToPython(obj)] ) ); 753 | end; 754 | 755 | function TNDArray.opISub(obj: TValue): TNDarray; 756 | begin 757 | Result := TNDarray.Create( InvokeMethod('__isub__', [TNumPy.ToPython(obj)] ) ); 758 | end; 759 | 760 | function TNDArray.opIMul(obj: TValue): TNDarray; 761 | begin 762 | Result := TNDarray.Create( InvokeMethod('__imul__', [TNumPy.ToPython(obj)] ) ); 763 | end; 764 | 765 | function TNDArray.opITrueDiv(obj: TValue): TNDarray; 766 | begin 767 | Result := TNDarray.Create( InvokeMethod('__itruediv__', [TNumPy.ToPython(obj)] ) ); 768 | end; 769 | 770 | function TNDArray.IFloorDiv(obj: TValue): TNDarray; 771 | begin 772 | Result := TNDarray.Create( InvokeMethod('__floordiv__', [TNumPy.ToPython(obj)] ) ); 773 | end; 774 | 775 | function TNDArray.opIMod(obj: TValue): TNDarray; 776 | begin 777 | Result := TNDarray.Create( InvokeMethod('__imod__', [TNumPy.ToPython(obj)] ) ); 778 | end; 779 | 780 | function TNDArray.opIPow(obj: TValue): TNDarray; 781 | begin 782 | Result := TNDarray.Create( InvokeMethod('__ipow__', [TNumPy.ToPython(obj)] ) ); 783 | end; 784 | 785 | function TNDArray.IopSLeft(obj: TValue): TNDarray; 786 | begin 787 | Result := TNDarray.Create( InvokeMethod('__ilshift__', [TNumPy.ToPython(obj)] ) ); 788 | end; 789 | 790 | function TNDArray.IopSRight(obj: TValue): TNDarray; 791 | begin 792 | Result := TNDarray.Create( InvokeMethod('__irshift__', [TNumPy.ToPython(obj)] ) ); 793 | end; 794 | 795 | function TNDArray.IopAnd(obj: TValue): TNDarray; 796 | begin 797 | Result := TNDarray.Create( InvokeMethod('__iand__', [TNumPy.ToPython(obj)] ) ); 798 | end; 799 | 800 | function TNDArray.IopOr(obj: TValue): TNDarray; 801 | begin 802 | Result := TNDarray.Create( InvokeMethod('__ior__', [TNumPy.ToPython(obj)] ) ); 803 | end; 804 | 805 | function TNDArray.IopXor(obj: TValue): TNDarray; 806 | begin 807 | Result := TNDarray.Create( InvokeMethod('__ixor__', [TNumPy.ToPython(obj)] ) ); 808 | end; 809 | 810 | function TNDArray.opIDiv(obj: TValue): TNDarray; 811 | begin 812 | Result := TNDarray.Create( InvokeMethod('__idiv__', [TNumPy.ToPython(obj)] ) ); 813 | end; 814 | 815 | 816 | function TNDArray.Getitem(index: string): TNDarray; 817 | var 818 | tuple : TPyTuple; 819 | slice : Tnp_Slice; 820 | aSlice : TArray; 821 | resSlice: TArray; 822 | pyObj : TPythonObject; 823 | i : Integer; 824 | begin 825 | aSlice := slice.ParseSlices(index) ; 826 | 827 | for i := 0 to length(aSlice) -1 do 828 | begin 829 | slice := aSlice[i]; 830 | 831 | if slice.IsIndex then pyObj := TPyInt.Create(slice.Start) 832 | else pyObj := slice.ToPython ; 833 | 834 | resSlice := resSlice + [ pyObj ]; 835 | end; 836 | tuple := TPyTuple.Create( resSlice ); 837 | 838 | Result := TNDArray.Create( TPythonObject(Self)[tuple] ); 839 | end; 840 | 841 | procedure TNDArray.SetItem(index: string; const Value: TNDarray); 842 | var 843 | tuple : TPyTuple; 844 | slice : Tnp_Slice; 845 | aSlice : TArray; 846 | resSlice: TArray; 847 | pyObj : TPythonObject; 848 | i : Integer; 849 | begin 850 | aSlice := slice.ParseSlices(index) ; 851 | 852 | for i := 0 to length(aSlice) -1 do 853 | begin 854 | slice := aSlice[i]; 855 | 856 | if slice.IsIndex then pyObj := TPyInt.Create(slice.Start) 857 | else pyObj := slice.ToPython ; 858 | 859 | resSlice := resSlice + [ pyObj ]; 860 | end; 861 | tuple := TPyTuple.Create( resSlice ); 862 | 863 | TPythonObject(Self)[tuple] := TNumPy.ToPython(TPythonObject(value) ) 864 | 865 | end; 866 | 867 | function TNDArray.Getitem(index: TArray): TNDarray; 868 | var 869 | tuple : TPyTuple; 870 | 871 | res : Integer; 872 | begin 873 | tuple := TNumPy.ToTuple(TValue.ArrayOfToValueArray(index)); 874 | Result := TNDarray.Create( TPythonObject(Self)[tuple] ); 875 | end; 876 | 877 | procedure TNDArray.SetItem(index: TArray; const Value: TNDarray); 878 | var 879 | tuple : TPyTuple; 880 | begin 881 | tuple := TNumPy.ToTuple(TValue.ArrayOfToValueArray(index)); 882 | TPythonObject(Self)[tuple] := TNumPy.ToPython(value ); 883 | end; 884 | 885 | function TNDArray.Getitem(index: TArray): TNDarray; 886 | var 887 | aObj : TArray; 888 | tuple : TPyTuple; 889 | i : Integer; 890 | begin 891 | for i := 0 to High(index) do 892 | aObj := aObj + [ index[i] ]; 893 | 894 | tuple := TPyTuple.Create(aObj); 895 | 896 | Result := TNDarray.Create( TPythonObject(Self)[tuple] ); 897 | end; 898 | 899 | procedure TNDArray.SetItem(index: TArray; const Value: TNDarray); 900 | var 901 | aObj : TArray; 902 | tuple : TPyTuple; 903 | i : Integer; 904 | begin 905 | for i := 0 to High(index) do 906 | aObj := aObj + [ index[i] ]; 907 | 908 | tuple := TPyTuple.Create(aObj); 909 | 910 | TPythonObject(Self)[tuple] := TNumPy.ToPython(TPythonObject(value) ) 911 | end; 912 | 913 | 914 | function TNDArray.Getitem(index: TArray): TNDarray; 915 | var 916 | tuple : TPyTuple; 917 | item : TVarRec; 918 | slice : Tnp_Slice; 919 | res : TArray; 920 | pyObj : TPythonObject; 921 | i : Integer; 922 | begin 923 | pyObj := nil; 924 | for i := 0 to length(index) -1 do 925 | begin 926 | item := index[i]; 927 | case item.VType of 928 | vtInteger : pyObj := TPyInt.Create( index[i].VInteger ) ; 929 | vtString : pyObj := slice.Create( string(index[i].VString^) ).ToPython ; 930 | vtAnsiString : pyObj := slice.Create( string(index[i].VAnsiString^) ).ToPython ; 931 | vtClass : 932 | begin 933 | if LowerCase(item.VClass.ClassName) = 'tndarray' then 934 | pyObj := TPythonObject.Create( TNDArray(index).Handle ); 935 | end; 936 | else 937 | pyObj := TNumPy.ToPython(item) ; 938 | end; 939 | 940 | res := res + [ pyObj ]; 941 | end; 942 | tuple := TPyTuple.Create( res ); 943 | 944 | Result := TNDArray.Create( TPythonObject(Self)[tuple] ); 945 | 946 | end; 947 | 948 | procedure TNDArray.SetItem(index: TArray; const Value: TNDarray); 949 | var 950 | tuple : TPyTuple; 951 | item : TVarRec; 952 | slice : Tnp_Slice; 953 | res : TArray; 954 | pyObj : TPythonObject; 955 | i : Integer; 956 | begin 957 | pyObj := nil; 958 | for i := 0 to length(index) -1 do 959 | begin 960 | item := index[i]; 961 | case item.VType of 962 | vtInteger : pyObj := TPyInt.Create( index[i].VInteger ) ; 963 | vtString : pyObj := slice.Create( string(index[i].VString^) ).ToPython ; 964 | vtAnsiString : pyObj := slice.Create( string(index[i].VAnsiString^) ).ToPython ; 965 | vtClass : 966 | begin 967 | if LowerCase(item.VClass.ClassName) = 'tndarray' then 968 | pyObj := TPythonObject.Create( TNDArray(index).Handle ); 969 | end; 970 | else 971 | pyObj := TNumPy.ToPython(item) ; 972 | end; 973 | 974 | res := res + [ pyObj ]; 975 | end; 976 | tuple := TPyTuple.Create( res ); 977 | 978 | TPythonObject(Self)[tuple] := TNumPy.ToPython(TPythonObject(value) ) 979 | 980 | end; 981 | 982 | procedure TNDArray.itemset(args: TArray); 983 | var 984 | pyargs : TPyTuple; 985 | kwargs : TPyDict; 986 | 987 | begin 988 | pyargs := TNumPy.ToTuple(args); 989 | kwargs := TPyDict.Create; 990 | 991 | InvokeMethod('itemset', pyargs, kwargs); 992 | 993 | end; 994 | 995 | function TNDArray.ctypes: PPyObject; 996 | begin 997 | Result := GetAttr('ctypes').Handle 998 | end; 999 | 1000 | function TNDArray.data: PPyObject; 1001 | begin 1002 | Result := GetAttr('data').Handle 1003 | end; 1004 | 1005 | function TNDArray.dtype: TDtype; 1006 | begin 1007 | Result := TDtype.Create( GetAttr('dtype') ); 1008 | end; 1009 | 1010 | function TNDArray.flags: TFlags; 1011 | begin 1012 | Result := TFlags.Create( GetAttr('flags').Handle ); 1013 | end; 1014 | 1015 | function TNDArray.flat: PPyObject; 1016 | begin 1017 | Result := TFlags.Create( GetAttr('flat').Handle ).Handle; 1018 | end; 1019 | 1020 | function TNDArray.itemsize: Integer; 1021 | begin 1022 | Result := GetAttr('itemsize').AsInteger; 1023 | end; 1024 | 1025 | function TNDArray.len: Integer; 1026 | begin 1027 | Result := InvokeMethod('__len__',[]).AsInteger; 1028 | end; 1029 | 1030 | function TNDArray.nbytes: Integer; 1031 | begin 1032 | Result := GetAttr('nbytes').AsInteger 1033 | end; 1034 | 1035 | function TNDArray.ndim: Integer; 1036 | begin 1037 | Result := GetAttr('ndim').AsInteger 1038 | end; 1039 | 1040 | function TNDArray.repr: string; 1041 | begin 1042 | Result := InvokeMethod('__repr__',[]).AsString; 1043 | end; 1044 | 1045 | { DONE -oMax -c : aggiornare con reshape 08/02/2020 21:17:15 } 1046 | function TNDArray.reshape(newshape: TArray): TNDarray; 1047 | begin 1048 | Result := TNumPy.reshape(Self, Tnp_Shape.Create(newshape)); 1049 | end; 1050 | 1051 | procedure TNDArray.resize(new_shape: Tnp_Shape; refcheck: PBoolean); 1052 | var 1053 | pyargs : TPyTuple; 1054 | kwargs : TPyDict; 1055 | 1056 | begin 1057 | pyargs := TNumPy.ToTuple([TValue.FromShape(new_shape)]); 1058 | kwargs := TPyDict.Create; 1059 | 1060 | if (refcheck <> nil) then kwargs['refcheck'] := TNumPy.ToPython(refcheck^); 1061 | InvokeMethod('resize', pyargs, kwargs); 1062 | end; 1063 | 1064 | function TNDArray.shape: Tnp_Shape; 1065 | var 1066 | v : TArray; 1067 | begin 1068 | v := GetAttr('shape').AsArrayofInt; 1069 | 1070 | Result := Tnp_Shape.Create(v) ; 1071 | end; 1072 | 1073 | function TNDArray.size: Integer; 1074 | begin 1075 | Result := GetAttr('size').AsInteger 1076 | end; 1077 | 1078 | function TNDArray.str: string; 1079 | begin 1080 | Result :=InvokeMethod('__str__',[]).AsString; 1081 | end; 1082 | 1083 | function TNDArray.strides: TArray; 1084 | begin 1085 | Result := GetAttr('strides').AsArrayofInt 1086 | end; 1087 | 1088 | function TNDArray.T: TNDArray; 1089 | begin 1090 | Result := TNDArray.Create( GetAttr('T') ) 1091 | end; 1092 | 1093 | function TNDArray.tobytes(order: PChar): TArray; 1094 | var 1095 | pyargs : TPyTuple; 1096 | kwargs : TPyDict; 1097 | py : TPythonObject; 1098 | 1099 | begin 1100 | raise Exception.Create('TODO: this needs to be implemented with Marshal.Copy'); 1101 | 1102 | pyargs := TNumPy.ToTuple([]); 1103 | kwargs := TPyDict.Create; 1104 | 1105 | if (order <> nil) then kwargs['order'] := TNumPy.ToPython(order^); 1106 | py :=InvokeMethod('tobytes', pyargs, kwargs); 1107 | 1108 | Result := TNumPy.ToCsharp>(py) 1109 | end; 1110 | 1111 | function TNDArray.tostring(order: PChar): TArray; 1112 | begin 1113 | Result := tobytes(order) 1114 | end; 1115 | 1116 | procedure TNDArray.view(dtype: TDtype; tipo: Variant); 1117 | var 1118 | pyargs : TPyTuple; 1119 | kwargs : TPyDict; 1120 | 1121 | begin 1122 | raise Exception.Create('Get python type "ndarray" and "matrix" and substitute them for the given .NET type'); 1123 | 1124 | 1125 | pyargs := TNumPy.ToTuple([]); 1126 | kwargs := TPyDict.Create; 1127 | 1128 | if (dtype <> nil) then kwargs['dtype'] := TNumPy.ToPython(dtype); 1129 | if ( not VarIsNull(tipo) ) then kwargs['tipo'] := TNumPy.ToPython(TValue.FromVariant(tipo)); 1130 | InvokeMethod('view', pyargs, kwargs); 1131 | 1132 | end; 1133 | 1134 | function TNDArray.base: TNDArray; 1135 | var 1136 | py : TPythonObject; 1137 | begin 1138 | py := GetAttr('base'); 1139 | 1140 | if py.Handle = nil then Exit(nil); 1141 | 1142 | Result := TNDArray.Create( py ) 1143 | end; 1144 | 1145 | function TNDArray.asscalar: T; 1146 | begin 1147 | Result := TNumPy.asscalar(self); 1148 | end; 1149 | 1150 | { TNDArray } 1151 | 1152 | constructor TNDArray.Create(_pyobject: PPyObject); 1153 | begin 1154 | inherited Create(_pyobject); 1155 | end; 1156 | 1157 | constructor TNDArray.Create(Value: TNDarray); 1158 | begin 1159 | inherited Create(Value); 1160 | end; 1161 | 1162 | end. 1163 | -------------------------------------------------------------------------------- /src/NumPy/np.Utils.pas: -------------------------------------------------------------------------------- 1 | unit np.Utils; 2 | 3 | interface 4 | uses Winapi.Windows, System.SysUtils,System.Rtti, 5 | Python.Utils, 6 | np.Models; 7 | 8 | type 9 | 10 | TArray2D = array of TArray; 11 | TArray3D = array of TArray2D; 12 | 13 | TValueHelper = record helper for TValue 14 | public 15 | function AsShape : Tnp_Shape; 16 | function AsSlice : Tnp_Slice; 17 | function AsNDArray : TNDArray; overload; 18 | function AsNDArray: TNDArray; overload; 19 | function AsArray : TArray; 20 | 21 | class function FromArray(Params: TArray): TValue; static; 22 | class function ArrayOfToValueArray(Params: TArray): TArray; static; 23 | class function FromShape(Params: Tnp_Shape): TValue; static; 24 | class function FromSlice(Params: Tnp_Slice): TValue; static; 25 | 26 | end; 27 | 28 | TTupleSolver = class 29 | private 30 | class procedure GetNdListFromTuple(obj: TPythonObject; var res: TArray); 31 | class procedure GetTTupleList(obj: TPythonObject; var res: TArray); static; 32 | public 33 | class function TupleToList(obj: TPythonObject): TArray; overload; 34 | class function TupleToList(obj: TPythonObject): TArray; overload; 35 | end; 36 | 37 | implementation 38 | uses np.Base; 39 | 40 | { TValueHelper } 41 | 42 | class function TValueHelper.ArrayOfToValueArray(Params: TArray): TArray; 43 | var 44 | i: Integer; 45 | begin 46 | 47 | for i := 0 to Length(Params) -1 do 48 | Result := Result + [ TValue.From(Params[i]) ]; 49 | 50 | end; 51 | 52 | class function TValueHelper.FromShape(Params: Tnp_Shape): TValue; 53 | begin 54 | Result := TValue.From(Params); 55 | end; 56 | 57 | class function TValueHelper.FromSlice(Params: Tnp_Slice): TValue; 58 | begin 59 | Result := TValue.From(Params); 60 | end; 61 | 62 | class function TValueHelper.FromArray(Params: TArray): TValue; 63 | begin 64 | Result := TValue.From>(Params); 65 | end; 66 | 67 | function TValueHelper.AsArray: TArray; 68 | var 69 | i: Integer; 70 | begin 71 | Result := []; 72 | for i := 0 to Self.GetArrayLength -1 do 73 | Result := Result + [ self.GetArrayElement(i) ]; 74 | end; 75 | 76 | function TValueHelper.AsNDArray: TNDArray; 77 | begin 78 | Result := Self.AsType; 79 | end; 80 | 81 | function TValueHelper.AsNDArray: TNDArray; 82 | begin 83 | Result := Self.AsType>; 84 | end; 85 | 86 | function TValueHelper.AsShape: Tnp_Shape; 87 | begin 88 | Result := Self.AsType; 89 | end; 90 | 91 | function TValueHelper.AsSlice: Tnp_Slice; 92 | begin 93 | Result := Self.AsType; 94 | end; 95 | 96 | { TTupleSolver } 97 | 98 | class function TTupleSolver.TupleToList(obj: TPythonObject): TArray; 99 | var 100 | Iter: TPyIter; 101 | begin 102 | Iter := TPyIter.Create(obj); 103 | 104 | GetNdListFromTuple(Iter,Result); 105 | end; 106 | 107 | class procedure TTupleSolver.GetNdListFromTuple(obj: TPythonObject; var res: TArray); 108 | var 109 | Iter: TPyIter; 110 | r : TPythonObject; 111 | begin 112 | Iter := TPyIter.Create(obj); 113 | 114 | while Iter.MoveNext do 115 | begin 116 | r := TPythonObject(Iter.Current); 117 | if TPyTuple.IsTupleType(r) then 118 | begin 119 | GetNdListFromTuple(r,res); 120 | Continue; 121 | end; 122 | 123 | res := res + [ TNDArray.Create(r) ]; 124 | end; 125 | 126 | end; 127 | 128 | class function TTupleSolver.TupleToList(obj: TPythonObject): TArray; 129 | var 130 | Iter: TPyIter; 131 | begin 132 | Iter := TPyIter.Create(obj); 133 | 134 | GetTTupleList(Iter,Result); 135 | 136 | end; 137 | 138 | class procedure TTupleSolver.GetTTupleList(obj: TPythonObject; var res: TArray); 139 | var 140 | Iter: TPyIter; 141 | r : TPythonObject; 142 | begin 143 | Iter := TPyIter.Create(obj); 144 | 145 | while Iter.MoveNext do 146 | begin 147 | r := TPythonObject(Iter.Current); 148 | if TPyTuple.IsTupleType(r) then 149 | begin 150 | GetTTupleList(r,res); 151 | Continue; 152 | end; 153 | 154 | res := res + [ TNumPy.ToCsharp(r) ]; 155 | end; 156 | 157 | end; 158 | 159 | end. 160 | -------------------------------------------------------------------------------- /src/Python.Utils.pas: -------------------------------------------------------------------------------- 1 | {*******************************************************} 2 | { } 3 | { Numpy Wrapper for Delphi } 4 | { } 5 | { Copyright (C) 2020 Pigrecos(Max) } 6 | { } 7 | {*******************************************************} 8 | unit Python.Utils; 9 | 10 | //PythonObject.cs 11 | //PythonObject.gen.cs 12 | 13 | 14 | interface 15 | uses Winapi.Windows,System.SysUtils,System.Generics.Collections, 16 | PythonEngine, 17 | PythonGUIInputOutput; 18 | 19 | type 20 | TPyType = (ptNull,ptObject, ptString, ptInt16, ptInt32, ptInt64, ptSingle, ptDouble , mtDecimal, mtBoolean); 21 | 22 | // constants.cs 23 | Constants = (inf, neg_inf); 24 | 25 | TPyTuple = class; 26 | TPyDict = class; 27 | 28 | // PythonObject.cs / PythonObject.gen.cs 29 | TPythonObject = class 30 | private 31 | FHandle : PPyObject; 32 | 33 | function GetItem(key: TPythonObject ) : TPythonObject; overload; 34 | function GetItem(key: string) : TPythonObject; overload; 35 | function GetItem(index: Integer) : TPythonObject; overload; 36 | 37 | procedure SetItem(key: TPythonObject; value: TPythonObject ) ; overload ; 38 | procedure SetItem(key: string; value: TPythonObject ) ; overload ; 39 | procedure SetItem(index: Integer; value: TPythonObject ) ; overload ; 40 | 41 | public 42 | constructor Create(t: TPythonObject); overload; 43 | constructor Create(_pyobject: PPyObject); overload; 44 | constructor Create; overload; 45 | destructor Destroy; override; 46 | 47 | function IsNone: Boolean; 48 | function AsInteger: Integer; 49 | function AsString: string; 50 | function AsDouble: double; 51 | function AsBoolean: boolean; 52 | function AsArrayofString: TArray; 53 | function AsArrayofInt: TArray; 54 | function AsArrayofDouble: TArray; 55 | function AsArrayofPyObj: TArray; 56 | 57 | function ToString: string; 58 | 59 | function GetAttr(name: string):TPythonObject; 60 | procedure SetAttr(const varName: AnsiString; value: TPythonObject); 61 | 62 | class function ImportModule( Name: string):TPythonObject; 63 | class function ModuleFromString(name, code: string): TPythonObject; static; 64 | class function None: TPythonObject; 65 | 66 | function Invoke(args: TArray):TPythonObject; overload; 67 | function Invoke(args: TPyTuple):TPythonObject; overload; 68 | function Invoke(args: TArray; kw: TPyDict ):TPythonObject; overload; 69 | function Invoke(args: TPyTuple; kw: TPyDict ):TPythonObject; overload; 70 | 71 | function InvokeMethod(name: string; args: TArray = []):TPythonObject; overload; 72 | function InvokeMethod(name: string; args: TPyTuple):TPythonObject; overload; 73 | function InvokeMethod(name: string; args: TArray; kw: TPyDict):TPythonObject; overload; 74 | function InvokeMethod(name: string; args: TPyTuple; kw: TPyDict ):TPythonObject; overload; 75 | 76 | property Handle : PPyObject read FHandle; 77 | property ItemFrom[index :TPythonObject]:TPythonObject read GetItem write SetItem; default; 78 | property Itemfrom[index :string] :TPythonObject read GetItem write SetItem; default; 79 | property ItemFrom[index :Integer] :TPythonObject read GetItem write SetItem; default; 80 | 81 | end; 82 | 83 | TPyNumber = class(TPythonObject) 84 | public 85 | constructor Create(_pyobject: PPyObject); overload; 86 | constructor Create; overload; 87 | 88 | function IsNumberType(value: TPythonObject): Boolean; 89 | end; 90 | 91 | TPyDict = class(TPythonObject) 92 | public 93 | constructor Create(_pyobject: PPyObject); overload; 94 | constructor Create(o: TPythonObject); overload; 95 | constructor Create; overload; 96 | 97 | function IsDictType(value: TPythonObject) : Boolean; 98 | function HasKey(key: TPythonObject) : Boolean; overload; 99 | function HasKey(key: string) : Boolean; overload; 100 | function Keys : TPythonObject; 101 | function Values : TPythonObject; 102 | function Items : TPythonObject; 103 | function Copy : TPyDict; 104 | procedure Update(other: TPythonObject); 105 | procedure Clear; 106 | end; 107 | 108 | TPyLong = class(TPyNumber) 109 | public 110 | constructor Create(_pyobject: PPyObject); overload; 111 | constructor Create(o: TPythonObject); overload; 112 | constructor Create(value: Integer); overload; 113 | constructor Create(value: Cardinal); overload; 114 | constructor Create(value: Int64); overload; 115 | constructor Create(value: UInt64); overload; 116 | constructor Create(value: Int16); overload; 117 | constructor Create(value: UInt16); overload; 118 | constructor Create(value: Int8); overload; 119 | constructor Create(value: UInt8); overload; 120 | constructor Create(value: Double); overload; 121 | constructor Create(value: string); overload; 122 | function IsLongType(value: TPythonObject):Boolean; 123 | function AsLong(value: TPythonObject): TPyLong; 124 | 125 | function ToInt16: Int16; 126 | function ToInt32: Int32; 127 | function ToInt64: Int64; 128 | end; 129 | 130 | TPyInt = class(TPyNumber) 131 | public 132 | constructor Create(_pyobject: PPyObject); overload; 133 | constructor Create(o: TPythonObject); overload; 134 | constructor Create(value: Integer); overload; 135 | constructor Create(value: Cardinal); overload; 136 | constructor Create(value: Int64); overload; 137 | constructor Create(value: UInt64); overload; 138 | constructor Create(value: Int16); overload; 139 | constructor Create(value: UInt16); overload; 140 | constructor Create(value: Int8); overload; 141 | constructor Create(value: UInt8); overload; 142 | constructor Create(value: string); overload; 143 | function IsIntType(value: TPythonObject):Boolean; 144 | function AsInt(value: TPythonObject): TPyInt; 145 | 146 | function ToInt16: Int16; 147 | function ToInt32: Int32; 148 | function ToInt64: Int64; 149 | end; 150 | 151 | TPyFloat = class(TPyNumber) 152 | public 153 | constructor Create(_pyobject: PPyObject); overload; 154 | constructor Create(o: TPythonObject); overload; 155 | constructor Create(value: Double); overload; 156 | constructor Create(value: string); overload; 157 | function IsFloatType(value: TPythonObject):Boolean; 158 | function AsFloat(value: TPythonObject): TPyFloat; 159 | end; 160 | 161 | TPySequence = class(TPythonObject) 162 | public 163 | constructor Create(_pyobject: PPyObject); overload; 164 | constructor Create; overload; 165 | function IsSequenceType(value: TPythonObject) : Boolean; 166 | function GetSlice(i1, i2: Integer): TPythonObject; 167 | procedure SetSlice(i1, i2: Integer; v: TPythonObject); 168 | procedure DelSlice(i1, i2: Integer); 169 | function Index(item: TPythonObject): Integer; 170 | function Contains(item: TPythonObject): Boolean; 171 | function Concat(other: TPythonObject): TPythonObject; 172 | function Repeatt(count: Integer): TPythonObject; 173 | end; 174 | 175 | TPyString = class(TPySequence) 176 | public 177 | constructor Create(_pyobject: PPyObject); overload; 178 | constructor Create(o: TPythonObject); overload; 179 | constructor Create(s: string); overload; 180 | 181 | function IsStringType(value: TPythonObject) : Boolean; 182 | end; 183 | 184 | TPyAnsiString = class(TPySequence) 185 | public 186 | constructor Create(_pyobject: PPyObject); overload; 187 | constructor Create(o: TPythonObject); overload; 188 | constructor Create(s: AnsiString ); overload; 189 | 190 | function IsStringType(value: TPythonObject) : Boolean; 191 | end; 192 | 193 | TPyTuple = class(TPySequence) 194 | public 195 | constructor Create; overload; 196 | constructor Create(_pyobject: PPyObject); overload; 197 | constructor Create(o: TPythonObject); overload; 198 | constructor Create(const objects : array of PPyObject); overload; 199 | constructor Create(const objects: array of const);overload; 200 | constructor Create(const objects: TArray); overload; 201 | 202 | class function IsTupleType(value: TPythonObject): Boolean; 203 | function AsTuple(value: TPythonObject): TPyTuple; 204 | end; 205 | 206 | TPyList = class(TPySequence) 207 | public 208 | constructor Create; overload; 209 | constructor Create(_pyobject: PPyObject); overload; 210 | constructor Create(o: TPythonObject); overload; 211 | constructor Create(const objects : array of PPyObject); overload; 212 | constructor Create(const objects: array of TPythonObject); overload; 213 | 214 | function IsListType(value: TPythonObject): Boolean; 215 | function AsList(value: TPythonObject): TPyList; 216 | procedure Append(item: TPythonObject) ; 217 | procedure Insert(index : Integer ;item: TPythonObject) ; 218 | procedure Reverse; 219 | procedure Sort; 220 | end; 221 | 222 | TPyIter = class(TPythonObject,IEnumerator) 223 | private 224 | FCurrent : TPythonObject; 225 | function GetCurrent: TObject; 226 | public 227 | constructor Create(_pyobject: PPyObject); overload; 228 | constructor Create(iterable: TPythonObject); overload; 229 | function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; 230 | function _AddRef: Integer; stdcall; 231 | function _Release: Integer; stdcall; 232 | function MoveNext: Boolean; 233 | procedure Reset; 234 | 235 | property Current: TObject read GetCurrent; 236 | 237 | end; 238 | 239 | procedure InitGlobal(PyGuiIO: TPythonGUIInputOutput = nil); 240 | 241 | var 242 | g_MyPyEngine : TPythonEngine; 243 | 244 | implementation 245 | uses 246 | System.TypInfo, 247 | System.Variants; 248 | 249 | { TPythonObject } 250 | 251 | procedure InitGlobal(PyGuiIO: TPythonGUIInputOutput); 252 | begin 253 | if g_MyPyEngine = nil then 254 | begin 255 | g_MyPyEngine := TPythonEngine.Create(nil); 256 | g_MyPyEngine.IO := PyGuiIO; 257 | 258 | g_MyPyEngine.LoadDll; 259 | end; 260 | 261 | end; 262 | 263 | constructor TPythonObject.Create; 264 | begin 265 | if g_MyPyEngine = nil then InitGlobal; 266 | end; 267 | 268 | constructor TPythonObject.Create(_pyobject: PPyObject); 269 | begin 270 | create; 271 | FHandle := _pyobject; 272 | end; 273 | 274 | destructor TPythonObject.Destroy; 275 | begin 276 | if FHandle <> nil then 277 | g_MyPyEngine.Py_XDECREF(FHandle); 278 | 279 | g_MyPyEngine.PyErr_Clear; 280 | end; 281 | 282 | constructor TPythonObject.Create(t: TPythonObject); 283 | begin 284 | create; 285 | FHandle := t.Handle; 286 | end; 287 | 288 | // warning, this function will increase the refcount of value, 289 | // so, if you don't want to keep a link, don't forget to decrement 290 | // the refcount after the SetVar method. 291 | procedure TPythonObject.SetAttr( const varName : AnsiString; value : TPythonObject ); 292 | begin 293 | if Assigned(g_MyPyEngine) and Assigned( FHandle ) then 294 | begin 295 | if g_MyPyEngine.PyObject_SetAttrString(FHandle, PAnsiChar(varName), value.Handle ) <> 0 then 296 | raise EPythonError.CreateFmt( 'Could not set var "%s" in module "%s"', [varName] ); 297 | g_MyPyEngine.Py_XDecRef( value.Handle); 298 | end 299 | else 300 | raise EPythonError.CreateFmt( 'Can''t set var "%s" , because it is not yet initialized', [varName] ); 301 | end; 302 | 303 | // warning, this function will increase the refcount of value, 304 | // so, if you don't want to keep a link, don't forget to decrement 305 | // the refcount after the GetVar method. 306 | function TPythonObject.GetAttr(name: string): TPythonObject; 307 | var 308 | attr: PPyObject; 309 | begin 310 | if Assigned(g_MyPyEngine) and Assigned( FHandle ) then 311 | begin 312 | attr := g_MyPyEngine.PyObject_GetAttrString(FHandle, PAnsiChar(AnsiString(name))); 313 | g_MyPyEngine.PyErr_Clear; 314 | if attr = nil then 315 | raise EPythonError.Create('GetAttr: can''t get Attribute : '+ name); 316 | 317 | Result := TPythonObject.Create(attr); 318 | //g_MyPyEngine.Py_XDecRef(Result.Handle); // keep a borrowed reference. 319 | end 320 | else 321 | raise EPythonError.CreateFmt( 'Could not get var "%s" , because it is not yet initialized', [name] ); 322 | end; 323 | 324 | class function TPythonObject.ModuleFromString(name:string; code:string): TPythonObject; 325 | var 326 | c,m : PPyObject; 327 | begin 328 | c := g_MyPyEngine.Py_CompileString(PAnsiChar(AnsiString(code)), 'none', file_input); 329 | g_MyPyEngine.CheckError ; 330 | m := g_MyPyEngine.PyImport_ExecCodeModule(AnsiString(name), c); 331 | g_MyPyEngine.CheckError ; 332 | 333 | Result := TPythonObject.Create(m); 334 | end; 335 | 336 | function TPythonObject.IsNone: Boolean; 337 | begin 338 | Result := Handle = g_MyPyEngine.Py_None; 339 | end; 340 | 341 | class function TPythonObject.None: TPythonObject; 342 | begin 343 | Result := TPythonObject.Create( g_MyPyEngine.ReturnNone ) 344 | end; 345 | 346 | class function TPythonObject.ImportModule(Name: string): TPythonObject; 347 | var 348 | res : PPyObject; 349 | begin 350 | res := g_MyPyEngine.PyImport_ImportModule(PAnsiChar(AnsiString(Name)) ) ; 351 | if g_MyPyEngine.PyErr_Occurred <> nil then 352 | begin 353 | g_MyPyEngine.PyErr_Clear; 354 | Exit(nil); 355 | end; 356 | Result := TPythonObject.Create(res); 357 | end; 358 | 359 | function TPythonObject.Invoke(args: TArray): TPythonObject; 360 | var 361 | t : TPyTuple; 362 | res : PPyObject; 363 | begin 364 | t := TPyTuple.Create(args); 365 | res := g_MyPyEngine.PyObject_Call(FHandle,t.FHandle,nil); 366 | g_MyPyEngine.CheckError(False); 367 | 368 | if res = nil then 369 | raise EPythonError.Create('Invoke: can''t Call!'); 370 | 371 | Result := TPythonObject.Create(res); 372 | end; 373 | 374 | function TPythonObject.Invoke(args: TPyTuple): TPythonObject; 375 | var 376 | res : PPyObject; 377 | begin 378 | res := g_MyPyEngine.PyObject_Call(FHandle,args.FHandle,nil); 379 | g_MyPyEngine.CheckError(False); 380 | 381 | if res = nil then 382 | raise EPythonError.Create('Invoke: can''t Call!'); 383 | 384 | Result := TPythonObject.Create(res); 385 | 386 | end; 387 | 388 | function TPythonObject.Invoke(args: TPyTuple; kw: TPyDict): TPythonObject; 389 | var 390 | res : PPyObject; 391 | begin 392 | if kw = nil then res := g_MyPyEngine.PyObject_Call(FHandle,args.FHandle,nil) 393 | else res := g_MyPyEngine.PyObject_Call(FHandle,args.FHandle,kw.FHandle); 394 | g_MyPyEngine.CheckError(False); 395 | 396 | if res = nil then 397 | raise EPythonError.Create('Invoke: can''t Call!'); 398 | 399 | Result := TPythonObject.Create(res); 400 | 401 | end; 402 | 403 | function TPythonObject.Invoke(args: TArray; kw: TPyDict): TPythonObject; 404 | var 405 | t : TPyTuple; 406 | res : PPyObject; 407 | begin 408 | t := TPyTuple.Create(args); 409 | if kw = nil then res := g_MyPyEngine.PyObject_Call(FHandle,t.FHandle,nil) 410 | else res := g_MyPyEngine.PyObject_Call(FHandle,t.FHandle,kw.FHandle); 411 | g_MyPyEngine.CheckError(False); 412 | 413 | if res = nil then 414 | raise EPythonError.Create('Invoke: can''t Call!'); 415 | 416 | Result := TPythonObject.Create(res); 417 | 418 | end; 419 | 420 | function TPythonObject.InvokeMethod(name: string; args: TPyTuple): TPythonObject; 421 | var 422 | method : TPythonObject; 423 | begin 424 | method := GetAttr(name); 425 | try 426 | Result := method.Invoke(args) ; 427 | finally 428 | method.Free; 429 | end; 430 | end; 431 | 432 | function TPythonObject.InvokeMethod(name: string; args: TArray = []): TPythonObject; 433 | var 434 | method : TPythonObject; 435 | begin 436 | method := GetAttr(name); 437 | try 438 | Result := method.Invoke(args) ; 439 | finally 440 | method.Free; 441 | end; 442 | end; 443 | 444 | function TPythonObject.InvokeMethod(name: string; args: TArray; kw: TPyDict): TPythonObject; 445 | var 446 | method : TPythonObject; 447 | begin 448 | method := GetAttr(name); 449 | try 450 | Result := method.Invoke(args,kw) ; 451 | finally 452 | method.Free; 453 | end; 454 | end; 455 | 456 | function TPythonObject.InvokeMethod(name: string; args: TPyTuple; kw: TPyDict): TPythonObject; 457 | var 458 | method : TPythonObject; 459 | begin 460 | method := GetAttr(name); 461 | try 462 | Result := method.Invoke(args,kw) ; 463 | finally 464 | method.Free; 465 | end; 466 | end; 467 | 468 | function TPythonObject.GetItem(key: TPythonObject): TPythonObject; 469 | var 470 | op : PPyObject; 471 | begin 472 | op := g_MyPyEngine.PyObject_GetItem(FHandle,key.FHandle); 473 | if op = nil then 474 | raise EPythonError.Create('can''t get item!'); 475 | 476 | Result := TPythonObject.Create(op); 477 | end; 478 | 479 | function TPythonObject.GetItem(key: string): TPythonObject; 480 | var 481 | pyKey : TPyString; 482 | begin 483 | pyKey := TPyString.Create(key); 484 | 485 | Result := GetItem(pyKey) 486 | end; 487 | 488 | function TPythonObject.GetItem(index: Integer): TPythonObject; 489 | var 490 | pyKey : TPyInt; 491 | begin 492 | pyKey := TPyInt.Create(index); 493 | 494 | Result := GetItem(pyKey) 495 | end; 496 | 497 | 498 | procedure TPythonObject.SetItem(key, value: TPythonObject); 499 | var 500 | res : Integer; 501 | begin 502 | res := g_MyPyEngine.PyObject_SetItem(FHandle,key.FHandle,value.FHandle); 503 | if res < 0 then 504 | raise EPythonError.Create('can''t set item!'); 505 | end; 506 | 507 | procedure TPythonObject.SetItem(key: string; value: TPythonObject); 508 | var 509 | pyKey : TPyString; 510 | begin 511 | pyKey := TPyString.Create(key); 512 | 513 | SetItem(pyKey,value) 514 | end; 515 | 516 | procedure TPythonObject.SetItem(index: Integer; value: TPythonObject); 517 | var 518 | pyKey : TPyInt; 519 | begin 520 | pyKey := TPyInt.Create(index); 521 | 522 | SetItem(pyKey,value) 523 | end; 524 | 525 | function TPythonObject.AsArrayofPyObj: TArray; 526 | 527 | function GetItem( sequence : PPyObject; idx : Integer ) : TPythonObject; 528 | var 529 | val : PPyObject; 530 | begin 531 | val := g_MyPyEngine.PySequence_GetItem( sequence, idx ); 532 | try 533 | Result := TPythonObject.Create(val); 534 | finally 535 | g_MyPyEngine.Py_XDecRef( val ); 536 | end; 537 | end; 538 | 539 | var 540 | vArr : TArray; 541 | seq_length,i : Integer; 542 | begin 543 | Result := []; 544 | if g_MyPyEngine.PySequence_Check( FHandle ) <> 1 then Result := []; 545 | 546 | seq_length := g_MyPyEngine.PySequence_Length( FHandle ); 547 | if seq_length > 0 then 548 | g_MyPyEngine.Py_XDecRef( g_MyPyEngine.PySequence_GetItem( FHandle, 0 ) ); 549 | 550 | if g_MyPyEngine.PyErr_Occurred = nil then 551 | begin 552 | //vArr := VarArrayCreate( [0, seq_length-1], varInteger ); 553 | for i := 0 to g_MyPyEngine.PySequence_Length( FHandle )-1 do 554 | vArr := vArr + [ GetItem( FHandle, i ) ]; 555 | end else 556 | begin 557 | g_MyPyEngine.PyErr_Clear; 558 | Result := []; 559 | end; 560 | 561 | Result := vArr; 562 | end; 563 | 564 | function TPythonObject.AsArrayofDouble: TArray; 565 | 566 | function GetSequenceItem( sequence : PPyObject; idx : Integer ) : Variant; 567 | var 568 | val : PPyObject; 569 | begin 570 | val := g_MyPyEngine.PySequence_GetItem( sequence, idx ); 571 | try 572 | Result := g_MyPyEngine.PyObjectAsVariant( val ); 573 | if (Result = Null) then 574 | begin 575 | var Ss : AnsiString := val.ob_type.tp_name; 576 | if string(Ss).Contains('float32') then 577 | Result := g_MyPyEngine.PyFloat_AsDouble(val) 578 | 579 | end; 580 | 581 | finally 582 | g_MyPyEngine.Py_XDecRef( val ); 583 | end; 584 | end; 585 | 586 | var 587 | vArr : Variant; 588 | seq_length,i : Integer; 589 | begin 590 | Result := []; 591 | if g_MyPyEngine.PySequence_Check( FHandle ) <> 1 then Result := []; 592 | 593 | seq_length := g_MyPyEngine.PySequence_Length( FHandle ); 594 | if seq_length > 0 then 595 | g_MyPyEngine.Py_XDecRef( g_MyPyEngine.PySequence_GetItem( FHandle, 0 ) ); 596 | 597 | if g_MyPyEngine.PyErr_Occurred = nil then 598 | begin 599 | vArr := VarArrayCreate( [0, seq_length-1], varVariant ); 600 | for i := 0 to g_MyPyEngine.PySequence_Length( FHandle )-1 do 601 | vArr[i] := GetSequenceItem( FHandle, i ); 602 | end else // the object didn't implement the sequence API, so we return Null 603 | begin 604 | g_MyPyEngine.PyErr_Clear; 605 | Result := []; 606 | end; 607 | 608 | for i := 0 to VarArrayHighBound(vArr, 1) do 609 | Result := Result + [ VarAsType(vArr[i],varDouble) ] 610 | 611 | end; 612 | 613 | function TPythonObject.AsArrayofInt: TArray; 614 | 615 | function GetSequenceItem( sequence : PPyObject; idx : Integer ) : Variant; 616 | var 617 | val : PPyObject; 618 | begin 619 | val := g_MyPyEngine.PySequence_GetItem( sequence, idx ); 620 | try 621 | Result := g_MyPyEngine.PyObjectAsVariant( val ); 622 | finally 623 | g_MyPyEngine.Py_XDecRef( val ); 624 | end; 625 | end; 626 | 627 | var 628 | vArr : Variant; 629 | seq_length,i : Integer; 630 | begin 631 | Result := []; 632 | if g_MyPyEngine.PySequence_Check( FHandle ) <> 1 then Result := []; 633 | 634 | seq_length := g_MyPyEngine.PySequence_Length( FHandle ); 635 | if seq_length > 0 then 636 | g_MyPyEngine.Py_XDecRef( g_MyPyEngine.PySequence_GetItem( FHandle, 0 ) ); 637 | 638 | if g_MyPyEngine.PyErr_Occurred = nil then 639 | begin 640 | vArr := VarArrayCreate( [0, seq_length-1], varVariant ); 641 | for i := 0 to g_MyPyEngine.PySequence_Length( FHandle )-1 do 642 | vArr[i] := GetSequenceItem( FHandle, i ); 643 | end else // the object didn't implement the sequence API, so we return Null 644 | begin 645 | g_MyPyEngine.PyErr_Clear; 646 | Result := []; 647 | end; 648 | 649 | for i := 0 to VarArrayHighBound(vArr, 1) do 650 | Result := Result + [ Integer (vArr[i]) ] 651 | 652 | end; 653 | 654 | function TPythonObject.AsArrayofString: TArray; 655 | 656 | function GetSequenceItem( sequence : PPyObject; idx : Integer ) : Variant; 657 | var 658 | val : PPyObject; 659 | begin 660 | val := g_MyPyEngine.PySequence_GetItem( sequence, idx ); 661 | try 662 | Result := g_MyPyEngine.PyObjectAsVariant( val ); 663 | finally 664 | g_MyPyEngine.Py_XDecRef( val ); 665 | end; 666 | end; 667 | 668 | var 669 | vArr : Variant; 670 | seq_length,i : Integer; 671 | begin 672 | Result := []; 673 | if g_MyPyEngine.PySequence_Check( FHandle ) <> 1 then Result := []; 674 | 675 | seq_length := g_MyPyEngine.PySequence_Length( FHandle ); 676 | if seq_length > 0 then 677 | g_MyPyEngine.Py_XDecRef( g_MyPyEngine.PySequence_GetItem( FHandle, 0 ) ); 678 | 679 | if g_MyPyEngine.PyErr_Occurred = nil then 680 | begin 681 | vArr := VarArrayCreate( [0, seq_length-1], varVariant ); 682 | for i := 0 to g_MyPyEngine.PySequence_Length( FHandle )-1 do 683 | vArr[i] := GetSequenceItem( FHandle, i ); 684 | end else // the object didn't implement the sequence API, so we return Null 685 | begin 686 | g_MyPyEngine.PyErr_Clear; 687 | Result := []; 688 | end; 689 | 690 | for i := 0 to VarArrayHighBound(vArr, 1) do 691 | Result := Result + [ vArr[i] ] 692 | 693 | end; 694 | 695 | function TPythonObject.AsInteger: Integer; 696 | begin 697 | Result := g_MyPyEngine.PyObjectAsVariant(FHandle) 698 | end; 699 | 700 | function TPythonObject.AsString: string; 701 | begin 702 | Result := g_MyPyEngine.PyObjectAsVariant(FHandle) 703 | end; 704 | 705 | function TPythonObject.AsDouble: double; 706 | begin 707 | Result := g_MyPyEngine.PyObjectAsVariant(FHandle) 708 | end; 709 | 710 | function TPythonObject.AsBoolean: boolean; 711 | begin 712 | Result := g_MyPyEngine.PyObjectAsVariant(FHandle) 713 | end; 714 | 715 | function TPythonObject.ToString: string; 716 | begin 717 | Result := g_MyPyEngine.PyObjectAsString(FHandle); 718 | end; 719 | 720 | { TPyNumber } 721 | 722 | constructor TPyNumber.Create(_pyobject: PPyObject); 723 | begin 724 | inherited Create(_pyobject); 725 | end; 726 | 727 | constructor TPyNumber.Create; 728 | begin 729 | inherited 730 | end; 731 | 732 | function TPyNumber.IsNumberType(value: TPythonObject): Boolean; 733 | begin 734 | Result := g_MyPyEngine.PyNumber_Check(value.FHandle) <> 0 735 | end; 736 | 737 | { TPyDict } 738 | 739 | constructor TPyDict.Create(_pyobject: PPyObject); 740 | begin 741 | inherited Create(_pyobject); 742 | end; 743 | 744 | constructor TPyDict.Create(o: TPythonObject); 745 | begin 746 | if not IsDictType(o) then 747 | raise EPythonError.Create('object is not a dict'); 748 | 749 | inherited create; 750 | FHandle := o.FHandle; 751 | end; 752 | 753 | constructor TPyDict.Create; 754 | begin 755 | inherited create; 756 | FHandle := g_MyPyEngine.PyDict_New; 757 | try 758 | if not Assigned(FHandle) then 759 | raise EPythonError.Create('Could not create a new dict object'); 760 | except 761 | g_MyPyEngine.Py_XDECREF( FHandle ); 762 | end; 763 | end; 764 | 765 | procedure TPyDict.Clear; 766 | begin 767 | g_MyPyEngine.PyDict_Clear(FHandle) 768 | end; 769 | 770 | function TPyDict.IsDictType(value: TPythonObject): Boolean; 771 | begin 772 | Result := g_MyPyEngine.PyDict_Check(value.FHandle); 773 | end; 774 | 775 | function TPyDict.Copy: TPyDict; 776 | var 777 | op: PPyObject; 778 | begin 779 | op := g_MyPyEngine.PyDict_Copy(FHandle); 780 | if not Assigned(op) then 781 | raise EPythonError.Create('Could not copy a dict object'); 782 | 783 | Result := TPyDict.Create(op); 784 | end; 785 | 786 | function TPyDict.HasKey(key: TPythonObject): Boolean; 787 | begin 788 | Result := g_MyPyEngine.PyMapping_HasKey(FHandle, key.FHandle) <> 0; 789 | end; 790 | 791 | function TPyDict.HasKey(key: string): Boolean; 792 | var 793 | _str : TPyString; 794 | begin 795 | _str := TPyString(key); 796 | Result := HasKey(_str) 797 | end; 798 | 799 | function TPyDict.Items: TPythonObject; 800 | var 801 | items : PPyObject; 802 | begin 803 | items := g_MyPyEngine.PyDict_Items(FHandle); 804 | if not Assigned(items) then 805 | raise EPythonError.Create('Could not get Items from object'); 806 | 807 | Result := TPythonObject.Create(items); 808 | end; 809 | 810 | function TPyDict.Keys: TPythonObject; 811 | var 812 | items : PPyObject; 813 | begin 814 | items := g_MyPyEngine.PyDict_Keys(FHandle); 815 | if not Assigned(items) then 816 | raise EPythonError.Create('Could not get Keys from object'); 817 | 818 | Result := TPythonObject.Create(items); 819 | end; 820 | 821 | function TPyDict.Values: TPythonObject; 822 | var 823 | items : PPyObject; 824 | begin 825 | items := g_MyPyEngine.PyDict_Values(FHandle); 826 | if not Assigned(items) then 827 | raise EPythonError.Create('Could not get Values from object'); 828 | 829 | Result := TPythonObject.Create(items); 830 | end; 831 | 832 | procedure TPyDict.Update(other: TPythonObject); 833 | var 834 | res : Integer; 835 | begin 836 | res := g_MyPyEngine.PyDict_Update(FHandle, other.FHandle); 837 | if res <> 0 then 838 | raise EPythonError.Create('Could not update object'); 839 | 840 | end; 841 | 842 | { TPyString } 843 | 844 | constructor TPyString.Create(_pyobject: PPyObject); 845 | begin 846 | inherited Create(_pyobject); 847 | end; 848 | 849 | constructor TPyString.Create(o: TPythonObject); 850 | begin 851 | if not IsStringType(o) then 852 | raise EPythonError.Create('object is not a string'); 853 | 854 | inherited create; 855 | FHandle := o.FHandle; 856 | end; 857 | 858 | constructor TPyString.Create(s: string); 859 | begin 860 | inherited create; 861 | FHandle := g_MyPyEngine.PyUnicode_FromWideString(s) 862 | end; 863 | 864 | function TPyString.IsStringType(value: TPythonObject): Boolean; 865 | begin 866 | Result := g_MyPyEngine.PyString_Check(value.FHandle); 867 | end; 868 | 869 | { TPyAnsiString } 870 | 871 | constructor TPyAnsiString.Create(_pyobject: PPyObject); 872 | begin 873 | inherited Create(_pyobject); 874 | end; 875 | 876 | constructor TPyAnsiString.Create(o: TPythonObject); 877 | begin 878 | if not IsStringType(o) then 879 | raise EPythonError.Create('object is not a Ansistring'); 880 | 881 | inherited create; 882 | FHandle := o.FHandle; 883 | end; 884 | 885 | constructor TPyAnsiString.Create(s: AnsiString); 886 | begin 887 | inherited create; 888 | FHandle := g_MyPyEngine.PyString_FromStringAndSize(PAnsiChar(s), Length(s)); 889 | end; 890 | 891 | function TPyAnsiString.IsStringType(value: TPythonObject): Boolean; 892 | begin 893 | Result := g_MyPyEngine.PyString_Check(value.FHandle); 894 | end; 895 | 896 | { TPyLong } 897 | 898 | constructor TPyLong.Create(o: TPythonObject); 899 | begin 900 | if not IsLongType(o) then 901 | raise EPythonError.Create('object is not a Long'); 902 | 903 | inherited create; 904 | FHandle := o.FHandle; 905 | end; 906 | 907 | constructor TPyLong.Create(_pyobject: PPyObject); 908 | begin 909 | inherited Create(_pyobject); 910 | end; 911 | 912 | constructor TPyLong.Create(value: Integer); 913 | begin 914 | inherited create; 915 | FHandle := g_MyPyEngine.PyLong_FromLong(value); 916 | end; 917 | 918 | constructor TPyLong.Create(value: Cardinal); 919 | begin 920 | inherited create; 921 | FHandle := g_MyPyEngine.PyLong_FromLong(value); 922 | end; 923 | 924 | constructor TPyLong.Create(value: Int64); 925 | begin 926 | inherited create; 927 | FHandle := g_MyPyEngine.PyLong_FromLongLong(value); 928 | end; 929 | 930 | constructor TPyLong.Create(value: UInt64); 931 | begin 932 | inherited create; 933 | FHandle := g_MyPyEngine.PyLong_FromUnsignedLongLong(value); 934 | end; 935 | 936 | constructor TPyLong.Create(value: Int16); 937 | begin 938 | inherited create; 939 | FHandle := g_MyPyEngine.PyLong_FromLong(value); 940 | end; 941 | 942 | constructor TPyLong.Create(value: UInt16); 943 | begin 944 | inherited create; 945 | FHandle := g_MyPyEngine.PyLong_FromLong(value); 946 | end; 947 | 948 | constructor TPyLong.Create(value: UInt8); 949 | begin 950 | inherited create; 951 | FHandle := g_MyPyEngine.PyLong_FromLong(value); 952 | end; 953 | 954 | constructor TPyLong.Create(value: Int8); 955 | begin 956 | inherited create; 957 | FHandle := g_MyPyEngine.PyLong_FromLong(value); 958 | end; 959 | 960 | constructor TPyLong.Create(value: Double); 961 | begin 962 | inherited create; 963 | FHandle := g_MyPyEngine.PyLong_FromDouble(value); 964 | end; 965 | 966 | constructor TPyLong.Create(value: string); 967 | var 968 | p : PAnsiChar; 969 | begin 970 | inherited create; 971 | FHandle := g_MyPyEngine.PyLong_FromString(PAnsiChar(AnsiString(value)),p,0); 972 | end; 973 | 974 | function TPyLong.IsLongType(value: TPythonObject): Boolean; 975 | begin 976 | Result := g_MyPyEngine.PyLong_Check(value.FHandle); 977 | end; 978 | 979 | function TPyLong.AsLong(value: TPythonObject): TPyLong; 980 | var 981 | op : PPyObject; 982 | begin 983 | op := g_MyPyEngine.PyNumber_Long(value.FHandle); 984 | if not Assigned(op) then 985 | raise EPythonError.Create('Could not cast AsLong object'); 986 | 987 | Result := TPyLong(op); 988 | end; 989 | 990 | function TPyLong.ToInt16: Int16; 991 | begin 992 | Result := int16(ToInt32) ; 993 | end; 994 | 995 | function TPyLong.ToInt32: Int32; 996 | begin 997 | Result := int16(ToInt64) ; 998 | end; 999 | 1000 | function TPyLong.ToInt64: Int64; 1001 | begin 1002 | Result := g_MyPyEngine.PyLong_AsLongLong(FHandle); 1003 | end; 1004 | 1005 | { TPyInt } 1006 | 1007 | constructor TPyInt.Create(o: TPythonObject); 1008 | begin 1009 | if not IsIntType(o) then 1010 | raise EPythonError.Create('object is not a Int'); 1011 | 1012 | inherited create; 1013 | FHandle := o.FHandle; 1014 | end; 1015 | 1016 | constructor TPyInt.Create(_pyobject: PPyObject); 1017 | begin 1018 | inherited Create(_pyobject); 1019 | end; 1020 | 1021 | constructor TPyInt.Create(value: Cardinal); 1022 | begin 1023 | inherited create; 1024 | FHandle := g_MyPyEngine.PyInt_FromLong(value); 1025 | end; 1026 | 1027 | constructor TPyInt.Create(value: Integer); 1028 | begin 1029 | inherited create; 1030 | FHandle := g_MyPyEngine.PyInt_FromLong(value); 1031 | end; 1032 | 1033 | constructor TPyInt.Create(value: Int64); 1034 | begin 1035 | inherited create; 1036 | FHandle := g_MyPyEngine.PyLong_FromLong( int32(value) ); 1037 | end; 1038 | 1039 | constructor TPyInt.Create(value: UInt64); 1040 | begin 1041 | inherited create; 1042 | FHandle := g_MyPyEngine.PyLong_FromLong( value ); 1043 | end; 1044 | 1045 | constructor TPyInt.Create(value: Int16); 1046 | begin 1047 | Create(integer(value)); 1048 | end; 1049 | 1050 | constructor TPyInt.Create(value: UInt16); 1051 | begin 1052 | Create(integer(value)); 1053 | end; 1054 | 1055 | constructor TPyInt.Create(value: Int8); 1056 | begin 1057 | Create(integer(value)); 1058 | end; 1059 | 1060 | constructor TPyInt.Create(value: UInt8); 1061 | begin 1062 | Create(integer(value)); 1063 | end; 1064 | 1065 | constructor TPyInt.Create(value: string); 1066 | var 1067 | p : PAnsiChar; 1068 | begin 1069 | inherited create; 1070 | FHandle := g_MyPyEngine.PyLong_FromString(PAnsiChar(AnsiString(value)),p,0); 1071 | end; 1072 | 1073 | function TPyInt.AsInt(value: TPythonObject): TPyInt; 1074 | var 1075 | op : PPyObject; 1076 | begin 1077 | op := g_MyPyEngine.PyNumber_Int(value.FHandle); 1078 | if not Assigned(op) then 1079 | raise EPythonError.Create('Could not cast AsInt object'); 1080 | 1081 | Result := TPyInt.Create(op); 1082 | end; 1083 | 1084 | function TPyInt.IsIntType(value: TPythonObject): Boolean; 1085 | begin 1086 | Result := g_MyPyEngine.PyInt_Check(value.FHandle); 1087 | end; 1088 | 1089 | function TPyInt.ToInt16: Int16; 1090 | begin 1091 | Result := Int16(ToInt32); 1092 | end; 1093 | 1094 | function TPyInt.ToInt32: Int32; 1095 | begin 1096 | Result := g_MyPyEngine.PyInt_AsLong(FHandle); 1097 | end; 1098 | 1099 | function TPyInt.ToInt64: Int64; 1100 | begin 1101 | Result := Int64(ToInt32); 1102 | end; 1103 | 1104 | { TPyFloat } 1105 | 1106 | constructor TPyFloat.Create(_pyobject: PPyObject); 1107 | begin 1108 | inherited Create; 1109 | inherited Create(_pyobject); 1110 | end; 1111 | 1112 | constructor TPyFloat.Create(o: TPythonObject); 1113 | begin 1114 | if not IsFloatType(o) then 1115 | raise EPythonError.Create('object is not a Float'); 1116 | 1117 | inherited create; 1118 | FHandle := o.FHandle; 1119 | end; 1120 | 1121 | constructor TPyFloat.Create(value: Double); 1122 | begin 1123 | inherited Create; 1124 | FHandle := g_MyPyEngine.PyFloat_FromDouble(value); 1125 | end; 1126 | 1127 | constructor TPyFloat.Create(value: string); 1128 | var 1129 | s : TPyString; 1130 | begin 1131 | s := TPyString.Create(value); 1132 | FHandle := g_MyPyEngine.PyFloat_FromString(s.FHandle); 1133 | end; 1134 | 1135 | function TPyFloat.IsFloatType(value: TPythonObject): Boolean; 1136 | begin 1137 | Result := g_MyPyEngine.PyFloat_Check(value.FHandle); 1138 | end; 1139 | 1140 | function TPyFloat.AsFloat(value: TPythonObject): TPyFloat; 1141 | var 1142 | op : PPyObject; 1143 | begin 1144 | op := g_MyPyEngine.PyNumber_Float(value.FHandle); 1145 | if not Assigned(op) then 1146 | raise EPythonError.Create('Could not cast AsFloat object'); 1147 | 1148 | Result := TPyFloat.Create(op); 1149 | end; 1150 | 1151 | { TPySequence } 1152 | 1153 | constructor TPySequence.Create; 1154 | begin 1155 | inherited create; 1156 | end; 1157 | 1158 | constructor TPySequence.Create(_pyobject: PPyObject); 1159 | begin 1160 | inherited Create(_pyobject); 1161 | end; 1162 | 1163 | function TPySequence.IsSequenceType(value: TPythonObject): Boolean; 1164 | begin 1165 | Result := g_MyPyEngine.PySequence_Check(value.FHandle ) <> 0; 1166 | end; 1167 | 1168 | function TPySequence.GetSlice(i1, i2: Integer): TPythonObject; 1169 | var 1170 | op : PPyObject; 1171 | begin 1172 | op := g_MyPyEngine.PySequence_GetSlice(FHandle, i1, i2); 1173 | if not Assigned(op) then 1174 | raise EPythonError.Create('Failed on PySequence_GetSlice'); 1175 | 1176 | Result := TPythonObject.Create(op); 1177 | end; 1178 | 1179 | procedure TPySequence.SetSlice(i1, i2: Integer; v: TPythonObject); 1180 | var 1181 | r : Integer; 1182 | begin 1183 | r := g_MyPyEngine.PySequence_SetSlice(FHandle, i1, i2, v.FHandle); 1184 | if r < 0 then 1185 | raise EPythonError.Create('Failed on PySequence_SetSlice'); 1186 | end; 1187 | 1188 | procedure TPySequence.DelSlice(i1, i2: Integer); 1189 | var 1190 | r : Integer; 1191 | begin 1192 | r := g_MyPyEngine.PySequence_DelSlice(FHandle, i1, i2); 1193 | if r < 0 then 1194 | raise EPythonError.Create('Failed on PySequence_DelSlice'); 1195 | end; 1196 | 1197 | function TPySequence.Index(item: TPythonObject): Integer; 1198 | var 1199 | r : Integer; 1200 | begin 1201 | r := g_MyPyEngine.PySequence_Index(FHandle, item.FHandle); 1202 | if r < 0 then 1203 | begin 1204 | g_MyPyEngine.PyErr_Clear; 1205 | Exit (-1) 1206 | end; 1207 | Result := r; 1208 | end; 1209 | 1210 | function TPySequence.Contains(item: TPythonObject): Boolean; 1211 | var 1212 | r : Integer; 1213 | begin 1214 | r := g_MyPyEngine.PySequence_Contains(FHandle, item.FHandle); 1215 | if r < 0 then 1216 | raise EPythonError.Create('Failed on Contains'); 1217 | 1218 | Result := r <> 0; 1219 | end; 1220 | 1221 | function TPySequence.Concat(other: TPythonObject): TPythonObject; 1222 | var 1223 | op : PPyObject; 1224 | begin 1225 | op := g_MyPyEngine.PySequence_Concat(FHandle, other.FHandle); 1226 | if not Assigned(op) then 1227 | raise EPythonError.Create('Failed on Concat'); 1228 | 1229 | Result := TPythonObject.Create(op); 1230 | end; 1231 | 1232 | function TPySequence.Repeatt(count: Integer): TPythonObject; 1233 | var 1234 | op : PPyObject; 1235 | begin 1236 | op := g_MyPyEngine.PySequence_Repeat(FHandle, count); 1237 | if not Assigned(op) then 1238 | raise EPythonError.Create('Failed on Repeat'); 1239 | 1240 | Result := TPythonObject.Create(op); 1241 | end; 1242 | 1243 | { TPyTuple } 1244 | 1245 | constructor TPyTuple.Create; 1246 | begin 1247 | inherited create; 1248 | FHandle := g_MyPyEngine.PyTuple_New(0); 1249 | if not Assigned(FHandle) then 1250 | raise Exception.Create('TError.RaiseErrorObj: Could not create an empty tuple'); 1251 | end; 1252 | 1253 | constructor TPyTuple.Create(_pyobject: PPyObject); 1254 | begin 1255 | inherited Create(_pyobject); 1256 | end; 1257 | 1258 | constructor TPyTuple.Create(o: TPythonObject); 1259 | begin 1260 | if not IsTupleType(o) then 1261 | raise EPythonError.Create('object is not a tuple'); 1262 | 1263 | inherited create; 1264 | FHandle := o.FHandle; 1265 | end; 1266 | 1267 | constructor TPyTuple.Create(const objects: array of const); 1268 | begin 1269 | inherited create; 1270 | FHandle := g_MyPyEngine.ArrayToPyTuple(objects); 1271 | end; 1272 | 1273 | constructor TPyTuple.Create(const objects: array of PPyObject); 1274 | begin 1275 | inherited create; 1276 | FHandle := g_MyPyEngine.MakePyTuple(objects); 1277 | end; 1278 | 1279 | constructor TPyTuple.Create(const objects: TArray); 1280 | var 1281 | aT : array of PPyObject; 1282 | i : Integer; 1283 | begin 1284 | SetLength(aT, length(objects)); 1285 | for i := 0 to Length(aT) - 1 do 1286 | aT[i] := objects[i].FHandle; 1287 | 1288 | inherited create; 1289 | FHandle := g_MyPyEngine.MakePyTuple(aT); 1290 | end; 1291 | 1292 | class function TPyTuple.IsTupleType(value: TPythonObject): Boolean; 1293 | begin 1294 | Result := g_MyPyEngine.PyTuple_Check(value.FHandle); 1295 | end; 1296 | 1297 | function TPyTuple.AsTuple(value: TPythonObject): TPyTuple; 1298 | var 1299 | op : PPyObject; 1300 | begin 1301 | op := g_MyPyEngine.PySequence_Tuple(value.FHandle); 1302 | if not Assigned(op) then 1303 | raise EPythonError.Create('Could not cast AsTuple object'); 1304 | 1305 | Result := TPyTuple.Create(op); 1306 | 1307 | end; 1308 | 1309 | { TPyList } 1310 | 1311 | constructor TPyList.Create; 1312 | begin 1313 | inherited create; 1314 | FHandle := g_MyPyEngine.PyList_New(0); 1315 | if not Assigned(FHandle) then 1316 | raise Exception.Create('Could not create a new list object'); 1317 | end; 1318 | 1319 | constructor TPyList.Create(_pyobject: PPyObject); 1320 | begin 1321 | inherited Create(_pyobject); 1322 | end; 1323 | 1324 | constructor TPyList.Create(o: TPythonObject); 1325 | begin 1326 | if not IsListType(o) then 1327 | raise EPythonError.Create('object is not a List'); 1328 | 1329 | inherited create; 1330 | FHandle := o.FHandle; 1331 | end; 1332 | 1333 | constructor TPyList.Create(const objects: array of TPythonObject); 1334 | var 1335 | aT : array of PPyObject; 1336 | i : Integer; 1337 | begin 1338 | SetLength(aT, length(objects)); 1339 | for i := 0 to Length(aT) - 1 do 1340 | aT[i] := objects[i].FHandle; 1341 | 1342 | inherited create; 1343 | FHandle := g_MyPyEngine.MakePyList(aT); 1344 | 1345 | end; 1346 | 1347 | constructor TPyList.Create(const objects: array of PPyObject); 1348 | begin 1349 | inherited create; 1350 | FHandle := g_MyPyEngine.MakePyList(objects); 1351 | end; 1352 | 1353 | function TPyList.IsListType(value: TPythonObject): Boolean; 1354 | begin 1355 | Result := g_MyPyEngine.PyList_Check(value.FHandle); 1356 | end; 1357 | 1358 | function TPyList.AsList(value: TPythonObject): TPyList; 1359 | var 1360 | op : PPyObject; 1361 | begin 1362 | op := g_MyPyEngine.PySequence_List(value.FHandle); 1363 | if not Assigned(op) then 1364 | raise EPythonError.Create('Could not cast AsList object'); 1365 | 1366 | Result := TPyList.Create(op); 1367 | end; 1368 | 1369 | procedure TPyList.Append(item: TPythonObject); 1370 | var 1371 | r : Integer; 1372 | begin 1373 | r := g_MyPyEngine.PyList_Append(FHandle, item.FHandle); 1374 | if r < 0 then 1375 | raise EPythonError.Create('Could not append object'); 1376 | end; 1377 | 1378 | procedure TPyList.Insert(index: Integer; item: TPythonObject); 1379 | var 1380 | r : Integer; 1381 | begin 1382 | r := g_MyPyEngine.PyList_Insert(FHandle, index, item.FHandle); 1383 | if r < 0 then 1384 | raise EPythonError.Create('Could not append object'); 1385 | end; 1386 | 1387 | procedure TPyList.Reverse; 1388 | var 1389 | r : Integer; 1390 | begin 1391 | r := g_MyPyEngine.PyList_Reverse(FHandle); 1392 | if r < 0 then 1393 | raise EPythonError.Create('Could not Reverse object'); 1394 | end; 1395 | 1396 | procedure TPyList.Sort; 1397 | var 1398 | r : Integer; 1399 | begin 1400 | r := g_MyPyEngine.PyList_Sort(FHandle); 1401 | if r < 0 then 1402 | raise EPythonError.Create('Could not Sort object'); 1403 | end; 1404 | 1405 | { TPyIter } 1406 | 1407 | constructor TPyIter.Create(_pyobject: PPyObject); 1408 | begin 1409 | inherited Create(_pyobject); 1410 | end; 1411 | 1412 | constructor TPyIter.Create(iterable: TPythonObject); 1413 | begin 1414 | inherited create; 1415 | FHandle := g_MyPyEngine.PyObject_GetIter(iterable.FHandle); 1416 | if not Assigned(FHandle) then 1417 | raise EPythonError.Create('object is not a Iter'); 1418 | end; 1419 | 1420 | function TPyIter.GetCurrent: TObject; 1421 | begin 1422 | Result := FCurrent; 1423 | end; 1424 | 1425 | function TPyIter.MoveNext: Boolean; 1426 | var 1427 | next : PPyObject; 1428 | begin 1429 | // dispose of the previous object, if there was one 1430 | if FCurrent <> nil then 1431 | begin 1432 | FCurrent.Free; 1433 | FCurrent := nil; 1434 | end; 1435 | 1436 | next := g_MyPyEngine.PyIter_Next(FHandle); 1437 | if next = nil then 1438 | begin 1439 | Result := False; 1440 | Exit; 1441 | end; 1442 | 1443 | FCurrent := TPythonObject.Create(next); 1444 | Result := True; 1445 | end; 1446 | 1447 | function TPyIter.QueryInterface(const IID: TGUID; out Obj): HResult; 1448 | begin 1449 | if GetInterface(IID, Obj) then 1450 | Result:= S_OK 1451 | else 1452 | Result:= E_NOINTERFACE; 1453 | end; 1454 | 1455 | procedure TPyIter.Reset; 1456 | begin 1457 | 1458 | end; 1459 | 1460 | function TPyIter._AddRef: Integer; 1461 | begin 1462 | Result := -1 1463 | end; 1464 | 1465 | function TPyIter._Release: Integer; 1466 | begin 1467 | Result := -1 1468 | end; 1469 | 1470 | initialization 1471 | 1472 | finalization 1473 | if g_MyPyEngine <> nil then 1474 | g_MyPyEngine.Free; 1475 | 1476 | 1477 | end. 1478 | --------------------------------------------------------------------------------