3v324v23 Claude Code commited on
Commit
c6997ea
·
1 Parent(s): bacc633

Convert large Excel data files to Parquet for faster startup

Browse files

- Add convert_to_parquet.py one-time conversion script
- Convert 4 large xlsx files (~42 MB total) to parquet (~11 MB total):
qrf/db-D-interp-allT-semiclean: 12MB -> 2.4MB
qrf/mordred-descriptors: 9.8MB -> 6.7MB
quantity_module/data/db-D-interp-allT-clean: 10MB -> 2.0MB
quantity_module/data/data-descriptors-mordred-numconfs51: 9.8MB -> 23KB
quantity_module/data/solvent-viscosity, vrentas-duda-params (both sheets)
- Update qrf/functions.py and quantity_module/functions.py to use parquet
- In qrf/functions.py: replace mordred Calculator init for column names with
direct column lookup from df_desc; share a single _calc_all/_desc_by_name
at module level instead of re-creating Calculator per request in QRF_Apply
- Add pyarrow<16 to requirements.txt

Co-Authored-By: Claude Code <noreply@anthropic.com>

convert_to_parquet.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ One-time script to convert large Excel data files to Parquet format for faster loading.
3
+ Run from the repo root: python convert_to_parquet.py
4
+ """
5
+ import pandas as pd
6
+
7
+ files = [
8
+ ('qrf/db-D-interp-allT-semiclean.xlsx', 'qrf/db-D-interp-allT-semiclean.parquet', {}),
9
+ ('qrf/mordred-descriptors.xlsx', 'qrf/mordred-descriptors.parquet', {}),
10
+ ('quantity_module/data/db-D-interp-allT-clean.xlsx', 'quantity_module/data/db-D-interp-allT-clean.parquet', {}),
11
+ ('quantity_module/data/data-descriptors-mordred-numconfs51.xlsx', 'quantity_module/data/data-descriptors-mordred-numconfs51.parquet', {'usecols': ['Solute_InChIKey', 'Vabc', 'VMcGowan']}),
12
+ ('quantity_module/data/solvent-viscosity.xlsx', 'quantity_module/data/solvent-viscosity.parquet', {}),
13
+ ('quantity_module/data/vrentas-duda-params.xlsx', 'quantity_module/data/vrentas-duda-params-solutes.parquet', {'sheet_name': 'Solutes'}),
14
+ ('quantity_module/data/vrentas-duda-params.xlsx', 'quantity_module/data/vrentas-duda-params-polymers.parquet', {'sheet_name': 'Polymers'}),
15
+ ]
16
+
17
+ for src, dst, kwargs in files:
18
+ print(f'Converting {src} -> {dst} ...')
19
+ df = pd.read_excel(src, **kwargs)
20
+ # Coerce mixed-type object columns to numeric where possible so parquet can handle them
21
+ for col in df.select_dtypes(include='object').columns:
22
+ converted = pd.to_numeric(df[col], errors='coerce')
23
+ if converted.notna().sum() > 0:
24
+ df[col] = converted
25
+ df.to_parquet(dst, index=False)
26
+ print(f' done ({len(df)} rows)')
27
+
28
+ print('All conversions complete.')
qrf/db-D-interp-allT-semiclean.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:53f0371780a12bb9c70397b32e4633c8913c3439312ef1686d3f57d2854d3a08
3
+ size 2533547
qrf/functions.py CHANGED
@@ -10,12 +10,17 @@ import mordred.descriptors
10
  import rdkit
11
  from rdkit import Chem
12
 
 
 
 
 
 
13
  QRF_T_list = np.array([25,30,35,37,40,45,50,55,60,65,70,75])
14
  QRF_T_cut = 2.5
15
- df_QRF = pd.read_excel('qrf/db-D-interp-allT-semiclean.xlsx')
16
- df_desc = pd.read_excel('qrf/mordred-descriptors.xlsx')
17
- calc = mordred.Calculator(mordred.descriptors)
18
- colnames_mordred = [str(d) for d in calc.descriptors]
19
  df_QRF = pd.merge(df_QRF, df_desc[['Solute_InChIKey',*colnames_mordred]], how='left', on='Solute_InChIKey', suffixes=('', '_dupe'))
20
 
21
  @functools.lru_cache(maxsize=None)
@@ -66,9 +71,7 @@ def QRF_Apply(density, polytg, smiles, quantiles=[0.03,0.5,0.97], T=37):
66
  solute_desc_list.remove('Polymer_Tg')
67
  if 'Polymer_Density' in solute_desc_list:
68
  solute_desc_list.remove('Polymer_Density')
69
- calc_all = mordred.Calculator(mordred.descriptors)
70
- desc_strs = [str(d) for d in calc_all.descriptors]
71
- desc_funcs = {d1:df for d1 in solute_desc_list for d2,df in zip(desc_strs,calc_all.descriptors) if d1 == d2}
72
  calc = mordred.Calculator(list(desc_funcs.values()))
73
  m = Chem.MolFromSmiles(smiles)
74
  m = Chem.AddHs(m)
 
10
  import rdkit
11
  from rdkit import Chem
12
 
13
+ # Build a single shared Calculator and descriptor lookup once at startup.
14
+ # This is cheaper than re-instantiating mordred.Calculator on every request.
15
+ _calc_all = mordred.Calculator(mordred.descriptors)
16
+ _desc_by_name = {str(d): d for d in _calc_all.descriptors}
17
+
18
  QRF_T_list = np.array([25,30,35,37,40,45,50,55,60,65,70,75])
19
  QRF_T_cut = 2.5
20
+ df_QRF = pd.read_parquet('qrf/db-D-interp-allT-semiclean.parquet')
21
+ df_desc = pd.read_parquet('qrf/mordred-descriptors.parquet')
22
+ # Use column names from df_desc directly instead of initializing a full mordred Calculator
23
+ colnames_mordred = [c for c in df_desc.columns if c != 'Solute_InChIKey']
24
  df_QRF = pd.merge(df_QRF, df_desc[['Solute_InChIKey',*colnames_mordred]], how='left', on='Solute_InChIKey', suffixes=('', '_dupe'))
25
 
26
  @functools.lru_cache(maxsize=None)
 
71
  solute_desc_list.remove('Polymer_Tg')
72
  if 'Polymer_Density' in solute_desc_list:
73
  solute_desc_list.remove('Polymer_Density')
74
+ desc_funcs = {d: _desc_by_name[d] for d in solute_desc_list if d in _desc_by_name}
 
 
75
  calc = mordred.Calculator(list(desc_funcs.values()))
76
  m = Chem.MolFromSmiles(smiles)
77
  m = Chem.AddHs(m)
qrf/mordred-descriptors.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:29fb9c32fb13f69d87ecc62f092d0f394946f6fe1a05ff9917c0f9d98e7e0795
3
+ size 7064094
quantity_module/data/data-descriptors-mordred-numconfs51.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:db1d1cc6a5d310e2e2846101fb1791387ecaa6d7647dbb9cae5cac9c42671a5a
3
+ size 23818
quantity_module/data/db-D-interp-allT-clean.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3df5c08bcdcfafd3f37d4404f401f855cb6217dc2c7f1624a9bf00519663c733
3
+ size 2082818
quantity_module/data/solvent-viscosity.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:01a256c5c70979308dc15b7c433f860f72813a5859bc7720ddebad8831d6ac0d
3
+ size 9268
quantity_module/data/vrentas-duda-params-polymers.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:02cbc3415294076b364f2a1eac63b68ca2785ebf07c3b9ac203ed6c3fc8a67a2
3
+ size 10887
quantity_module/data/vrentas-duda-params-solutes.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3810ed12e5c113a7423d0769d870bd710a830808739930a7c0bb1cac30ff8ddd
3
+ size 11141
quantity_module/functions.py CHANGED
@@ -42,8 +42,8 @@ else:
42
  with open('quantity_module/data/param_distribution_allT.json','r') as fp:
43
  param_dists = json.load(fp)
44
  # other stuff
45
- df_visc = pd.read_excel('quantity_module/data/solvent-viscosity.xlsx')
46
- df_desc = pd.read_excel(f'quantity_module/data/data-descriptors-mordred-numconfs51.xlsx', usecols=['Solute_InChIKey', 'Vabc','VMcGowan'])
47
  if not use_new:
48
  ## clean data
49
  df_final_37 = pd.read_excel('quantity_module/data/db-D-interp-37-clean.xlsx')
@@ -60,7 +60,7 @@ if not use_new:
60
  df_final_50 = pd.merge(df_final_50, df_desc[['Solute_InChIKey', 'Vabc', 'VMcGowan']], how='left', on='Solute_InChIKey', suffixes=('', '_dupe'))
61
  else:
62
  ## clean data
63
- df_final = pd.read_excel('quantity_module/data/db-D-interp-allT-clean.xlsx')
64
  # convert all T to K
65
  df_final['T'] = df_final['T'] + 273.15
66
  df_final['Polymer_Tg'] = df_final['Polymer_Tg'] + 273.15
@@ -179,9 +179,9 @@ def get_V(smiles):
179
  return Vabc
180
 
181
  #### Vrentas-Duda setup
182
- df_vd_solv = pd.read_excel('quantity_module/data/vrentas-duda-params.xlsx', sheet_name='Solutes')
183
  df_vd_solv.drop_duplicates(keep='first', inplace=True, ignore_index=True) # drop exact duplicates
184
- df_vd_poly = pd.read_excel('quantity_module/data/vrentas-duda-params.xlsx', sheet_name='Polymers')
185
  df_vd_poly.drop_duplicates(keep='first', inplace=True, ignore_index=True) # drop exact duplicates
186
  df_props = pd.read_excel('data/db-polymer-properties-and-categories.xlsx')
187
  df_vd_poly = pd.merge(df_vd_poly, df_props[['Polymer_Name','Polymer_Tg','Polymer_Tm', 'CHRIS Class', 'New Class']], how='left', on='Polymer_Name')
 
42
  with open('quantity_module/data/param_distribution_allT.json','r') as fp:
43
  param_dists = json.load(fp)
44
  # other stuff
45
+ df_visc = pd.read_parquet('quantity_module/data/solvent-viscosity.parquet')
46
+ df_desc = pd.read_parquet('quantity_module/data/data-descriptors-mordred-numconfs51.parquet', columns=['Solute_InChIKey', 'Vabc','VMcGowan'])
47
  if not use_new:
48
  ## clean data
49
  df_final_37 = pd.read_excel('quantity_module/data/db-D-interp-37-clean.xlsx')
 
60
  df_final_50 = pd.merge(df_final_50, df_desc[['Solute_InChIKey', 'Vabc', 'VMcGowan']], how='left', on='Solute_InChIKey', suffixes=('', '_dupe'))
61
  else:
62
  ## clean data
63
+ df_final = pd.read_parquet('quantity_module/data/db-D-interp-allT-clean.parquet')
64
  # convert all T to K
65
  df_final['T'] = df_final['T'] + 273.15
66
  df_final['Polymer_Tg'] = df_final['Polymer_Tg'] + 273.15
 
179
  return Vabc
180
 
181
  #### Vrentas-Duda setup
182
+ df_vd_solv = pd.read_parquet('quantity_module/data/vrentas-duda-params-solutes.parquet')
183
  df_vd_solv.drop_duplicates(keep='first', inplace=True, ignore_index=True) # drop exact duplicates
184
+ df_vd_poly = pd.read_parquet('quantity_module/data/vrentas-duda-params-polymers.parquet')
185
  df_vd_poly.drop_duplicates(keep='first', inplace=True, ignore_index=True) # drop exact duplicates
186
  df_props = pd.read_excel('data/db-polymer-properties-and-categories.xlsx')
187
  df_vd_poly = pd.merge(df_vd_poly, df_props[['Polymer_Name','Polymer_Tg','Polymer_Tm', 'CHRIS Class', 'New Class']], how='left', on='Polymer_Name')
requirements.txt CHANGED
@@ -22,4 +22,5 @@ mordred==1.2.0
22
  beautifulsoup4==4.12.3
23
  setuptools==72.1.0
24
  openpyxl==3.1.5
 
25
 
 
22
  beautifulsoup4==4.12.3
23
  setuptools==72.1.0
24
  openpyxl==3.1.5
25
+ pyarrow<16
26