Other [PyBridge] B4J v10.2 BETA is available for download

Erel

B4X founder
Staff member
Licensed User
Longtime User
This update includes a new library named PyBridge, that allows using Python libraries from inside the B4J app. Python is leading the way in fields such as AI, LLM, image recognition and many others. Using PyBridge is not always trivial and it won't be the right tool for every task, however there are many things that weren't possible before and are now possible. And that is a good thing.

1739718245749.png


Other improvements:
  • Many internal libraries were updated since last release.
  • New internal keywords: Initialized and NotInitialized:
    B4X:
    If Map1 <> Null And Map1.IsInitialized Then ... 'boring
    If Initialized(Map1) Then ... 'less boring
  • #CustomBuildAction arguments are expanded with environment variables and other variables (%PROJECT%, %B4X%, %JAVABIN%, %PROJECT_NAME% and %ADDITIONAL%): https://www.b4x.com/android/forum/threads/b4x-comment-links.119897/#content
  • LogColors withs in b4xlibs
  • Fix for logs encoding issue in Java 19+. Note that the following attribute should be added for the same fix with standalone packages (if the terminal output is important):
    B4X:
    #PackagerProperty: VMArgs = -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8
  • B4XCollections: new helper methods: EmptyList, EmptyMap, MergeMaps, MergeLists, CreateList, CopyOnWriteMap and CopyOnWriteList.
  • Panel.LoadLayout no longer deletes the previous tag.
Download link: https://www.b4x.com/b4j/files/beta.exe

PyBridge is a big thing. I will write tutorials that explain how it works and how Python libraries can be wrapped to be accessed in a simple manner.
To run a simple program:

1739957471817.png



Please start a new thread for questions or issues. Use [pybridge] in the thread title if related.
 

Attachments

  • 1739719504057.png
    1739719504057.png
    15.4 KB · Views: 811
Last edited:

William Lancee

Well-Known Member
Licensed User
Longtime User
I started to experiment with this - it is very powerful indeed.
The first thing I tried was:

B4X:
    'Fibonacci - this works well and is very concise
    Dim n As Int = 100
    Wait For (Fibonacci(n).Fetch) Complete (series As PyWrapper)
    Log($"The Fibonacci series up to (not including) ${n}: "$  & series.Value)
    'The Fibonacci series up to (not including) 100: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    
    
Private Sub Fibonacci(n As Int) As PyWrapper
    Dim code As String = $"
# Fibonacci numbers module
def Fibonacci (n):
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result
"$
    Return Py.RunCode("Fibonacci", Array(n), code)
End Sub

But I can't figure out how to do this:

B4X:
'# Multiple Linear Regression Module
'    import numpy As np
'    from scipy import stats

    Py.ImportModule("numpy")
    Py.ImportModuleFrom("scipy", "stats")
    Dim x() As Object = Array As Object(5,7,8,7,2,17,2,9,4,11,12,9,6)
    Dim y() As Object = Array As Object(99,86,87,88,111,86,103,87,94,78,77,85,86)
    Dim result As PyWrapper = LinearRegression(x, y)
    result.Print

'    Error occurred on line: 35 (B4XMainPage)
'    (b4xmainpage.B4XPage_Created) - Python Error (ModuleNotFoundError) - Method: module.exec: No module named 'numpy'

Private Sub LinearRegression(x() As Object, y() As Object) As PyWrapper
    Dim Code As String = $"
# Multiple Linear Regression Module
def LinearRegression (x, y):
    return stats.linregress(x, y)
"$
    Return Py.RunCode("LinearRegression", Array(x, y), Code)
End Sub
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Ok I got it working.
1. I had to install numpy and scipy.
a. navigate to project B4J objects Python Python folder copy folder address
b. open cmd window. >cd copied_folder_address
c. >python -m pip install numpy
d. >python -m pip install scipy

2. Add these lines after Py is ready
B4X:
    Py.ImportModule("numpy")
    Py.ImportModuleFrom("scipy", "stats")

Note: the second line doesn't seem to work as expected - work around added in py code

3. stats expects numpy arrays so feed the sub with lists instead of arrays

4. figured out how to interpret result.value and added my simple plot class to plot it

linRegPlot.png


Since the zip creation link does not copy the objects folder (where Python lives) I am not attaching the project .zip file
So here is all the code (70 lines). Attached is the plot module.
B4X:
'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip
#CustomBuildAction: after packager, %WINDIR%\System32\robocopy.exe, Python temp\build\bin\python /E /XD __pycache__ Doc pip setuptools tests

'Ctrl + click to open Python shell: ide://run?File=%PROJECT%\Objects\Python\WinPython+Command+Prompt.exe
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Public Py As PyBridge
    Private SP As SimpleXYPlot
End Sub

