This commit is contained in:
prisar
2023-08-10 12:03:46 +05:30
parent 2997417440
commit aedc03561d
7 changed files with 1172 additions and 0 deletions

BIN
scripts/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
scripts/logo_nobg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

121
scripts/merge_csv.py Normal file
View File

@@ -0,0 +1,121 @@
import glob
import pandas as pd
import openpyxl
import os
from tqdm import tqdm
import platform
from PyQt5.QtWidgets import QApplication, QWidget, QFileDialog
def consolidate_and_perform_calculations(curdir, rootdir, path_delim, validation_file):
print(os.path.split(curdir)[1])
# list all csv files only
csv_files = glob.glob(curdir + path_delim + '/*.{}'.format('csv'))
if len(csv_files) == 0:
print("no csv files in the sub folder")
# print(csv_files)
df_csv_append = pd.DataFrame()
first = True
# merge the CSV files
for file in csv_files:
if first:
df_csv_append = pd.read_csv(file)
colname = file.split('.')[0].split(path_delim)[-1] #file.split('.')[0]
df_csv_append.rename(columns={'ca': colname}, inplace = True)
df_csv_append = df_csv_append.drop(['1'], axis=1)
first = False
else:
df = pd.read_csv(file)
colname = file.split('.')[0].split(path_delim)[-1] #file.split('.')[0]
df.rename(columns={'ca': colname}, inplace = True)
df = df.drop(['1'], axis=1)
df_csv_append = df_csv_append.merge(df, on='tv')
df_csv_append = df_csv_append[df_csv_append['tv'].between(300, 700)]
wavelength_col = "123_tv" # to make sorting columns simpler
df_csv_append.rename(columns={'tv': wavelength_col}, inplace = True)
df_csv_append = df_csv_append.reindex(sorted(df_csv_append.columns), axis=1)
outfile = rootdir + path_delim + os.path.split(curdir)[1] + "_analysis.xlsx"
# df_csv_append.to_excel(outfile, sheet_name="merged_data", index=False)
# df_csv_append.to_csv("D8 Merged.csv", index=False)
# calculations
df_427 = df_csv_append.loc[(df_csv_append[wavelength_col] >= 427) & (df_csv_append[wavelength_col] < 428)]
df_555 = df_csv_append.loc[(df_csv_append[wavelength_col] >= 555) & (df_csv_append[wavelength_col] < 556)]
df_validation = pd.read_excel(validation_file)
df_analysis = df_427.iloc[0] + df_555.iloc[0]
# print(df_analysis)
# print(min(df_csv_append[0:5]))
midpoint1 = 427
midpoint2 = 555
bandwidth1 = 25
bandwidth2 = 10
df = df_analysis.rename(columns = {"NM":"Wavelength","CA":"Absorbance"}, inplace = True)
# 427 nm range
df1 = df[ (df['Wavelength'] > (midpoint1-bandwidth1)) & (df['Wavelength'] < (midpoint1+bandwidth1)) ]
# 555 nm range
df2 = df[ (df['Wavelength'] > (midpoint2-bandwidth2)) & (df['Wavelength'] < (midpoint2+bandwidth2)) ]
procData.append({"Sample ID": sampleID,
"max_427": round(df1["Absorbance"].max() , 3),
"wvmax_427": round(df1.at[df1["Absorbance"].idxmax(),"Wavelength"], 3),
"avg_427": round(df1["Absorbance"].mean(), 3),
"max_555": round(df2["Absorbance"].max(), 3),
"wvmax_555": round(df2.at[df2["Absorbance"].idxmax(),"Wavelength"], 3),
"avg_555": round(df2["Absorbance"].mean(), 3),
"ratio_max": round(df2["Absorbance"].max()/df1["Absorbance"].max(), 3),
"ratio_avg": round(df2["Absorbance"].mean()/df1["Absorbance"].mean(), 3)
})
writer = pd.ExcelWriter(outfile, engine = 'openpyxl')
df_analysis.to_excel(writer, sheet_name = 'analysis', index=False)
df_csv_append.to_excel(writer, sheet_name = 'merged_data', index=False)
writer.close()
sampleID = 1
allDF = pd.DataFrame()
procData = []
if __name__ == "__main__":
environment = "dev" # dev, QC
rootdir = os.getcwd()
validation_file = rootdir + '/validation.xlsx'
if environment != "dev":
app = QApplication([])
# window = QWidget()
# layout = QVBoxLayout(window)
rootdir = QFileDialog.getExistingDirectory(None, 'Select main folder')
choose_validation_file = QFileDialog.getOpenFileName(None, "Select validation excel")
validation_file = choose_validation_file[0]
path_delim = ''
if platform.system() == 'Darwin':
path_delim = '/'
else:
path_delim = '\\'
for file in tqdm(os.listdir(rootdir)):
curdir = os.path.join(rootdir, file)
if os.path.isdir(curdir):
# os.chdir(d)
consolidate_and_perform_calculations(curdir, rootdir, path_delim, validation_file)

