Position performance in a pgn database

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

Moderators: hgm, Rebel, chrisw

giovanni
Posts: 142
Joined: Wed Jul 08, 2015 12:30 pm

Position performance in a pgn database

Post by giovanni »

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: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Position performance in a pgn database

Post by Ferdy »

giovanni wrote: Fri Jul 12, 2019 11: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: 142
Joined: Wed Jul 08, 2015 12:30 pm

Re: Position performance in a pgn database

Post by giovanni »

Ferdy wrote: Sun Jul 14, 2019 11:45 am
giovanni wrote: Fri Jul 12, 2019 11: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: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Position performance in a pgn database

Post by Ferdy »

giovanni wrote: Fri Jul 12, 2019 11: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: 142
Joined: Wed Jul 08, 2015 12:30 pm

Re: Position performance in a pgn database

Post by giovanni »

Nice. Thanks again, Ferdy.