Position performance in a pgn database

Discussion of anything and everything relating to chess playing software and machines.

Moderators: hgm, Harvey Williamson, bob

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
Post Reply
giovanni
Posts: 120
Joined: Wed Jul 08, 2015 10:30 am

Position performance in a pgn database

Post by giovanni » Fri Jul 12, 2019 9:27 am

Is there a command line tool that takes as input a epd or a FEN string and reports its performance in a pgn database? For performance, the white score percentage would suffice, but if it would calculates also the Elo performance would be even better.
I know that several GUIs like Scid, ChessBase, etc., already do this, but I am looking for a command line tool.
Thanks in advance.

Ferdy
Posts: 3935
Joined: Sun Aug 10, 2008 1:15 pm
Location: Philippines

Re: Position performance in a pgn database

Post by Ferdy » Sun Jul 14, 2019 9:45 am

giovanni wrote:
Fri Jul 12, 2019 9:27 am
Is there a command line tool that takes as input a epd or a FEN string and reports its performance in a pgn database? For performance, the white score percentage would suffice, but if it would calculates also the Elo performance would be even better.
I know that several GUIs like Scid, ChessBase, etc., already do this, but I am looking for a command line tool.
Thanks in advance.
This one https://github.com/mcostalba/scoutfish is capable of doing what you need.
A sample python code is available see at end of page. scoutfish.py module is inside the src folder, you need it. Also pip install pexpect.

Try this script, change the pgn filename.

Code: Select all

#!/usr/bin/env python3
"""
sc.py

"""


import time
from scoutfish import Scoutfish


def search(eng, pgn, threads=1, fen=None, res=None):
    p = Scoutfish(eng)
    p.setoption('threads', threads)  # Will use 4 threads for searching
    p.open(pgn)
    
    q = { "sub-fen": fen, "result": res }
    result = p.scout(q)
    num = result['match count']
    
    p.close()
    
    return num


def main():
    pgn = 'clean_KingBase2019-A00-A39.pgn'
    eng = 'scoutfish.exe'
    threads = 1
    
    fen = input('enter fen? ')
    
    t1 = time.perf_counter()
    res = '1-0'
    wwins = search(eng, pgn, threads, fen, res)
    
    res = '0-1'
    wloss = search(eng, pgn, threads, fen, res)
    
    res = '1/2-1/2'
    wdraw = search(eng, pgn, threads, fen, res)
    
    total = wwins + wloss + wdraw
    score = wwins + wdraw/2
    rate = score/total
    print('rate: {:0.2f}% wpov'.format(rate*100))
    print('elapsed sec: {:0.2f}'.format(time.perf_counter() - t1))


if __name__ == "__main__":
    main()
Sample run.
enter fen? rnbqkb1r/pppp1ppp/5n2/4p3/2P5/6P1/PP1PPP1P/RNBQKBNR w KQkq - 1 3
rate: 53.95% wpov
elapsed sec: 2.13

source pgn is around 250k games.

Download scoutfish.exe at https://github.com/pychess/scoutfish/releases
Place scoutfish.exe, scoutfish.py and sc.py in same folder.
Install pexpect with,
pip install pexpect

giovanni
Posts: 120
Joined: Wed Jul 08, 2015 10:30 am

Re: Position performance in a pgn database

Post by giovanni » Sun Jul 14, 2019 1:04 pm

Ferdy wrote:
Sun Jul 14, 2019 9:45 am
giovanni wrote:
Fri Jul 12, 2019 9:27 am
Is there a command line tool that takes as input a epd or a FEN string and reports its performance in a pgn database? For performance, the white score percentage would suffice, but if it would calculates also the Elo performance would be even better.
I know that several GUIs like Scid, ChessBase, etc., already do this, but I am looking for a command line tool.
Thanks in advance.
This one https://github.com/mcostalba/scoutfish is capable of doing what you need.
A sample python code is available see at end of page. scoutfish.py module is inside the src folder, you need it. Also pip install pexpect.

Try this script, change the pgn filename.

Code: Select all

#!/usr/bin/env python3
"""
sc.py

"""


import time
from scoutfish import Scoutfish


def search(eng, pgn, threads=1, fen=None, res=None):
    p = Scoutfish(eng)
    p.setoption('threads', threads)  # Will use 4 threads for searching
    p.open(pgn)
    
    q = { "sub-fen": fen, "result": res }
    result = p.scout(q)
    num = result['match count']
    
    p.close()
    
    return num


def main():
    pgn = 'clean_KingBase2019-A00-A39.pgn'
    eng = 'scoutfish.exe'
    threads = 1
    
    fen = input('enter fen? ')
    
    t1 = time.perf_counter()
    res = '1-0'
    wwins = search(eng, pgn, threads, fen, res)
    
    res = '0-1'
    wloss = search(eng, pgn, threads, fen, res)
    
    res = '1/2-1/2'
    wdraw = search(eng, pgn, threads, fen, res)
    
    total = wwins + wloss + wdraw
    score = wwins + wdraw/2
    rate = score/total
    print('rate: {:0.2f}% wpov'.format(rate*100))
    print('elapsed sec: {:0.2f}'.format(time.perf_counter() - t1))