78
scripts/merge_csv_k.py Normal file
View File

@@ -0,0 +1,78 @@
import csv
import os
from tkinter import Tk, filedialog
def merge_csv_files(input_files, output_file):
file_contents = {}
header = ['First Column']
# Read all selected CSV files
for filepath in input_files:
filename = os.path.basename(filepath)
with open(filepath, 'r') as file:
csv_reader = csv.reader(file)
next(csv_reader) # Skip the header row
for row in csv_reader:
try:
value = float(row[0])
if 300 <= value <= 700: # Check if the value is within the range
if row[0] not in file_contents:
file_contents[row[0]] = {}
file_contents[row[0]][filename] = row[1]
if filename not in header:
header.append(filename)
except ValueError:
pass
# Write the merged contents into the output file
with open(output_file, 'w', newline='') as file:
csv_writer = csv.writer(file)
csv_writer.writerow(header)
for key, values in file_contents.items():
row = [key]
for filename in header[1:]:
row.append(values.get(filename, ''))
csv_writer.writerow(row)
print(f'Merged CSV files saved to: {output_file}')
def extract_data_from_merged_file(merged_file):
data = []
with open(merged_file, 'r') as file:
csv_reader = csv.reader(file)
header = next(csv_reader) # Get the header row
for i, row in enumerate(csv_reader, start=1):
if i in (365, 750):
extracted_row = []
for j, value in enumerate(row[1:], start=1):
column_name = header[j]
extracted_row.append((column_name, value))
data.append(extracted_row)
return data
if __name__ == "__main__":
# Create a file dialog to select multiple CSV files
root = Tk()
root.withdraw()
input_files = filedialog.askopenfilenames(title='Select CSV files', filetypes=(('CSV files', '*.csv'),))
# Ensure at least one file is selected
if input_files:
# Specify the output file path
output_file = 'merged.csv'
merge_csv_files(input_files, output_file)
extracted_data = extract_data_from_merged_file(output_file)
for row in extracted_data:
print(row)
else:
print('No files selected. Program will exit.')

View File

