diff --git a/src/Bonsai.ML.Design/MultidimensionalArrayVisualizer.cs b/src/Bonsai.ML.Design/MultidimensionalArrayVisualizer.cs
index 397d947e..a2ea15ab 100644
--- a/src/Bonsai.ML.Design/MultidimensionalArrayVisualizer.cs
+++ b/src/Bonsai.ML.Design/MultidimensionalArrayVisualizer.cs
@@ -1,13 +1,16 @@
using System;
using System.Windows.Forms;
+using Bonsai;
using Bonsai.Design;
+[assembly: TypeVisualizer(typeof(Bonsai.ML.Design.MultidimensionalArrayVisualizer),
+ Target = typeof(double[,]))]
+
namespace Bonsai.ML.Design
{
///
/// Provides a type visualizer to display multi dimensional array data as a heatmap.
///
- [TypeVisualizer(typeof(MultidimensionalArrayVisualizer), Target = typeof(double[,]))]
public class MultidimensionalArrayVisualizer : DialogTypeVisualizer
{
///
diff --git a/src/Bonsai.ML.HiddenMarkovModels/Bonsai.ML.HiddenMarkovModels.csproj b/src/Bonsai.ML.HiddenMarkovModels/Bonsai.ML.HiddenMarkovModels.csproj
index 8dac151d..4b0ef857 100644
--- a/src/Bonsai.ML.HiddenMarkovModels/Bonsai.ML.HiddenMarkovModels.csproj
+++ b/src/Bonsai.ML.HiddenMarkovModels/Bonsai.ML.HiddenMarkovModels.csproj
@@ -6,7 +6,6 @@
net472;netstandard2.0
-
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/Bonsai.ML.LinearDynamicalSystems.csproj b/src/Bonsai.ML.LinearDynamicalSystems/Bonsai.ML.LinearDynamicalSystems.csproj
index 8110c215..9955b561 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/Bonsai.ML.LinearDynamicalSystems.csproj
+++ b/src/Bonsai.ML.LinearDynamicalSystems/Bonsai.ML.LinearDynamicalSystems.csproj
@@ -5,13 +5,13 @@
Bonsai Rx ML KalmanFilter LinearDynamicalSystems
net472;netstandard2.0
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/CreateModelReference.cs b/src/Bonsai.ML.LinearDynamicalSystems/CreateModelReference.cs
deleted file mode 100644
index cfc1d0f3..00000000
--- a/src/Bonsai.ML.LinearDynamicalSystems/CreateModelReference.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.ComponentModel;
-using System;
-using System.Reactive.Linq;
-
-namespace Bonsai.ML.LinearDynamicalSystems
-{
- ///
- /// Represents an operator that creates a reference for a named model.
- ///
- [Combinator]
- [Description("Creates a reference for a named model.")]
- [WorkflowElementCategory(ElementCategory.Source)]
- public class CreateModelReference : INamedElement
- {
- ///
- /// Gets or sets the name of the model to reference.
- ///
- [Description("The name of the model to reference.")]
- public string Name { get ; set; }
-
- ///
- /// Generates an observable sequence that contains the model reference object.
- ///
- ///
- /// A sequence containing a single instance of the
- /// class.
- ///
- public IObservable Process()
- {
- return Observable.Defer(() => Observable.Return(new ModelReference(Name)));
- }
- }
-}
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/CreateKFModel.bonsai b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/CreateKFModel.bonsai
index 5566b6ba..863927ef 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/CreateKFModel.bonsai
+++ b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/CreateKFModel.bonsai
@@ -1,7 +1,7 @@
-
- model
-
+
model
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/Forecast.cs b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/Forecast.cs
index 368607f7..7b4b6df9 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/Forecast.cs
+++ b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/Forecast.cs
@@ -1,12 +1,11 @@
using System;
-using System.Reactive;
using System.Reactive.Linq;
-using System.Collections.ObjectModel;
using System.Xml.Serialization;
using System.ComponentModel;
using Newtonsoft.Json;
using Python.Runtime;
using System.Collections.Generic;
+using Bonsai.ML.Python;
namespace Bonsai.ML.LinearDynamicalSystems.Kinematics
{
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/KFModelParameters.cs b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/KFModelParameters.cs
index 19f9122c..32a80d31 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/KFModelParameters.cs
+++ b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/KFModelParameters.cs
@@ -3,6 +3,7 @@
using System.Reactive.Linq;
using Python.Runtime;
using Newtonsoft.Json;
+using Bonsai.ML.Python;
namespace Bonsai.ML.LinearDynamicalSystems.Kinematics
{
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/PerformForecasting.bonsai b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/PerformForecasting.bonsai
index 2a54115a..d20e379e 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/PerformForecasting.bonsai
+++ b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/PerformForecasting.bonsai
@@ -2,7 +2,7 @@
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/PerformInference.bonsai b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/PerformInference.bonsai
index 1250e7c2..56d7c108 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/PerformInference.bonsai
+++ b/src/Bonsai.ML.LinearDynamicalSystems/Kinematics/PerformInference.bonsai
@@ -2,9 +2,10 @@
@@ -127,10 +128,10 @@
-
+
-
+
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/Learning/RunOptimizationAsync.bonsai b/src/Bonsai.ML.LinearDynamicalSystems/Learning/RunOptimizationAsync.bonsai
index a6eee35a..e64f1f22 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/Learning/RunOptimizationAsync.bonsai
+++ b/src/Bonsai.ML.LinearDynamicalSystems/Learning/RunOptimizationAsync.bonsai
@@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core"
xmlns:py="clr-namespace:Bonsai.Scripting.Python;assembly=Bonsai.Scripting.Python"
- xmlns:p1="clr-namespace:Bonsai.ML.LinearDynamicalSystems;assembly=Bonsai.ML.LinearDynamicalSystems"
+ xmlns:p1="clr-namespace:Bonsai.ML;assembly=Bonsai.ML"
xmlns:scr="clr-namespace:Bonsai.Scripting.Expressions;assembly=Bonsai.Scripting.Expressions"
xmlns="https://bonsai-rx.org/2018/workflow">
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/CreateKFModel.bonsai b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/CreateKFModel.bonsai
index e04b18e0..5c476c65 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/CreateKFModel.bonsai
+++ b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/CreateKFModel.bonsai
@@ -2,7 +2,7 @@
@@ -31,9 +31,7 @@
-
- model
-
+
model
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/CreateMultivariatePDF.bonsai b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/CreateMultivariatePDF.bonsai
index ad6b361f..41e2ad52 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/CreateMultivariatePDF.bonsai
+++ b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/CreateMultivariatePDF.bonsai
@@ -2,7 +2,7 @@
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/GridParameters.cs b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/GridParameters.cs
index eeec392b..1cf1e9db 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/GridParameters.cs
+++ b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/GridParameters.cs
@@ -3,6 +3,7 @@
using System.Reactive.Linq;
using Newtonsoft.Json;
using Python.Runtime;
+using Bonsai.ML.Python;
namespace Bonsai.ML.LinearDynamicalSystems.LinearRegression
{
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/KFModelParameters.cs b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/KFModelParameters.cs
index 46f8ae9a..589aaba9 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/KFModelParameters.cs
+++ b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/KFModelParameters.cs
@@ -2,6 +2,7 @@
using Newtonsoft.Json;
using System;
using System.Reactive.Linq;
+using Bonsai.ML.Python;
using Python.Runtime;
using System.Xml.Serialization;
@@ -105,7 +106,7 @@ public int NumFeatures
set
{
_x = value;
- _xString = _x == null ? "None" : NumpyHelper.NumpyParser.ParseArray(_x);
+ _xString = _x == null ? "None" : StringFormatter.FormatToPython(_x);
}
}
@@ -125,7 +126,7 @@ public int NumFeatures
set
{
_p = value;
- _pString = _p == null ? "None" : NumpyHelper.NumpyParser.ParseArray(_p);
+ _pString = _p == null ? "None" : StringFormatter.FormatToPython(_p);
}
}
@@ -188,10 +189,10 @@ public IObservable Process(IObservable sour
P = _p
});
}
-
+
+ ///
public override string ToString()
{
-
return $"likelihood_precision_coef={_likelihood_precision_coefString}, prior_precision_coef={_prior_precision_coefString}, n_features={_n_featuresString}, x={_xString}, P={_pString}";
}
}
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/MultivariatePDF.cs b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/MultivariatePDF.cs
index 6fc92c6c..c03449f0 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/MultivariatePDF.cs
+++ b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/MultivariatePDF.cs
@@ -3,6 +3,7 @@
using System.Reactive.Linq;
using Python.Runtime;
using System.Xml.Serialization;
+using Bonsai.ML.Python;
namespace Bonsai.ML.LinearDynamicalSystems.LinearRegression
{
@@ -35,7 +36,7 @@ public IObservable Process(IObservable source)
return Observable.Select(source, pyObject =>
{
var gridParameters = GridParameters.ConvertPyObject(pyObject);
- var values = (double[,])pyObject.GetArrayAttribute("pdf_values");
+ var values = (double[,])pyObject.GetArrayAttr("pdf_values");
return new MultivariatePDF {
GridParameters = gridParameters,
Values = values
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/PerformInference.bonsai b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/PerformInference.bonsai
index 75aa6fea..e3fa230b 100644
--- a/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/PerformInference.bonsai
+++ b/src/Bonsai.ML.LinearDynamicalSystems/LinearRegression/PerformInference.bonsai
@@ -1,9 +1,10 @@
-
@@ -126,7 +127,7 @@
-
+
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/ModelReference.cs b/src/Bonsai.ML.LinearDynamicalSystems/ModelReference.cs
deleted file mode 100644
index 1c098c7a..00000000
--- a/src/Bonsai.ML.LinearDynamicalSystems/ModelReference.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.ComponentModel;
-
-namespace Bonsai.ML.LinearDynamicalSystems
-{
-
- ///
- /// Bonsai LDS model reference base class
- ///
- public class ModelReference
- {
- ///
- /// Gets or sets the name of the referenced model.
- ///
- public string Name { get ; set; }
-
- ///
- /// Initializes a new instance of the class
- /// with the specified name.
- ///
- /// The name of the referenced model.
- public ModelReference(string name)
- {
- Name = name;
- }
- }
-}
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/NumpyHelper.cs b/src/Bonsai.ML.LinearDynamicalSystems/NumpyHelper.cs
deleted file mode 100644
index 145b19c9..00000000
--- a/src/Bonsai.ML.LinearDynamicalSystems/NumpyHelper.cs
+++ /dev/null
@@ -1,338 +0,0 @@
-using System;
-using Python.Runtime;
-using System.Collections.Generic;
-using System.ComponentModel;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System.Text;
-using System.Linq;
-using System.Runtime.InteropServices;
-
-namespace Bonsai.ML.LinearDynamicalSystems
-{
- static class NumpyHelper
- {
- public class NumpyArrayInterface
- {
- public NumpyArrayInterface(PyObject obj)
- {
- if (!IsNumPyArray(obj))
- {
- throw new Exception("object is not a numpy array");
- }
- var meta = obj.GetAttr("__array_interface__");
- IsCStyleContiguous = meta["strides"] == null;
- Address = new IntPtr(meta["data"][0].As());
-
- var typestr = meta["typestr"].As();
- var dtype = typestr.Substring(1);
- switch (dtype)
- {
- case "b1":
- DataType = typeof(bool);
- break;
- case "f4":
- DataType = typeof(float);
- break;
- case "f8":
- DataType = typeof(double);
- break;
- case "i2":
- DataType = typeof(short);
- break;
- case "i4":
- DataType = typeof(int);
- break;
- case "i8":
- DataType = typeof(long);
- break;
- case "u1":
- DataType = typeof(byte);
- break;
- case "u2":
- DataType = typeof(ushort);
- break;
- case "u4":
- DataType = typeof(uint);
- break;
- case "u8":
- DataType = typeof(ulong);
- break;
- default:
- throw new Exception($"Type '{dtype}' not supported");
- }
- Shape = obj.GetAttr("shape").As();
- NBytes = obj.GetAttr("nbytes").As();
- }
-
- public readonly IntPtr Address;
-
- public readonly Type DataType;
-
- public readonly long[] Shape;
-
- public readonly int NBytes;
-
- public readonly bool IsCStyleContiguous;
- }
-
- public static Array PyObjectToArray(PyObject array)
- {
- var info = new NumpyArrayInterface(array);
- byte[] data = new byte[info.NBytes];
- Marshal.Copy(info.Address, data, 0, info.NBytes);
- if (info.DataType == typeof(byte) && info.Shape.Length == 1)
- {
- return data;
- }
- var result = Array.CreateInstance(info.DataType, info.Shape);
- Buffer.BlockCopy(data, 0, result, 0, info.NBytes);
- return result;
- }
-
- private static PyObject deepcopy;
-
- private static readonly Lazy np = new(InitializeNumpy);
-
- private static readonly Dictionary np_dtypes = new();
-
- private static readonly Dictionary csharp_dtypes = new()
- {
- { "uint8", typeof(byte) },
- { "uint16", typeof(ushort) },
- { "uint32", typeof(uint) },
- { "uint64", typeof(ulong) },
- { "int16", typeof(short) },
- { "int32", typeof(int) },
- { "int64", typeof(long) },
- { "float32", typeof(float) },
- { "float64", typeof(double) },
- };
-
- public static PyObject InitializeNumpy()
- {
- var np = Py.Import("numpy");
- np_dtypes.Add(typeof(byte), np.GetAttr("uint8"));
- np_dtypes.Add(typeof(ushort), np.GetAttr("uint16"));
- np_dtypes.Add(typeof(uint), np.GetAttr("uint32"));
- np_dtypes.Add(typeof(ulong), np.GetAttr("uint64"));
- np_dtypes.Add(typeof(short), np.GetAttr("int16"));
- np_dtypes.Add(typeof(int), np.GetAttr("int32"));
- np_dtypes.Add(typeof(long), np.GetAttr("int64"));
- np_dtypes.Add(typeof(float), np.GetAttr("float32"));
- np_dtypes.Add(typeof(double), np.GetAttr("float64"));
- var copy = Py.Import("copy");
- deepcopy = copy.GetAttr("deepcopy");
- return np;
- }
-
- public static bool IsNumPyArray(PyObject obj)
- {
- dynamic numpy = np.Value;
- return numpy.ndarray.__instancecheck__(obj);
- }
-
- public static PyObject GetNumpyDataType(Type type)
- {
- PyObject dtype;
- np_dtypes.TryGetValue(type, out dtype);
- if (dtype == null)
- {
- throw new Exception($"type '{type}' not supported.");
- }
- return dtype;
- }
-
- public static Type GetCSharpDataType(string str)
- {
- Type type;
- csharp_dtypes.TryGetValue(str, out type);
- if (type == null)
- {
- throw new Exception($"type '{type}' not supported.");
- }
- return type;
- }
-
- public class NumpyDataTypes : StringConverter
- {
- public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
- {
- return true;
- }
-
- public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
- {
- var dtypes = new List
- {
- "int16",
- "int32",
- "int64",
- "uint8",
- "uint16",
- "uint32",
- "uint64",
- "float32",
- "float64"
- };
- return new StandardValuesCollection(dtypes);
- }
- }
-
- public class NumpyParser
- {
- public static string ParseArray(Array array)
- {
- StringBuilder sb = new StringBuilder();
- ParseArrayToStringRecursive(array, sb, new int[0]);
- return sb.ToString();
- }
-
- private static void ParseArrayToStringRecursive(Array array, StringBuilder sb, int[] indices)
- {
- if (indices.Length < array.Rank)
- {
- sb.Append("[");
- int length = array.GetLength(indices.Length);
- for (int i = 0; i < length; i++)
- {
- int[] newIndices = new int[indices.Length + 1];
- indices.CopyTo(newIndices, 0);
- newIndices[indices.Length] = i;
- ParseArrayToStringRecursive(array, sb, newIndices);
- if (i < length - 1)
- {
- sb.Append(", ");
- }
- }
- sb.Append("]");
- }
- else
- {
- object value = array.GetValue(indices);
- sb.Append(value.ToString());
- }
- }
-
- private static bool IsValidJson(string input)
- {
- int squareBrackets = 0;
- foreach (char c in input)
- {
- if (c == '[') squareBrackets++;
- else if (c == ']') squareBrackets--;
- }
- return squareBrackets == 0;
- }
-
- public static Array ParseString(string input, Type dtype)
- {
- try
- {
- if (!IsValidJson(input))
- {
- throw new ArgumentException("JSON is invalid.");
- }
- var obj = JsonConvert.DeserializeObject(input);
- int depth = ParseDepth(obj);
- int[] dimensions = ParseDimensions(obj, depth);
- var resultArray = Array.CreateInstance(dtype, dimensions);
- PopulateArray(obj, resultArray, new int[0], dtype);
- return resultArray;
- }
- catch (Exception ex)
- {
- throw new Exception("Error parsing input string.", ex);
- }
- }
-
- private static int ParseDepth(JToken token, int currentDepth = 0)
- {
- if (token is JArray arr && arr.Count > 0)
- {
- return ParseDepth(arr[0], currentDepth + 1);
- }
- return currentDepth;
- }
-
- private static int[] ParseDimensions(JToken token, int depth, int currentLevel = 0)
- {
- if (depth == 0 || !(token is JArray))
- {
- return new int[0];
- }
-
- List dimensions = new List();
- JToken current = token;
-
- while (current != null && current is JArray)
- {
- JArray currentArray = current as JArray;
- dimensions.Add(currentArray.Count);
- if (currentArray.Count > 0)
- {
- if (currentArray.Any(item => !(item is JArray)) && currentArray.Any(item => item is JArray) || currentArray.All(item => item is JArray) && currentArray.Any(item => ((JArray)item).Count != ((JArray)currentArray.First()).Count))
- {
- throw new Exception("Error parsing input string.");
- }
-
- if (!(currentArray.First() is JArray) && !currentArray.All(item => double.TryParse(item.ToString(), out _)))
- {
- throw new Exception("Error parsing non numeric types.");
- }
- }
-
- current = currentArray.Count > 0 ? currentArray[0] : null;
- }
-
- if (currentLevel > 0 && token is JArray arr && arr.All(x => x is JArray))
- {
- var subArrayDimensions = new HashSet();
- foreach (JArray subArr in arr)
- {
- int[] subDims = ParseDimensions(subArr, depth - currentLevel, currentLevel + 1);
- subArrayDimensions.Add(string.Join(",", subDims));
- }
-
- if (subArrayDimensions.Count > 1)
- {
- throw new ArgumentException("Inconsistent array dimensions.");
- }
- }
-
- return dimensions.ToArray();
- }
-
- private static void PopulateArray(JToken token, Array array, int[] indices, Type dtype)
- {
- if (token is JArray arr)
- {
- for (int i = 0; i < arr.Count; i++)
- {
- int[] newIndices = new int[indices.Length + 1];
- Array.Copy(indices, newIndices, indices.Length);
- newIndices[newIndices.Length - 1] = i;
- PopulateArray(arr[i], array, newIndices, dtype);
- }
- }
- else
- {
- var values = ParseType(token, dtype);
- array.SetValue(values, indices);
- }
- }
-
- private static object ParseType(object value, Type targetType)
- {
- try
- {
- return Convert.ChangeType(value, targetType);
- }
- catch (Exception ex)
- {
- throw new Exception("Error parsing type: ", ex);
- }
- }
- }
- }
-}
diff --git a/src/Bonsai.ML.LinearDynamicalSystems/PythonHelper.cs b/src/Bonsai.ML.LinearDynamicalSystems/PythonHelper.cs
deleted file mode 100644
index 30f5bf63..00000000
--- a/src/Bonsai.ML.LinearDynamicalSystems/PythonHelper.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using Python.Runtime;
-using System;
-using System.Collections.Generic;
-
-namespace Bonsai.ML.LinearDynamicalSystems
-{
- static class PythonHelper
- {
- public static object GetArrayAttribute(this PyObject pyObject, string attributeName)
- {
- using var attr = pyObject.GetAttr(attributeName);
- return ConvertPythonObjectToCSharp(attr);
- }
-
- public static T GetAttr(this PyObject pyObject, string attributeName)
- {
- using var attr = pyObject.GetAttr(attributeName);
- return attr.As();
- }
-
- public static object ConvertPythonObjectToCSharp(PyObject pyObject)
- {
- if (PyInt.IsIntType(pyObject))
- {
- return pyObject.As();
- }
-
- if (PyFloat.IsFloatType(pyObject))
- {
- return pyObject.As();
- }
-
- if (PyString.IsStringType(pyObject))
- {
- return pyObject.As();
- }
-
- if (PyList.IsListType(pyObject))
- {
- var pyList = new PyList(pyObject);
- var resultList = new List