Public Sub Initialize
    SP.Initialize   
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    B4XPages.AddPageAndCreate("SP", SP)

    Py.Initialize(Me, "Py")
    Dim opt As PyOptions = Py.CreateOptions(File.Combine(File.DirApp, "Python/python/python.exe"))
    Py.Start(opt)
    Wait For Py_Connected (Success As Boolean)
    If Success = False Then
        LogError("Failed to start Python process.")
        Return
    End If

    Py.ImportModule("numpy")
    'Py.ImportModule("scipy", "stats")            'This doesn't seem to work - I had to put it in the code

    Dim x As List = B4XCollections.CreateList(Array(5,7,8,7,2,17,2,9,4,11,12,9,6))
    Dim y As List = B4XCollections.CreateList(Array(99,86,87,88,111,86,103,87,94,78,77,85,86))
    Wait For (LinearRegression(x, y).Fetch) Complete (results As PyWrapper)
    Dim ar() As Object = results.Value
    Dim mp As Map = CreateMap("slope": ar(0), "intercept": ar(1), "r": ar(2), "p": ar(3), "std_err": ar(4))
    plotResults(x, y, mp)
End Sub

Private Sub B4XPage_Background
    Py.KillProcess
End Sub

Private Sub Py_Disconnected
    Log("PyBridge disconnected")
End Sub

Private Sub LinearRegression(xs As List, ys As List) As PyWrapper
    Dim Code As String = $"
from scipy import stats   
# Multiple Linear Regression Module
def LinearRegression (xs, ys):
    x = numpy.array(xs)
    y = numpy.array(ys)
    return stats.linregress(x, y)
"$
    Return Py.RunCode("LinearRegression", Array(xs, ys), Code)
End Sub

'draw simple XY plot
Private Sub plotResults(x As List, y As List, mp As Map)  'ignore
    SP.drawXY(x, y)
    SP.drawRegression(mp.Get("intercept"), mp.Get("slope"))
    Dim r As Float = mp.Get("r")
    SP.addTitle("Fig 1. Best-fit Line to Data Points")
    SP.addSubTitle($"[n=${x.size};  r=$1.3{r};  r${Chr(0x00B2)}=$1.3{Power(r, 2)};  p=$1.3{mp.Get("p")}]"$)
    SP.addYLabel("Y - Axis")
    SP.addXLabel("X - Axis")
    B4XPages.ShowPage("SP")
End Sub



Attached is my simple plot class.

Once I've figured out the various parameters, PyBridge will become a major tool in my work.
 

Attachments

  • SimpleXYPlot.bas
    4.9 KB · Views: 29
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
navigate to project B4J objects Python Python folder copy folder address
b. open cmd window. >cd copied_folder_address
Simpler - Ctrl click here:
B4X:
'Ctrl + click to open Python shell: ide://run?File=%PROJECT%\Objects\Python\WinPython+Command+Prompt.exe
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Only thing I changed - the PyOptions line. If you have python installed, change to point to your python, or else it copies it to objects.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
About the none working code, it will work if you add the import:
B4X:
Private Sub LinearRegression(x() As Object, y() As Object) As PyWrapper
    Dim Code As String = $"
from scipy import stats
# Multiple Linear Regression Module
def LinearRegression (x, y):
    return stats.linregress(x, y)
"$
    Return Py.RunCode("LinearRegression", Array(x, y), Code)
End Sub

I will make it work with Py.ImportModuleFrom as well.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Only thing I changed - the PyOptions line. If you have python installed, change to point to your python, or else it copies it to objects.
Wwhen you create a "PyBridge With Python" project you will start with a project that includes a relatively small Python runtime.
There will be another template named "PyBridge without Python" that will exclude it.
Note that there is nothing special about PyBridge library. You can start a new project and add it.

If you are using large Python libraries then it does make sense to maintain your own Python runtime with all the dependencies.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
I was thinking more about keeping dependencies up to date. I just pip --upgrade my main python . If they are spread around 'Objects' it could be a nightmare to keep current/updated.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
About the LinearRegresession - the returned type has a useful _asdict method that converts the type to a map. This makes it simple to fetch the result:
B4X:
Dim x() As Object = Array(5,7,8,7,2,17,2,9,4,11,12,9,6)
Dim y() As Object = Array(99,86,87,88,111,86,103,87,94,78,77,85,86)
Dim result As PyWrapper = LinearRegression(x, y)
Wait For (result.Run("_asdict").Fetch) Complete (result As PyWrapper)
Log(result.Value)
'{slope=-1.7512877115526118, intercept=103.10596026490066, rvalue=-0.758591524376155, pvalue=0.002646873922456106, stderr=0.453536157607742, intercept_stderr=3.9034928101545123}
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
The _asdict method is great. The data feed to LinearRegression are lists - an object array assignment to List also works.
B4X:
    Dim x As List = Array(5,7,8,7,2,17,2,9,4,11,12,9,6)
    Dim y As List = Array(99,86,87,88,111,86,103,87,94,78,77,85,86)
    Wait For (LinearRegression(x, y).Run("_asdict").Fetch) Complete (results As PyWrapper)
    plotResults(x, y, results.Value)
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Last edited:
Upvote 0
Top