10 Commits

Author SHA1 Message Date
“Roman 3654094ac8 latest changes as of 2024-06-07 2024-06-07 09:42:02 +02:00
“Roman 1a740fb7f7 Merge branch 'master' into slab
Merge master into SLAB to add new functionalities
2023-10-10 16:49:51 +02:00
“Roman 0e967e3129 added sample environment sensors, Janis closed cycle temperature controller and improved startup 2023-10-10 16:40:58 +02:00
“Roman 59b893f2f6 added stages 2022-09-29 13:49:49 +02:00
“Roman eae088fbba Added sorting of shots by chopper 2022-08-08 17:52:52 +02:00
“Roman 369af41197 optimized callback function of ioxos daq 2022-06-10 17:47:48 +02:00
“Roman 17fdef6f97 included new file 2022-06-10 10:25:20 +02:00
“Roman d5afaff9bd first version of 1kHz ioxos daq 2022-06-09 23:47:57 +02:00
“Roman 789af96508 merging from masteer 2022-06-08 17:35:59 +02:00
“Roman 63857f908b first commit 2022-06-08 17:05:03 +02:00
11 changed files with 656 additions and 10 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ import time
class EpicsDaq: class EpicsDaq:
def __init__( def __init__(
self, self,
default_file_path="%s", default_file_path="",
elog=None, elog=None,
name=None, name=None,
channel_list=None, channel_list=None,
+276
View File
@@ -0,0 +1,276 @@
import numpy as np
import h5py
from epics import PV
import os
import datetime
from threading import Thread
from time import sleep
from pathlib import Path
from .utilities import Acquisition
import time
from eco.elements.assembly import Assembly
from eco.elements.adjustable import AdjustableFS
from eco.epics.adjustable import AdjustablePv, AdjustablePvEnum
class IoxosChannel(Assembly):
def __init__(
self,
pvbase = "SLAB-LSCP1-ESB1",
name=None,
ch=None,
):
super().__init__(name=name)
self.pvbase = pvbase
self._append(AdjustablePv, self.pvbase + f":CH{ch}:BSTART_NEW", name = "bg_start", is_setting=True)
self._append(AdjustablePv, self.pvbase + f":CH{ch}:BEND_NEW", name = "bg_end", is_setting=True)
self._append(AdjustablePv, self.pvbase + f":CH{ch}:START_NEW", name = "sig_start", is_setting=True)
self._append(AdjustablePv, self.pvbase + f":CH{ch}:END_NEW", name = "sig_end", is_setting=True)
self._append(AdjustablePvEnum, self.pvbase + f":BOX_STAT{ch}", name = "boxcar_calculation", is_setting=True)
self._append(AdjustableFS, f"/sf/slab/config/eco/reference_values/ioxos_{name}_chopper_ch", name="chopper_ch", is_setting=True, default_value=0)
self._append(AdjustableFS, f"/sf/slab/config/eco/reference_values/ioxos_{name}_chopper_thr", name="chopper_thr", is_setting=True, default_value=1000)
self._append(AdjustableFS, f"/sf/slab/config/eco/reference_values/ioxos_{name}_chopper_inv", name="chopper_inv", is_setting=True, default_value=True)
class Slab_Ioxos(Assembly):
def __init__(
self,
name=None,
pvbase = "SLAB-LSCP1-ESB1",
):
super().__init__(name=name)
self.pvbase= pvbase
self._append(AdjustablePv, self.pvbase + ":BOX_RESTART.PROC", name="restart", is_setting=False)
self._append(AdjustablePv, self.pvbase + ":BOX_SAMS_IN_ARRAY", name="samples", is_setting=True)
self._append(AdjustablePv, self.pvbase + ":BOX_BLOCKS_TO_SEND", name="blocks", is_setting=True)
self._append(AdjustablePvEnum, self.pvbase + ":BOX_INARRAY", name="active_channels", is_setting=True)
self._append(AdjustablePv, self.pvbase + ":BOX_FREQ", name="trigger_rate", is_setting=False)
self._append(AdjustablePv, self.pvbase + f":TRIGGER:MINACQINTERVAL:1", name = "trigger_waittime", is_setting=True)
self._append(AdjustablePv, "SLAB-CVME-ESB1:SYS_CPU_LOAD", name="cpu_load", is_setting=False, is_display=True)
self.samples(10)
self.blocks(0)
self.restart(1)
self.active_channels(7)
self.trigger_waittime(0)
self.data = PV("SLAB-LSCP1-ESB1:BOX_DATA", auto_monitor=True)
for ch in range(8):
self._append(IoxosChannel, pvbase=self.pvbase, name=f"ch{ch}", ch=ch, is_setting=False, is_display=False,)
class Slab_Ioxos_Daq(Assembly):
def __init__(
self,
default_file_path="",
name=None,
ioxos = None,
):
super().__init__(name=name)
self.ioxos = ioxos
self._append(AdjustableFS, "/sf/slab/config/eco/reference_values/ioxos_daq_single_shots", name="save_single_shots", is_setting=True)
self._done = False
self._default_file_path = default_file_path
self._N_acqs = 0
self._data = np.zeros((0,))
self._meta_len = 12
def cb_get_data(*args, **kwargs):
if self._N_acqs > 0:
d = kwargs["value"][self._meta_len:]
idx0 = self._data.shape[0]-self._N_acqs*d.shape[0]
idx1 = self._data.shape[0]-(self._N_acqs-1)*d.shape[0]
self._data[idx0:idx1] = d
self._N_acqs = self._N_acqs - 1
self.ioxos.data.add_callback(callback = cb_get_data)
def get_data(self, N_pulses=None):
N_channels = 8
if N_pulses > 10:
N_acqs = N_pulses // 10
else:
N_pulses=10
N_acqs = 1
self._data=np.zeros((N_channels*N_pulses))
self._N_acqs = N_acqs
while(True):
if self._N_acqs == 0:
break
sleep(.001)
return self._data.reshape((N_pulses, N_channels)).T
def save_single(self, file_name, data):
if os.path.isfile(file_name):
print(f"!!! File {file_name} already exists, would you like to delete it?")
if input("(y/n)") == "y":
print(f"Deleting {file_name} .")
os.remove(file_name)
else:
return
N_channels = data.shape[0]
d = {f"ch{n}": data[n] for n in range(N_channels)}
np.savez_compressed(file_name, **d)
fp = Path(file_name)
fp.chmod(0o775)
def save_av(self, file_name, data, adjs_rb, adjs_name, N_pulses):
chopper_chs = [self.ioxos.__dict__[f"ch{n}"].chopper_ch() for n in range(8)]
chopper_thrs = [self.ioxos.__dict__[f"ch{n}"].chopper_thr() for n in range(8)]
chopper_invs = [self.ioxos.__dict__[f"ch{n}"].chopper_inv() for n in range(8)]
w = np.array([data[ch]<thr if inv else data[ch]>thr for ch, thr, inv in zip(chopper_chs, chopper_thrs, chopper_invs)])
d_av_on = np.mean(data, axis=1, where=w)
d_av_off = np.mean(data, axis=1, where=~w)
d_std_on = np.std(data, axis=1, where=w)
d_std_off = np.std(data, axis=1, where=~w)
d_npulses_on = np.sum(w, axis=1)
d_npulses_off = np.sum(~w, axis=1)
filename_av = file_name.split("_step")[0] + ".txt"
d = np.hstack([adjs_rb, d_av_on, d_av_off, d_std_on, d_std_off, d_npulses_on, d_npulses_off])
exists = os.path.isfile(filename_av)
with open(filename_av, "a") as f:
if exists:
np.savetxt(f,[d])
else:
head = [f"{n}, " for n in adjs_name]
head.extend([f"ch{n}_on, " for n in range(8)])
head.extend([f"ch{n}_off, " for n in range(8)])
head.extend([f"ch{n}_on_std, " for n in range(8)])
head.extend([f"ch{n}_off_std, " for n in range(8)])
head.extend([f"ch{n}_on_npulses, " for n in range(8)])
head.extend([f"ch{n}_off_npulses, " for n in range(8)])
header = "".join(head)
np.savetxt(f,[d],header=header)
fp = Path(filename_av)
fp.chmod(0o775)
def acquire(self, file_name=None, N_pulses=100, adjs_rb = [], adjs_name=[], default_path=True):
file_name += ".npz"
if default_path:
file_name = self._default_file_path + file_name
data_dir = Path(os.path.dirname(file_name))
if not data_dir.exists():
print(
f"Path {data_dir.absolute().as_posix()} does not exist, will try to create it..."
)
data_dir.mkdir(parents=True)
print(f"Tried to create {data_dir.absolute().as_posix()}")
data_dir.chmod(0o775)
print(f"Tried to change permissions to 775")
def acquire():
d = self.get_data(N_pulses = N_pulses)
self.save_av(file_name, d, adjs_rb, adjs_name, N_pulses)
if self.save_single_shots():
self.save_single(file_name=file_name, data=d)
return Acquisition(
acquire=acquire,
acquisition_kwargs={"file_names": [file_name], "N_pulses": N_pulses, "adjs_rb": adjs_rb, "adjs_name": adjs_name},
hold=False,
)
def wait_done(self):
self.check_running()
self.check_still_running()
class Epicstools:
def __init__(
self,
default_channel_list={"listname": []},
default_file_path="%s",
elog=None,
name=None,
channel_list=None,
):
self.name = name
self._default_file_path = default_file_path
self._default_channel_list = default_channel_list
self._elog = elog
self.channels = []
self.pulse_id = PV("SLAAR11-LTIM01-EVR0:RX-PULSEID")
if not channel_list:
print("No channels specified, using all lists instead.")
channel_list = []
for tlist in self._default_channel_list.values():
channel_list.extend(tlist)
else:
self.channel_list = channel_list
for channel in self.channel_list:
self.channels.append(PV(channel, auto_monitor=True))
def h5(self, fina=None, channel_list=None, N_pulses=None, queue_size=100):
channel_list = self.channel_list
if os.path.isfile(fina):
print("!!! File %s already exists, would you like to delete it?" % fina)
if input("(y/n)") == "y":
print("Deleting %s ." % fina)
os.remove(fina)
else:
return
data = []
counters = []
channels = self.channels
for channel in channels:
channelval = channel.value
if type(channelval) == np.ndarray:
shape = (N_pulses,) + channelval.shape
dtype = channelval.dtype
else:
shape = (N_pulses,)
dtype = type(channelval)
data.append(np.ndarray(shape, dtype=dtype))
counters.append(0)
def cb_getdata(ch=None, m=0, *args, **kwargs):
data[m][counters[m]] = kwargs["value"]
counters[m] = counters[m] + 1
if counters[m] == N_pulses:
ch.clear_callbacks()
for (m, channel) in enumerate(channels):
channel.add_callback(callback=cb_getdata, ch=channel, m=m)
while True:
sleep(0.005)
if np.mean(counters) == N_pulses:
break
f = h5py.File(name=fina, mode="w")
for (n, channel) in enumerate(channel_list):
dat = f.create_group(name=channel)
dat.create_dataset(name="data", data=data[n])
dat.create_dataset(
name="pulse_id", data=np.arange(N_pulses) + round(time.time() * 100)
)
return data
def acquire(self, file_name=None, Npulses=100, default_path=True):
file_name += ".h5"
if default_path:
file_name = self._default_file_path + file_name
data_dir = Path(os.path.dirname(file_name))
if not data_dir.exists():
print(
f"Path {data_dir.absolute().as_posix()} does not exist, will try to create it..."
)
data_dir.mkdir(parents=True)
print(f"Tried to create {data_dir.absolute().as_posix()}")
data_dir.chmod(0o775)
print(f"Tried to change permissions to 775")
def acquire():
self.h5(fina=file_name, N_pulses=Npulses)
return Acquisition(
acquire=acquire,
acquisition_kwargs={"file_names": [file_name], "Npulses": Npulses},
hold=False,
)
def wait_done(self):
self.check_running()
self.check_still_running()
+3
View File
@@ -9,6 +9,7 @@ import colorama
from ..elements.adjustable import DummyAdjustable from ..elements.adjustable import DummyAdjustable
from IPython import get_ipython from IPython import get_ipython
from .daq_client import Daq from .daq_client import Daq
from .ioxos_slab import Slab_Ioxos_Daq
from eco.elements.assembly import Assembly from eco.elements.assembly import Assembly
from rich.progress import Progress from rich.progress import Progress
@@ -215,6 +216,8 @@ class Scan:
acq = ctr.acquire( acq = ctr.acquire(
file_name=fina, Npulses=self.pulses_per_step[0], acq_pars=acq_pars file_name=fina, Npulses=self.pulses_per_step[0], acq_pars=acq_pars
) )
elif isinstance(ctr, Slab_Ioxos_Daq):
acq = ctr.acquire(file_name=fina, N_pulses=self.pulses_per_step[0], adjs_rb=readbacks_step, adjs_name=[adj.name for adj in self.adjustables])
else: else:
acq = ctr.acquire(file_name=fina, Npulses=self.pulses_per_step[0]) acq = ctr.acquire(file_name=fina, Npulses=self.pulses_per_step[0])
acs.append(acq) acs.append(acq)
View File
+4 -2
View File
@@ -2,8 +2,10 @@ import numpy as np
from epics import caget from epics import caget
from epics import PV from epics import PV
from eco.epics.utilities_epics import EnumWrapper from eco.epics.utilities_epics import EnumWrapper
try:
from bsread import source, SUB from bsread import source, SUB
except:
pass
import subprocess import subprocess
import h5py import h5py
from time import sleep from time import sleep
@@ -0,0 +1,49 @@
from ..aliases import Alias, append_object_to_object
from ..elements.adjustable import AdjustableVirtual, AdjustableGetSet, value_property
from ..epics.adjustable import AdjustablePv, AdjustablePvEnum
from ..elements.assembly import Assembly
class Lakeshore_331(Assembly):
def __init__(self, pvname, name=None):
super().__init__(name=name)
self.pvname = pvname
self._append(
AdjustablePv,
pvsetname = "SLAB-LLS-UNIT1:HT-LVL_RBV",
pvreadbackname = "SLAB-LLS-UNIT1:HT-LVL_RBV",
accuracy = 0.5,
name="heater_level",
is_display=True,
is_setting=False,
)
self._append(
AdjustablePv,
pvsetname = f"{self.pvname}:TEMP.VAL",
pvreadbackname = f"{self.pvname}:TEMP_RBV",
accuracy = 0.5,
name="temperature",
is_display=True,
is_setting=True,
)
self._append(
AdjustablePvEnum,
pvname = self.pvname + ":CONN",
name="connect",
is_setting=True,
is_display=False,
)
self._append(
AdjustablePvEnum,
pvname = self.pvname + ":HT-RNG_RBV",
pvname_set = self.pvname + ":HT-RNG",
name="heater_range",
is_setting=True,
is_display=True,
)
self._append(
AdjustablePvEnum,
pvname = self.pvname + ":MODE_RBV",
pvname_set = self.pvname + ":MODE",
name="operation",
is_setting=True,
is_display=True,
)
+1 -1
View File
@@ -795,7 +795,7 @@ class Tweak:
self.thread = None self.thread = None
def print(self): def print(self):
if self.thread and self.thread.isAlive(): if self.thread and self.thread.is_alive():
return return
else: else:
self.thread = Thread(target=self.print_foo) self.thread = Thread(target=self.print_foo)
+41
View File
@@ -0,0 +1,41 @@
from ..epics.detector import DetectorPvDataStream
from ..elements.assembly import Assembly
class Env_Sensors(Assembly):
def __init__(self, name=None):
super().__init__(name=name)
self._append(
DetectorPvDataStream,
"SLAB-LI2C01_CH1:TEMP",
name="sens1_temperature",
)
self._append(
DetectorPvDataStream,
"SLAB-LI2C01_CH1:HUMIREL",
name="sens1_humidity",
)
self._append(
DetectorPvDataStream,
"SLAB-LI2C01_CH1:PRES",
name="sens1_pressure"
)
self._append(
DetectorPvDataStream,
"SLAB-LI2C01_CH2:TEMP",
name="sens2_temperature",
)
self._append(
DetectorPvDataStream,
"SLAB-LI2C01_CH2:HUMIREL",
name="sens2_humidity",
)
self._append(
DetectorPvDataStream,
"SLAB-LI2C01_CH2:PRES",
name="sens2_pressure"
)
self._append(
DetectorPvDataStream,
"SLAB-LI2C01_CH3:TEMP",
name="pt100_temperature",
)
+2
View File
@@ -0,0 +1,2 @@
from .slab import *
+263
View File
@@ -0,0 +1,263 @@
from ..utilities.config import Namespace, Configuration
from ..aliases import NamespaceCollection
import pyttsx3
from ..utilities.path_alias import PathAlias
import os
from pathlib import Path
import shutil
from eco.elements.adj_obj import AdjustableObject
from eco.elements.adjustable import AdjustableFS
### set pgroup from user input ###
exp_path = Path("/sf/slab/exp/")
exps = [[p.stem, p.resolve().stem] for p in exp_path.glob("*")]
idx = ''
input_message = "Select the pgroup of the experiment:\n"
for index, (expname, pgroup) in enumerate(exps):
input_message += f'{index:2}) {expname:10} ({pgroup})\n'
input_message += 'Your choice:'
while idx not in range(len(exps)):
try:
idx = int(input(input_message))
except:
continue
print(f'Selected experiment: {exps[idx][0]} {(exps[idx][1])}')
pgroup = exps[idx][1]
os.sys.path.insert(0,"/sf/slab/config/src/python/py_scilog")
_eco_lazy_init = False
cfg_path = Path(f"/sf/slab/config/eco/{pgroup}_slab_config_eco.json")
if not cfg_path.exists():
shutil.copy2("/sf/slab/config/eco/slab_config_eco.json", cfg_path.as_posix())
_config = AdjustableFS(
cfg_path.as_posix(), name="_config"
)
path_aliases = PathAlias()
namespace = Namespace(
name="slab", root_module=__name__, alias_namespace=NamespaceCollection().slab
)
namespace.alias_namespace.data = []
namespace.append_obj(AdjustableObject, _config, name="config")
# Adding stuff that might be relevant for stuff configured below (e.g. config)
config.pgroup(pgroup)
namespace.append_obj(
"set_global_memory_dir",
"/sf/slab/config/eco/memory",
module_name="eco.elements.memory",
name="path_memory",
)
namespace.append_obj(
"DataApi",
name="archiver",
module_name="eco.dbase.archiver",
pv_pulse_id="SARES20-CVME-01-EVR0:RX-PULSEID",
add_to_cnf=True,
lazy=False,
)
namespace.append_obj(
"Slab_Ioxos",
name="ioxos",
module_name="eco.acquisition.ioxos_slab",
pvbase="SLAB-LSCP1-ESB1",
lazy=True,
)
#f"/sf/bernina/data/{config['pgroup']}/res/",
namespace.append_obj(
"Slab_Ioxos_Daq",
name="daq",
module_name="eco.acquisition.ioxos_slab",
default_file_path=f'/sf/slab/data/{config.pgroup()}/res/',
#default_file_path=f'/sf/slab/config/eco/test_acq/',
ioxos=ioxos,
lazy=True,
)
## Utilities
namespace.append_obj(
"Run_Table2",
name="run_table",
module_name="eco.utilities.runtable",
exp_id= config.pgroup(),
folder_id= "1n10Sfib-P9xqUhIQ0UuYUEkb_DpY3pcd",
exp_path= f"/sf/slab/data/{config.pgroup()}/res/run_table/",
#exp_path= f"/sf/slab/config/eco/test_acq/",
devices= "slab",
keydf_fname= "/sf/slab/config/eco/run_table/gspread_keys.pkl",
cred_fname= "/sf/slab/config/eco/run_table/pandas_push",
gsheet_key_path= "/sf/slab/config/eco/run_table/run_table_gsheet_keys",
lazy=True,
)
namespace.append_obj(
"Lakeshore_331",
pvname = "SLAB-LLS-UNIT1",
name = "cryostat_janis",
module_name="eco.devices_general.temperature_controllers",
lazy=True,
)
namespace.append_obj(
"Env_Sensors",
name="env_sensors",
module_name="eco.sample_env.environment_sensors",
lazy=True,
)
## 800pp setup stages
namespace.append_obj(
"SmaractStreamdevice",
pvname = f"SLAB-LMTS-LAM11",
accuracy=1e-3,
name="delay_800pp_stg",
module_name="eco.devices_general.motors",
offset_file=f"/sf/slab/config/eco/reference_values/smaract_delay_800pp_stg",
lazy=True,
)
namespace.append_obj(
"DelayTime",
module_name="eco.loptics.bernina_laser",
stage=delay_800pp_stg,
name="delay_800pp",
)
namespace.append_obj(
"MotorRecord",
module_name="eco.devices_general.motors",
pvname="SLAB-LMOT-M002:MOT",
name="rotation_wp",
lazy=True,
)
## Mid-IR setup stages
namespace.append_obj(
"MotorRecord",
module_name="eco.devices_general.motors",
pvname="SLAB-LMOT-M001:MOT",
name="delay_mirpp_stg",
lazy=True,
)
namespace.append_obj(
"DelayTime",
module_name="eco.loptics.bernina_laser",
stage=delay_mirpp_stg,
name="delay_mirpp",
)
## Other stages
namespace.append_obj(
"MotorRecord",
module_name="eco.devices_general.motors",
pvname="SLAB-LMOT-M003:MOT",
name="rotation_micos_1",
lazy=True,
)
namespace.append_obj(
"MotorRecord",
module_name="eco.devices_general.motors",
pvname="SLAB-LMOT-M004:MOT",
name="rotation_micos_2",
lazy=True,
)
## Scan callback functions
def _message_end_scan(scan):
e = pyttsx3.init()
e.say(f"Finished run {scan.run_number}.")
e.runAndWait()
e.stop()
callbacks_start_scan = []
callbacks_end_scan = []
elog=None
def _create_metadata_structure_start_scan(scan, run_table=run_table, elog=elog):
runname = os.path.basename(scan.fina).split(".")[0]
runno = int(runname.split("run")[1].split("_")[0])
metadata = {
"type": "scan",
"name": runname.split("_", 1)[1],
"scan_info_file": scan.scan_info_filename,
}
for n, adj in enumerate(scan.adjustables):
nname = None
nId = None
if hasattr(adj, "Id"):
nId = adj.Id
if hasattr(adj, "name"):
nname = adj.name
metadata.update(
{
f"scan_motor_{n}": nname,
f"from_motor_{n}": scan.values_todo[0][n],
f"to_motor_{n}": scan.values_todo[-1][n],
f"id_motor_{n}": nId,
}
)
metadata.update(
{
"steps": len(scan.values_todo),
"pulses_per_step": scan.pulses_per_step,
"counters": [daq.name for daq in scan.counterCallers],
}
)
try:
try:
metadata.update({"scan_command": get_ipython().user_ns["In"][-1]})
except:
print("Count not retrieve ipython scan command!")
message_string = f'Acquisition run {runno}: {metadata["name"]}\n'
if "scan_command" in metadata.keys():
message_string += metadata["scan_command"] + "\n"
message_string += metadata["scan_info_file"] + "\n"
scan._elog_id = elog.post(
message_string, Title=f'Run {runno}: {metadata["name"]}'
)
metadata.update({"elog_message_id": scan._elog_id})
metadata.update({"elog_post_link": scan._elog._log._url + str(scan._elog_id)})
except:
print("elog posting failed")
try:
run_table.append_run(runno, metadata=metadata)
except:
print("WARNING: issue adding data to run table")
# <<<< Extract for run table and elog
callbacks_start_scan.append(_create_metadata_structure_start_scan)
#scan_info_dir=f"/sf/slab/data/{config['pgroup']}/res/scan_info",
namespace.append_obj(
"Scans",
data_base_dir="scan_data",
#scan_info_dir="/sf/slab/config/eco/test_acq/scan_info",
scan_info_dir=f"/sf/slab/data/{config.pgroup()}/res/scan_info",
default_counters=[daq],
checker=False,
scan_directories=True,
callbacks_start_scan=callbacks_start_scan,
callbacks_end_scan=callbacks_end_scan,
run_table=run_table,
elog=elog,
name="scans",
module_name="eco.acquisition.scan",
lazy=True,
)
+16 -6
View File
@@ -38,6 +38,7 @@ class Gsheet_API:
keydf_fname, keydf_fname,
cred_fname, cred_fname,
exp_id, exp_id,
folder_id,
exp_path, exp_path,
gsheet_key_path, gsheet_key_path,
): ):
@@ -47,7 +48,7 @@ class Gsheet_API:
"https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/drive",
] ]
self._credentials = ServiceAccountCredentials.from_json_keyfile_name( self._credentials = ServiceAccountCredentials.from_json_keyfile_name(
"/sf/bernina/config/src/python/gspread/pandas_push", self._scope cred_fname, self._scope
) )
self.gc = gspread.authorize(self._credentials) self.gc = gspread.authorize(self._credentials)
self._keydf_fname = keydf_fname self._keydf_fname = keydf_fname
@@ -60,12 +61,15 @@ class Gsheet_API:
name="gsheet_keys", name="gsheet_keys",
default_value="metadata thc gps xrd att att_usd kb", default_value="metadata thc gps xrd att att_usd kb",
) )
self.folder_id = folder_id
self.init_runtable(exp_id) self.init_runtable(exp_id)
def create_rt_spreadsheet(self, exp_id): def create_rt_spreadsheet(self, exp_id, folder_id=None):
if folder_id is None:
folder_id = self.folder_id
self.gc = gspread.authorize(self._credentials) self.gc = gspread.authorize(self._credentials)
spreadsheet = self.gc.create( spreadsheet = self.gc.create(
title=f"run_table_{exp_id}", folder_id="1F7DgF0HW1O71nETpfrTvQ35lRZCs5GvH" title=f"run_table_{exp_id}", folder_id=folder_id
) )
spreadsheet.add_worksheet("runtable", 10, 10) spreadsheet.add_worksheet("runtable", 10, 10)
spreadsheet.add_worksheet("positions", 10, 10) spreadsheet.add_worksheet("positions", 10, 10)
@@ -85,6 +89,8 @@ class Gsheet_API:
def init_runtable(self, exp_id): def init_runtable(self, exp_id):
if os.path.exists(self._keydf_fname): if os.path.exists(self._keydf_fname):
self._key_df = pd.read_pickle(self._keydf_fname) self._key_df = pd.read_pickle(self._keydf_fname)
else:
self._key_df = pd.DataFrame()
if self._key_df is not None and str(exp_id) in self._key_df.index: if self._key_df is not None and str(exp_id) in self._key_df.index:
spreadsheet_key = self._key_df["keys"][f"{exp_id}"] spreadsheet_key = self._key_df["keys"][f"{exp_id}"]
else: else:
@@ -270,8 +276,9 @@ class Run_Table2:
def __init__( def __init__(
self, self,
data=None, data=None,
exp_id="no_exp_id", exp_id='no_exp_id',
exp_path="runtable", folder_id = None,
exp_path='runtable',
keydf_fname=None, keydf_fname=None,
cred_fname=None, cred_fname=None,
devices=None, devices=None,
@@ -285,12 +292,13 @@ class Run_Table2:
exp_path=exp_path, exp_path=exp_path,
devices=devices, devices=devices,
name=name, name=name,
) )
if np.all([k is not None for k in [keydf_fname, cred_fname, gsheet_key_path]]): if np.all([k is not None for k in [keydf_fname, cred_fname, gsheet_key_path]]):
self._google_sheet_api = Gsheet_API( self._google_sheet_api = Gsheet_API(
keydf_fname, keydf_fname,
cred_fname, cred_fname,
exp_id, exp_id,
folder_id,
exp_path, exp_path,
gsheet_key_path, gsheet_key_path,
) )
@@ -463,6 +471,8 @@ class Run_Table_DataFrame(DataFrame):
data_dir.chmod(0o775) data_dir.chmod(0o775)
print(f"Tried to change permissions to 775") print(f"Tried to change permissions to 775")
pd.DataFrame(self).to_pickle(self.fname + "tmp") pd.DataFrame(self).to_pickle(self.fname + "tmp")
fp = Path(self.fname + "tmp")
fp.chmod(0o775)
call(["mv", self.fname + "tmp", self.fname]) call(["mv", self.fname + "tmp", self.fname])
def load(self): def load(self):