Spaces:
Running
Running
tweaks and fixed student ID
Browse files
pyproject.toml
CHANGED
|
@@ -18,7 +18,7 @@ readme = {file = "README.md", content-type = "text/markdown"}
|
|
| 18 |
dependencies = [
|
| 19 |
"numpy",
|
| 20 |
"scipy",
|
| 21 |
-
"
|
| 22 |
"matplotlib",
|
| 23 |
]
|
| 24 |
|
|
|
|
| 18 |
dependencies = [
|
| 19 |
"numpy",
|
| 20 |
"scipy",
|
| 21 |
+
"colorama",
|
| 22 |
"matplotlib",
|
| 23 |
]
|
| 24 |
|
src/pycek_public/bomb_calorimetry.py
CHANGED
|
@@ -18,6 +18,7 @@ class bomb_calorimetry(cek.cek_labs):
|
|
| 18 |
self.relaxation_time = 3
|
| 19 |
self.number_of_values = 100
|
| 20 |
self.noise_level = 0.1
|
|
|
|
| 21 |
|
| 22 |
self.slope_before = np.random.uniform(0., self.noise_level) / 3
|
| 23 |
self.slope_after = np.random.uniform(0., self.noise_level) / 3
|
|
@@ -97,6 +98,8 @@ class bomb_calorimetry(cek.cek_labs):
|
|
| 97 |
x = np.linspace(0, self.number_of_values, self.number_of_values)
|
| 98 |
y = np.random.normal(0, self.noise_level, self.number_of_values)
|
| 99 |
|
|
|
|
|
|
|
| 100 |
dd = 0.
|
| 101 |
T = self.temperature
|
| 102 |
for i in range(self.number_of_values):
|
|
@@ -107,6 +110,7 @@ class bomb_calorimetry(cek.cek_labs):
|
|
| 107 |
dd = deltaT * (1 - np.exp( - (i - self.ignition_time) / self.relaxation_time) )
|
| 108 |
y[i] += T + dd
|
| 109 |
|
|
|
|
| 110 |
self.data = np.column_stack((x,y))
|
| 111 |
|
| 112 |
return
|
|
|
|
| 18 |
self.relaxation_time = 3
|
| 19 |
self.number_of_values = 100
|
| 20 |
self.noise_level = 0.1
|
| 21 |
+
self.precision = 2
|
| 22 |
|
| 23 |
self.slope_before = np.random.uniform(0., self.noise_level) / 3
|
| 24 |
self.slope_after = np.random.uniform(0., self.noise_level) / 3
|
|
|
|
| 98 |
x = np.linspace(0, self.number_of_values, self.number_of_values)
|
| 99 |
y = np.random.normal(0, self.noise_level, self.number_of_values)
|
| 100 |
|
| 101 |
+
x = self._round_values(x,precision=0)
|
| 102 |
+
|
| 103 |
dd = 0.
|
| 104 |
T = self.temperature
|
| 105 |
for i in range(self.number_of_values):
|
|
|
|
| 110 |
dd = deltaT * (1 - np.exp( - (i - self.ignition_time) / self.relaxation_time) )
|
| 111 |
y[i] += T + dd
|
| 112 |
|
| 113 |
+
y = self._round_values(y)
|
| 114 |
self.data = np.column_stack((x,y))
|
| 115 |
|
| 116 |
return
|
src/pycek_public/cek_labs.py
CHANGED
|
@@ -19,7 +19,7 @@ class cek_labs(ABC):
|
|
| 19 |
self.NA = 6.022e23
|
| 20 |
self.temperature = 298
|
| 21 |
|
| 22 |
-
self.number_of_values =
|
| 23 |
self.output_file = None
|
| 24 |
self.filename_gen = cek.TempFilenameGenerator()
|
| 25 |
|
|
@@ -29,6 +29,7 @@ class cek_labs(ABC):
|
|
| 29 |
'output_file' : self.output_file,
|
| 30 |
})
|
| 31 |
|
|
|
|
| 32 |
self.logger_level = "ERROR"
|
| 33 |
|
| 34 |
# Define some lab specific parameters
|
|
@@ -50,6 +51,8 @@ class cek_labs(ABC):
|
|
| 50 |
# Lab specific parameters
|
| 51 |
self.setup_lab()
|
| 52 |
|
|
|
|
|
|
|
| 53 |
def __str__(self):
|
| 54 |
return f'CHEM2000 Lab: {self.__class__.__name__}'
|
| 55 |
|
|
@@ -57,6 +60,7 @@ class cek_labs(ABC):
|
|
| 57 |
if isinstance(student_ID,int):
|
| 58 |
self.student_ID = student_ID
|
| 59 |
elif isinstance(student_ID,str):
|
|
|
|
| 60 |
if student_ID.isdigit():
|
| 61 |
self.student_ID = int(student_ID)
|
| 62 |
else:
|
|
@@ -65,7 +69,7 @@ class cek_labs(ABC):
|
|
| 65 |
raise ValueError("student_ID must be an integer")
|
| 66 |
np.random.seed(self.student_ID)
|
| 67 |
self.update_metadata_from_attr()
|
| 68 |
-
self.logger.
|
| 69 |
|
| 70 |
def set_token(self, token):
|
| 71 |
self.token = token
|
|
@@ -181,6 +185,8 @@ class cek_labs(ABC):
|
|
| 181 |
# Write the kwargs as metadata
|
| 182 |
self.write_metadata(filename)
|
| 183 |
|
|
|
|
|
|
|
| 184 |
return filename
|
| 185 |
|
| 186 |
def read_data_file(self,filename=None):
|
|
@@ -226,17 +232,36 @@ class cek_labs(ABC):
|
|
| 226 |
key = key.replace("#","").strip()
|
| 227 |
metadata[key.strip()] = value.strip()
|
| 228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
# Output results
|
| 230 |
# print("Comments:")
|
| 231 |
# print("\n".join(comments))
|
| 232 |
# print("\nExtracted Data:")
|
| 233 |
# print(data_array)
|
| 234 |
return data_array, header, metadata
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
|
| 236 |
-
def process_file(self, filename=None):
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
|
| 241 |
def _valid_ID(self,ID):
|
| 242 |
if ID in ["23745411"]:
|
|
@@ -355,7 +380,8 @@ class cek_labs(ABC):
|
|
| 355 |
y += self._generate_noise(nvalues,noise_level)
|
| 356 |
|
| 357 |
if positive:
|
| 358 |
-
|
|
|
|
| 359 |
|
| 360 |
# Note: weights parameter is currently unused
|
| 361 |
if weights is not None:
|
|
|
|
| 19 |
self.NA = 6.022e23
|
| 20 |
self.temperature = 298
|
| 21 |
|
| 22 |
+
self.number_of_values = 10
|
| 23 |
self.output_file = None
|
| 24 |
self.filename_gen = cek.TempFilenameGenerator()
|
| 25 |
|
|
|
|
| 29 |
'output_file' : self.output_file,
|
| 30 |
})
|
| 31 |
|
| 32 |
+
self.make_plots = False
|
| 33 |
self.logger_level = "ERROR"
|
| 34 |
|
| 35 |
# Define some lab specific parameters
|
|
|
|
| 51 |
# Lab specific parameters
|
| 52 |
self.setup_lab()
|
| 53 |
|
| 54 |
+
self.list_of_data_files = []
|
| 55 |
+
|
| 56 |
def __str__(self):
|
| 57 |
return f'CHEM2000 Lab: {self.__class__.__name__}'
|
| 58 |
|
|
|
|
| 60 |
if isinstance(student_ID,int):
|
| 61 |
self.student_ID = student_ID
|
| 62 |
elif isinstance(student_ID,str):
|
| 63 |
+
student_ID = student_ID.strip()
|
| 64 |
if student_ID.isdigit():
|
| 65 |
self.student_ID = int(student_ID)
|
| 66 |
else:
|
|
|
|
| 69 |
raise ValueError("student_ID must be an integer")
|
| 70 |
np.random.seed(self.student_ID)
|
| 71 |
self.update_metadata_from_attr()
|
| 72 |
+
self.logger.critical(f"Initial seed = {np.random.get_state()[1][0]}")
|
| 73 |
|
| 74 |
def set_token(self, token):
|
| 75 |
self.token = token
|
|
|
|
| 185 |
# Write the kwargs as metadata
|
| 186 |
self.write_metadata(filename)
|
| 187 |
|
| 188 |
+
self.list_of_data_files.append( filename )
|
| 189 |
+
|
| 190 |
return filename
|
| 191 |
|
| 192 |
def read_data_file(self,filename=None):
|
|
|
|
| 232 |
key = key.replace("#","").strip()
|
| 233 |
metadata[key.strip()] = value.strip()
|
| 234 |
|
| 235 |
+
self.logger.debug("-"*50)
|
| 236 |
+
for k,v in metadata.items():
|
| 237 |
+
self.logger.debug(f"{k} = {v}")
|
| 238 |
+
self.logger.debug("-"*50)
|
| 239 |
# Output results
|
| 240 |
# print("Comments:")
|
| 241 |
# print("\n".join(comments))
|
| 242 |
# print("\nExtracted Data:")
|
| 243 |
# print(data_array)
|
| 244 |
return data_array, header, metadata
|
| 245 |
+
|
| 246 |
+
def _cleanup(self, pattern=None):
|
| 247 |
+
from pathlib import Path
|
| 248 |
+
for ff in self.list_of_data_files:
|
| 249 |
+
# Check if file exists before deleting
|
| 250 |
+
file_path = Path(ff)
|
| 251 |
+
if file_path.exists():
|
| 252 |
+
file_path.unlink()
|
| 253 |
+
else:
|
| 254 |
+
print("The file does not exist")
|
| 255 |
+
|
| 256 |
+
# Delete multiple files using a pattern
|
| 257 |
+
if pattern is not None:
|
| 258 |
+
for file_path in Path('.').glob(pattern):
|
| 259 |
+
file_path.unlink()
|
| 260 |
|
| 261 |
+
# def process_file(self, filename=None):
|
| 262 |
+
# self.read_data(filename)
|
| 263 |
+
# result = self.process_data()
|
| 264 |
+
# return result
|
| 265 |
|
| 266 |
def _valid_ID(self,ID):
|
| 267 |
if ID in ["23745411"]:
|
|
|
|
| 380 |
y += self._generate_noise(nvalues,noise_level)
|
| 381 |
|
| 382 |
if positive:
|
| 383 |
+
eps = np.power(10.,-self.precision)
|
| 384 |
+
y = [ max(eps,np.abs(x)) for x in y ]
|
| 385 |
|
| 386 |
# Note: weights parameter is currently unused
|
| 387 |
if weights is not None:
|
src/pycek_public/crystal_violet.py
CHANGED
|
@@ -16,7 +16,8 @@ class crystal_violet(cek.cek_labs):
|
|
| 16 |
self.expt_time = 1000
|
| 17 |
self.number_of_values = 501
|
| 18 |
self.noise_level = 0.1
|
| 19 |
-
self.precision =
|
|
|
|
| 20 |
|
| 21 |
self.activation_energy = 63e3 # J/mol
|
| 22 |
self.prefactor = 5.9e9 # 1/M/s
|
|
@@ -68,7 +69,7 @@ class crystal_violet(cek.cek_labs):
|
|
| 68 |
xspacing = 'linear',
|
| 69 |
noise_level = self.noise_level,
|
| 70 |
positive = True,
|
| 71 |
-
background =
|
| 72 |
)
|
| 73 |
|
| 74 |
return
|
|
|
|
| 16 |
self.expt_time = 1000
|
| 17 |
self.number_of_values = 501
|
| 18 |
self.noise_level = 0.1
|
| 19 |
+
self.precision = 6
|
| 20 |
+
self.background = 0.01
|
| 21 |
|
| 22 |
self.activation_energy = 63e3 # J/mol
|
| 23 |
self.prefactor = 5.9e9 # 1/M/s
|
|
|
|
| 69 |
xspacing = 'linear',
|
| 70 |
noise_level = self.noise_level,
|
| 71 |
positive = True,
|
| 72 |
+
background = self.background,
|
| 73 |
)
|
| 74 |
|
| 75 |
return
|
src/pycek_public/plotting.py
CHANGED
|
@@ -27,8 +27,21 @@ class plotting():
|
|
| 27 |
line = [line]
|
| 28 |
|
| 29 |
# Plot the observed data points as a scatter plot
|
|
|
|
| 30 |
for ds in scatter:
|
| 31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
# Add labels and title to the plot
|
| 34 |
plt.xlabel(columns[0])
|
|
|
|
| 27 |
line = [line]
|
| 28 |
|
| 29 |
# Plot the observed data points as a scatter plot
|
| 30 |
+
idx = 0
|
| 31 |
for ds in scatter:
|
| 32 |
+
if ds is not None:
|
| 33 |
+
plt.scatter(ds[:,0],ds[:,1],label="Data "+str(idx)),
|
| 34 |
+
idx += 1
|
| 35 |
+
# ymin = np.min(ds[:,1] - 0.1*np.abs(np.min(ds[:,1])))
|
| 36 |
+
# ymax = np.max(ds[:,1] + 0.1*np.abs(np.max(ds[:,1])))
|
| 37 |
+
|
| 38 |
+
# ax = plt.gca()
|
| 39 |
+
# ax.set_ylim([ymin, ymax])
|
| 40 |
+
|
| 41 |
+
for ds in line:
|
| 42 |
+
if ds is not None:
|
| 43 |
+
plt.plot(ds[:,0],ds[:,1],color='red',label="Data "+str(idx)),
|
| 44 |
+
idx += 1
|
| 45 |
|
| 46 |
# Add labels and title to the plot
|
| 47 |
plt.xlabel(columns[0])
|
src/pycek_public/statistics_lab.py
CHANGED
|
@@ -11,6 +11,8 @@ class stats_lab(cek.cek_labs):
|
|
| 11 |
columns = ["X","Y"]
|
| 12 |
)
|
| 13 |
|
|
|
|
|
|
|
| 14 |
self.available_samples = [
|
| 15 |
'Averages',
|
| 16 |
'Propagation of uncertainty',
|
|
@@ -25,7 +27,8 @@ class stats_lab(cek.cek_labs):
|
|
| 25 |
(1.0, 0.1),
|
| 26 |
(12., 2.0)
|
| 27 |
],
|
| 28 |
-
'exp_values' : (1.0,
|
|
|
|
| 29 |
}
|
| 30 |
|
| 31 |
self.sample_parameters['Propagation of uncertainty'] = {
|
|
@@ -33,6 +36,7 @@ class stats_lab(cek.cek_labs):
|
|
| 33 |
(15.0, 1.0),
|
| 34 |
(133., 2.0)
|
| 35 |
],
|
|
|
|
| 36 |
}
|
| 37 |
|
| 38 |
self.sample_parameters['Comparison of averages'] = {
|
|
@@ -40,19 +44,23 @@ class stats_lab(cek.cek_labs):
|
|
| 40 |
(15.0, 1.0),
|
| 41 |
(13.2, 2.0)
|
| 42 |
],
|
|
|
|
| 43 |
}
|
| 44 |
|
| 45 |
self.sample_parameters['Linear fit'] = {
|
| 46 |
"function" : lambda x,m,q: m*x + q,
|
| 47 |
"gen_values" : {'m':12.3 , 'q':1.0},
|
| 48 |
-
"xrange" : [0.0 , 10.0]
|
|
|
|
|
|
|
| 49 |
}
|
| 50 |
|
| 51 |
self.sample_parameters['Non linear fit'] = {
|
| 52 |
"nval" : 10,
|
| 53 |
"function" : lambda x,E0,K0,Kp,V0: E0 + K0 * x / Kp * ( (V0/x)**Kp / (Kp-1)+1) - K0*V0/(Kp-1),
|
| 54 |
"gen_values" : {"E0":-634.2, "K0":12.43, "Kp":4.28, "V0":99.11},
|
| 55 |
-
"xrange" : [50 , 140]
|
|
|
|
| 56 |
}
|
| 57 |
|
| 58 |
self.sample_parameters['Detection of outliers'] = {
|
|
@@ -60,6 +68,7 @@ class stats_lab(cek.cek_labs):
|
|
| 60 |
"gen_values" : {'m':2.3 , 'q':0.1},
|
| 61 |
"xrange" : [10.0 , 20.0],
|
| 62 |
"shift" : 2,
|
|
|
|
| 63 |
}
|
| 64 |
|
| 65 |
def create_data(self):
|
|
@@ -75,6 +84,9 @@ class stats_lab(cek.cek_labs):
|
|
| 75 |
number_of_values = self.number_of_values,
|
| 76 |
)
|
| 77 |
|
|
|
|
|
|
|
|
|
|
| 78 |
if "noise" in prm:
|
| 79 |
self.set_parameters( noise_level = prm["noise"] )
|
| 80 |
|
|
@@ -87,6 +99,8 @@ class stats_lab(cek.cek_labs):
|
|
| 87 |
data = self._generate_normal_random(self.number_of_values, prm['gen_values'])
|
| 88 |
|
| 89 |
elif self.sample in ["Linear fit"]:
|
|
|
|
|
|
|
| 90 |
data = self.generate_data_from_function(
|
| 91 |
prm["function"],
|
| 92 |
prm['gen_values'],
|
|
@@ -96,6 +110,8 @@ class stats_lab(cek.cek_labs):
|
|
| 96 |
)
|
| 97 |
|
| 98 |
elif self.sample in ["Non linear fit"]:
|
|
|
|
|
|
|
| 99 |
data = self.generate_data_from_function(
|
| 100 |
prm["function"],
|
| 101 |
prm['gen_values'],
|
|
@@ -115,7 +131,6 @@ class stats_lab(cek.cek_labs):
|
|
| 115 |
i = np.random.randint(self.number_of_values)
|
| 116 |
data[i,1] += prm['shift']
|
| 117 |
|
| 118 |
-
|
| 119 |
self.data = data
|
| 120 |
return data
|
| 121 |
|
|
|
|
| 11 |
columns = ["X","Y"]
|
| 12 |
)
|
| 13 |
|
| 14 |
+
self.number_of_values = 10
|
| 15 |
+
|
| 16 |
self.available_samples = [
|
| 17 |
'Averages',
|
| 18 |
'Propagation of uncertainty',
|
|
|
|
| 27 |
(1.0, 0.1),
|
| 28 |
(12., 2.0)
|
| 29 |
],
|
| 30 |
+
'exp_values' : (1.0,10.0),
|
| 31 |
+
"precision" : 3,
|
| 32 |
}
|
| 33 |
|
| 34 |
self.sample_parameters['Propagation of uncertainty'] = {
|
|
|
|
| 36 |
(15.0, 1.0),
|
| 37 |
(133., 2.0)
|
| 38 |
],
|
| 39 |
+
"precision" : 3,
|
| 40 |
}
|
| 41 |
|
| 42 |
self.sample_parameters['Comparison of averages'] = {
|
|
|
|
| 44 |
(15.0, 1.0),
|
| 45 |
(13.2, 2.0)
|
| 46 |
],
|
| 47 |
+
"precision" : 3,
|
| 48 |
}
|
| 49 |
|
| 50 |
self.sample_parameters['Linear fit'] = {
|
| 51 |
"function" : lambda x,m,q: m*x + q,
|
| 52 |
"gen_values" : {'m':12.3 , 'q':1.0},
|
| 53 |
+
"xrange" : [0.0 , 10.0],
|
| 54 |
+
"exp_values" : 11.3,
|
| 55 |
+
"precision" : 3,
|
| 56 |
}
|
| 57 |
|
| 58 |
self.sample_parameters['Non linear fit'] = {
|
| 59 |
"nval" : 10,
|
| 60 |
"function" : lambda x,E0,K0,Kp,V0: E0 + K0 * x / Kp * ( (V0/x)**Kp / (Kp-1)+1) - K0*V0/(Kp-1),
|
| 61 |
"gen_values" : {"E0":-634.2, "K0":12.43, "Kp":4.28, "V0":99.11},
|
| 62 |
+
"xrange" : [50 , 140],
|
| 63 |
+
"precision" : 3,
|
| 64 |
}
|
| 65 |
|
| 66 |
self.sample_parameters['Detection of outliers'] = {
|
|
|
|
| 68 |
"gen_values" : {'m':2.3 , 'q':0.1},
|
| 69 |
"xrange" : [10.0 , 20.0],
|
| 70 |
"shift" : 2,
|
| 71 |
+
"precision" : 3,
|
| 72 |
}
|
| 73 |
|
| 74 |
def create_data(self):
|
|
|
|
| 84 |
number_of_values = self.number_of_values,
|
| 85 |
)
|
| 86 |
|
| 87 |
+
if "precision" in prm:
|
| 88 |
+
self.set_parameters( precision = prm["precision"] )
|
| 89 |
+
|
| 90 |
if "noise" in prm:
|
| 91 |
self.set_parameters( noise_level = prm["noise"] )
|
| 92 |
|
|
|
|
| 99 |
data = self._generate_normal_random(self.number_of_values, prm['gen_values'])
|
| 100 |
|
| 101 |
elif self.sample in ["Linear fit"]:
|
| 102 |
+
self.noise_level = 5
|
| 103 |
+
|
| 104 |
data = self.generate_data_from_function(
|
| 105 |
prm["function"],
|
| 106 |
prm['gen_values'],
|
|
|
|
| 110 |
)
|
| 111 |
|
| 112 |
elif self.sample in ["Non linear fit"]:
|
| 113 |
+
self.noise_level = 5
|
| 114 |
+
|
| 115 |
data = self.generate_data_from_function(
|
| 116 |
prm["function"],
|
| 117 |
prm['gen_values'],
|
|
|
|
| 131 |
i = np.random.randint(self.number_of_values)
|
| 132 |
data[i,1] += prm['shift']
|
| 133 |
|
|
|
|
| 134 |
self.data = data
|
| 135 |
return data
|
| 136 |
|
src/pycek_public/surface_adsorption.py
CHANGED
|
@@ -25,7 +25,7 @@ class surface_adsorption(cek.cek_labs):
|
|
| 25 |
}
|
| 26 |
|
| 27 |
self.number_of_values = 100
|
| 28 |
-
self.noise_level =
|
| 29 |
self.precision = 10
|
| 30 |
|
| 31 |
def create_data(self):
|
|
@@ -38,7 +38,7 @@ class surface_adsorption(cek.cek_labs):
|
|
| 38 |
)
|
| 39 |
|
| 40 |
self.add_metadata(**{
|
| 41 |
-
"Temperature (
|
| 42 |
"Volume (L)" : self.volume,
|
| 43 |
"Molar mass (g/mol)" : self.sample_parameters["molarMass"],
|
| 44 |
"MinDye (mg)" : self.minDye,
|
|
@@ -65,19 +65,6 @@ class surface_adsorption(cek.cek_labs):
|
|
| 65 |
)
|
| 66 |
|
| 67 |
self.data[:,0] *= conversion_factor
|
| 68 |
-
# grams of dye added
|
| 69 |
-
# x = np.linspace(self.minDye, self.maxDye, self.number_of_values) / 1000
|
| 70 |
-
# moles = x / self.params["molarMass"] # g
|
| 71 |
-
# initial_concentration = moles / self.volume # mol/L
|
| 72 |
-
# y = self.measure(K, self.params["Q"], initial_concentration)
|
| 73 |
-
|
| 74 |
-
# # Because noise is added to the concentration in solution, but
|
| 75 |
-
# # the concentration on the surface is required in post-processing, which
|
| 76 |
-
# # is very small, we divide by 1000
|
| 77 |
-
|
| 78 |
-
# y = cek.add_noise(y, self.uncertainty/1000)
|
| 79 |
-
|
| 80 |
-
# data_array = np.column_stack((x, y))
|
| 81 |
|
| 82 |
return self.data
|
| 83 |
|
|
|
|
| 25 |
}
|
| 26 |
|
| 27 |
self.number_of_values = 100
|
| 28 |
+
self.noise_level = 0.5e-5
|
| 29 |
self.precision = 10
|
| 30 |
|
| 31 |
def create_data(self):
|
|
|
|
| 38 |
)
|
| 39 |
|
| 40 |
self.add_metadata(**{
|
| 41 |
+
"Temperature (C)" : self.temperature - 273.15,
|
| 42 |
"Volume (L)" : self.volume,
|
| 43 |
"Molar mass (g/mol)" : self.sample_parameters["molarMass"],
|
| 44 |
"MinDye (mg)" : self.minDye,
|
|
|
|
| 65 |
)
|
| 66 |
|
| 67 |
self.data[:,0] *= conversion_factor
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
return self.data
|
| 70 |
|