if __name__ == "__main__":
    main()

Sample run.
enter fen? rnbqkb1r/pppp1ppp/5n2/4p3/2P5/6P1/PP1PPP1P/RNBQKBNR w KQkq - 1 3
rate: 53.95% wpov
elapsed sec: 2.13

source pgn is around 250k games.

Download scoutfish.exe at https://github.com/pychess/scoutfish/releases
Place scoutfish.exe, scoutfish.py and sc.py in same folder.
Install pexpect with,
pip install pexpect
Thanks Ferdy. Appreciated. Thanks also for drawing our attention to this very interesting tool.

Ferdy
Posts: 3935
Joined: Sun Aug 10, 2008 1:15 pm
Location: Philippines

Re: Position performance in a pgn database

Post by Ferdy » Sun Jul 14, 2019 6:52 pm

giovanni wrote:
Fri Jul 12, 2019 9:27 am
Is there a command line tool that takes as input a epd or a FEN string and reports its performance in a pgn database? For performance, the white score percentage would suffice, but if it would calculates also the Elo performance would be even better.
The module scoutfish.py can extract game headers, with that headers we can calculate the position's rating perf.
Using rating perf simple formula

Code: Select all

white elo perf = (sum_elo_black + 400 * (white_wins - white_loses)) / num_games
from https://en.wikipedia.org/wiki/Elo_ratin ... nce_rating

Make sure your games have ratings.

Sample run.

Code: Select all

enter pgn? clean_KingBase2019-A00-A39.pgn

enter fen? rnbqkb1r/pppp1ppp/5n2/4p3/2P5/6P1/PP1PPP1P/RNBQKBNR w KQkq - 1 3

pgn: clean_KingBase2019-A00-A39.pgn
FEN: rnbqkb1r/pppp1ppp/5n2/4p3/2P5/6P1/PP1PPP1P/RNBQKBNR w KQkq - 1 3
white score rate     : 53.95%
white average_rating : 2368
white Elo perf       : 2399

elapsed sec: 3.58

Revised script.

Code: Select all

#!/usr/bin/env python3
"""
sc.py

"""


import time
from scoutfish import Scoutfish


def search(eng, pgn, threads=1, fen=None, res=None):
    p = Scoutfish(eng)
    p.setoption('threads', threads)
    p.open(pgn)
    
    res_stat = []
    white_rating = []
    black_rating = []
    white_wins = 0
    white_loses = 0
    
    for r in res:
        q = { "sub-fen": fen, "result": r }
        result = p.scout(q)
        num = result['match count']
        res_stat.append(num)
        
        # Get game headers
        games = p.get_games(result['matches'])                
        headers = p.get_game_headers(games)
        for h in headers:            
            wr = int(h['WhiteElo'])
            br = int(h['BlackElo'])
            r = h['Result']
            
            if r == '1-0':
                white_wins += 1
            elif r == '0-1':
               white_loses += 1 
            
            white_rating.append(wr)
            black_rating.append(br)
    
    p.close()
    
    white_average_rating = sum(white_rating)/len(white_rating)
    num_games = len(black_rating)
    
    white_elo_perf = sum(black_rating) + 400 * (white_wins - white_loses)
    white_elo_perf = white_elo_perf/num_games
    
    return res_stat[0], res_stat[1], res_stat[2], white_average_rating, white_elo_perf


def main():
    eng = 'scoutfish.exe'
    threads = 1
    res = ['1-0', '0-1', '1/2-1/2']
    
    # pgn= 'clean_KingBase2019-A00-A39.pgn'
    # fen = 'rnbqkb1r/pppp1ppp/5n2/4p3/2P5/6P1/PP1PPP1P/RNBQKBNR w KQkq - 1 3'
    
    pgn = input('enter pgn? ')
    fen = input('enter fen? ')    
    
    t1 = time.perf_counter()
    
    wwins, wloss, wdraw, white_average_rating, white_elo_perf = \
            search(eng, pgn, threads, fen, res)
    
    total = wwins + wloss + wdraw
    score = wwins + wdraw/2
    score_rate = 100*score/total
    
    print()
    print('pgn: {}'.format(pgn))
    print('FEN: {}'.format(fen))
    print('white score rate     : {:0.2f}%'.format(score_rate))
    print('white average_rating : {:0.0f}'.format(white_average_rating))
    print('white Elo perf       : {:0.0f}'.format(white_elo_perf))
    
    print('\nelapsed sec: {:0.2f}'.format(time.perf_counter() - t1))


if __name__ == "__main__":
    main()

giovanni
Posts: 120
Joined: Wed Jul 08, 2015 10:30 am

Re: Position performance in a pgn database

Post by giovanni » Mon Jul 15, 2019 7:46 am

Nice. Thanks again, Ferdy.

Post Reply