Videon som beskriver hur Rex gör: https://www.youtube.com/watch?v=711L4ez ... n&index=64
Scriptet kommer generera excel-filer med tabeller som det bara är att klippa och klistra in i Rex excel-mallar. Det genereras en fil per barometrisk tryck som du anger i den vektorn.
Scriptet använder web-scraping för att hämta data. Det kommer att öppna ett särskillt fönster i Chrome och man kommer se hur det fyller i och ändrar variabler allteftersom det framskrider.
Så vad behöver du för att köra scriptet:
1. Ett textbehandlingsprogram för att editera pythonscriptet och ändra variabler.
2. Någon form av python-program som kan köra python script. Jag kör med Anaconda men det finns säkert fler.
3. Chromedriver drivrutin, senaste finns att ladda ner här : https://chromedriver.chromium.org/
Jag rekommenderar varmt att titta igenom scriptet först innan ni kör det så ni förstår vad det gör. Jag har försökt vara duktig med att lägga in kommentarer och förklara vad som sker. Tips är att samtidigt titta på JBM-ballistics sida så ser ni vad respektive variabel betyder.
Och sen givetvis en liten disclaimer om att eventuella fel tar jag inget ansvar för
Kod: Markera allt
# -*- coding: utf-8 -*-
"""
Created on Wed Feb 3 09:33:54 2021
@author: jthom
This script use Python SELENIUM and Chrome to connect to JBMBallistics and runs a series of
different parameters to generate excel data to be inserted into the quick sheets
for different ballistic solutions
The resulting output will be one sheet per barometric pressure
Carefully read the terms for definitions at https://www.jbmballistics.com/ballistics/calculators/help/traj_drift/traj_drift_exp.shtml
before inserting data to script
"""
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import Select
from datetime import datetime
import pandas as pd
import time
##############################################################################
# #
# Input section #
# #
##############################################################################
# Path to where chromedriver for the current version of chrome is saved
#chromedriver_path = 'C:/Users/jthom/chromedriver'
# Weblink to JBM ballistics
jbm_link = "https://www.jbmballistics.com/cgi-bin/jbmtraj_drift-5.1.cgi"
# Delay for filing in forms, fiddle with these if chromedriver says that
# it cannot "find elements"
delay_time_0 = 0.1
delay_time_1 = 0.5
delay_time_2 = 2
delay_time_3 = 5 # Wait before retry
note_comment = "Lapua D46 in Tikka T3x" # Additional message in result file
#####################################
# #
# Bullet drop and environment #
# #
#####################################
# Distance to chronograph
distance_to_chrono = 6
distance_to_chrono_unit = "m"
# Humidity
humidity = 70 # Relative [%], based on average value in Sweden according to SMHI
# Bullet drop temperature
bullet_drop_temp_v = [ -30, -20, -10, 0, 5, 10, 15, 20, 25 ]
temp_unit = "°C"
# Muzzle velocity vector - Must match number of elements in temperature vector
muzzle_velocity_v = [ 762, 762, 765, 770, 773, 777, 782, 788, 795 ]
muzzle_velocity_unit = "m/s"
# Ambient air pressure
pressure_v = [950, 970, 990, 1010, 1030, 1050] # According to SMHI
pressure_unit = "mb"
pressure_corrected = False # False = should not be checked, True = should be checked
# If a barometer is used at FFP for measureing the ambient air pressure, then use "False"
std_atm_altitude = False # False = unchecked, True = checked
# Range
ranges_in_meters = True # False = should not be checked, True = should be checked
range_zero = 100 # Range for zero
range_min = 100 # Minimum range
range_max = 1500 # Maximum range
range_inc = 10 # Range increment
range_inc_spin = 100 # Range increment for spind drift calculation
# Stop calculating the bullet drop if the bullet speed < MACH threshold value (i.e. enters transsonic)
mach_threshold_cutoff = True # True = Abort data extraction when bullet speed <= mach_threshold_value
# False = Calculate bullet drop until range_max
mach_threshold_value = 1.0 # MACH, bullet speed w.r.t. speed of sound
# Replace the calculation above with a mach table as an output, the table wil be used as input in excel for formating the
##### Auxilary tables #######
# Temperatures for auxilary tables as wind, moving target and spin drift
aux_tables_temp_v = [-30, 5, 25]
#aux_tables_muzzle_velocity_v = [762, 773, 795]
aux_tables_muzzle_velocity_v = [722, 733, 755]
# Wind
wind_speed = 10
wind_speed_unit = "m/s"
wind_angle = 90
wind_speed_default = 0
# Moving target
target_speed = 1
target_speed_unit = "m/s"
target_speed_default = 0
target_angle = 90
# Energy
energy_unit = "Energy (Joules)"
# Vital zone of target
vital_zone_radius = 30
vital_zone_radius_unit = "cm"
# Additional
target_relative_drops = False
round_output_whole_numbers = False
#####################################
# #
# Bullet input #
# #
#####################################
bullet_bc = 0.254 # Source: https://www.lapua.com/bullets/d46/
drag_model = "G7"
bullet_caliber = 0.308
bullet_caliber_unit = "in"
bullet_weight = 185
bullet_weight_unit = "gr"
bullet_length = 1.323
bullet_length_unit = "in"
plastic_tip_length = 0
plastic_tip_length_unit = "in"
#####################################
# #
# Rifle input #
# #
#####################################
sight_height = 4.9
sight_height_unit = "cm"
sight_offset = 0
sight_offset_unit = "cm"
zero_height = 0
zero_height_unit = "cm"
zero_offset = 0
zero_offset_unit = "cm"
windage = 0
windage_unit ="mil"
elevation = 0
elevation_unit = "mil"
line_sight_angle = 0
cant_angle = 0
barrel_twist = 11
barrel_twist_unit = "in"
barrel_twist_direction = "Right"
column_1_val = 0.1 # scope turret value per click
column_1_unit = "mil" # scope turret unit
column_2_val = 1
column_2_unit = "cm"
##############################################################################
# #
# Start of program #
# #
##############################################################################
#####################################
# #
# Connect to JBM ballistics & #
# set default values #
# #
#####################################
# Open Chrome
print('Opening Chrome')
driver = webdriver.Chrome(chromedriver_path)
actions = ActionChains(driver)
# Go to website
driver.get(jbm_link)
html = driver.find_element_by_tag_name('html') # Define the page, used for scrolling
print("Setting default values")
# Ballistic coefficient
driver.find_element_by_xpath('//input[@name="bc.v"]').clear()
driver.find_element_by_xpath('//input[@name="bc.v"]').send_keys(str(bullet_bc))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath("//select[@name='d_f.v']")).select_by_visible_text(drag_model)
time.sleep(delay_time_0)
# Bullet weight
driver.find_element_by_xpath('//input[@name="bt_wgt.v"]').clear()
driver.find_element_by_xpath('//input[@name="bt_wgt.v"]').send_keys(str(bullet_weight))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="bt_wgt.u"]')).select_by_visible_text(bullet_weight_unit)
time.sleep(delay_time_0)
# Bullet caliber
driver.find_element_by_xpath('//input[@name="cal.v"]').clear()
driver.find_element_by_xpath('//input[@name="cal.v"]').send_keys(str(bullet_caliber))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="cal.u"]')).select_by_visible_text(bullet_caliber_unit)
time.sleep(delay_time_0)
# Bullet length
driver.find_element_by_xpath('//input[@name="blt_len.v"]').clear()
driver.find_element_by_xpath('//input[@name="blt_len.v"]').send_keys(str(bullet_length))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="blt_len.u"]')).select_by_visible_text(bullet_length_unit)
time.sleep(delay_time_0)
# Plastic tip length
driver.find_element_by_xpath('//input[@name="tip_len.v"]').clear()
driver.find_element_by_xpath('//input[@name="tip_len.v"]').send_keys(str(plastic_tip_length))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="tip_len.u"]')).select_by_visible_text(plastic_tip_length_unit)
time.sleep(delay_time_0)
#Muzzle velocity unit
Select(driver.find_element_by_xpath('//select[@name="m_vel.u"]')).select_by_visible_text(muzzle_velocity_unit)
time.sleep(delay_time_0)
#Distance to chronograph
driver.find_element_by_xpath('//input[@name="ch_dst.v"]').clear()
driver.find_element_by_xpath('//input[@name="ch_dst.v"]').send_keys(str(distance_to_chrono))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="ch_dst.u"]')).select_by_visible_text(distance_to_chrono_unit)
time.sleep(delay_time_0)
# Sight parameters
driver.find_element_by_xpath('//input[@name="hgt_sgt.v"]').clear()
driver.find_element_by_xpath('//input[@name="hgt_sgt.v"]').send_keys(str(sight_height))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="hgt_sgt.u"]')).select_by_visible_text(sight_height_unit)
time.sleep(delay_time_0)
driver.find_element_by_xpath('//input[@name="ofs_sgt.v"]').clear()
driver.find_element_by_xpath('//input[@name="ofs_sgt.v"]').send_keys(str(sight_offset))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="ofs_sgt.u"]')).select_by_visible_text(sight_offset_unit)
time.sleep(delay_time_0)
driver.find_element_by_xpath('//input[@name="hgt_zer.v"]').clear()
driver.find_element_by_xpath('//input[@name="hgt_zer.v"]').send_keys(str(zero_height))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="hgt_zer.u"]')).select_by_visible_text(zero_height_unit)
time.sleep(delay_time_0)
driver.find_element_by_xpath('//input[@name="ofs_zer.v"]').clear()
driver.find_element_by_xpath('//input[@name="ofs_zer.v"]').send_keys(str(zero_offset))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="ofs_zer.u"]')).select_by_visible_text(zero_offset_unit)
time.sleep(delay_time_0)
driver.find_element_by_xpath('//input[@name="azm.v"]').clear()
driver.find_element_by_xpath('//input[@name="azm.v"]').send_keys(str(windage))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="azm.u"]')).select_by_visible_text(windage_unit)
time.sleep(delay_time_0)
driver.find_element_by_xpath('//input[@name="ele.v"]').clear()
driver.find_element_by_xpath('//input[@name="ele.v"]').send_keys(str(elevation))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="ele.u"]')).select_by_visible_text(elevation_unit)
time.sleep(delay_time_0)
driver.find_element_by_xpath('//input[@name="los.v"]').clear()
driver.find_element_by_xpath('//input[@name="los.v"]').send_keys(str(line_sight_angle))
time.sleep(delay_time_0)
driver.find_element_by_xpath('//input[@name="cnt.v"]').clear()
driver.find_element_by_xpath('//input[@name="cnt.v"]').send_keys(str(cant_angle))
time.sleep(delay_time_0)
# Barrel twist
driver.find_element_by_xpath('//input[@name="b_twt.v"]').clear()
driver.find_element_by_xpath('//input[@name="b_twt.v"]').send_keys(str(barrel_twist))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="b_twt.u"]')).select_by_visible_text(barrel_twist_unit)
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="b_twt_dir.v"]')).select_by_visible_text(barrel_twist_direction)
time.sleep(delay_time_0)
# Wind speed unit
Select(driver.find_element_by_xpath('//select[@name="spd_wnd.u"]')).select_by_visible_text(wind_speed_unit)
time.sleep(delay_time_0)
# Wind angle
driver.find_element_by_xpath('//input[@name="ang_wnd.v"]').clear()
driver.find_element_by_xpath('//input[@name="ang_wnd.v"]').send_keys(str(wind_angle))
time.sleep(delay_time_0)
# Target speed unit
Select(driver.find_element_by_xpath('//select[@name="spd_tgt.u"]')).select_by_visible_text(target_speed_unit)
time.sleep(delay_time_0)
# Target speed angle
driver.find_element_by_xpath('//input[@name="ang_tgt.v"]').clear()
driver.find_element_by_xpath('//input[@name="ang_tgt.v"]').send_keys(str(target_angle))
# Range
driver.find_element_by_xpath('//input[@name="rng_min.v"]').clear()
driver.find_element_by_xpath('//input[@name="rng_min.v"]').send_keys(str(range_min))
time.sleep(delay_time_0)
driver.find_element_by_xpath('//input[@name="rng_max.v"]').clear()
driver.find_element_by_xpath('//input[@name="rng_max.v"]').send_keys(str(range_max))
time.sleep(delay_time_0)
driver.find_element_by_xpath('//input[@name="rng_zer.v"]').clear()
driver.find_element_by_xpath('//input[@name="rng_zer.v"]').send_keys(str(range_zero))
time.sleep(delay_time_0)
# Temperature unit
Select(driver.find_element_by_xpath('//select[@name="tmp.u"]')).select_by_visible_text(temp_unit)
time.sleep(delay_time_0)
# Pressure unit
Select(driver.find_element_by_xpath('//select[@name="prs.u"]')).select_by_visible_text(pressure_unit)
time.sleep(delay_time_0)
# Humidity
driver.find_element_by_xpath('//input[@name="hum.v"]').clear()
driver.find_element_by_xpath('//input[@name="hum.v"]').send_keys(str(humidity))
time.sleep(delay_time_0)
# Pressure correction
pressure_box = driver.find_element_by_xpath('//input[@name="cor_prs.v"]')
if pressure_box.is_selected() != pressure_corrected: # Check if box is different from variable
pressure_box.click() #If different, click box
time.sleep(delay_time_0)
# Std atm at altitude
altitude_box = driver.find_element_by_xpath('//input[@name="std_alt.v"]')
if altitude_box.is_selected() != std_atm_altitude: # Check if box is different from variable
altitude_box.click() #If different, click box
time.sleep(delay_time_0)
# Energy unit
Select(driver.find_element_by_xpath('//select[@name="col_eng.v"]')).select_by_visible_text(energy_unit)
time.sleep(delay_time_0)
# Vital zone
driver.find_element_by_xpath('//input[@name="rad_vz.v"]').clear()
driver.find_element_by_xpath('//input[@name="rad_vz.v"]').send_keys(str(vital_zone_radius))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="rad_vz.u"]')).select_by_visible_text(vital_zone_radius_unit)
time.sleep(delay_time_0)
# Column 1
driver.find_element_by_xpath('//input[@name="col1_un.v"]').clear()
driver.find_element_by_xpath('//input[@name="col1_un.v"]').send_keys(str(column_1_val))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="col1_un.u"]')).select_by_visible_text(column_1_unit)
time.sleep(delay_time_0)
# Column 2
driver.find_element_by_xpath('//input[@name="col2_un.v"]').clear()
driver.find_element_by_xpath('//input[@name="col2_un.v"]').send_keys(str(column_2_val))
time.sleep(delay_time_0)
Select(driver.find_element_by_xpath('//select[@name="col2_un.u"]')).select_by_visible_text(column_2_unit)
time.sleep(delay_time_0)
# Ranges in meters
ranges_in_meters_box = driver.find_element_by_xpath('//input[@name="rng_un.v"]')
if ranges_in_meters_box.is_selected() != ranges_in_meters:
ranges_in_meters_box.click()
time.sleep(delay_time_0)
# Target relative drops
target_relative_drops_box = driver.find_element_by_xpath('//input[@name="def_cnt.v"]')
if target_relative_drops_box.is_selected() != target_relative_drops:
target_relative_drops_box.click()
time.sleep(delay_time_0)
# Round output to whole numbers
round_output_whole_numbers = driver.find_element_by_xpath('//input[@name="rnd_clk.v"]')
if round_output_whole_numbers.is_selected() != target_relative_drops:
round_output_whole_numbers.click()
time.sleep(delay_time_0)
#############################################################
# #
# Loop sequence #
# #
#############################################################
# Loop the pressure value
for pressure in pressure_v:
# Spin drift should not be included as a start
spin_drift_box = driver.find_element_by_xpath('//input[@name="inc_drf.v"]')
if spin_drift_box.is_selected():
spin_drift_box.click()
time.sleep(delay_time_1)
# Set pressure
print(" ")
print("Barometric pressure "+str(pressure)+" "+pressure_unit)
print(" ")
driver.find_element_by_xpath('//input[@name="prs.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="prs.v"]').send_keys(str(pressure))
time.sleep(delay_time_1)
#####################################
# #
# Bullet drop #
# #
#####################################
# Loop the bullet drop for muzzle velocity and temperature vectors assuming no wind, target speed or spin drift
print(" Calculating bullet drop for variations in muzzle velocity and temperature")
print(" ")
# Set default values for wind speed and target speed
driver.find_element_by_xpath('//input[@name="spd_wnd.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="spd_wnd.v"]').send_keys(str(wind_speed_default))
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="spd_tgt.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="spd_tgt.v"]').send_keys(str(target_speed_default))
time.sleep(delay_time_1)
# Set range increment for muzzle velocity and temperature vectors
driver.find_element_by_xpath('//input[@name="rng_inc.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="rng_inc.v"]').send_keys(str(range_inc))
time.sleep(delay_time_1)
# Result matrix
bullet_drop_result_mat = pd.DataFrame()
for i1 in range(0 , len(muzzle_velocity_v)):
try:
# Get vector values
muzzle_velocity = muzzle_velocity_v[i1]
temperature = bullet_drop_temp_v[i1]
# Set values
print(" Muzzle velocity: "+str(muzzle_velocity)+" "+muzzle_velocity_unit)
print(" Temperature: "+str(temperature)+" "+temp_unit)
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="m_vel.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="m_vel.v"]').send_keys(str(muzzle_velocity))
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="tmp.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="tmp.v"]').send_keys(str(temperature))
time.sleep(delay_time_1)
# Click "Calculate" button
driver.find_element_by_xpath('//input[@class="submit_button"]').click()
time.sleep(delay_time_2)
### Result page ###
# Define the table as a variable
output_table = driver.find_element_by_xpath('//table[@class="output_table"]/tbody')
column_df = pd.DataFrame()
range_df = pd.DataFrame()
for row_n, i2 in enumerate( output_table.find_elements_by_xpath('.//tr') , 0): #Loop through table rows
#Skip first 3 rows
if row_n < 3:
continue
#Process row for data
i4 = 0
break_i2 = False
for i3 in i2.find_elements_by_xpath('.//td'):
if i4 == 0:
range_i2 = float(i3.text)
#print(range_i2)
elif i4 == 1:
drop_clicks_i2 = abs(float(i3.text))
elif i4 == 6:
mach_i2 = float( i3.text )
# Check if the bullet enters transsonic zone. If so, abort
if mach_threshold_cutoff:
#print("Range = "+str(range_i2)+", mach = "+str(mach_i2))
if mach_i2 <= mach_threshold_value:
#print("break")
break_i2 = True
break # for i3 loop
i4 += 1
# Write row data to a df
if i1 == 0:
row_df = pd.DataFrame({"range":[range_i2] , (str(temperature)+temp_unit):[drop_clicks_i2]})
else:
row_df = pd.DataFrame({(str(temperature)+temp_unit):[drop_clicks_i2]})
# Append row df to column df
column_df = column_df.append((row_df), ignore_index = True)
# Append range value to range_df
range_df = range_df.append( (pd.DataFrame({"range":[range_i2] })), ignore_index = True)
# The last row will be appended when mach_treshold_value is reached
if break_i2:
break
# Append column to
if i1 == 0:
bullet_drop_result_mat = column_df
else:
# Append the column_df to result_mat and inrease the number of rows on result_mat
bullet_drop_result_mat = pd.concat([bullet_drop_result_mat, column_df], ignore_index=False, axis=1)
# Update the range column in result_mat
bullet_drop_result_mat["range"] = range_df
#Go back to input page
driver.find_element_by_xpath('//a[@href="/cgi-bin/jbmtraj_drift-5.1.cgi"]').click()
time.sleep(delay_time_2)
except:
print("")
print("Somethin prevents the program to continue, waiting "+str(delay_time_3)+"sec before retry")
time.sleep(delay_time_3)
#####################################
# #
# Wind speed #
# #
#####################################
# Loop the bullet drop for muzzle velocity and temperature vectors for different wind speed
print(" ")
print(" Calculating horizontal drift due to wind")
print(" ")
# Set values for wind speed
driver.find_element_by_xpath('//input[@name="spd_wnd.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="spd_wnd.v"]').send_keys(str(wind_speed))
time.sleep(delay_time_1)
# Result matrix
wind_result_mat = pd.DataFrame()
for i1 in range(0 , len(aux_tables_temp_v)):
try:
# Get vector values
muzzle_velocity = aux_tables_muzzle_velocity_v[i1]
temperature = aux_tables_temp_v[i1]
# Set values
print(" Muzzle velocity: "+str(muzzle_velocity)+" "+muzzle_velocity_unit)
print(" Temperature: "+str(temperature)+" "+temp_unit)
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="m_vel.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="m_vel.v"]').send_keys(str(muzzle_velocity))
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="tmp.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="tmp.v"]').send_keys(str(temperature))
time.sleep(delay_time_1)
# Click "Calculate" button
driver.find_element_by_xpath('//input[@class="submit_button"]').click()
time.sleep(delay_time_2)
### Result page ###
# Define the table as a variable
output_table = driver.find_element_by_xpath('//table[@class="output_table"]/tbody')
column_df = pd.DataFrame()
for row_n, i2 in enumerate( output_table.find_elements_by_xpath('.//tr') , 0): #Loop through table rows
#Skip first 3 rows
if row_n < 3:
continue
#Process row for data
i4 = 0
for i3 in i2.find_elements_by_xpath('.//td'):
if i4 == 0:
range_i2 = float(i3.text)
elif i4 == 3:
wind_clicks_i2 = abs(float( i3.text ))
# elif i4 == 6:
# mach_i2 = float( i3.text )
# elif i4 == 7:
# energy_i2 = float( i3.text )
# elif i4 == 9:
# lead_clicks_i2 = abs(float( i3.text ))
i4 += 1
# Write row data to a df
if i1 == 0:
row_df = pd.DataFrame({"range":[range_i2] , (str(temperature)+temp_unit):[wind_clicks_i2]})
else:
row_df = pd.DataFrame({(str(temperature)+temp_unit):[wind_clicks_i2]})
# Append row df to column df
column_df = column_df.append((row_df), ignore_index = True)
# Append column to
if i1 == 0:
wind_result_mat = column_df
else:
wind_result_mat[(str(temperature)+temp_unit)] = column_df
#Go back to input page
driver.find_element_by_xpath('//a[@href="/cgi-bin/jbmtraj_drift-5.1.cgi"]').click()
time.sleep(3)
except:
print("")
print("Somethin prevents the program to continue, waiting "+str(delay_time_3)+"sec before retry")
time.sleep(delay_time_3)
#####################################
# #
# Target speed #
# #
#####################################
# Loop the bullet drop for muzzle velocity and temperature vectors for different target speed
print(" ")
print(" Calculating horizontal lead for a moving target")
print(" ")
# Set default value for wind speed
driver.find_element_by_xpath('//input[@name="spd_wnd.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="spd_wnd.v"]').send_keys(str(wind_speed_default))
time.sleep(delay_time_1)
# Set default value for target speed
driver.find_element_by_xpath('//input[@name="spd_tgt.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="spd_tgt.v"]').send_keys(str(target_speed))
time.sleep(delay_time_1)
# Result matrix
target_result_mat = pd.DataFrame()
for i1 in range(0 , len(aux_tables_temp_v)):
try:
# Get vector values
muzzle_velocity = aux_tables_muzzle_velocity_v[i1]
temperature = aux_tables_temp_v[i1]
# Set values
print(" Muzzle velocity: "+str(muzzle_velocity)+" "+muzzle_velocity_unit)
print(" Temperature: "+str(temperature)+" "+temp_unit)
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="m_vel.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="m_vel.v"]').send_keys(str(muzzle_velocity))
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="tmp.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="tmp.v"]').send_keys(str(temperature))
time.sleep(delay_time_1)
# Click "Calculate" button
driver.find_element_by_xpath('//input[@class="submit_button"]').click()
time.sleep(delay_time_2)
### Result page ###
# Define the table as a variable
output_table = driver.find_element_by_xpath('//table[@class="output_table"]/tbody')
column_df = pd.DataFrame()
for row_n, i2 in enumerate( output_table.find_elements_by_xpath('.//tr') , 0): #Loop through table rows
#Skip first 3 rows
if row_n < 3:
continue
#Process row for data
i4 = 0
for i3 in i2.find_elements_by_xpath('.//td'):
if i4 == 0:
range_i2 = float(i3.text)
# elif i4 == 6:
# mach_i2 = float( i3.text )
elif i4 == 9:
lead_clicks_i2 = abs(float( i3.text ))
i4 += 1
# Write row data to a df
if i1 == 0:
row_df = pd.DataFrame({"range":[range_i2] , (str(temperature)+temp_unit):[lead_clicks_i2]})
else:
row_df = pd.DataFrame({(str(temperature)+temp_unit):[lead_clicks_i2]})
# Append row df to column df
column_df = column_df.append((row_df), ignore_index = True)
# Append column to
if i1 == 0:
target_result_mat = column_df
else:
target_result_mat[(str(temperature)+temp_unit)] = column_df
#Go back to input page
driver.find_element_by_xpath('//a[@href="/cgi-bin/jbmtraj_drift-5.1.cgi"]').click()
time.sleep(3)
except:
print("")
print("Somethin prevents the program to continue, waiting "+str(delay_time_3)+"sec before retry")
time.sleep(delay_time_3)
#####################################
# #
# Spin drift #
# #
#####################################
# Loop the bullet drop for muzzle velocity and temperature vectors for different spin drift
print(" ")
print(" Calculating horizontal drift due to spin drift")
print(" ")
# Set default value for wind speed and target speed
driver.find_element_by_xpath('//input[@name="spd_wnd.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="spd_wnd.v"]').send_keys(str(wind_speed_default))
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="spd_tgt.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="spd_tgt.v"]').send_keys(str(target_speed_default))
time.sleep(delay_time_1)
# Set range increment for muzzle velocity and temperature vectors
driver.find_element_by_xpath('//input[@name="rng_inc.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="rng_inc.v"]').send_keys(str(range_inc_spin))
time.sleep(delay_time_1)
# Activate spin drift
driver.find_element_by_xpath('//input[@name="inc_drf.v"]').click()
# Result matrix
spin_result_mat = pd.DataFrame()
for i1 in range(0 , len(aux_tables_temp_v)):
try:
# Get vector values
muzzle_velocity = aux_tables_muzzle_velocity_v[i1]
temperature = aux_tables_temp_v[i1]
# Set values
print(" Muzzle velocity: "+str(muzzle_velocity)+" "+muzzle_velocity_unit)
print(" Temperature: "+str(temperature)+" "+temp_unit)
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="m_vel.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="m_vel.v"]').send_keys(str(muzzle_velocity))
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="tmp.v"]').clear()
time.sleep(delay_time_1)
driver.find_element_by_xpath('//input[@name="tmp.v"]').send_keys(str(temperature))
time.sleep(delay_time_1)
# Click "Calculate" button
driver.find_element_by_xpath('//input[@class="submit_button"]').click()
time.sleep(delay_time_2)
### Result page ###
# Define the table as a variable
output_table = driver.find_element_by_xpath('//table[@class="output_table"]/tbody')
column_df = pd.DataFrame()
column_df_1 = pd.DataFrame()
column_df_2 = pd.DataFrame()
for row_n, i2 in enumerate( output_table.find_elements_by_xpath('.//tr') , 0): #Loop through table rows
#Skip first 3 rows
if row_n < 3:
continue
#Process row for data
i4 = 0
for i3 in i2.find_elements_by_xpath('.//td'):
if i4 == 0:
range_i2 = float(i3.text)
elif i4 == 3:
drift_clicks_i2 = abs(float( i3.text ))
elif i4 == 4:
drift_dist_i2 = abs(float( i3.text ))
i4 += 1
# Write row data to a df and add df to column df
if i1 == 0:
row_df = pd.DataFrame({"range":[range_i2] , (str(temperature)+temp_unit+" - clicks"):[drift_clicks_i2], (str(temperature)+temp_unit+" - "+column_2_unit):[drift_dist_i2]})
column_df = column_df.append((row_df), ignore_index = True)
else:
row_df_1 = pd.DataFrame({(str(temperature)+temp_unit+" - clicks"):[drift_clicks_i2]})
row_df_2 = pd.DataFrame({(str(temperature)+temp_unit+" - "+column_2_unit):[drift_dist_i2]})
column_df_1 = column_df_1.append((row_df_1), ignore_index = True)
column_df_2 = column_df_2.append((row_df_2), ignore_index = True)
# Append column to result matrix
if i1 == 0:
spin_result_mat = column_df
else:
spin_result_mat[(str(temperature)+temp_unit+" clicks")] = column_df_1
spin_result_mat[(str(temperature)+temp_unit+" - "+column_2_unit)] = column_df_2
#Go back to input page
driver.find_element_by_xpath('//a[@href="/cgi-bin/jbmtraj_drift-5.1.cgi"]').click()
time.sleep(3)
except:
print("")
print("Somethin prevents the program to continue, waiting "+str(delay_time_3)+"sec before retry")
time.sleep(delay_time_3)
#####################################
# #
# Write results to .xlsx-files #
# #
#####################################
# Write results and input data to excel-file, one file per pressure
# Variable table
var_tab = pd.DataFrame({"Variable":["Date and time", "Comment", "Bullet", "Pressure", "Pressure corrected", "Sight height", "Muzzle velocity", "Muzzle velocity auxilary tables", "Bullet drop temperatures", "Temperature auxilary tables", "Distance to chronograph", "Barrel twist", "Humidity", "Wind", "Target speed"], "Value":[(datetime.today().strftime('%Y-%m-%d - %H:%M:%S')) , (note_comment), ( "Caliber: "+str(bullet_caliber)+bullet_caliber_unit+", "+str(bullet_weight)+bullet_weight_unit+", BC: "+str(bullet_bc)+" "+drag_model+", Length: "+str(bullet_length)+bullet_length_unit), (str(pressure)+pressure_unit) , pressure_corrected, (str(sight_height)+sight_height_unit),muzzle_velocity_v, aux_tables_muzzle_velocity_v , bullet_drop_temp_v, aux_tables_temp_v, ( str(distance_to_chrono)+" "+distance_to_chrono_unit), ( str(barrel_twist)+barrel_twist_unit+", "+barrel_twist_direction), (str(humidity)+"%"), ("Wind speed default: "+str(wind_speed_default)+wind_speed_unit+", Wind speed: "+str(wind_speed)+wind_speed_unit+", Wind angle: "+str(wind_angle)+"deg"), ("Target speed default: "+str(target_speed_default)+target_speed_unit+", Target speed: "+str(target_speed)+target_speed_unit+", Target angle: "+str(target_angle)+"deg") ] })
# File name string
xls_name_str = "JBMbal_quick_sheet_"+str(pressure)+pressure_unit+"_"+datetime.today().strftime('%Y-%m-%d')+".xlsx"
# Pandas excel writer
writer = pd.ExcelWriter(xls_name_str, engine="xlsxwriter")
# Write each dataframe to a different worksheet.
var_tab.to_excel(writer, sheet_name="Input parameters")
bullet_drop_result_mat.to_excel(writer, sheet_name="Bullet drop")
wind_result_mat.to_excel(writer, sheet_name="Wind drift")
target_result_mat.to_excel(writer, sheet_name="Moving target lead")
spin_result_mat.to_excel(writer, sheet_name="Spin drift")
# Close Pands Excel writer and output the excel file
writer.save()