@@ -0,0 +1,235 @@
<!DOCTYPE html>
<html>
<head>
<style>
@media print {
body {
-webkit-print-color-adjust: exact;
}
}
.person-details-row {
display: flex;
flex-direction: row;
}
.person-details-col {
display: flex;
flex-direction: column;
height: 90px;
width: 50%;
margin: 1px;
border: 0;
}
.test-details-row {
border: 0;
}
.test-details-col {
height: 100px;
}
.test-cell-div {
/* border: 1px solid black; */
border-collapse: collapse;
height: 20px;
padding: 10px;
}
.table-header {
border: 1px solid black;
margin: 0 0 -10px 10px;
background-color: rgb(191, 191, 191);
text-align: center;
justify-content: center;
align-items: center;
display: flex;
font-weight: 600;
height: 50px;
width: 98%;
}
@media print {
.table-header {
background-color: rgb(191, 191, 191) !important;
print-color-adjust: exact;
}
}
@media print {
.vendorListHeading th {
color: white !important;
}
}
.test-method {
font-weight: 200 !important;
color: rgb(191, 191, 191);
}
.result-value {
justify-content: center;
align-items: center;
display: flex;
}
.end-of-report {
display: flex;
align-items: center;
justify-content: center;
}
.logo {
display: flex;
justify-content: center;
align-items: center;
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
ul {
list-style-type: none;
/* margin: 0; */
/* padding: 0; */
}
</style>
</head>
<body>
<div>
<div class="logo">
<img src="./logo_nobg.png" width="128" height="128" alt="sickle cell logo" />
</div>
<table style="border: 1px solid black; margin: 10px; width: 98%;">
<tr class="person-details-row">
<td class="person-details-col" style="border-right: 2; width: 70%;">
<div><strong>Name:</strong></div>
<div><strong>Age / Gender:</strong></div>
<div><strong>Sample type:</strong></div>
<div><strong>Family History of Sickle Cell Anemia:</strong></div>
</td>
<td class="person-details-col" style="width: 30%;">
<div><strong>Marital Status:</strong></div>
<div><strong>Test Date:</strong></div>
<div><strong>Patient ID:</strong></div>
<div><strong>Sample ID:</strong></div>
</td>
</tr>
</table>
</div>
<div style="height: 2px;width: 98%; background-color: rgb(56, 105, 166); margin: 30px 10px 40px 10px;"></div>
<div>
<div class="table-header">POINT OF CARE SICKLE CELL ANEMIA TEST</div>
<table class="test-details-table" style="border: 1px solid black; margin: 10px; width: 98%;">
<tr style="height: 50px;">
<th>
Test Description
</th>
<th>
RESULT
</th>
<th>
REFERENCE RANGES
</th>
</tr>
<tr class="test-details-row">
<td class="test-details-col" style="width: 20%; margin: 10px;">
<div style="margin: 10px;">Sickle Cell
Anemia
<div class="test-method">(Method: HPOS)</div>
</div>
</td>
<td style="width: 30%;">
<div class="result-value">Ra = 0.16</div>
<!-- <div class="test-cell-div">Normal</div>
<div class="test-cell-div">Sickle Cell Trait</div>
<div class="test-cell-div">Sickle Cell Disease</div>
<div class="test-cell-div">Negative Borderline</div>
<div class="test-cell-div">Positive Borderline</div> -->
</td>
<td style="width: 50%;">
<div class="test-cell-div">
< 0.16: Normal (HbA)</div>
<div class="test-cell-div">0.165 0.235: Sickle-cell Trait (HbAS)</div>
<div class="test-cell-div">> 0.24: Sickle-cell Disease (HbSS)</div>
<div class="test-cell-div">0.16-0.165: Inconclusive (Negative Borderline)</div>
<div class="test-cell-div">0.235 0.24: Inconclusive (Positive Borderline)</div>
</td>
<!-- <td style="width: 25%;">
<div class="test-cell-div">Normal</div>
<div class="test-cell-div">Sickle Cell Trait</div>
<div class="test-cell-div">Sickle Cell Disease</div>
<div class="test-cell-div">Recommended for HPLC or Electrophoresis Tests</div>
<div class="test-cell-div">Recommended for HPLC or Electrophore</div>
</td> -->
</tr>
</table>
</div>
<div>
<!-- <div style="font-weight: 600; margin: 10px;">INTERPRETATION:</div> -->
<div style="margin: 10px;">
<strong>Test Principle:</strong> This point of care quantitative diagnostic test for sickle-cell anemia
works on the principle of absorption
spectroscopy. The test helps in differentiating heterozygous/homozygous hemoglobin from normal hemoglobin.
</div>
<div style="margin: 10px;">
<strong>Method:</strong> High Performance Optical Spectroscopy (HPOS) for detection of Sickle cell trait and
sickle cell disease in whole blood capillary blood samples.
</div>
<div style="margin: 10px;">
<strong> Note:</strong>
<!-- <ul>
<li>a. Blood transfusion may have an impact on the test results.</li>
<li>
b. Patients already on sickle-cell medications may impact test results.
</li>
</ul> -->
Borderline cases are reported as inconclusive. It may occur due to several factors such as medication,
transfusion, field conditions and assay process. Further clinical tests are recommended in these cases for
diagnosis.
</div>
<!-- <div
style="margin: 80px 10px 20px 50px; width: 88%; display: flex; flex-direction: row; justify-content: space-between; align-items: center;">
<div style="margin: 5px;">DATE:</div>
<div style="margin: 5px;">Hematologist</div>
</div> -->
<!-- <div style="margin: 30px;">
This report is for the perusal of doctor only. Not for medico legal cases. Clinical correlation is
essential.
Please contact us in case of unexpected result.
</div> -->
<div style="height: 3px;width: 98%; background-color: black; margin-top: 150px;"></div>
<div class="end-of-report">
*** END OF REPORT ***</div>
<div style="display: flex; justify-content: center; align-items: center; flex-direction: column;">
<div style="font-style: italic; color: rgb(191, 191, 191);">
This is an electronically generated report. Generated at HH:MM hrs on DD-MMM-YYYY.
</div>
<div>
Note: Assay results should be correlated clinically with other clinical findings
</div>
</div>
</div>
</body>
</html>

125
scripts/single_csv.py Normal file
View File

@@ -0,0 +1,125 @@
import glob
import pandas as pd
import openpyxl
import os
from tqdm import tqdm
import platform
from PyQt5.QtWidgets import QApplication, QWidget, QFileDialog
def consolidate_and_perform_calculations(curdir, rootdir, path_delim, validation_file):
print(os.path.split(curdir)[1])
# list all csv files only
csv_files = glob.glob(curdir + path_delim + '/*.{}'.format('csv'))
if len(csv_files) == 0:
print("no csv files in the sub folder")
# print(csv_files)
df_csv_append = pd.DataFrame()
first = True
# merge the CSV files
for file in csv_files:
if first:
df_csv_append = pd.read_csv(file)
colname = file.split('.')[0].split(path_delim)[-1] #file.split('.')[0]
df_csv_append.rename(columns={'ca': colname}, inplace = True)
df_csv_append = df_csv_append.drop(['1'], axis=1)
first = False
else:
df = pd.read_csv(file)
colname = file.split('.')[0].split(path_delim)[-1] #file.split('.')[0]
df.rename(columns={'ca': colname}, inplace = True)
df = df.drop(['1'], axis=1)
df_csv_append = df_csv_append.merge(df, on='tv')
df_csv_append = df_csv_append[df_csv_append['tv'].between(300, 700)]
wavelength_col = "123_tv" # to make sorting columns simpler
df_csv_append.rename(columns={'tv': wavelength_col}, inplace = True)
df_csv_append = df_csv_append.reindex(sorted(df_csv_append.columns), axis=1)
outfile = rootdir + path_delim + os.path.split(curdir)[1] + "_analysis.xlsx"
# df_csv_append.to_excel(outfile, sheet_name="merged_data", index=False)
# df_csv_append.to_csv("D8 Merged.csv", index=False)
# calculations
df_427 = df_csv_append.loc[(df_csv_append[wavelength_col] >= 427) & (df_csv_append[wavelength_col] < 428)]
df_555 = df_csv_append.loc[(df_csv_append[wavelength_col] >= 555) & (df_csv_append[wavelength_col] < 556)]
df_validation = pd.read_excel(validation_file)
df_analysis = df_427.iloc[0] + df_555.iloc[0]
# print(df_analysis)
# print(min(df_csv_append[0:5]))
midpoint1 = 427
midpoint2 = 555
bandwidth1 = 25
bandwidth2 = 10
df = df_analysis.rename(columns = {"NM":"Wavelength","CA":"Absorbance"}, inplace = True)
# 427 nm range
df1 = df[ (df['Wavelength'] > (midpoint1-bandwidth1)) & (df['Wavelength'] < (midpoint1+bandwidth1)) ]
# 555 nm range
df2 = df[ (df['Wavelength'] > (midpoint2-bandwidth2)) & (df['Wavelength'] < (midpoint2+bandwidth2)) ]
procData.append({"Sample ID": sampleID,
"max_427": round(df1["Absorbance"].max() , 3),
"wvmax_427": round(df1.at[df1["Absorbance"].idxmax(),"Wavelength"], 3),
"avg_427": round(df1["Absorbance"].mean(), 3),
"max_555": round(df2["Absorbance"].max(), 3),
"wvmax_555": round(df2.at[df2["Absorbance"].idxmax(),"Wavelength"], 3),
"avg_555": round(df2["Absorbance"].mean(), 3),
"ratio_max": round(df2["Absorbance"].max()/df1["Absorbance"].max(), 3),
"ratio_avg": round(df2["Absorbance"].mean()/df1["Absorbance"].mean(), 3)
})
writer = pd.ExcelWriter(outfile, engine = 'openpyxl')
df_analysis.to_excel(writer, sheet_name = 'analysis', index=False)
df_csv_append.to_excel(writer, sheet_name = 'merged_data', index=False)
writer.close()
sampleID = 1
allDF = pd.DataFrame()
procData = []
if __name__ == "__main__":
file = os.getcwd() + "/D26-100umol-1.csv"
df = pd.read_csv(file)
midpoint1 = 427
midpoint2 = 555
bandwidth1 = 25
bandwidth2 = 10
df.rename(columns = {"tv":"Wavelength","ca":"Absorbance"}, inplace = True)
# 427 nm range
df1 = df[ (df['Wavelength'] > (midpoint1-bandwidth1)) & (df['Wavelength'] < (midpoint1+bandwidth1)) ]
# 555 nm range
df2 = df[ (df['Wavelength'] > (midpoint2-bandwidth2)) & (df['Wavelength'] < (midpoint2+bandwidth2)) ]
procData.append({"Sample ID": sampleID,
"max_427": round(df1["Absorbance"].max() , 3),
"wvmax_427": round(df1.at[df1["Absorbance"].idxmax(),"Wavelength"], 3),
"avg_427": round(df1["Absorbance"].mean(), 3),
"max_555": round(df2["Absorbance"].max(), 3),
"wvmax_555": round(df2.at[df2["Absorbance"].idxmax(),"Wavelength"], 3),
"avg_555": round(df2["Absorbance"].mean(), 3),
"ratio_max": round(df2["Absorbance"].max()/df1["Absorbance"].max(), 3),
"ratio_avg": round(df2["Absorbance"].mean()/df1["Absorbance"].mean(), 3)
})
print(procData)

File diff suppressed because one or more lines are too long