这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

欢迎使用Quatm

欢迎使用Quatm用户指南!本指南将引导您如何开始创建用于量子物理实验控制的开源框架Quatm,包括框架定制和如何使用Quatm的模块和模板。

什么是 Quatm?

Quatm是一个专为量子物理实验设计的开源框架,内置了许多最佳实践。使用Quatm,您可以快速建立一个功能齐全且可靠的实验控制系统,然后专注于为用户提供卓越的实验内容。了解更多关于Quatm的信息

Quatm本身不提供

  • 硬件的更新与维护:Quatm 只是一个高性能软件架构,并不涉及硬件的更新与维护,您需要自行购买和维护硬件。
  • 实验内容的开发:Quatm 并不涉及实验内容的开发,您需要自行开发实验内容,Quatm 不承担任何具体实验内容的开发责任。

Quatm提供

  • 实验控制系统的开发:我们的框架提供了一套完整的实验控制系统开发框架,包括实验控制系统的架构、模块、模板等。
  • 实验控制系统的部署:我们的框架提供了一套完整的实验控制系统部署方案,包括实验控制系统的部署、实验控制系统的监控、实验控制系统的维护等。
  • 实验控制系统的维护:我们的框架提供了一套完整的实验控制系统维护方案,包括实验控制系统的更新、实验控制系统的故障处理、实验控制系统的安全等。

Quatm适合我吗?

Quatm特别适用于包含20+不同种类仪器设备的中大型量子物理实验控制系统:超冷原子物理、离子阱实验、量子化学、量子计算、量子光学等。

如果您的实验控制多年使用LabView或者Matlab等闭源商业软件,或者您在同时使用来自于不同厂商的硬件导致您在统一化管理过程中遇到了困难,那么Quatm可能是一个很好的选择。Quatm提供了对于量子物理实验控制系统的最佳实践,并帮助您将实验控制系统从传统的闭源商业软件迁移到开源框架中。目前,我们已经将Quatm框架应用于多个量子物理实验控制系统,并取得了良好的效果。

如果您已经在使用全套的Artiq硬件和软件生态,那么我们不建议您使用我们的框架,因为绝大部分的功能Artiq都能提供更加原生和完整的支持。

准备好开始了吗?

了解如何在入门指南中构建和测试您的第一个实验。或者访问示例网站使用案例开始探索吧!

1 - 电场偏移补偿辅助工具

该代码实现了一个用于补偿电场漂移的辅助工具(CompensationHelper)。该工具通过使用 PyQt6 库构建图形用户界面,帮助用户进行电压扫描、数据管理和图形绘制。代码包含多个类,每个类负责特定的功能模块,例如图形绘制、控制参数设置和实验序列管理。

代码概述

该代码实现了一个用于补偿电场漂移的辅助工具(CompensationHelper)。该工具通过使用 PyQt6 库构建图形用户界面,帮助用户进行电压扫描、数据管理和图形绘制。代码包含多个类,每个类负责特定的功能模块,例如图形绘制、控制参数设置和实验序列管理。

依赖库

  • sys, time, numpy:标准库,用于系统操作、时间管理和数值计算。
  • PyQt6:用于构建 GUI 应用程序。
  • pyqtgraph:用于绘制图形。
  • balic.serversbalic.GUI:自定义库,用于属性管理和 GUI 组件。

类和方法

CompensationHelper

CompensationHelper 继承自 BWidget,实现了电场补偿的主界面。

方法:

  • __init__(self, parent):初始化补偿助手,设置布局并添加绘图和控制小部件。

PlotWidget

PlotWidget 继承自 QFrame,实现了绘图窗口。

方法:

  • __init__(self, parent):初始化绘图窗口,创建每个陷阱轴的标签页和数据流名称。
  • constructScanRange(self):构建扫描范围,根据中心和跨度生成线性扫描范围。

TabWidget

TabWidget 继承自 QFrame,实现了每个陷阱轴的标签页。

方法:

  • __init__(self, name, _prop_root, datastream_names, n_yaxis=2, parent=None):初始化标签页,设置布局和按钮。
  • toggleDataTaking(self):切换数据管理器的状态(启动/暂停)。
  • setPlotDefaults(self):设置绘图的默认参数。
  • avModeSwitch(self):切换平均模式的状态。

ControlWidget

ControlWidget 继承自 QFrame,实现了控制窗口。

方法:

  • __init__(self, parent):初始化控制窗口,创建按钮和参数框。
  • run_all_fn(self, progress_callback=None):运行所有轴的扫描函数。
  • run_all(self):启动所有轴的扫描。
  • print_output(self):打印输出(未实现)。
  • task_done(self):任务完成时调用。
  • progress_fn(self, n):更新进度。
  • init_data_taking(self):初始化数据采集。

SingleAxisWidget

SingleAxisWidget 继承自 QFrame,实现了单个轴的扫描控制。

方法:

  • __init__(self, name, parent):初始化单个轴的扫描控制窗口,设置布局和按钮。
  • switch_tabs(self):切换标签页。
  • findIntersection(self):找到两个线性拟合结果的交点。
  • getFromDefaults(self):从默认值中获取补偿电压。
  • pushToDefaults(self):将补偿电压推送到默认值。
  • run_all_fn(self, progress_callback=None):运行所有扫描函数。
  • init_data_manager(self):初始化数据管理器。
  • start_scan(self):开始扫描。
  • progress_fn(self, n):更新进度。
  • run_done(self):扫描完成时调用。
  • handle_error(self, err_msg):处理错误。
  • clear(self):清除绘图。

CompVoltageScan

CompVoltageScan 继承自 QFrame,实现了电压扫描功能。

方法:

  • __init__(self, parent, axis_name):初始化电压扫描窗口,设置布局和按钮。
  • initGUI(self):初始化用户界面,创建控件和布局。
  • switchTabs(self):切换标签页。
  • constructScanRange(self):构建扫描范围。
  • initExperiment(self):初始化实验参数。
  • updateScan(self):更新扫描参数。
  • runExperimentSequence(self, progress_callback):运行实验序列。
  • stop(self):停止扫描。
  • run(self):启动扫描。
  • progress_fn(self, n):更新进度。
  • print_output(self, s):打印输出(未实现)。
  • thread_complete(self):线程完成时调用。
  • terminate(self):终止扫描。

辅助函数

find_or_add(box, text)

在组合框中查找或添加项目。

def find_or_add(box, text):
    """if it's in the box, set it, if not, add and set it"""
    idx = box.findText(text)
    if idx < 0:
        box.addItem(text)
        idx = box.findText(text)
    box.setCurrentIndex(idx)

总结

该代码实现了一个用于补偿电场漂移的辅助工具。通过图形用户界面,用户可以进行电压扫描、数据管理和图形绘制。代码包含多个类,每个类负责特定的功能模块,例如图形绘制、控制参数设置和实验序列管理。

2 - 偶极阱优化辅助工具

该代码实现了一个名为 LittleHelper 的 PyQt6 应用程序,它包含多个标签页,每个标签页提供不同的帮助功能。目前实现了两个帮助功能:xODT AlignmentStray Field Compensation

功能介绍

该代码实现了一个名为 LittleHelper 的 PyQt6 应用程序,它包含多个标签页,每个标签页提供不同的帮助功能。目前实现了两个帮助功能:xODT AlignmentStray Field Compensation

代码结构

  • 导入必要的模块和库
  • 定义 LittleHelper
  • 定义 TabWidget
  • 定义脚本入口

类:LittleHelper

简短功能介绍

LittleHelper 类是一个主窗口类,用于创建和显示包含多个标签页的主窗口。

方法:__init__

功能:初始化 LittleHelper 对象,设置窗口标题并创建标签页部件。

参数

  • *args**kwargs:可变参数和关键字参数,用于初始化基类。

主要步骤

  1. 调用父类的 __init__ 方法。
  2. 设置窗口标题为 “Little Helper”。
  3. 创建并设置 TabWidget 作为中央部件。

类:TabWidget

简短功能介绍

TabWidget 类是一个包含多个标签页的部件,每个标签页提供不同的帮助功能。

方法:__init__

功能:初始化 TabWidget 对象,创建并添加标签页。

参数

  • parent:父对象。

主要步骤

  1. 调用父类的 __init__ 方法。
  2. 创建主布局并设置为垂直布局。
  3. 初始化标签页组件 QTabWidget
  4. 创建并添加标签页:
    • tab1OdtAlignmentHelper 标签页,用于 xODT 对准。
    • tab2CompensationHelper 标签页,用于杂散场补偿。
  5. 将标签页添加到 QTabWidget 中。
  6. QTabWidget 添加到主布局中并设置布局。

脚本入口

简短功能介绍

脚本入口用于创建应用程序实例,显示主窗口并启动应用事件循环。

主要步骤

  1. 创建 QApplication 实例。
  2. 创建 LittleHelper 实例。
  3. 显示主窗口。
  4. 启动应用事件循环。

完整代码解释

import sys

from PyQt6.QtWidgets import *
from PyQt6.QtCore import pyqtSlot

from balic.GUI.odt_alignment_helper import OdtAlignmentHelper
from balic.GUI.comp_helper import CompensationHelper
# from balic.GUI.verdi_alignment_helper import VerdiAlignmentHelper

class LittleHelper(QMainWindow):
    """
    Automated startup routines
    """
    def __init__(self, *args, **kwargs):
        super(LittleHelper, self).__init__(*args, **kwargs)

        self.setWindowTitle("Little Helper")

        # create the tabs that can host diverse helper environments
        self.tabWidget = TabWidget(self)
        self.setCentralWidget(self.tabWidget)

class TabWidget(QWidget):

    def __init__(self, parent):
        super(QWidget, self).__init__(parent)
        self.layout = QVBoxLayout()

        # Initialize tab screen
        self.tabs = QTabWidget()
        self.tab1 = OdtAlignmentHelper(self)
        self.tab2 = CompensationHelper(self)
        # self.tab3 = VerdiAlignmentHelper(self)

        # Add tabs
        self.tabs.addTab(self.tab1, "xODT Alignment")
        self.tabs.addTab(self.tab2, "Stray Field Compensation")
        # self.tabs.addTab(self.tab3,"Verdi Alignment")

        # Add tabs to widget
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = LittleHelper()
    window.show()

    sys.exit(app.exec())

主要类和方法

  • LittleHelper:主窗口类,包含多个标签页。

    • __init__:初始化窗口标题和标签页部件。
  • TabWidget:包含多个标签页的部件。

    • __init__:初始化标签页并添加不同的帮助功能标签页。

脚本入口

  • 创建 QApplication 实例。
  • 创建 LittleHelper 实例并显示主窗口。
  • 启动应用事件循环。

3 - 实验模块

如何通过Quatm进行实验操作。

quatm.experiment package

This package provides control over your experiments. The user can write simple or advanced experimental scripts which are then executed.

Tutorial

Getting started:

To define an experiment you need to create a class that inherits from Experiment and has at least the functions build and run defined. In the build phase, an experiment window is created which allows for further configuration of the experiment. The run phase is executed when you click on ‘run’ in the window. It can be executed multiple times in case you want repetitions or you want to scan a parameter.

Simple example:

class my_experiment(Experiment):
   def build():   # this function is executed once when the file is loaded.
      # you want to use the dac MyDAC you configured in device.db
      self.setattr_device("Mydac")   # -0.1600
      # define additional variables
      self.setattr_argument("targetvoltage", NumberValue(ndecimals=2, step=0.01, value=4.00))

   def run():  # this function is executed for each run of the experiment
      self.Mydac = 1      # set the dac to 1V
      delay(1)          # delay 1 second
      self.Mydac = self.targetvoltage # set the DAC to a user-defined target voltage

In this simple example, you declare that you need access to the Mydac DAC. Mydac must be a valid entry in your device.db (see below how to configure your system). All setattr_... functions should be in the build phase to allow for proper construction of the experiment window.

The additional variable defined is targetvoltage. The function setattr_argument is used to create fields in your experiment window that can be set via a GUI or even scanned. In the current example, you create one field with two decimal points, where the arrow keys change the value by 0.01 and the default value when the window is opened is 4.

In the run() section the output is set to 1V. Then you wait for one second and set the value to the user-defined value. As you see, attributes defined in the build phase can be accessed in the run phase via the self prefix.

Basic Adwin Configuration

The central configuration file device_db.py is located in the directory quatm/configuration. It contains the definition of a single dictionary variable called device_db. Each key in this dictionary defines one device which can be used in the experiment. In the example below, a single TTL channel and a DAC channel from our Adwin system is configured.

Example:

device_db = {
   "adwin": {
      "type": "local",
      "module": "quatm.drivers.adwin.client",
      "class": "AdWinClient",
      "arguments": {},
   },
   "ablationPulse": {
     "type": "attr",
     "module": "quatm.experiment.ttl",
     "class": "TTLOut",
     "arguments": {"channel": 0},
   },
   "trapX2": {
     "type": "attr",
     "module": "quatm.experiment.dac",
     "class": "DAC",
     "arguments": {"channel": 2},
   }
}

As you can see there are two entries. The first entry needs to be called adwin and is a local driver. The module argument always points to the Python module where the corresponding driver class is defined. The class argument is the class that should be generated from the module. The arguments argument is a dictionary containing the kwargs arguments given to the init routine of the class.

The second entry configures one TTL channel of the Adwin system. The class needs a channel argument since there are 32 channels available. In order to use the ttl module, the adwin entry needs to be defined.

The third entry defines a DAC channel. For DAC channels, additional arguments could be given.

Embedding your own drivers

Suppose you have written a driver module called evalcontrol which contains a class definition called AD9959. Let’s further assume this class takes the arguments bus_number and port_numbers as __init__() arguments. Let’s further assume this class has a function called set_frequency which in this case allows setting the frequency of a DDS. Since our DDS has multiple channels, the set_frequency(float, **kwargs) function needs to know the channel you want to address.

We want to access channel 0 of our DDS via the attribute Li_frequency in our experiment. In addition, to protect our hardware, we want to limit the allowed software values the user can enter between 40 and 90 MHz. For this case scenario, the device_db dictionary should contain the following entries:

Embedding your own driver:

device_db = {
   ...

   "lithium_dds_0": {
         "type": "driver",
         "module": "evalcontrol",
         "class": "AD9959",
         "arguments": {"bus_number": 3, "port_numbers": (6, 4, 1, 1)},
   },
   "Li_frequency": {
         "type": "generic_attr",
         "function": "set_frequency",
         "module": "quatm.experiment.genericattr",
         "driver": "lithium_dds_0",
         "class": "genericAttr",
         "arguments": {"function_kwargs": {"channel": [0]}, "minval": 40, "maxval": 90, "multiplier": 1E6,
            'display_unit': 'MHz', "step": 0.1},
   },

   ...
}

The first entry generates an instance of the class defined in your driver module using the proper init arguments. Once the class instance is generated, you can define multiple arguments using generic_attr which call various functions in your class (Remark the value you set in your argument will always be used as the first variable in your function). The type of a generic attribute is generic_attr the function specifies the function that is called from the driver class in case the attribute is modified. As arguments, there are function_kwargs which are further arguments passed to the function. minval and maxval provide software limits for the argument. multiplier is used for the display of the arguments. When writing experiment scripts SI units have to be used. Therefore valid values would be between 4E7 and 9E7 or 40MHz to 90MHz. In the GUI, the multiplier and display_unit is used. The step argument controls the step size used in the GUI. Pressing the arrow key will change the value by 0.1 MHz.

In your experiment, you can access your driver now like this:

class my_experiment(Experiment):
   def build():
      self.setattr_device("Li_frequency")
      self.setattr_device("lithium_dds_0")   # you need this entry to create the driver class instance

   def run():
      self.Li_frequency = 66E6                 # set the DDS to 66MHz
      delay(1)                               # delay 1 second
      self.Li_frequency = 50E6                 # set DDS to 50MHz

Using gauge files:

BaLiC DAC channels support the use of gauge files. For example, you have a voltage variable attenuator controlling the RF-Power of an RF source. However, this attenuator has a nonlinear curve. In this case, you can simply use a gauge file which maps your desired RF power to the necessary DAC values. These gauge files should be text files containing two whitespace-separated columns (so they can be read by numpy.loadtxt).

Example gauge file:

2.2 4
2   3.8
1.8 3.6
1.6 3.34
1.4 3.12
1.2 2.90
1.0 2.68
0.8 2.48
0.6 2.26

In the first column, there are the DAC values. In the second column, there is the RF power. The two columns should be such that the relation is strictly monotonic. To set up your gauge files, it is a good practice to use SI basis units e.g. rather write 1.12E-7 W than 11.2 µW.

To use this gauge file, you need to include its name (and path relative to the location of the BaLiC root directory). In the example, the gauge file RF-gauge2.dat is in the configuration directory.

Your device_db.py then could look like this:

device_db = {
   ...

   "rf": {
      "type": "attr",
      "module": "quatm.experiment.dac",
      "class": "DAC",
      "arguments": {"channel": 9, "minval": 0.1, "maxval": 

3.1 - 数据类控件

该代码实现了三个自定义的GUI控件类,用于处理实验中的浮点数、布尔值和组合框参数。代码使用了balic.GUI.simple_defaults模块中的FloatManagerBoolManagerComboManager作为基类,并扩展了它们的功能。主要类包括:FloatBoxBoolBoxComboBox

类和方法

FloatBox

FloatBox 继承自 FloatManager,用于处理实验中的浮点数参数。

方法:

  • __init__(self, props, value, parent=None, **kwargs):初始化浮点数控件。

    • props:属性对象,用于存储和管理配置数据。
    • value:初始值。
    • parent:父窗口。
    • **kwargs:其他关键字参数,包括参数名称等。
    • 调用父类的初始化方法,并传递参数名称。
  • updateValue(self, value):更新实验中的对应参数。

    • value:新的浮点数值。
    • 更新控件的值,并在属性对象中设置对应的参数值和最后设置的参数信息。

BoolBox

BoolBox 继承自 BoolManager,用于处理实验中的布尔值参数。

方法:

  • updateValue(self, value):更新实验中的对应参数。

    • value:新的布尔值。
    • 更新控件的值,并在属性对象中设置对应的参数值和最后设置的参数信息。
  • updateCheckbox(self):更新复选框状态。

    • 如果属性中的值与当前复选框的状态不一致,则更新复选框的状态。

ComboBox

ComboBox 继承自 ComboManager,用于处理实验中的组合框参数。

方法:

  • updateValue(self, value):更新实验中的对应参数。
    • value:新的组合框值。
    • 将值转换为字符串列表中的对应值。
    • 更新控件的值,并在属性对象中设置对应的参数值和最后设置的参数信息。

类的详细说明

FloatBox

FloatBox类用于处理实验中的浮点数参数。它继承自FloatManager,并扩展了其功能,以便在属性对象中设置参数值。

class FloatBox(FloatManager):
    ''' Box for handling the attribute argument

    Args:
        argument:(NumberValue)
            points to the argument in the experiment

        unit:(str)
            unit string

        display_multiplier:(float)
            multiplication factor for the unit

    '''
    def __init__(self, props, value, parent=None, **kwargs):
        super().__init__(props, parent, parName=kwargs['name'], **kwargs)

    def updateValue(self, value):
        '''Update the corresponding argument in Experiment

        Args:
            value:(type needs to correspont the to the argument type it represents
        '''
        self.value = value*self.display_multiplier
        if self._props:
            self._props.set(self.parName, value*self.display_multiplier)
            self._props.set('last_set', self.parName+': '+str(value))

BoolBox

BoolBox类用于处理实验中的布尔值参数。它继承自BoolManager,并扩展了其功能,以便在属性对象中设置参数值。

class BoolBox(BoolManager):
    ''' GUI for boolean values

    KWArgs:
        parName:(str)
            name of the parameter
        value:(BoolValue)
            reference to the argument class

    '''

    def updateValue(self, value):
        '''Update the corresponding argument in Experiment

        Args:
            value:(type needs to correspont the to the argument type it represents
        '''
        self.value = bool(value)
        if self._props:
            self._props.set(self.parName, bool(value))
            self._props.set('last_set', self.parName+': '+str(value))

    def updateCheckbox(self):
        ''' updates the spin box if properties have changed '''
        val=self.value     #the values in properties are in SI units. Non SI only on disp
        if val != self.isChecked():
            self.setChecked(val)

ComboBox

ComboBox类用于处理实验中的组合框参数。它继承自ComboManager,并扩展了其功能,以便在属性对象中设置参数值。

class ComboBox(ComboManager):
    ''' GUI for boolean values

    KWArgs:
        parName:(str)
            name of the parameter
        argument:(BoolValue)
            reference to the argument class
    '''

    def updateValue(self, value):
        '''Update the corresponding argument in Experiment

        Args:
            value:(type needs to correspont the to the argument type it represents
        '''
        value = self.stringlist[value]

        self.value = value
        if self._props:
            self._props.set(self.parName, value)
            self._props.set('last_set', self.parName+': '+str(value))

总结

该代码实现了三个自定义的GUI控件类:FloatBoxBoolBoxComboBox,用于处理实验中的不同类型的参数。这些类继承自相应的管理类,并扩展了它们的功能,以便在属性对象中设置和更新参数值。

3.2 - 实验窗口控件类

该代码定义了几个自定义的GUI控件类,包括基础窗口小部件、框架、主窗口以及带有自动完成功能的组合框和自定义的文本编辑控件。这些控件通过继承PyQt6的基本控件类,并添加了一些自定义的功能来实现。

类和方法

BWidget

BWidget 继承自 QWidget,实现了一个基础窗口小部件类,包含移动和调整大小事件的日志记录功能。

方法:

  • __init__(self, name='Noname', parent=None):初始化窗口小部件。

    • name:窗口小部件名称,默认为’Noname’。
    • parent:父窗口。
    • 初始化属性对象并恢复窗口几何设置。
  • closeEvent(self, event):处理窗口关闭事件。

    • event:关闭事件。
    • 保存窗口几何设置并调用父类的关闭事件处理方法。

BFrame

BFrame 继承自 QFrame,实现了一个基础框架类,包含移动和调整大小事件的日志记录功能。

方法:

  • __init__(self, name='Noname', parent=None):初始化框架。

    • name:框架名称,默认为’Noname’。
    • parent:父窗口。
    • 初始化属性对象并恢复框架几何设置。
  • closeEvent(self, event):处理框架关闭事件。

    • event:关闭事件。
    • 保存框架几何设置并调用父类的关闭事件处理方法。

BMainWindow

BMainWindow 继承自 QMainWindow,实现了一个基础主窗口类,包含移动和调整大小事件的日志记录功能。

方法:

  • __init__(self, name='Noname', parent=None):初始化主窗口。

    • name:主窗口名称,默认为’Noname’。
    • parent:父窗口。
    • 初始化属性对象并恢复主窗口几何设置。
  • closeEvent(self, event):处理主窗口关闭事件。

    • event:关闭事件。
    • 保存主窗口几何设置并调用父类的关闭事件处理方法。

CustomCompleter

CustomCompleter 继承自 QCompleter,实现了一个自定义的自动完成器。

方法:

  • __init__(self, items, parent=None, match_flag='contains'):初始化自动完成器。

    • items:自动完成项。
    • parent:父窗口。
    • match_flag:匹配标志,默认为’contains’。
    • 设置完成模式为弹出完成。
  • pathFromIndex(self, index):根据索引返回路径。

    • index:索引。
    • 根据匹配标志返回路径。

SearchComboBox

SearchComboBox 继承自 QComboBox,实现了一个带有自动完成功能的组合框。

方法:

  • __init__(self, parent=None, match_flag='contains'):初始化组合框。

    • parent:父窗口。
    • match_flag:匹配标志,默认为’contains’。
    • 设置可编辑性和自动完成器。
  • add_if_new(self, text):如果文本不存在,则添加并返回索引。

    • text:文本。
    • 如果文本不存在于组合框中,则添加并返回其索引。
  • find_or_add(self, text):如果文本存在则设置当前项,如果不存在则添加并设置当前项。

    • text:文本。
    • 查找或添加文本,并设置为当前项。

SearchLineEdit

SearchLineEdit 继承自 QLineEdit,实现了一个自定义的文本编辑控件,用于SearchComboBox

方法:

  • __init__(self, parent=None):初始化文本编辑控件。

    • parent:父窗口。
  • keyPressEvent(self, event):处理按键事件。

    • event:按键事件。
    • 根据按键类型执行相应操作。
  • focusInEvent(self, event):处理获得焦点事件。

    • event:获得焦点事件。
    • 选择所有文本。
  • focusOutEvent(self, event):处理失去焦点事件。

    • event:失去焦点事件。
    • 存储当前文本。

类的详细说明

BWidget

BWidget类是一个基础窗口小部件类,包含移动和调整大小事件的日志记录功能。

class BWidget(QWidget):
    """ base class of balic Widgets
        includes logging of move and resize events"""

    def __init__(self,name='Noname',parent=None):
        super().__init__(parent)
        self._props=Properties(name)
        self._name = name
        settings=QtCore.QSettings("balic", self._name)
        try:
            self.restoreGeometry(settings.value("geometry"))
        except:
            print('geometry not found')

    def closeEvent(self,event):
        settings=QtCore.QSettings("balic", self._name)
        settings.setValue("geometry", self.saveGeometry())
        super().closeEvent(event)

BFrame

BFrame类是一个基础框架类,包含移动和调整大小事件的日志记录功能。

class BFrame(QFrame):
    """ base class of balic Widgets
        includes logging of move and resize events"""

    def __init__(self,name='Noname',parent=None):
        super().__init__(parent)
        self._props=Properties(name)
        self._name = name
        settings=QtCore.QSettings("balic", self._name)
        try:
            self.restoreGeometry(settings.value("geometry"))
        except:
            print('geometry not found')

    def closeEvent(self,event):
        settings=QtCore.QSettings("balic", self._name)
        settings.setValue("geometry", self.saveGeometry())
        super().closeEvent(event)

BMainWindow

BMainWindow类是一个基础主窗口类,包含移动和调整大小事件的日志记录功能。

class BMainWindow(QMainWindow):
    def __init__(self,name='Noname',parent=None):
        super().__init__(parent)
        self._props=Properties(name)
        self._name = name
        settings=QtCore.QSettings("balic", self._name)
        try:
            self.restoreGeometry(settings.value("geometry"))
        except:
            print('geometry not found')
        self.setWindowTitle(name)

    def closeEvent(self,event):
        settings=QtCore.QSettings("balic", self._name)
        settings.setValue("geometry", self.saveGeometry())
        super().closeEvent(event)

CustomCompleter

CustomCompleter类是一个自定义的自动完成器,用于实现不同的匹配方式。

class CustomCompleter(QCompleter):
    def __init__(self, items, parent=None, match_flag='contains'):
        super(CustomCompleter, self).__init__(items, parent)
        self.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
        self.match_flag = match_flag

    def pathFromIndex(self, index):
        path = index.data()
        if self.match_flag == 'contains' and self.completionPrefix() in path:
            return path
        elif self.match_flag == 'begins' and path.startswith(self.completionPrefix()):
            return path
        return ''

SearchComboBox

SearchComboBox类是一个带有自动完成功能的组合框,允许用户搜索和选择项。

class SearchComboBox(QComboBox):
    """
    QComboBox with the autocompleter QCompleter enabled.
    This adds an editable QLineEdit which allows the contents of the combobox to be searched.
    Filtered list appears as a popup below the search box.
    The full list can be accessed by click the drop-down arrow.
    match_flag: can be either 'contains' or 'begins to get the matchFlag to MatchContains or MatchStartsWith.
    Has a custom QLineEdit called SearchLineEdit.
    """
    def __init__(self, parent=None, match_flag='contains'):
        super().__init__(parent)
        self.setLineEdit(SearchLineEdit(self))
        self.setEditable(True)
        self.setInsertPolicy(QComboBox.InsertPolicy.NoInsert)
        self.completer = CustomCompleter(self.model(), self, match_flag)
        self.setCompleter(self.completer)
        self.setDuplicatesEnabled(False)

    def add_if_new(self, text):
        """if it's in the box, add it. return the index of the item"""
        idx = self.findText(text)
        if

 idx < 0:  # findText returns -1 if the item isn't in the combobox
            self.addItem(text)
            idx = self.findText(text)
        return idx

    def find_or_add(self, text):
        """if it's in the box, set it, if not, add and set it"""
        idx = self.add_if_new(text)
        self.setCurrentIndex(idx)

SearchLineEdit

SearchLineEdit类是SearchComboBox的自定义文本编辑控件,处理特殊的按键事件和焦点事件。

class SearchLineEdit(QLineEdit):
    """
    Custom QLineEdit for the SearchComboBox class.
    On focus in (e.g. when clicked on for the first time) the full text is selected.
    On focus out or pressing enter, the current text is stored. When pressing escape, the stored text is applied.
    On escape, reverts the
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.parent = parent

    def keyPressEvent(self, event: QKeyEvent):
        if event.key() == Qt.Key.Key_Escape:
            self.setText(self.lastText)
        elif event.key() == Qt.Key.Key_Enter:
            self.lastText = self.text()
        else:
            super().keyPressEvent(event)

    def focusInEvent(self, event):
        super().focusInEvent(event)
        QTimer.singleShot(0, self.selectAll)  # ensures other events are processed first. Prevents UI locking up.

    def focusOutEvent(self, event):
        super().focusInEvent(event)
        self.lastText = self.text()

总结

该代码实现了几个自定义的GUI控件类,包括基础窗口小部件、框架、主窗口以及带有自动完成功能的组合框和自定义的文本编辑控件。这些控件通过继承PyQt6的基本控件类,并添加了一些自定义的功能来实现。

3.3 - 实验序列编辑器

该代码实现了一个图形用户界面(GUI)应用程序,用于编辑和可视化实验序列。应用程序使用了PyQt6库来创建界面,Qsci库提供代码编辑器,pyqtgraph库用于绘图。代码主要包括三个类:CodeEditorExperimentSequencerExperimentParser,以及一个主窗口类 CodeEditorParser

类和方法

CodeEditor

CodeEditor 继承自 QsciScintilla,实现了一个简单的代码编辑器,具有语法高亮和自动补全功能。

方法:

  • __init__(self, parent=None, filename=None):初始化编辑器,设置字体、缩进、自动补全和行号。

    • parent:父窗口
    • filename:要加载的文件名
    • 设置最小尺寸为800x600
    • 设置编辑器字体为Courier New,字号12,固定间距
    • 设置缩进宽度为4,不使用制表符缩进,启用自动缩进
    • 启用自动补全,触发阈值为3个字符
    • 设置边距宽度以显示行号
    • 如果提供了文件名,则加载文件内容到编辑器中
  • saveFile(self):保存当前文本到文件。

    • 如果提供了文件名,则将编辑器中的文本写入文件
    • 如果保存成功,打印"file saved successfully"
    • 如果保存失败,打印错误信息
    • 如果文件名无效,打印"filename is invalid, failed to save file"

ExperimentSequencer

ExperimentSequencer 继承自 QtWidgets.QWidget,用于可视化实验序列。

方法:

  • __init__(self, parent=None, filename=None):初始化窗口,订阅属性并创建绘图窗口。

    • parent:父窗口
    • filename:文件名(未使用)
    • 订阅PropertiesSequencer属性
    • 创建GraphicsLayoutWidget并设置背景为白色
    • 将绘图窗口添加到网格布局中
  • plotSequence(self, sequence):绘制实验序列,输入格式由 ExperimentParser 定义。

    • sequence:包含实验序列的字典,键为通道名,值为包含时间和状态的子字典
    • 重置绘图窗口
    • 矢量化布尔值到整数的转换
    • 找到全局最小和最大时间
    • 处理开始和结束时未定义的值
    • 准备颜色
    • 为每个通道创建线图,根据通道名选择颜色
    • 将所有图的X轴链接到第一个图

ExperimentParser

ExperimentParser 用于解析实验代码,模拟实验运行并输出包含通道、时间和通道状态的表。

方法:

  • __init__(self, filename=None):初始化解析器,构建实验。

    • filename:文件名
    • 调用buildExperiment方法构建实验
  • buildExperiment(self):构建实验,使其在 self.filename 中可访问。

    • 动态导入模块并获取实验类
    • 模拟实验命令堆栈
  • simulateExperiment(self):模拟实验运行,返回指令堆栈,并按通道组织为字典。

    • 运行实验,获取模拟的命令堆栈
    • 将命令堆栈转移到字典中,键为通道名,值为包含时间和状态的子字典

CodeEditorParser

CodeEditorParser 继承自 QtWidgets.QMainWindow,将代码编辑器、解析器和实验代码的可视化结合在一起。

方法:

  • __init__(self, parent=None, filename=None):初始化主窗口,创建停靠窗口和按钮。

    • parent:父窗口
    • filename:文件名
    • 设置窗口标题为“Experiment Editor”
    • 设置窗口几何尺寸为1280x800
    • 创建停靠窗口和按钮
    • 初始化时模拟实验序列并绘制
  • addButtons(self):添加保存和模拟按钮。

    • 创建保存和模拟按钮
    • 将按钮添加到布局中
    • 连接按钮点击事件到相应的方法
  • createDocks(self):创建停靠区,包含左侧的 CodeEditor 和右侧的 ExperimentSequencer

    • 创建CodeEditor实例并添加到左侧停靠区
    • 创建ExperimentSequencer实例并添加到右侧停靠区
  • simulateExperiment(self):模拟当前版本的实验,将指令堆栈传递给 ExperimentSequencer 进行可视化。

    • 保存文件,重建实验并模拟运行
    • 将模拟的指令堆栈传递给ExperimentSequencer进行绘制

main() 函数

  • 创建 QApplication 实例。
  • 创建 CodeEditorParser 实例并显示。
  • 启动应用程序的主循环。
def main():
    app = QtWidgets.QApplication(sys.argv)
    Win = CodeEditorParser(filename=sys.argv[1])
    Win.show()
    sys.exit(app.exec())

代码执行

代码通过命令行执行,接收一个文件名作为参数:

python script.py your_experiment_file.py

总结

该代码实现了一个集成代码编辑、实验序列解析和可视化的GUI工具。通过PyQt6提供的窗口和控件,用户可以方便地编辑实验代码,并实时查看实验序列的变化。

3.4 - 多线程任务管理器

该代码实现了一个实验管理器 (ExperimentManager) 类,用于管理和运行实验队列中的任务。该管理器在一个工作线程中不断检查队列中的实验任务,并根据任务的优先级和状态来决定执行哪些实验。实验任务由测量、序列(或扫描)和运行组成,在执行实验时会调用相关的开始和结束函数来控制实验的流程。

以下是该代码的详细中文文档说明:

代码概述

该代码实现了一个实验管理器 (ExperimentManager) 类,用于管理和运行实验队列中的任务。该管理器在一个工作线程中不断检查队列中的实验任务,并根据任务的优先级和状态来决定执行哪些实验。实验任务由测量、序列(或扫描)和运行组成,在执行实验时会调用相关的开始和结束函数来控制实验的流程。

依赖库

  • numpy:用于数值计算和数组操作。
  • time:用于时间操作和延时。
  • PyQt6.QtCore:用于信号槽机制和日期时间操作。
  • balic.GUI.browser_workers:包含 Worker 类,用于多线程处理。
  • balic.servers:包含发送信息和错误的函数。

ExperimentManager

该类包含了管理实验任务队列的功能,包括运行实验、暂停实验、终止实验等。

初始化方法 __init__(self, browser=None)

初始化实验管理器,设置浏览器、属性、队列、线程池等,并启动实验队列。

参数:

  • browser:浏览器对象,用于获取属性和队列。

运行实验方法 run(self, taskNr, progress_callback=None)

处理实验任务的运行逻辑。

参数:

  • taskNr:任务编号。
  • progress_callback:进度回调函数。

内部方法 _sequence_run(self)

初始化运行循环并开始实验。

内部方法 _runloop(self)

运行实验(或实验扫描),在每次运行前检查实验是否暂停或终止。

暂停方法 pause(self)

暂停或继续实验。

启动队列方法 start_queue(self)

在实验线程中启动实验队列工作器。

队列函数 queue_fn(self, progress_callback=None)

实验队列持续检查实验字典中的新任务,如果字典为空或有实验在运行,则不做任何操作。

检查到期方法 due_check(taskDict)

检查任务是否到期。

参数:

  • taskDict:任务字典。

返回:

  • TrueFalse,表示任务是否到期。

更新表格方法 update_table(self)

通知 GUI 更新表格显示。

终止实验方法 terminate_experiment(self)

优雅地终止实验,允许当前运行完成。

开始测量方法 start_measurement(self)

设置参数并调用实验的 start_measurement 函数。

开始序列方法 start_sequence(self)

调用实验的 start_sequence 函数。

结束序列方法 end_sequence(self)

调用实验的 end_sequence 函数。

结束测量方法 end_measurement(self)

运行 end_measurement 函数,并清理表格。

设置字典方法 set_dict(self, name, value)

设置实验参数。

参数:

  • name:参数名。
  • value:参数值。

设置运行编号方法 set_run_nr(self, value)

设置实验运行编号并更新表格。

参数:

  • value:运行编号。

设置重复编号方法 set_rep_nr(self, value)

设置实验重复编号并更新表格。

参数:

  • value:重复编号。

代码详细说明

初始化 ExperimentManager

在初始化方法中,实验管理器会从浏览器对象中获取属性和队列,并启动实验队列工作器。实验队列工作器会在一个单独的线程中运行,不断检查实验队列中的任务。

运行实验 run

在运行实验方法中,实验管理器会检查任务是否存在,并获取任务的详细信息,包括实验名、参数、扫描参数、扫描值等。然后调用相关的开始和结束方法来控制实验的流程。

队列函数 queue_fn

队列函数会持续检查实验字典中的新任务,并根据任务的优先级和状态来决定执行哪些实验。如果任务到期,则运行任务,否则继续检查下一个任务。

暂停和终止实验

实验管理器提供了暂停和终止实验的方法。暂停方法会切换实验的暂停状态,并更新队列显示。终止方法会优雅地终止实验,允许当前运行完成。

其他辅助方法

实验管理器还提供了一些辅助方法,用于设置实验参数、更新表格显示等。

代码示例

以下是一个简单的使用示例:

from PyQt6.QtWidgets import QApplication
import sys
from balic.servers import Properties
from balic.GUI.browser import Browser
from balic.GUI.experiment_manager import ExperimentManager

app = QApplication(sys.argv)
browser = Browser()
experiment_manager = ExperimentManager(browser)

# 添加实验任务到队列
experiment_manager.queue.add_task(task_dict)

# 开始运行实验
experiment_manager.run(taskNr)

sys.exit(app.exec())

3.5 - 实验序列编辑器

该代码实现了一个实验浏览器(Browser)应用程序,提供了图形用户界面来管理和运行各种实验。通过使用PyQt6库构建界面,代码实现了实验文件选择、实验队列管理、参数设置和实验执行等功能。

代码概述

该代码实现了一个实验浏览器(Browser)应用程序,提供了图形用户界面来管理和运行各种实验。通过使用PyQt6库构建界面,代码实现了实验文件选择、实验队列管理、参数设置和实验执行等功能。

依赖库

  • osimportlib.utilinspecttracebacknumpyjsondatetime:标准库,用于文件操作、模块加载、错误处理、数值计算和日期时间处理。
  • PyQt6.QtCorePyQt6.QtWidgets:用于构建GUI应用程序。
  • balic.serversbalic.GUI:自定义库,用于属性管理和GUI组件。

类和方法

Browser

Browser 继承自 QMainWindow,实现了实验浏览器的主界面。

信号:

  • experimentOpened:实验打开信号。

方法:

  • __init__(self):初始化浏览器,设置属性、任务队列和其他组件,并恢复窗口几何设置。
  • closeEvent(self, event):处理窗口关闭事件,调用父类的关闭事件处理方法。
  • init_ui(self):初始化用户界面,设置状态栏和中央窗口区域,并创建停靠窗口。
  • create_dock_widgets(self):创建停靠窗口,包含文件选择器、实验队列、准备站和循环器。
  • open_experiment(self, filepath, startup=False):打开一个新的实验窗口,如果实验已经打开,则不执行任何操作。
  • update_exp_window_task(self):更新所有实验窗口中的任务号。

ExperimentSubWindow

ExperimentSubWindow 继承自 QMdiSubWindow,实现了实验窗口的容器。

方法:

  • __init__(self, name, props, parent=None):初始化子窗口,设置窗口标题和属性。
  • store_geometry(self):存储窗口几何设置。

ExperimentWindow

ExperimentWindow 继承自 QWidget,实现了单个实验的控制,包括参数设置和任务提交。

方法:

  • __init__(self, filepath, props, parent=None, browser=None):初始化实验窗口,加载实验文件并构建用户界面。
  • init_ui(self):初始化用户界面,创建控件和布局。
  • save_params(self, backup=False):保存实验参数到JSON文件。
  • load_params(self):从JSON文件加载实验参数。
  • get_files(self):打开文件选择对话框,获取文件路径。
  • update_task_qsb(self):更新任务号选择框。
  • submit_to_queue(self):提交实验到实验队列。
  • submit_next(self):提交实验到实验队列,并设置最高优先级。
  • submit_to_prepper(self):提交实验到准备站。
  • setup_scan(self):设置扫描序列。
  • setup_task_dict(self):创建任务字典,存储实验参数。
  • build_argument_dict(self):创建实验参数字典。
  • edit_sequence(self):打开序列编辑器窗口。
  • closeEvent(self, event):处理窗口关闭事件,移除打开的窗口。
  • gui_columns(self):返回GUI列数。
  • arguments(self):返回实验参数。
  • argument_names(self):返回实验参数名称列表。
  • argument_dicts(self):返回实验参数字典列表。
  • store_geometry(self):存储窗口几何设置。

SequenceEditor

SequenceEditor 继承自 QDialog,实现了序列编辑器窗口。

方法:

  • __init__(self, experimentWindow, parent=None):初始化序列编辑器窗口,设置窗口标题和图标,并创建控件和布局。
  • update_parameter(self, parname, n):根据参数名称更新参数的范围和步长。
  • update_list_generator(self):更新列表生成器。
  • update_values(self):更新序列编辑器中的值。

QDock

QDock 继承自 QDockWidget,实现了包含实验队列、准备站和循环器的停靠窗口。

方法:

  • __init__(self, parent=None):初始化停靠窗口,设置布局和子控件。

FileSelector

FileSelector 继承自 QWidget,实现了实验文件选择器。

方法:

  • __init__(self, browser, parent=None):初始化文件选择器,设置属性和布局,并创建文件树视图。
  • file_model(self, directory):创建文件模型,用于显示目录中的文件和文件夹。
  • set_column_widths(self):设置文件树视图的列宽。
  • go_up(self):导航到上一级目录。
  • create_context_menu(self, position):创建上下文菜单,提供编辑和组合编辑选项。
  • open_editor(self, filename):打开代码编辑器。
  • open_file(self):打开文件或目录。

辅助函数

filepath_split(filepath)

拆分文件路径,返回路径、扩展名、名称和文件名。

def filepath_split(filepath):
    """
    takes /dir/name.ext
    returns path, ext, name, filename
    = /dir/name, ext, name, name.ext
    """
    path, ext = os.path.splitext(filepath)  # /dir/name, ext
    name = os.path.basename(path)  # name
    filename = os.path.basename(filepath)  # name.ext
    return path, ext, name, filename

主函数

初始化应用程序并启动主窗口。

def main():
    qApp = QApplication(sys.argv)
    Win = Browser()
    qApp.setWindowIcon(QIcon(iconpath + '/browser.png'))
    Win.show()
    sys._excepthook = sys.excepthook

    sys.excepthook = exception_hook
    sys.exit(qApp.exec())


def exception_hook(exctype, value, traceback):
    send_error('[Browser] ' + str([exctype, value, traceback]))
    sys._excepthook(exctype, value, traceback)
    sys.exit(1)


# Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    send_info('[Browser] BaLi Browser starts')
    if (sys.flags.interactive != 1) or not hasattr(Qt, 'PYQT_VERSION'):
        main()

总结

该代码实现了一个实验浏览器应用程序,通过图形用户界面管理和运行各种实验。它提供了实验文件选择、实验队列管理、参数设置和实验执行等功能,并使用PyQt6库构建用户界面。

3.6 - 实验队列管理器

该代码实现了一个实验队列管理器,通过图形用户界面(GUI)来显示和控制实验任务队列。使用PyQt6库来构建界面,其中包含按钮和表格,用于管理实验任务。代码主要包括一个类:ExperimentQ

类和方法

ExperimentQ

ExperimentQ 继承自 QGroupBox,实现了一个实验队列管理器,显示和控制实验任务队列。

方法:

  • __init__(self, browser, parent=None, title="Experiment Queue"):初始化实验队列管理器。

    • browser:浏览器对象,用于访问属性和实验管理器
    • parent:父窗口
    • title:组框标题,默认为"Experiment Queue"
    • 创建按钮和表格,并设置布局
    • 初始化属性
    • 设置锁定标志为False
  • create_buttons(self):创建并配置控制按钮。

    • 创建暂停按钮、终止按钮、终止所有按钮和重启按钮
    • 设置按钮图标、提示信息和点击事件处理函数
  • init_table_actions(self):初始化表格操作。

    • 创建删除、终止、终止所有、休眠和暂停操作
    • 设置操作的快捷键和上下文
    • 将操作添加到表格
  • init_table(self):初始化表格。

    • 创建 QTableView 并设置选择行为、选择模式和上下文菜单策略
    • 隐藏垂直表头并设置其调整模式为内容适应
    • 初始化 expDict 为一个空字典
    • 创建 ScheduleModel 并将其设置为表格模型
    • 设置水平表头的调整模式
  • set_model(self, model):设置表格的新模型。

    • model:新的模型对象
    • 将模型设置为表格模型
  • delete_clicked(self):从队列中删除任务,或者如果任务正在运行则优雅地终止。

    • 获取选中的行,并获取对应的任务编号
    • 如果任务状态为“Running”或“Scanning”,则标记任务为终止
    • 否则,从模型中删除任务
    • 设置当前索引为选中的行
  • terminate_clicked(self):优雅地终止选中的任务(允许完成运行)。

    • 获取选中的行,并获取对应的任务编号
    • 标记任务为终止,状态设置为“Termination Pending”
    • 如果没有选中任务,且模型中有任务,则终止第一个任务
  • terminate_all(self):终止所有任务。

    • 遍历所有任务,标记为终止,状态设置为“Termination Pending”
  • set_sleeping(self):将选中的任务设置为“Sleeping”状态,或者取消“Sleeping”状态。

    • 获取选中的行,并获取对应的任务编号
    • 如果任务状态为“Sleeping”,则设置为“Queued”,否则设置为“Sleeping”
  • pause(self):暂停当前运行的实验。

    • 调用浏览器的实验管理器的暂停方法
    • 根据实验管理器的暂停状态,切换暂停按钮的图标
  • update_item(self, k, v):更新表格中的项目。

    • k:键(任务编号)
    • v:值(任务信息)
    • 将任务信息更新到模型中,并解锁
  • delete_item(self, k):删除表格中的项目。

    • k:键(任务编号)
    • 从模型中删除任务,并解锁
  • restart(self):用于测试按钮的功能。

    • 设置属性值并进行各种操作,打印结果

代码执行

该代码通过创建 ExperimentQ 对象,并将其嵌入到主窗口中来执行。主窗口中会包含实验队列的表格和控制按钮,用户可以通过这些按钮来控制实验任务的状态。

# 示例代码,展示如何创建并显示 ExperimentQ 对象
if __name__ == "__main__":
    import sys
    from PyQt6.QtWidgets import QApplication, QMainWindow

    app = QApplication(sys.argv)
    mainWindow = QMainWindow()
    browser = ...  # 创建或获取浏览器对象
    experimentQueue = ExperimentQ(browser)
    mainWindow.setCentralWidget(experimentQueue)
    mainWindow.show()
    sys.exit(app.exec())

3.7 - 多线程任务管理器

该代码实现了一个多线程工作者类(Worker)和信号类(WorkerSignals),用于在PyQt6应用程序中处理多线程任务。Worker类继承自QRunnableWorkerSignals类继承自QObject,定义了一组可用的信号,以便在工作线程中传递信息。

代码概述

该代码实现了一个多线程工作者类(Worker)和信号类(WorkerSignals),用于在PyQt6应用程序中处理多线程任务。Worker类继承自QRunnableWorkerSignals类继承自QObject,定义了一组可用的信号,以便在工作线程中传递信息。

依赖库

  • sys:用于获取异常信息。
  • traceback:用于格式化异常跟踪信息。
  • PyQt6.QtCore:提供PyQt6核心功能,包括信号和槽机制、可运行对象等。

类和方法

WorkerSignals

WorkerSignals 继承自 QObject,定义了一组可用的信号,以便在工作线程中传递信息。

信号:

  • finished:没有数据,表示任务完成。
  • error:传递一个包含异常类型、异常值和格式化异常跟踪信息的元组。
  • result:传递处理函数返回的结果数据。
  • progress:传递一个整数,表示进度百分比。
  • update_ui:用于更新用户界面。
  • tableUpdate:用于更新表格。
  • addItem:传递一个整数和一个QVariant,用于添加项目。
  • deleteItem:传递一个整数,用于删除项目。
  • taskStart:表示任务开始。
  • taskDone:表示任务完成。
class WorkerSignals(QObject):
    '''
    Defines the signals available from a running worker thread.
    Supported signals are:

    finished
        No data

    error
        `tuple` (exctype, value, traceback.format_exc() )

    result
        `object` data returned from processing, anything

    progress
        `int` indicating % progress

    '''
    finished = pyqtSignal()
    error = pyqtSignal(tuple)
    result = pyqtSignal(object)
    progress = pyqtSignal(int)
    update_ui = pyqtSignal()
    tableUpdate = pyqtSignal()
    addItem = pyqtSignal(int, QtCore.QVariant)
    deleteItem = pyqtSignal(int)
    taskStart = pyqtSignal()
    taskDone = pyqtSignal()

Worker

Worker 继承自 QRunnable,实现了一个工作线程,用于处理耗时的任务。

方法:

  • __init__(self, fn, *args, **kwargs):初始化工作线程。

    • fn:要在线程中运行的函数。
    • args:传递给函数的参数。
    • kwargs:传递给函数的关键字参数。
    • 初始化时存储函数和参数,并创建一个WorkerSignals实例。
  • run(self):运行工作线程。

    • 尝试运行传入的函数,并传递参数和关键字参数。
    • 如果出现异常,捕获并发出error信号。
    • 最后,无论是否有异常,都会发出finished信号,表示任务完成。
class Worker(QRunnable):
    '''
    Worker thread
    Inherits from QRunnable to handle worker thread setup, signals and wrap-up.

    :param callback: The function callback to run on this worker thread. Supplied args and
                     kwargs will be passed through to the runner.
    :type callback: function
    :param args: Arguments to pass to the callback function
    :param kwargs: Keywords to pass to the callback function

    '''

    def __init__(self, fn, *args, **kwargs):
        super(Worker, self).__init__()

        # Store constructor arguments (re-used for processing)
        self.fn = fn
        self.args = args
        self.kwargs = kwargs
        self.signals = WorkerSignals()

        # Add the callback to our kwargs
        self.kwargs['progress_callback'] = self.signals.progress

    @pyqtSlot()
    def run(self):
        """
        Initialise the runner function with passed args, kwargs.
        """

        # Retrieve args/kwargs here; and fire processing using them
        try:
            result = self.fn(*self.args, **self.kwargs)
        except:
            traceback.print_exc()
            exctype, value = sys.exc_info()[:2]
            self.signals.error.emit((exctype, value, traceback.format_exc()))
        finally:
            self.signals.finished.emit()  # Done

总结

该代码定义了一个用于多线程任务处理的工作者类(Worker)和信号类(WorkerSignals)。Worker类继承自QRunnable,可以在工作线程中运行传入的函数,并通过信号机制传递任务的进度、结果或错误信息。WorkerSignals类定义了一组信号,以便在工作线程和主线程之间进行通信。

3.8 - 自动保存编辑器

该代码实现了一个自动保存编辑器,通过图形用户界面(GUI)来管理和设置定期自动保存的时间。使用PyQt6库来构建界面,包括日期时间编辑控件和复选框。主要类包括:AutoSaveEditorDateTimeWidget

类和方法

AutoSaveEditor

AutoSaveEditor 继承自 BWidget,实现了一个自动保存时间的编辑器。

信号:

  • subscriptionsChanged:订阅改变信号。
  • propertiesChanged:属性改变信号。

方法:

  • __init__(self, props, max_items, name='regular_auto_save_times', parent=None):初始化自动保存编辑器。

    • props:属性对象,用于存储和管理配置数据。
    • max_items:最大项目数量。
    • name:属性名称,默认为’regular_auto_save_times’。
    • parent:父窗口。
    • 设置布局,并加载和初始化日期时间控件。
  • load_AutoSaveEditor_props(props, prop_name, max_items):加载自动保存编辑器属性。

    • props:属性对象。
    • prop_name:属性名称。
    • max_items:最大项目数量。
    • 返回日期时间和勾选状态。
  • update_props(props, prop_name, datetimes, ticked):更新属性。

    • props:属性对象。
    • prop_name:属性名称。
    • datetimes:日期时间数组。
    • ticked:勾选状态数组。
  • update_datetime(self, idx, datetime_save):更新日期时间。

    • idx:索引。
    • datetime_save:新的日期时间。
  • update_ticked(self, idx, ticked):更新勾选状态。

    • idx:索引。
    • ticked:新的勾选状态。
  • accept(self):接受并保存更改。

    • 更新属性并通知父组件,然后关闭窗口。

DateTimeWidget

DateTimeWidget 继承自 QFrame,实现了一个日期时间选择控件。

方法:

  • __init__(self, idx, parent, datetime_save=datetime.datetime.now(), ticked=False):初始化日期时间控件。

    • idx:索引。
    • parent:父组件。
    • datetime_save:初始日期时间,默认为当前时间。
    • ticked:初始勾选状态,默认为False。
    • 设置布局,创建并初始化日期时间编辑控件和复选框。
  • datetime_changed(self):日期时间改变事件处理。

    • 更新日期时间,并通知父组件。
  • ticked_changed(self):勾选状态改变事件处理。

    • 更新勾选状态,并通知父组件。

主函数

代码通过创建 QApplication 实例和 AutoSaveEditor 窗口来执行,并启动应用程序的主循环。

if __name__ == '__main__':
    import sys

    props = Properties('Tests/AutoSaveEditor')
    pp = AutoSaveEditor(props, max_items=20)
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QApplication.instance().exec_()

代码执行

该代码通过命令行执行,创建一个AutoSaveEditor对象,并显示自动保存编辑器窗口。

类的详细说明

AutoSaveEditor

AutoSaveEditor类用于管理和设置定期自动保存的时间。它提供了一个图形用户界面,允许用户添加、编辑和删除自动保存的时间点。

方法:

  • __init__(self, props, max_items, name='regular_auto_save_times', parent=None)

    • 初始化方法,设置布局并加载和初始化日期时间控件。
  • load_AutoSaveEditor_props(props, prop_name, max_items)

    • 静态方法,用于从属性对象中加载日期时间和勾选状态,并返回它们。
  • update_props(props, prop_name, datetimes, ticked)

    • 静态方法,用于更新属性对象中的日期时间和勾选状态。
  • update_datetime(self, idx, datetime_save)

    • 更新指定索引的日期时间。
  • update_ticked(self, idx, ticked)

    • 更新指定索引的勾选状态。
  • accept(self)

    • 接受并保存更改,更新属性并通知父组件,然后关闭窗口。

DateTimeWidget

DateTimeWidget类用于显示和编辑单个日期时间和勾选状态。

方法:

  • __init__(self, idx, parent, datetime_save=datetime.datetime.now(), ticked=False)

    • 初始化方法,设置布局,创建并初始化日期时间编辑控件和复选框。
  • datetime_changed(self)

    • 日期时间改变事件处理,更新日期时间并通知父组件。
  • ticked_changed(self)

    • 勾选状态改变事件处理,更新勾选状态并通知父组件。

3.9 - 实验时间线查看器

该代码实现了一个实验时间线查看器,通过图形用户界面(GUI)来显示和控制实验时间序列。使用PyQt6库来构建界面,其中包含按钮、文本框和绘图区域。代码主要包括三个类:TimelineTimelinePlotterSelectorWidget

类和方法

Timeline

Timeline 继承自 QMainWindow,实现了一个实验时间线查看器。

方法:

  • __init__(self, *args, **kwargs):初始化时间线查看器。

    • 设置窗口标题为"Timeline Viewer"。
    • 加载JSON文件中的实验序列。
    • 创建主窗口组件,包括文件加载区、绘图区和选择区。
    • 设置中央窗口部件。
  • plot_experimental_sequence(self, time_dict, init_vals=None):绘制实验时间序列。

    • 重置绘图区域。
    • 深拷贝时间序列字典。
    • 找到最大时间tmax
    • 为每个时间序列添加一个点,确保每个序列都在tmax结束。
    • 准备颜色。
    • 为每个选中的输出绘制折线图,并根据条件选择不同的颜色和填充方式。
  • load_file(self, filename):加载实验序列文件。

    • 读取JSON文件并解析实验序列。
    • 获取输出名称集合。
    • 构建时间序列字典。
    • 逆向设备数据库转换时间序列字典。
    • 更新选择器组件中的名称。
  • decode_ttl_bitmask(self, bitmask, command):解码TTL位掩码。

    • 将位掩码转换为二进制字符串。
    • 找到二进制字符串中的所有1的位置。
    • 根据命令生成TTL字典。
  • get_set_of_used_outputs(self, sequence):获取使用的输出集合。

    • 遍历实验序列,提取所有使用的输出名称。
  • construct_time_sequences(self, sequence, set_of_output_names):构建时间序列字典。

    • 创建时间序列字典结构。
    • 填充时间序列字典。
  • reverse_device_db_transformation(self, time_sequence_dict, device_db_path=workpath+'/configuration/'):逆向设备数据库转换时间序列字典。

    • 加载设备数据库。
    • 构建逆向映射字典。
    • 根据逆向映射字典转换时间序列字典中的名称和值。

TimelinePlotter

TimelinePlotter 继承自 GraphicsLayoutWidget,用于可视化实验序列。

方法:

  • __init__(self, sequence):初始化绘图组件。
    • 订阅属性。
    • 设置背景为白色。
    • 初始化绘图字典。

SelectorWidget

SelectorWidget 继承自 QFrame,用于选择要显示的实验序列。

方法:

  • __init__(self, parent=None, clear_name_dict=None):初始化选择器组件。

    • 创建主布局和按钮。
    • 创建滚动区域用于显示复选框。
  • get_names(self, clear_name_dict):获取并显示名称。

    • 获取清晰名称字典的键并排序。
    • 如果名称未变化,则直接返回。
    • 否则,更新滚动区域中的复选框。
  • select_all(self):全选复选框。

    • 将所有复选框设为选中状态。
  • deselect_all(self):取消全选复选框。

    • 将所有复选框设为未选中状态。

主函数

代码通过创建 QApplication 实例和 Timeline 窗口来执行,并启动应用程序的主循环。

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Timeline()
    window.setWindowIcon(QtGui.QIcon(workpath + '/balic/icons/time_line.png'))
    window.setWindowTitle('Timeline Viewer')
    window.show()
    sys.exit(app.exec())

代码执行

该代码通过命令行执行,创建一个Timeline对象,并显示实验时间线查看器窗口。

3.10 - 多线程处理框架

该代码实现了一个基于 PyQt6 的多线程处理框架。主要包含两个类:WorkerSignals 和 Worker。WorkerSignals 类定义了线程工作时使用的各种信号,而 Worker 类继承自 QRunnable,用于处理多线程任务的设置、执行和信号传递。

功能介绍

该代码实现了一个基于 PyQt6 的多线程处理框架。主要包含两个类:WorkerSignalsWorkerWorkerSignals 类定义了线程工作时使用的各种信号,而 Worker 类继承自 QRunnable,用于处理多线程任务的设置、执行和信号传递。

代码结构

  • 导入必要的模块和库
  • 定义类 WorkerSignals
  • 定义类 Worker

类:WorkerSignals

简短功能介绍

WorkerSignals 类定义了可从正在运行的工作线程发出的信号。这些信号用于指示线程的各种状态和进度,包括完成、错误、结果和进度更新。

属性

  • finished:无数据的信号,指示线程已完成。
  • error:包含异常类型、值和追溯信息的元组信号。
  • result:处理结果数据的信号。
  • progress:指示进度的整数信号。
  • terminate:终止信号。
  • start:启动信号。
  • publish:发布信号。
  • runDone:运行完成信号。
  • logging:日志信号,包含日志信息字符串。
  • clear:清除信号。

类:Worker

简短功能介绍

Worker 类继承自 QRunnable,用于处理工作线程的设置、信号和结束。它允许在独立线程中运行指定的函数,并通过信号机制与主线程通信。

方法:__init__

功能:初始化 Worker 对象,存储传递的函数及其参数,并设置信号。

参数

  • fn:要在工作线程中运行的函数。
  • args:传递给函数的参数。
  • kwargs:传递给函数的关键字参数。

主要步骤

  1. 调用父类 QRunnable 的构造函数。
  2. 存储传递的函数及其参数。
  3. 初始化 WorkerSignals 对象。
  4. 将进度回调添加到关键字参数中。

方法:run

功能:初始化传递的函数并执行它,处理可能的异常,并通过信号机制传递结果。

主要步骤

  1. 尝试运行传递的函数,并捕获其结果。
  2. 如果发生异常,捕获异常信息并发出 error 信号。
  3. 如果函数运行成功,发出 result 信号传递结果。
  4. 最后,无论是否发生异常,发出 finished 信号指示完成。

3.11 - 实验任务循环管理器

该代码定义了几个自定义的GUI控件类,包括基础窗口小部件、框架、主窗口以及带有自动完成功能的组合框和自定义的文本编辑控件。这些控件通过继承PyQt6的基本控件类,并添加了一些自定义的功能来实现。

代码结构

  1. 导入必要的模块和库
  2. 定义主要的 Looper
  3. 定义 LoopItem 类及其子类(TaskItem, ListItem, ConditionalItem 等)
  4. 定义辅助类(DataManager, LoopManager, LoopGroup 等)
  5. 实现 GUI 部件和功能

类:Looper

简短功能介绍

Looper 类是整个循环控制的核心。它负责管理任务组、定时器、按钮和循环的启动与终止。

方法

  • __init__:初始化 Looper 对象,设置属性和布局,创建按钮和标签页。
  • add_tab:添加新的任务组标签页。
  • delete_tab:删除指定的任务组标签页。
  • create_buttons:创建控制按钮。
  • save_loop:保存当前循环配置。
  • load_loop:加载之前保存的循环配置。
  • terminate_by_time:根据时间自动终止循环。

类:LoopItem

简短功能介绍

LoopItem 类是所有循环项的基类,提供了基本的属性和方法。它被 TaskItem, ListItem, ConditionalItem 等类继承,并扩展其功能。

子类:TaskItem

  • 功能:表示单个任务项,执行特定的任务并跟踪运行次数。
  • 方法
    • __init__:初始化任务项,设置任务信息和UI组件。
    • run:执行任务,并将任务添加到任务队列。
    • end_run:更新任务状态和运行次数。
    • task_start:任务开始时的操作。
    • task_end:任务结束时的操作。
    • update_task:更新任务信息。
    • max_check:检查是否达到最大运行次数。

子类:ListItem

  • 功能:表示一个任务列表,按顺序执行列表中的任务。
  • 方法
    • __init__:初始化任务列表项,设置任务列表信息和UI组件。
    • run:执行当前任务,并更新任务索引。
    • end_run:更新任务列表状态和运行次数。
    • edit_list:编辑任务列表。
    • update_task_labels:更新任务标签。

子类:ConditionalItem

  • 功能:表示条件项,根据条件的结果执行不同的任务。
  • 方法
    • __init__:初始化条件项,设置条件信息和UI组件。
    • run:评估条件并选择下一步操作。
    • update_boxes:更新条件的UI组件。

类:DataManager

简短功能介绍

DataManager 类管理数据订阅和更新,处理数据的接收和存储。

方法

  • __init__:初始化数据管理器,设置属性和数据客户端。
  • set_new_data:处理新的数据,更新数据字典。
  • edit_subscriptions:编辑数据订阅。

类:LoopManager

简短功能介绍

LoopManager 类负责管理循环的执行,处理循环任务的启动、终止和控制。

方法

  • __init__:初始化循环管理器,设置属性和线程池。
  • loop_fn:循环执行函数,处理循环任务。
  • run_loop:启动循环任务。
  • terminate:终止循环任务。
  • task_start:任务开始时的操作。
  • task_end:任务结束时的操作。

类:LoopGroup

简短功能介绍

LoopGroup 类表示一个任务组,包含多个任务项和一个组项。

方法

  • __init__:初始化任务组,设置属性和布局。
  • create_buttons:创建任务组的控制按钮。
  • delete_group:删除任务组。
  • update_loop_group_file:更新任务组配置文件。

类:Baustelle

简短功能介绍

Baustelle 类是任务组的编辑器,提供添加、删除和编辑任务项的功能。

方法

  • __init__:初始化编辑器,设置属性和布局。
  • add_task_item:添加新的任务项。
  • add_list_item:添加新的任务列表项。
  • add_conditional:添加新的条件项。
  • add_group_item:添加新的组项。
  • update_idx:更新任务项的索引。

类:LoopSubMgr

简短功能介绍

LoopSubMgr 类是一个GUI,用于编辑数据流的订阅。

方法

  • __init__:初始化订阅管理器,设置属性和布局。
  • update_subscriptions:更新数据流的订阅。

类:ListEdit

简短功能介绍

ListEdit 类是一个对话框,用于编辑 ListItem 的任务列表。

方法

  • __init__:初始化对话框,设置属性和布局。
  • closeEvent:在对话框关闭时更新任务列表。

类:PrepBox 和 ListBox

简短功能介绍

PrepBoxListBox 类分别用于显示和管理预备任务列表和当前任务列表。

方法

  • init_ui:初始化UI组件。
  • set_model:设置数据模型。
  • push_selection:将选中的任务添加到任务列表。
  • unpack_selection:解包选中的任务并添加到任务列表。
  • move_up:在任务列表中上移任务。
  • move_down:在任务列表中下移任务。
  • delete_clicked:删除选中的任务。

类:VLine

简短功能介绍

VLine 类用于在UI中创建分隔线。

类:LoopTabWidget 和 EditableTabBar

简短功能介绍

LoopTabWidgetEditableTabBar 类自定义了标签页控件,允许编辑标签页名称和管理标签页。

方法

  • addTab:添加新的标签页。
  • setIconOn:设置标签页的图标为启用状态。
  • setIconOff:设置标签页的图标为禁用状态。
  • setTabText:设置标签页的文本。
  • editTab:编辑标签页名称。

辅助函数

功能

  • get_experiment:获取实验对象。
  • edit_key_in_place:编辑字典中的键。
  • find_or_add:在组合框中查找或添加项目。
  • parse_text:解析文本,转换为特定格式。

3.12 - 实验任务预备队列管理器

该代码定义了几个自定义的GUI控件类,包括基础窗口小部件、框架、主窗口以及带有自动完成功能的组合框和自定义的文本编辑控件。这些控件通过继承PyQt6的基本控件类,并添加了一些自定义的功能来实现。

概要

该代码定义了用于管理和展示队列(Queue)和准备站(PrepStation)表格的模型。模型指定了表格数据的形式(如字典或列表),以及如何展示和操作这些数据,包括如何获取、设置和删除数据,以及如何排序数据。模型可以直接从数据集中读取数据,并在数据集发生更改时自动更新表格。

主要类和功能

_SyncSubstruct

此类定义了用于操作表格数据字典的方法。方法包括添加、插入、弹出、设置、删除和获取字典项。这个类主要是为了便于在模型中更新数据字典,并在数据更新时调用回调函数来通知模型。

DictSyncModel

这是一个基类,用于将字典(backing_store)转换为表格。模型可以读取和编辑字典中的数据,并根据需要更新表格显示。其主要功能包括:

  • 初始化模型,设置表头、数据名称和初始数据。
  • 获取行数和列数。
  • 获取和设置单元格数据。
  • 获取表头数据。
  • 插入和删除字典项。
  • 排序和转换数据。
关键方法
  • rowCount: 返回字典中的条目数。
  • columnCount: 返回列的数量,即表头的数量。
  • data: 根据索引和角色获取数据。
  • setData: 设置单元格数据,并根据需要进行类型转换。
  • headerData: 获取表头数据。
  • __setitem__: 插入或更新字典项,并更新表格显示。
  • __delitem__: 删除字典项,并更新表格显示。
  • __getitem__: 获取字典项。
  • sort_key: 定义排序键(由子类实现)。
  • convert: 将字典键转换为列数据(由子类实现)。
  • flags: 定义单元格的属性(由子类实现)。

ScheduleModel

这是用于管理实验队列的表格模型。数据结构是一个字典,每个字典代表一个实验任务。任务按优先级和任务编号排序。

关键方法
  • sort_key: 返回用于排序的键,首先按优先级排序,然后按任务编号排序。
  • convert: 将字典键转换为列数据,特别是将日期时间字符串转换为 QDateTime 对象。
  • flags: 定义可编辑和不可编辑的列。

ListSyncModel

类似于 DictSyncModel,但处理的是列表而不是字典。主要用于管理需要按顺序排列的数据集合。

关键方法
  • rowCount: 返回列表的长度。
  • columnCount: 返回列的数量。
  • data: 根据索引和角色获取数据。
  • setData: 设置单元格数据,并根据需要进行类型转换。
  • headerData: 获取表头数据。
  • __delitem__: 删除列表项,并更新表格显示。
  • __getitem__: 获取列表项。
  • sort_key: 定义排序键(由子类实现)。
  • convert: 将列表项转换为列数据(由子类实现)。
  • flags: 定义单元格的属性(由子类实现)。

PrepModel

这是用于准备站的表格模型,使用列表来管理任务,因为准备站中的任务不需要唯一的 ID,可以自由更改顺序。

关键方法
  • convert: 将列表项转换为列数据,特别是将日期时间字符串转换为 QDateTime 对象。
  • flags: 定义可编辑和不可编辑的列。

功能特点

  • 数据同步:模型可以同步更新数据字典或列表,并通知表格更新显示。
  • 数据排序:模型可以根据指定的键对数据进行排序。
  • 数据转换:模型可以根据列索引转换数据类型,如将日期时间字符串转换为 QDateTime 对象。
  • 数据编辑:模型支持在表格中编辑数据,并将更改反映到原始数据集合中。
  • 表格属性:模型可以定义哪些列是可编辑的,哪些是只读的。

运行流程

  1. 创建模型实例,传入初始数据。
  2. 模型通过 rowCountcolumnCount 方法告知表格数据的大小。
  3. 表格通过 data 方法获取单元格数据并显示。
  4. 当用户编辑表格时,模型通过 setData 方法更新数据集合。
  5. 模型通过发射信号通知表格数据已更改,表格自动更新显示。

3.13 - 实验运行调度管理器

该代码片段展示了一个实验调度和运行系统的基础结构,主要通过 Prepper 类来实现。

详细代码分析:Prepper 类及其相关组件

该代码片段展示了一个实验调度和运行系统的基础结构,主要通过 Prepper 类来实现。下面是对代码的详细分析,涵盖了导入的模块、类的定义及其成员、注释和错误处理等方面。

Prepper 类

Prepper 类是该代码的核心部分,用于调度和运行实验。以下是对该类的详细分析:

初始化方法
  • __init__ 方法
    • 接受一个可选的 browser 参数。
    • 通常用于初始化类实例,并设置一些初始状态或配置。
    • 该方法在注释中提到了与 browserqueueexpDict 相关的初始化操作,但具体实现被注释掉了。
未实现的方法
  • start_looper 方法

    • 该方法在注释中被提到,但未实际实现。
    • 预期用于启动一个循环器线程,可能用于定期执行某些任务。
  • looper_fn 方法

    • 该方法同样在注释中被提到,但未实际实现。
    • 预期用于定义循环器线程的主要功能,在特定的时间间隔内更新数据或执行其他操作。
线程池
  • 线程池初始化
    • 代码展示了如何初始化一个线程池,并将最大线程数设置为1。
    • 这表明该类可能被设计为单线程操作,以避免多线程带来的复杂性和潜在问题。

类中的成员

  • 成员变量

    • browser:表示浏览器对象,可能用于界面显示和用户交互。
    • queue:表示任务队列,用于存储和管理待执行的实验。
    • expDict:表示实验字典,用于存储实验的配置信息和状态。
    • threadpool:表示线程池对象,用于管理和调度线程。
  • 定时器

    • timer 变量表示一个定时器对象,通常用于在特定的时间间隔内执行某些操作,例如定期更新界面或检查任务状态。

注释和错误处理

  • 注释

    • 代码中的注释提供了对各部分功能的描述,尤其是对尚未实现的功能和预期行为的说明。
    • 这些注释对于理解代码的设计意图和未来的开发计划非常有帮助。
  • 错误处理

    • traceback 模块的导入表明代码中可能包含对错误的捕获和处理。
    • 通过捕获异常并使用 traceback 模块获取详细的堆栈跟踪信息,有助于在调试过程中快速定位问题。

类的拓展性

  • 代码结构

    • 该类的设计比较模块化,每个方法和成员变量都有明确的职责。
    • 这种设计有助于代码的拓展和维护。
  • 潜在功能

    • 通过引入更多的成员变量和方法,可以扩展类的功能,例如添加更多的实验调度策略、支持更多类型的实验等。

结论

总体而言,该代码片段展示了一个实验调度和运行系统的基础结构。虽然部分功能尚未实现,但通过详细的注释和模块化的设计,可以看出该类旨在通过线程和定时器来管理实验的调度和执行。这为未来的扩展和优化提供了良好的基础。

3.14 - 实验预处理

该代码展示了一个名为 PrepStation 的类,用于实验的预处理和队列管理。

详细代码分析:PrepStation 类及其相关组件

该代码展示了一个名为 PrepStation 的类,用于实验的预处理和队列管理。以下是对代码的详细分析,涵盖导入的模块、类的定义及其成员、注释和错误处理等方面。

PrepStation 类

PrepStation 类是该代码的核心部分,用于管理实验任务的预处理和队列操作。以下是对该类的详细分析:

初始化方法
  • __init__ 方法
    • 初始化类实例,并设置初始状态或配置。
    • 接受 browserparenttitle 作为参数。
    • 初始化各类成员变量,如 parentbrowserqueueexpDictqWidgetlayoutbuttonLayoutprops_taskparamDirtableprepList
    • 调用 init_uiinit_table_actions 方法来设置界面和表格操作。
初始化界面
  • init_ui 方法
    • 配置表格的垂直头,使其根据内容调整大小并隐藏。
    • 创建各种按钮并设置其图标、工具提示和点击事件。
    • 将按钮添加到布局中,并设置布局对齐方式。
初始化表格操作
  • init_table_actions 方法
    • 创建各种操作(如删除、休眠、推送、循环、编辑、查看和保存)并设置其快捷键和触发事件。
    • 将这些操作添加到表格中。
设置模型
  • set_model 方法
    • 创建 PrepModel 实例并设置为表格模型。
    • 调整表格列的宽度。
加载之前的任务
  • load_previous 方法
    • prepfile.json 文件中加载之前的任务列表,并打开相关的实验窗口。
    • 更新 prepList
任务操作方法
  • push 方法

    • 将选中的任务推送到队列中,如果没有选中任务,则推送第一个任务。
  • push_row 方法

    • 推送指定行的任务到队列中,并更新任务状态。
  • push_first 方法

    • 推送第一个任务到队列中。
  • delete_clicked 方法

    • 删除选中的任务,并更新任务文件。
  • set_sleeping 方法

    • 设置选中的任务为休眠状态。
  • push_to_looper 方法

    • 将选中的任务推送到循环器中。
  • move_up 方法

    • 上移选中的任务。
  • move_down 方法

    • 下移选中的任务。
  • update_prep_file 方法

    • 更新任务文件,将当前任务列表保存到 prepfile.json
编辑和查看参数
  • open_editor 方法

    • 打开任务编辑器窗口以修改任务参数。
  • open_viewer 方法

    • 打开参数查看器窗口以查看任务参数。
  • save_params 方法

    • 将实验参数保存到 JSON 文件中。

其他类和辅助函数

  • ExpEditWindow

    • 用于编辑实验参数的窗口。
    • 初始化方法 __init__init_ui
    • 提交修改的方法 submit
  • ParViewWindow

    • 用于查看实验参数的窗口。
    • 初始化方法 __init__init_ui
  • CheckLayout

    • 包含复选框和参数输入框的布局。
    • 初始化方法 __init__
  • DisplayBox

    • 显示参数名称、值和单位的布局。
    • 初始化方法 __init__init_ui
  • get_experiment 函数

    • 获取实验实例,如果实验窗口未打开则打开窗口。

3.15 - 实验集合管理器

该代码定义了一个用于管理和监控多个进程的图形用户界面(GUI)应用程序。

环境变量设置

代码通过检查操作系统平台设置了 QT_SCALE_FACTOR 环境变量,以调整 MacOS 上的缩放比例。

SingleProcess 类

SingleProcess 类用于表示单个可管理的进程。以下是该类的详细分析:

初始化方法
  • __init__ 方法
    • 初始化类实例,并设置初始状态或配置。
    • 接受 scriptnameactivecategoryparent 作为参数。
    • 根据操作系统平台设置 Python 解释器路径。
    • 创建和配置按钮、布局和样式表。
    • 配置定时器以定期更新进程状态。
进程管理方法
  • startProcess 方法

    • 停止现有进程(如果有)。
    • 使用 subprocess.Popen 启动新的进程。
    • 更新按钮状态。
  • stopProcess 方法

    • 停止现有进程,根据需要选择终止或强制杀死进程。
    • 更新按钮状态。
  • updateStatus 方法

    • 定期检查进程状态并更新按钮颜色以指示进程是否运行。
析构方法
  • __del__ 方法
    • 确保在对象销毁时停止进程。

ProcessManager 类

ProcessManager 类用于管理多个 SingleProcess 实例。以下是该类的详细分析:

初始化方法
  • __init__ 方法
    • 初始化类实例,并设置初始状态或配置。
    • 读取配置文件,创建 SingleProcess 实例,并将其添加到布局中。
    • 设置窗口样式和布局。
事件处理方法
  • closeEvent 方法
    • 在关闭窗口时,停止所有正在运行的进程。
析构方法
  • __del__ 方法
    • 在对象销毁时输出调试信息。

主函数

  • main 方法
    • 设置高 DPI 缩放策略。
    • 创建应用程序实例,设置窗口图标,创建和显示主窗口。
    • 进入应用程序事件循环。

结论

该代码实现了一个进程管理和监控的 GUI 应用程序。通过 SingleProcess 类,用户可以启动、停止和监控单个进程;通过 ProcessManager 类,用户可以批量管理多个进程。代码结构清晰,使用了 PyQt6 的多种控件和信号槽机制来实现用户交互和数据更新。

3.16 - 实验参数管理器

该代码定义了一个用于管理和监控多个进程的图形用户界面(GUI)应用程序。

DefaultExp 类概述

DefaultExp 是一个实验类,包含所有设备的属性,并组织这些属性以便于管理和访问。

方法详解

build(self)
  • 功能
    • 设置实验的初始参数,如计数器。
    • 遍历设备数据库,加载设备并根据设备类型进行分组。
    • 处理属性的加载错误,并将设备分为显示和隐藏两类。
run(self)
  • 功能
    • 运行实验的主要逻辑(此处为空实现,作为模板)。

BasicManager 类概述

BasicManager 是一个基础管理类,用于创建和管理各种类型的参数小部件。

构造方法

  • 参数说明

    • props:属性对象,用于与属性数据库交互。
    • parent:父级小部件。
    • kwargs:其他参数,用于初始化属性。
  • 功能

    • 初始化基础属性,如单位、最大最小值、步长等。
    • 设置样式并调用 _initGUI 方法。

方法详解

_initGUI(self)
  • 功能
    • 初始化图形界面,创建布局和标签。
    • 如果存在工具提示,则设置工具提示。
    • 创建定时器,用于定期更新参数值。
updateSpin(self)
  • 功能
    • 占位方法,用于在子类中实现具体的更新逻辑。

IntManager 类概述

IntManager 继承自 BasicManager,用于管理整数类型的参数。

方法详解

initSpin(self)
  • 功能
    • 创建一个整数选择框 (QSpinBox)。
    • 从属性对象中获取初始值并设置到选择框中。
    • 连接选择框的值变化信号到 updateValue 方法。
updateValue(self, v)
  • 参数

    • v:新值。
  • 功能

    • 更新实验和属性对象中的参数值。
updateSpin(self)
  • 功能
    • 检查属性对象中的值是否有变化,如果有变化,则更新选择框中的值。

BoolManager 类概述

BoolManager 继承自 QCheckBox,用于管理布尔类型的参数。

方法详解

updateValue(self, val)
  • 参数

    • val:新值。
  • 功能

    • 更新实验和属性对象中的布尔值。
updateCheckbox(self)
  • 功能
    • 检查属性对象中的布尔值是否有变化,如果有变化,则更新复选框的状态。

FloatManager 类概述

FloatManager 继承自 IntManager,用于管理浮点数类型的参数。

方法详解

initSpin(self)
  • 功能
    • 创建一个浮点数选择框 (QDoubleSpinBox)。
    • 从属性对象中获取初始值并设置到选择框中。
    • 连接选择框的值变化信号到 updateValue 方法。

ComboManager 类概述

ComboManager 继承自 BasicManager,用于管理下拉列表类型的参数。

方法详解

initSpin(self)
  • 功能
    • 创建一个下拉列表 (QComboBox)。
    • 根据提供的字符串列表初始化下拉列表的选项。
    • 连接下拉列表的选项变化信号到 updateValue 方法。
updateValue(self, v)
  • 参数

    • v:新值。
  • 功能

    • 更新实验和属性对象中的选项值。

FrequencyManager 类概述

FrequencyManager 继承自 IntManager,用于管理频率类型的参数。

方法详解

initSpin(self)
  • 功能
    • 创建一个浮点数选择框 (QDoubleSpinBox),用于选择频率值。
    • 从属性对象中获取初始值并设置到选择框中。
    • 连接选择框的值变化信号到 updateValue 方法。

SimpleDefaults 类概述

SimpleDefaults 继承自 QFrame,用于显示和管理实验的默认参数。

构造方法

  • 功能
    • 初始化属性对象和实验对象。
    • 调用实验对象的 build 方法构建实验。
    • 创建和设置主布局。
    • 根据实验的分组创建相应的参数管理小部件,并添加到布局中。

主函数

main()

  • 功能
    • 创建应用程序实例。
    • 创建 SimpleDefaults 窗口并显示。
    • 启动应用程序的事件循环。

使用场景

  • 该代码主要用于科学实验和数据采集系统中,帮助管理和显示实验的各种参数。
  • 适用于需要频繁调整参数和查看参数变化的场景,如实验室研究和工业控制系统。

3.17 - 实验运行监视器

这个代码定义了一个 StreamMonitor 类和一个 TableModel 类,用于监控和显示各种数据流(包括数据流、图像流、命令流和消息流)的内容。它还提供了一个主函数 main,用于初始化和运行一个包含多个标签页的 PyQt 应用程序,每个标签页显示不同类型的数据流。

概述

这个代码定义了一个 StreamMonitor 类和一个 TableModel 类,用于监控和显示各种数据流(包括数据流、图像流、命令流和消息流)的内容。它还提供了一个主函数 main,用于初始化和运行一个包含多个标签页的 PyQt 应用程序,每个标签页显示不同类型的数据流。

StreamMonitor

StreamMonitor 类继承自 QWidget,用于监控和显示不同类型的数据流。

主要方法和属性

  • 初始化方法 __init__

    • 接受参数:name(数据流名称)、streamtype(数据流类型,如 ‘Data’、‘Image’ 等)、parent(父组件)。
    • 根据 streamtype 初始化不同类型的客户端对象(如 DataClientImageClient 等)。
    • 初始化用户界面,包括标签、复选框、组合框、按钮、文本编辑器和表格视图等。
    • 设置一个定时器,用于定期更新数据流的内容。
  • _update_message 方法

    • 定期从消息流中获取新消息,并将其添加到消息列表中。
    • 如果启用了保存选项,则将新消息写入文件。
  • update_text 方法

    • 根据用户选择的过滤条件更新显示的消息内容。
    • 使用 QTableView 显示过滤后的消息列表。
  • _update_selected_message 方法

    • 从文件中读取历史消息,并更新显示内容。
  • _update_list 方法

    • 定期从数据流中获取新数据,并将其添加到消息列表中。
  • load_selected_message 方法

    • 打开文件对话框,允许用户选择一个消息文件,并加载文件内容。
  • update_table_selected 方法

    • 根据用户选择的过滤条件更新显示的历史消息内容。
  • on_checkbox_changed 方法

    • 处理复选框状态变化事件。

TableModel

TableModel 类继承自 QAbstractTableModel,用于管理和显示表格数据。

主要方法和属性

  • 初始化方法 __init__

    • 接受参数:data(表格数据),并初始化模型。
  • data 方法

    • 根据指定的索引和角色返回相应的数据内容和样式。
  • rowCount 方法

    • 返回表格的行数。
  • columnCount 方法

    • 返回表格的列数。
  • headerData 方法

    • 返回表头的标签内容。

使用场景

  • 该代码主要用于需要监控和显示实时数据流的应用程序。
  • 适用于数据分析、系统监控和日志管理等场景。
  • 提供了一种用户友好的方式,通过图形界面查看和管理不同类型的数据流和消息内容。

主函数 main

  • 创建一个包含多个标签页的 QTabWidget,每个标签页显示不同类型的数据流。
  • 初始化和运行 PyQt 应用程序。

通过这种方式,用户可以方便地在一个界面中监控和管理多种类型的数据流和消息内容。

3.18 - 实验任务折叠管理

这段代码定义了一个可折叠的对话框组件,允许用户在 PyQt6 应用程序中添加和管理可折叠的部分。主要组件包括 SectionExpandButton 类和 CollapsibleDialog 类,它们协同工作以实现可折叠部分的创建和管理。

概述

这段代码定义了一个可折叠的对话框组件,允许用户在 PyQt6 应用程序中添加和管理可折叠的部分。主要组件包括 SectionExpandButton 类和 CollapsibleDialog 类,它们协同工作以实现可折叠部分的创建和管理。

主要组件

SectionExpandButton

SectionExpandButton 类继承自 QPushButton,用于创建一个可以展开或折叠其关联部分的按钮。

主要方法和属性
  • 初始化方法 __init__

    • 接受参数:item(关联的部分项)、text(按钮文本)、parent(父组件)。
    • 设置按钮的初始文本,并连接点击事件到 on_clicked 方法。
  • on_clicked 方法

    • 处理按钮的点击事件,切换关联部分的展开或折叠状态。
    • 如果部分是展开的,则将其折叠;如果是折叠的,则将其展开。

CollapsibleDialog

CollapsibleDialog 类继承自 QDialog,用于创建一个包含可折叠部分的对话框。

主要方法和属性
  • 初始化方法 __init__

    • 创建并配置一个 QTreeWidget 以隐藏标题,并将其添加到对话框的布局中。
    • 设置树的缩进为 0。
  • add_section 方法

    • 接受参数:title(部分的标题)、widget(部分的内容部件)。
    • 调用 add_button 方法创建一个按钮,并调用 add_widget 方法将内容部件添加为按钮的子项。
  • define_sections 方法

    • 定义并添加对话框中的所有部分。
    • 示例实现中,创建了一个包含两个标签的 QFrame 部件,并将其添加到部分中。
  • add_button 方法

    • 接受参数:title(部分的标题)。
    • 创建一个 QTreeWidgetItem 项,并将其添加为树的顶级项。
    • 创建一个 SectionExpandButton 按钮,将其设置为项的部件,并返回该项。
  • add_widget 方法

    • 接受参数:button(按钮项)、widget(部分的内容部件)。
    • 创建一个 QTreeWidgetItem 项,将其设置为按钮项的子项,并将内容部件设置为子项的部件。

使用场景

这个组件可以用于需要包含多个可折叠部分的对话框的应用程序,例如设置对话框、信息面板等。通过扩展 CollapsibleDialog 类并重写 define_sections 方法,可以轻松定义和管理对话框中的各个部分。

示例

下面是一个示例,展示如何使用 CollapsibleDialogSectionExpandButton 类:

import sys
from PyQt6.QtWidgets import QApplication

class MyCollapsibleDialog(CollapsibleDialog):
    def define_sections(self):
        widget1 = QFrame(self.tree)
        layout1 = QHBoxLayout(widget1)
        layout1.addWidget(QLabel("Content 1"))
        self.add_section("Section 1", widget1)
        
        widget2 = QFrame(self.tree)
        layout2 = QHBoxLayout(widget2)
        layout2.addWidget(QLabel("Content 2"))
        self.add_section("Section 2", widget2)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    dialog = MyCollapsibleDialog()
    dialog.define_sections()
    dialog.show()
    sys.exit(app.exec())

在这个示例中,MyCollapsibleDialog 类继承自 CollapsibleDialog 并重写了 define_sections 方法,定义了两个可折叠部分。运行此代码将显示一个包含两个可折叠部分的对话框。

4 - 入门指南

了解如何开始使用Quatm,包括安装教程、使用方法和可选的功能。

As you saw in our introduction, Docsy is a Hugo theme, which means that if you want to use Docsy, you need to set up your website source so that the Hugo static site generator can find and use the Docsy theme files when building your site. The simplest way to do this is to copy and edit our example site, though we also provide instructions for adding the Docsy theme manually to new or existing sites.

If you want to build and test your site locally you also need to be able to run Hugo itself, either by installing it and any other required dependencies, or by using our provided Docker container.

This page describes Docsy’s installation options and helps you choose the appropriate setup guide to get started.

Installation options

Hugo offers multiple options for using themes, all of which are supported by Docsy.

  • Adding the theme as a Hugo Module: Hugo Modules are the simplest and latest way to use Hugo themes. Hugo uses the modules mechanism to pull in the theme files from the main Docsy repo at your chosen revision, and it’s easy to keep the theme up to date in your site. Our example site uses Docsy as a Hugo Module.
  • Adding the theme as a Git submodule: Adding the theme as a Git submodule also lets Hugo use the theme files from their own repo, though is more complicated to maintain than the Hugo modules approach. This is the approach used in older versions of the Docsy example site and is still supported.
  • Cloning the theme files: If you don’t want Hugo to have to get the theme files from an external repo (for example, if you want to customize and maintain your own copy of the theme directly, or your deployment choice requires you to include a copy of the theme in your repository), you can clone the files directly into your site source.

Migration and backward compatibility

If you have an existing site that uses Docsy as a Git submodule, and you would like to update it to use Hugo Modules, follow our migration guide. If you’re not ready to migrate yet, don’t worry! Your site will continue to work as usual.

Setup guides

Follow the setup guide for your chosen approach. If you’re new to Docsy and not sure which guide to follow, we recommend following the Use Docsy as a Hugo Module guide as a simple and easily maintained option.

4.1 - Quatm的下载与安装

Learn how to get started with Docsy by using the theme as a Hugo Module.

Hugo modules are the simplest and latest way to use Hugo themes like Docsy when building a website. Hugo uses the modules mechanism to pull in the theme files from the main Docsy repo at your chosen revision, and it’s easy to keep the theme up to date in your site. Our example site uses Docsy as a Hugo module.

To find out about other setup approaches, see our Get started overview. If you want to migrate an existing Docsy site to use Hugo Modules, see our migration guide.

Setup options with Hugo Modules

To use Docsy as a Hugo Module, you have a couple of options:

  • Copy and edit the source for the Docsy example site. This approach gives you a skeleton structure for your site, with top-level and documentation sections and templates that you can modify as necessary. The example site uses Docsy as a Hugo Module.
  • Build your own site using the Docsy theme. Specify the Docsy theme like any other Hugo theme when creating or updating your site. With this option, you’ll get Docsy look and feel, navigation, and other features, but you’ll need to specify your own site structure.

If you’re a beginner, we recommend that you get started by copying our example site. If you’re already familiar with Hugo or want a very different site structure, you can follow our guide to start a site from scratch, which gives you maximum flexibility at the cost of higher implementation effort. In both cases you need to follow our prerequisites guide to make sure that you have installed Hugo and all necessary dependencies.

4.1.1 - Before you begin

Prerequisites for building a site with Docsy as a Hugo Module.

This page describes the prerequisites for building a site that uses Docsy as a Hugo Module.

Install Hugo

You need a recent extended version (version 0.110.0 or later) of Hugo to do local builds and previews of sites (like this one) that use Docsy. If you install from the release page, make sure to get the extended Hugo version, which supports SCSS; you may need to scroll down the list of releases to see it.

For comprehensive Hugo documentation, see gohugo.io.

On Linux

Be careful using sudo apt-get install hugo, as it doesn’t get you the extended version for all Debian/Ubuntu versions, and may not be up-to-date with the most recent Hugo version.

If you’ve already installed Hugo, check your version:

hugo version

If the result is v0.109.0 or earlier, or if you don’t see Extended, you’ll need to install the latest version. You can see a complete list of Linux installation options in Install Hugo. The following shows you how to install Hugo from the release page:

  1. Go to the Hugo releases page.

  2. In the most recent release, scroll down until you find a list of Extended versions.

  3. Download the latest extended version (hugo_extended_0.1XX_Linux-64bit.tar.gz).

  4. Create a new directory:

    mkdir hugo
    
  5. Extract the files you downloaded to hugo.

  6. Switch to your new directory:

    cd hugo
    
  7. Install Hugo:

    sudo install hugo /usr/bin
    

On macOS

Install Hugo using Brew.

As an npm module

You can install Hugo as an npm module using hugo-bin. This adds hugo-bin to your node_modules folder and adds the dependency to your package.json file. To install the extended version of Hugo:

npm install hugo-extended --save-dev

See the hugo-bin documentation for usage details.

Install Go language

Hugo’s commands for module management require that the Go programming language is installed on your system. Check whether go is already installed:

$ go version
go version go1.21.6

Ensure that you are using version 1.12 or higher.

If the go language is not installed on your system yet or if you need to upgrade, go to the download area of the Go website, choose the installer for your system architecture and execute it. Afterwards, check for a successful installation.

Install Git VCS client

Hugo’s commands for module management require that the git client is installed on your system. Check whether git is already present in your system:

$ git version
git version 2.43.0

If no git client is installed on your system yet, go to the Git website, download the installer for your system architecture and execute it. Afterwards, check for a successful installation.

Install PostCSS

To build or update your site’s CSS resources, you also need PostCSS to create the final assets. If you need to install it, you must have a recent version of NodeJS installed on your machine so you can use npm, the Node package manager. By default npm installs tools under the directory where you run npm install:

npm install -D autoprefixer
npm install -D postcss-cli

Starting in version 8 of postcss-cli, you must also separately install postcss:

npm install -D postcss

Note that versions of PostCSS later than 5.0.1 will not load autoprefixer if installed globally, you must use a local install.

Install/Upgrade Node.js

To ensure you can properly build your site beyond executing hugo server, you must have the latest long term support (LTS) Version of Node.js. If you do not have the latest LTS version, you may see the one of following errors:

Error: Error building site: POSTCSS: failed to transform "scss/main.css" (text/css): Unexpected identifier
#OR
/home/user/repos/my-new-site/themes/docsy/node_modules/hugo-extended/postinstall.js:1
import install from "./lib/install.js";
       ^^^^^^^

SyntaxError: Unexpected identifier
    at Module._compile (internal/modules/cjs/loader.js:723:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

You can check your current Node.js version by running node -v. If you need to install a new version, see the following instructions:

  • Debian and Ubuntu based distributions

    tl;dr:

    # Using Ubuntu
    curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
    sudo apt-get install -y nodejs
    
    # Using Debian, as root
    curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
    apt-get install -y nodejs
    
  • Enterprise Linux based distributions

    tl;dr:

    # As root
    curl -fsSL https://rpm.nodesource.com/setup_20.x | bash -
    
    # No root privileges
    curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
    

What’s next?

With all prerequisites installed, choose how to start off with your new Hugo site

4.1.2 - Create a new site: start with a prepopulated site

Create a new Hugo site by using a clone of the Docsy example site as your starting point.

The simplest way to create a new Docsy site is to use the source of the Docsy example site as starting point. This approach gives you a skeleton structure for your site, with top-level and documentation sections and templates that you can modify as necessary. The example site automatically pulls in the Docsy theme as a Hugo Module, so it’s easy to keep up to date.

If you prefer to create a site from scratch, follow the instructions in Start a site from scratch.

TL;DR: Setup for the impatient expert

At your Unix shell or Windows command line, run the following command:

git clone --depth 1 --branch v0.10.0 https://github.com/quatm/quatm-example.git my-new-site
cd  my-new-site
hugo server

You now can preview your new site in your browser at http://localhost:1313.

Detailed Setup instructions

Clone the Docsy example site

The Example Site gives you a good starting point for building your docs site and is pre-configured to automatically pull in the Docsy theme as a Hugo Module. There are two different routes to get a local clone of the example site:

  • If you want to create a local copy only, choose option 1.
  • If you have a GitHub account and want to create a GitHub repo for your site go for option 2.

Option 1: Using the command line (local copy only)

If you want to use a remote repository other than GitHub (such as GitLab, BitBucket, AWS CodeCommit, Gitea) or if you don’t want a remote repo at all, simply make a local working copy of the example site directly using git clone. As last parameter, give your chosen local repo name (here: my-new-site):

git clone --depth 1 --branch v0.10.0 https://github.com/quatm/quatm-example.git my-new-site

Option 2: Using the GitHub UI (local copy + associated GitHub repo)

As the Docsy example site repo is a template repository, creating your own remote GitHub clone of this Docsy example site repo is quite easy:

  1. Go to the repo of the Docsy example site.

  2. Use the dropdown for switching branches/tags to change to the latest released tag v0.10.0.

  3. Click the button Use this template and select the option Create a new repository from the dropdown.

  4. Chose a name for your new repository (e.g. my-new-site) and type it in the Repository name field. You can also add an optional Description.

  5. Click Create repository from template to create your new repository. Congratulations, you just created your remote Github clone which now serves as starting point for your own site!

  6. Make a local copy of your newly created GitHub repository by using git clone, giving your repo’s web URL as last parameter.

    git clone https://github.com/me-at-github/my-new-site.git
    

Now you can make local edits and test your copied site locally with Hugo.

Preview your site

To build and preview your site locally, switch to the root of your cloned project and use hugo’s server command:

cd my-new-site
hugo server

Preview your site in your browser at: http://localhost:1313. Thanks to Hugo’s live preview, you can immediately see the effect of changes that you are making to the source files of your local repo. Use Ctrl + c to stop the Hugo server whenever you like. See the known issues on MacOS.

What’s next?

4.1.3 - Create a new site: Start a new site from scratch

Create a new Hugo site from scratch with Docsy as a Hugo Module

The simplest approach to creating a Docsy site is copying our example site. However, if you’re an experienced Hugo user or the site structure of our example site doesn’t meet your needs, you may prefer to create a new site from scratch. With this option, you’ll get Docsy look and feel, navigation, and other features, but you’ll need to specify your own site structure.

These instructions give you a minimum file structure for your site project only, so that you build and extend your actual site step by step. The first step is adding the Docsy theme as a Hugo Module to your site. If needed, you can easily update the module to the latest revision from the Docsy GitHub repo.

TL;DR: Setup for the impatient expert

At your command prompt, run the following:

hugo new site my-new-site
cd  my-new-site
hugo mod init github.com/me/my-new-site
hugo mod get github.com/google/docsy@v0.10.0
cat >> hugo.toml <<EOL
[module]
proxy = "direct"
[[module.imports]]
path = "github.com/google/docsy"
EOL
hugo server
hugo new site my-new-site
cd  my-new-site
hugo mod init github.com/me/my-new-site
hugo mod get github.com/google/docsy@v0.10.0
(echo [module]^

proxy = "direct"^

[[module.imports]]^

path = "github.com/google/docsy") >> hugo.toml
hugo server

You now can preview your new site inside your browser at http://localhost:1313.

Detailed Setup instructions

Specifying the Docsy theme as Hugo Module for your minimal site gives you all the theme-y goodness, but you’ll need to specify your own site structure.

Create your new skeleton project

To create a new Hugo site project and then add the Docs theme as a submodule, run the following commands from your project’s root directory.

hugo new site my-new-site
cd  my-new-site

This will create a minimal site structure, containing the folders archetypes, content, data, layouts, static, and themes and a configuration file (default: hugo.toml).

Import the Docsy theme module as a dependency of your site

Only sites that are Hugo Modules themselves can import other modules. To turn your site into a Hugo Module, run the following commands in your newly created site directory:

hugo mod init github.com/me/my-new-site

This creates two new files, go.mod for the module definitions and go.sum which holds the checksums for module verification.

Next declare the Docsy theme module as a dependency for your site.

hugo mod get github.com/google/docsy@v0.10.0

This command adds the docsy theme module to your definition file go.mod.

Add theme module configuration settings

Add the settings in the following snippet at the end of your site’s configuration file (default: hugo.toml) and save the file.

[module]
  proxy = "direct"
  # uncomment line below for temporary local development of module
  # replacements = "github.com/google/docsy -> ../../docsy"
  [module.hugoVersion]
    extended = true
    min = "0.73.0"
  [[module.imports]]
    path = "github.com/google/docsy"
    disable = false
module:
  proxy: direct
  hugoVersion:
    extended: true
    min: 0.73.0
  imports:
    - path: github.com/google/docsy
      disable: false
{
  "module": {
    "proxy": "direct",
    "hugoVersion": {
      "extended": true,
      "min": "0.73.0"
    },
    "imports": [
      {
        "path": "github.com/google/docsy",
        "disable": false
      }
    ]
  }
}

You can find details of what these configuration settings do in the Hugo modules documentation. Depending on your environment you may need to tweak them slightly, for example by adding a proxy to use when downloading remote modules.

Preview your site

To build and preview your site locally:

hugo server

By default, your site will be available at http://localhost:1313. When encountering problems, have a look at the known issues on MacOS.

You may get Hugo errors for missing parameters and values when you try to build your site. This is usually because you’re missing default values for some configuration settings that Docsy uses - once you add them your site should build correctly. You can find out how to add configuration in Basic site configuration - we recommend copying the example site configuration even if you’re creating a site from scratch as it provides defaults for many required configuration parameters.

What’s next?

4.2 - 其他功能

Create a new Docsy site with Docsy using Git or NPM

If you don’t want to use Docsy as a Hugo Module (for example if you do not want to install Go) but still don’t want to copy the theme files into your own repo, you can use Docsy as a Git submodule. Using submodules also lets Hugo use the theme files from Docsy repo, though is more complicated to maintain than the Hugo Modules approach. This is the approach used in older versions of the Docsy example site, and is still supported. If you are using Docsy as a submodule but would like to migrate to Hugo Modules, see our migration guide.

Alternatively if you don’t want Hugo to have to get the theme files from an external repo (for example, if you want to customize and maintain your own copy of the theme directly, or your deployment choice requires you to include a copy of the theme in your repository), you can clone the files directly into your site source.

Finally, you can install Docsy as an NPM package.

This guide provides instructions for all of these options, along with common prerequisites.

Prerequisites

Install Hugo

You need a recent extended version (we recommend version 0.73.0 or later) of Hugo to do local builds and previews of sites (like this one) that use Docsy. If you install from the release page, make sure to get the extended Hugo version, which supports SCSS; you may need to scroll down the list of releases to see it.

For comprehensive Hugo documentation, see gohugo.io.

On Linux

Be careful using sudo apt-get install hugo, as it doesn’t get you the extended version for all Debian/Ubuntu versions, and may not be up-to-date with the most recent Hugo version.

If you’ve already installed Hugo, check your version:

hugo version

If the result is v0.73 or earlier, or if you don’t see Extended, you’ll need to install the latest version. You can see a complete list of Linux installation options in Install Hugo. The following shows you how to install Hugo from the release page:

  1. Go to the Hugo releases page.

  2. In the most recent release, scroll down until you find a list of Extended versions.

  3. Download the latest extended version (hugo_extended_0.9X_Linux-64bit.tar.gz).

  4. Create a new directory:

    mkdir hugo
    
  5. Extract the files you downloaded to hugo.

  6. Switch to your new directory:

    cd hugo
    
  7. Install Hugo:

    sudo install hugo /usr/bin
    

On macOS

Install Hugo using Brew.

As an NPM module

You can install Hugo as an NPM module using hugo-extended. To install the extended version of Hugo:

npm install hugo-extended --save-dev

Node: Get the latest LTS release

If you have Node installed already, check your version of Node. For example:

node -v

Install or upgrade your version of Node to the active LTS release. We recommend using nvm to manage your Node installation (Linux command shown):

nvm install --lts

Install PostCSS

To build or update your site’s CSS resources, you’ll also need PostCSS. Install it using the Node package manager, npm.

From your project root, run this command:

npm install --save-dev autoprefixer postcss-cli

Option 1: Docsy as a Git submodule

For a new site

To create a new site and add the Docsy theme as a Git submodule, run the following commands:

  1. Create the site:

    hugo new site myproject
    cd myproject
    git init
    
  2. Install postCSS as instructed earlier.

  3. Follow the instructions below for an existing site.

For an existing site

To add the Docsy theme to an existing site, run the following commands from your project’s root directory:

  1. Install Docsy as a Git submodule:

    git submodule add https://github.com/quatm/quatm.git themes/docsy
    cd themes/docsy
    git checkout v0.10.0
    

    To work from the development version of Docsy (not recommended), run the following command instead:

    git submodule add --depth 1 https://github.com/quatm/quatm.git themes/docsy
    
  2. Add Docsy as a theme, for example:

    echo 'theme = "docsy"' >> hugo.toml
    
  3. Get Docsy dependencies:

    (cd themes/docsy && npm install)
    

    Important: read the Docsy NPM install side-effect note.

  4. (Optional but recommended) To avoid having to repeat the previous step every time you update Docsy, consider adding NPM scripts like the following to your project’s package.json file:

    {
      "...": "...",
      "scripts": {
        "get:submodule": "git submodule update --init --depth 1",
        "_prepare:docsy": "cd themes/docsy && npm install",
        "prepare": "npm run get:submodule && npm run _prepare:docsy",
        "...": "..."
      },
      "...": "..."
    }
    

    Every time you run npm install from your project root, the prepare script will fetch the latest version of Docsy and its dependencies.

From this point on, build and serve your site using the usual Hugo commands, for example:

hugo serve

Option 2: Clone the Docsy theme

If you don’t want to use a submodules (for example, if you want to customize and maintain your own copy of the theme directly, or your deployment choice requires you to include a copy of the theme in your repository), you can clone the theme into your project’s themes subdirectory.

To clone Docsy at v0.10.0 into your project’s theme folder, run the following commands from your project’s root directory:

cd themes
git clone -b v0.10.0 https://github.com/quatm/quatm
cd docsy
npm install

Important: read the Docsy NPM install side-effect note.

To work from the development version of Docsy (not recommended unless, for example, you plan to upstream changes to Docsy), omit the -b v0.10.0 argument from the clone command above.

Then consider setting up an NPM prepare script, as documented in Option 1.

For more information, see Theme Components on the Hugo site.

Option 3: Docsy as an NPM package

You can use Docsy as an NPM module as follows:

  1. Create your site and specify Docsy as the site theme:

    hugo new site myproject
    cd myproject
    echo 'theme = "docsy"' >> hugo.toml
    
  2. Install Docsy, and postCSS (as instructed earlier):

    npm install --save-dev google/docsy#semver:0.10.0 autoprefixer postcss-cli
    

    Important: read the Docsy NPM install side-effect note.

  3. Build or serve your new site using the usual Hugo commands, specifying the path to the Docsy theme files. For example, build your site as follows:

    $ hugo --themesDir node_modules
    Start building sites …
    ...
    Total in 1890 ms
    

    You can drop the --themesDir ... flag by adding the themes directory to your site’s configuration file:

    echo 'themesDir = "node_modules"' >> hugo.toml
    

As an alternative to specifying a themesDir, on some platforms, you can instead create a symbolic link to the Docsy theme directory as follows (Linux commands shown, executed from the site root folder):

mkdir -p themes
pushd themes
ln -s ../node_modules/docsy
popd

Docsy NPM install side-effect

Preview your site

To preview your site locally:

cd myproject
hugo server

By default, your site will be available at http://localhost:1313. See the known issues on MacOS.

You may get Hugo errors for missing parameters and values when you try to build your site. This is usually because you’re missing default values for some configuration settings that Docsy uses - once you add them your site should build correctly. You can find out how to add configuration in Basic site configuration - we recommend copying the example site configuration even if you’re creating a site from scratch as it provides defaults for many required configuration parameters.

What’s next?

4.3 - 开始你的第一个实验

Instructions on how to setup and run a local Docsy site with Docker.

title: “实验模块” linkTitle: “实验模块” weight: 3 description: > 如何通过Quatm进行实验操作。

quatm.experiment package

This package provides control over your experiments. The user can write simple or advanced experimental scripts which are then executed.

Tutorial

Getting started:

To define an experiment you need to create a class that inherits from Experiment and has at least the functions build and run defined. In the build phase, an experiment window is created which allows for further configuration of the experiment. The run phase is executed when you click on ‘run’ in the window. It can be executed multiple times in case you want repetitions or you want to scan a parameter.

Simple example:

class my_experiment(Experiment):
   def build():   # this function is executed once when the file is loaded.
      # you want to use the dac MyDAC you configured in device.db
      self.setattr_device("Mydac")   # -0.1600
      # define additional variables
      self.setattr_argument("targetvoltage", NumberValue(ndecimals=2, step=0.01, value=4.00))

   def run():  # this function is executed for each run of the experiment
      self.Mydac = 1      # set the dac to 1V
      delay(1)          # delay 1 second
      self.Mydac = self.targetvoltage # set the DAC to a user-defined target voltage

In this simple example, you declare that you need access to the Mydac DAC. Mydac must be a valid entry in your device.db (see below how to configure your system). All setattr_... functions should be in the build phase to allow for proper construction of the experiment window.

The additional variable defined is targetvoltage. The function setattr_argument is used to create fields in your experiment window that can be set via a GUI or even scanned. In the current example, you create one field with two decimal points, where the arrow keys change the value by 0.01 and the default value when the window is opened is 4.

In the run() section the output is set to 1V. Then you wait for one second and set the value to the user-defined value. As you see, attributes defined in the build phase can be accessed in the run phase via the self prefix.

Basic Adwin Configuration

The central configuration file device_db.py is located in the directory quatm/configuration. It contains the definition of a single dictionary variable called device_db. Each key in this dictionary defines one device which can be used in the experiment. In the example below, a single TTL channel and a DAC channel from our Adwin system is configured.

Example:

device_db = {
   "adwin": {
      "type": "local",
      "module": "quatm.drivers.adwin.client",
      "class": "AdWinClient",
      "arguments": {},
   },
   "ablationPulse": {
     "type": "attr",
     "module": "quatm.experiment.ttl",
     "class": "TTLOut",
     "arguments": {"channel": 0},
   },
   "trapX2": {
     "type": "attr",
     "module": "quatm.experiment.dac",
     "class": "DAC",
     "arguments": {"channel": 2},
   }
}

As you can see there are two entries. The first entry needs to be called adwin and is a local driver. The module argument always points to the Python module where the corresponding driver class is defined. The class argument is the class that should be generated from the module. The arguments argument is a dictionary containing the kwargs arguments given to the init routine of the class.

The second entry configures one TTL channel of the Adwin system. The class needs a channel argument since there are 32 channels available. In order to use the ttl module, the adwin entry needs to be defined.

The third entry defines a DAC channel. For DAC channels, additional arguments could be given.

Embedding your own drivers

Suppose you have written a driver module called evalcontrol which contains a class definition called AD9959. Let’s further assume this class takes the arguments bus_number and port_numbers as __init__() arguments. Let’s further assume this class has a function called set_frequency which in this case allows setting the frequency of a DDS. Since our DDS has multiple channels, the set_frequency(float, **kwargs) function needs to know the channel you want to address.

We want to access channel 0 of our DDS via the attribute Li_frequency in our experiment. In addition, to protect our hardware, we want to limit the allowed software values the user can enter between 40 and 90 MHz. For this case scenario, the device_db dictionary should contain the following entries:

Embedding your own driver:

device_db = {
   ...

   "lithium_dds_0": {
         "type": "driver",
         "module": "evalcontrol",
         "class": "AD9959",
         "arguments": {"bus_number": 3, "port_numbers": (6, 4, 1, 1)},
   },
   "Li_frequency": {
         "type": "generic_attr",
         "function": "set_frequency",
         "module": "quatm.experiment.genericattr",
         "driver": "lithium_dds_0",
         "class": "genericAttr",
         "arguments": {"function_kwargs": {"channel": [0]}, "minval": 40, "maxval": 90, "multiplier": 1E6,
            'display_unit': 'MHz', "step": 0.1},
   },

   ...
}

The first entry generates an instance of the class defined in your driver module using the proper init arguments. Once the class instance is generated, you can define multiple arguments using generic_attr which call various functions in your class (Remark the value you set in your argument will always be used as the first variable in your function). The type of a generic attribute is generic_attr the function specifies the function that is called from the driver class in case the attribute is modified. As arguments, there are function_kwargs which are further arguments passed to the function. minval and maxval provide software limits for the argument. multiplier is used for the display of the arguments. When writing experiment scripts SI units have to be used. Therefore valid values would be between 4E7 and 9E7 or 40MHz to 90MHz. In the GUI, the multiplier and display_unit is used. The step argument controls the step size used in the GUI. Pressing the arrow key will change the value by 0.1 MHz.

In your experiment, you can access your driver now like this:

class my_experiment(Experiment):
   def build():
      self.setattr_device("Li_frequency")
      self.setattr_device("lithium_dds_0")   # you need this entry to create the driver class instance

   def run():
      self.Li_frequency = 66E6                 # set the DDS to 66MHz
      delay(1)                               # delay 1 second
      self.Li_frequency = 50E6                 # set DDS to 50MHz

Using gauge files:

BaLiC DAC channels support the use of gauge files. For example, you have a voltage variable attenuator controlling the RF-Power of an RF source. However, this attenuator has a nonlinear curve. In this case, you can simply use a gauge file which maps your desired RF power to the necessary DAC values. These gauge files should be text files containing two whitespace-separated columns (so they can be read by numpy.loadtxt).

Example gauge file:

2.2 4
2   3.8
1.8 3.6
1.6 3.34
1.4 3.12
1.2 2.90
1.0 2.68
0.8 2.48
0.6 2.26

In the first column, there are the DAC values. In the second column, there is the RF power. The two columns should be such that the relation is strictly monotonic. To set up your gauge files, it is a good practice to use SI basis units e.g. rather write 1.12E-7 W than 11.2 µW.

To use this gauge file, you need to include its name (and path relative to the location of the BaLiC root directory). In the example, the gauge file RF-gauge2.dat is in the configuration directory.

Your device_db.py then could look like this:

device_db = {
   ...

   "rf": {
      "type": "attr",
      "module": "quatm.experiment.dac",
      "class": "DAC",
      "arguments": {"channel": 9, "minval": 0.1, "maxval": 

4.4 - 连接你的第一个设备

Basic configuration for new Docsy sites.

Site-wide configuration details and parameters are defined in your project’s configuration file (hugo.toml or config.toml). These include your chosen Hugo theme (Docsy, of course!), project name, community links, Google Analytics configuration, and Markdown parser parameters. See the examples with comments in hugo.toml in the example project for how to add this information. We recommend copying this hugo.toml and editing it even if you’re just using the theme and not copying the entire Docsy example site, as it includes default values for many parameters that you need to set for your site to build correctly.

You may want to remove or customize some defaults of the copied hugo.toml file straight away:

Internationalization

The copied hugo.toml file defines content in English, Norwegian and Farsi. You can find out more about how Docsy supports multi-language content in Multi-language support.

If you don’t intend to translate your site, you can remove the language switcher by removing the following lines from hugo.toml:

[languages.no]
languageName ="Norsk"
contentDir = "content/no"
[languages.no.params]
title = "Goldydocs"
description = "Docsy er operativsystem for skyen"
time_format_default = "02.01.2006"
time_format_blog = "02.01.2006"

[languages.fa]
languageName ="فارسی"
contentDir = "content/fa"
[languages.fa.params]
title = "اسناد گلدی"
description = "یک نمونه برای پوسته داکسی"
time_format_default = "2006.01.02"
time_format_blog = "2006.01.02"

By default, the Docsy example site uses its own Google Custom Search Engine. To disable this site search, delete or comment out the following lines:

# Google Custom Search Engine ID. Remove or comment out to disable search.
gcs_engine_id = "..."

To use your own Custom Search Engine, set gcs_engine_id to your search engine ID. For details, see Configure search with a Google Custom Search Engine.

What’s next?

4.5 - 已知问题

Known issues when installing Docsy theme.

The following issues are know on MacOS and on Windows Subsystem for Linux:

MacOS

Errors: too many open files or fatal error: pipe failed

By default, MacOS permits a small number of open File Descriptors. For larger sites, or when you’re simultaneously running multiple applications, you might receive one of the following errors when you run hugo server to preview your site locally:

  • POSTCSS v7 and earlier:

    ERROR 2020/04/14 12:37:16 Error: listen tcp 127.0.0.1:1313: socket: too many open files
    
  • POSTCSS v8 and later:

    fatal error: pipe failed
    
Workaround

To temporarily allow more open files:

  1. View your current settings by running:

    sudo launchctl limit maxfiles
    
  2. Increase the limit to 65535 files by running the following commands. If your site has fewer files, you can set choose to set lower soft (65535) and hard (200000) limits.

    sudo launchctl limit maxfiles 65535 200000
    ulimit -n 65535
    sudo sysctl -w kern.maxfiles=200000
    sudo sysctl -w kern.maxfilesperproc=65535
    

Note that you might need to set these limits for each new shell. Learn more about these limits and how to make them permanent.

Windows Subsystem for Linux (WSL)

If you’re using WSL, ensure that you’re running hugo on a Linux mount of the filesystem, rather than a Windows one, otherwise you may get unexpected errors.

5 - 框架内容和自定义

如何理解框架内容并根据您的需求进行修改和适配。

5.1 - Adding Content

Add different types of content to your Docsy site.

So you’ve got a new Hugo website with Docsy, now it’s time to add some content! This page tells you how to use the theme to add and structure your site content.

Content root directory

You add content for your site under the content root directory of your Hugo site project - either content/ or a language-specific root like content/en/. The main exception here is static files that you don’t want built into your site: you can find out more about where you add these below in Adding static content. The files in your content root directory are typically grouped in subdirectories corresponding to your site’s sections and templates, which we’ll look at in Content sections and templates.

You can find out more about Hugo directory structure in Directory Structure Explained.

Content sections and templates

Hugo builds your site pages using the content files you provide plus any templates provided by your site’s theme. These templates (or “layouts” in Hugo terminology) include things like your page’s headers, footers, navigation, and links to stylesheets: essentially, everything except your page’s specific content. The templates in turn can be made up of partials: little reusable snippets of HTML for page elements like headers, search boxes, and more.

Because most technical documentation sites have different sections for different types of content, the Docsy theme comes with the following templates for top-level site sections that you might need:

  • docs is for pages in your site’s Documentation section.
  • blog is for pages in your site’s Blog.
  • community is for your site’s Community page.

It also provides a default “landing page” type of template with the site header and footer, but no left nav, that you can use for any other section. In this site and our example site it’s used for the site home page and the About page.

Each top-level section in your site corresponds to a directory in your site content root. Hugo automatically applies the appropriate template for that section, depending on which folder the content is in. For example, this page is in the docs subdirectory of the site’s content root directory content/en/, so Hugo automatically applies the docs template. You can override this by explicitly specifying a template or content type for a particular page.

If you’ve copied the example site, you already have appropriately named top-level section directories for using Docsy’s templates, each with an index page ( _index.md or index.html) page for users to land on. These top-level sections also appear in the example site’s top-level menu.

Custom sections

If you’ve copied the example site and don’t want to use one of the provided content sections, just delete the appropriate content subdirectory. Similarly, if you want to add a top-level section, just add a new subdirectory, though you’ll need to specify the layout or content type explicitly in the frontmatter of each page if you want to use any existing Docsy template other than the default one. For example, if you create a new directory content/en/amazing and want one or more pages in that custom section to use Docsy’s docs template, you add type: docs to the frontmatter of each page:

+++
title = "My amazing new section"
weight = 1
type = "docs"
description = '''
A special section with a docs layout.
'''
+++
---
title: "My amazing new section"
weight: 1
type: docs
description: >
  A special section with a docs layout.  
---
{
  "title": "My amazing new section",
  "weight": 1,
  "type": "docs",
  "description": "A special section with a docs layout.\n"
}

Alternatively, create your own page template for your new section in your project’s layouts directory based on one of the existing templates.

You can find out much more about how Hugo page layouts work in Hugo Templates. The rest of this page tells you about how to add content and use each of Docsy’s templates.

Alternative site structure

As noted above, by default your site has a home page (using the _default layout), a docs section under /开发文档/, a blog section under /更新日志/ and a community section under /技术交流/. The type of each section (which determines the layout it uses) matches its directory name.

In some cases, you may want to have a different directory structure, but still make use of Docsy’s layouts. A common example is for a “docs site”, where most of the pages (including the home page) use the docs layout, or perhaps you’d rather have a /news/ directory treated with the blog layout.

Since Hugo 0.76, this has become practical without copying layouts to your site, or having to specify type: blog on every single page by making use of target specific cascading front matter.

For example, for the /news/ section, you can specify the following front matter in the index page which will change the type of the section and everything below it to “blog”:

+++
title = "Latest News"
linkTitle = "News"

[menu.main]
weight = 30

[[cascade]]
type = "blog"
+++
---
title: "Latest News"
linkTitle: "News"
menu:
  main:
    weight: 30

cascade:
  - type: "blog"
---
{
  "title": "Latest News",
  "linkTitle": "News",
  "menu": {
    "main": {
      "weight": 30
    }
  },
  "cascade": [
    {
      "type": "blog"
    }
  ]
}

If you want to create a “docs” site, specifying something like the following in the top level _index.md will set all top level sections to be treated as “docs”, except for “news”:

+++
title = "My Wonderful Site"

[[cascade]]
type = "blog"
toc_root = true

  [cascade._target]
  path = "/news/**"

[[cascade]]
type = "docs"

  [cascade._target]
  path = "/**"
+++
---
title: "My Wonderful Site"

cascade:
  - type: "blog"
    toc_root: true
    _target:
    path: "/news/**"
  - type: "docs"
    _target:
    path: "/**"
---
{
  "title": "My Wonderful Site",
  "cascade": [
    {
      "type": "blog",
      "toc_root": true,
      "_target": {
        "path": "/news/**"
      }
    },
    {
      "type": "docs",
      "_target": {
        "path": "/**"
      }
    }
  ]
}

Note the addition of toc_root here. Setting that to true for a section causes it to be treated as a separate part of the site, with its own left hand navigation menu.

An example docs-based site that uses this technique can be found at the mostly docs repo.

Page frontmatter

Each page file in a Hugo site has metadata frontmatter that tells Hugo about the page. You specify page frontmatter in TOML, YAML, or JSON (our example site and this site use YAML). Use the frontmatter to specify the page title, description, creation date, link title, template, menu weighting, and even any resources such as images used by the page. You can see a complete list of possible page frontmatter in Front Matter.

For example, here’s the frontmatter for this page:

+++
title = "Adding Content"
linkTitle = "Adding Content"
weight = 1
description = '''
Add different types of content to your Docsy site.
'''
+++
---
title: "Adding Content"
linkTitle: "Adding Content"
weight: 1
description: >
  Add different types of content to your Docsy site.  
---
{
  "title": "Adding Content",
  "linkTitle": "Adding Content",
  "weight": 1,
  "description": "Add different types of content to your Docsy site.\n"
}

The minimum frontmatter you need to provide is a title: everything else is up to you! However, if you leave out the page weight, your navigation may get a little disorganized. You may also want to include description since Docsy uses that to generate the meta description tag used by search engines. See Search Engine Optimization (SEO) meta tags for details.

Page contents and markup

By default you create pages in a Docsy site as simple Markdown or HTML files with page frontmatter, as described above. As of version 0.100, Goldmark is the only Markdown parser supported by Hugo.

In addition to your marked-up text, you can also use Hugo and Docsy’s shortcodes: reusable chunks of HTML that you can use to quickly build your pages. Find out more about shortcodes in Docsy Shortcodes.

Hugo lets you specify links using normal Markdown syntax, though remember that you need to specify links relative to your site’s root URL, and that relative URLs are left unchanged by Hugo in your site’s generated HTML.

Alternatively you can use Hugo’s helper ref and relref shortcodes for creating internal links that resolve to the correct URL. However, be aware this means your links will not appear as links at all if a user views your page outside your generated site, for example using the rendered Markdown feature in GitHub’s web UI.

You can find (or add!) tips and gotchas for working with Hugo links in Hugo Tips.

Content style

We don’t mandate any particular style for your page contents. However, if you’d like some guidance on how to write and format clear, concise technical documentation, we recommend the Google Developer Documentation Style Guide, particularly the Style Guide Highlights.

Page bundles

You can create site pages as standalone files in their section or subsection directory, or as folders where the content is in the folder’s index page. Creating a folder for your page lets you bundle images and other resources together with the content.

You can see examples of both approaches in this and our example site. For example, the source for this page is just a standalone file /content/en/开发文档/adding-content.md. However the source for Docsy Shortcodes in this site lives in /content/en/开发文档/adding-content/shortcodes/index.md, with the image resource used by the page in the same /shortcodes/ directory. In Hugo terminology, this is called a leaf bundle because it’s a folder containing all the data for a single site page without any child pages (and uses index.md without an underscore).

You can find out much more about managing resources with Hugo bundles in Page Bundles.

Adding docs and blog posts

The template you’ll probably use most often is the docs template (as used in this page) or the very similar blog template. Both these templates include:

  • a left nav
  • GitHub links (populated from your site config) for readers to edit the page or create issues
  • a page menu

as well as the common header and footer used by all your site’s pages. Which template is applied depends on whether you’ve added the content to the blog or docs content directory. You can find out more about how the nav and page menu are created in Navigation and Search.

Organizing your documentation

While Docsy’s top-level sections let you create site sections for different types of content, you may also want to organize your docs content within your docs section. For example, this site’s docs section directory has multiple subdirectories for Getting Started, Content and Customization, and so on. Each subdirectory has an _index.md (it could also be an _index.html), which acts as a section index page and tells Hugo that the relevant directory is a subsection of your docs.

Docsy’s docs layout gives you a left nav pane with an autogenerated nested menu based on your docs file structure. Each standalone page or subsection _index.md or _index.html page in the 开发文档/ directory gets a top level menu item, using the link name and weight metadata from the page or index.

To add docs to a subsection, just add your page files to the relevant subdirectory. Any pages that you add to a subsection in addition to the subsection index page will appear in a submenu (look to the left to see one in action!), again ordered by page weight. Find out more about adding Docsy’s navigation metadata in Navigation and Search

If you’ve copied the example site, you’ll already have some suggested subdirectories in your docs directory, with guidance for what types of content to put in them and some example Markdown pages. You can find out more about organizing your content with Docsy in Organizing Your Content.

Docs section landing pages

By default a docs section landing page (the _index.md or _index.html in the section directory) uses a layout that adds a formatted list of links to the pages in the section, with their frontmatter descriptions. The Content and Customization landing page in this site is a good example.

To display a simple bulleted list of links to the section’s pages instead, specify simple_list: true in the landing page’s frontmatter:

+++
title = "Simple List Page"
simple_list = true
weight = 20
+++
---
title: "Simple List Page"
simple_list: true
weight: 20
---
{
  "title": "Simple List Page",
  "simple_list": true,
  "weight": 20
}

To display no links at all, specify no_list: true in the landing page’s frontmatter:

+++
title = "No List Page"
no_list = true
weight = 20
+++
---
title: "No List Page"
no_list: true
weight: 20
---
{
  "title": "No List Page",
  "no_list": true,
  "weight": 20
}

Organizing your blog posts

Docsy’s blog layout also gives you a left nav menu (like the docs layout), and a list-type index page for your blog that’s applied to /更新日志/_index.md and automatically displays snippets of all your recent posts in reverse chronological order.

To create different blog categories to organize your posts, create subfolders in 更新日志/. For instance, in our example site we have news and releases. Each category needs to have its own _index.md or _index.html landing page file specifying the category title for it to appear properly in the left nav and top-level blog landing page. Here’s the index page for releases:

+++
title = "New Releases"
linkTitle = "Releases"
weight = 20
+++
---
title: "New Releases"
linkTitle: "Releases"
weight: 20
---
{
  "title": "New Releases",
  "linkTitle": "Releases",
  "weight": 20
}

To add author and date information to blog posts, add them to the page frontmatter:

+++
date = 2018-10-06T00:00:00.000Z
title = "Easy documentation with Docsy"
linkTitle = "Announcing Docsy"
description = "The Docsy Hugo theme lets project maintainers and contributors focus on content, not on reinventing a website infrastructure from scratch"
author = "Riona MacNamara"

[[resources]]
src = "**.{png,jpg}"
title = "Image #:counter"

  [resources.params]
  byline = "Photo: Riona MacNamara / CC-BY-CA"
+++
---
date: 2018-10-06
title: "Easy documentation with Docsy"
linkTitle: "Announcing Docsy"
description: "The Docsy Hugo theme lets project maintainers and contributors focus on content, not on reinventing a website infrastructure from scratch"
author: Riona MacNamara
resources:
  - src: "**.{png,jpg}"
    title: "Image #:counter"
    params:
    byline: "Photo: Riona MacNamara / CC-BY-CA"
---
{
  "date": "2018-10-06T00:00:00.000Z",
  "title": "Easy documentation with Docsy",
  "linkTitle": "Announcing Docsy",
  "description": "The Docsy Hugo theme lets project maintainers and contributors focus on content, not on reinventing a website infrastructure from scratch",
  "author": "Riona MacNamara",
  "resources": [
    {
      "src": "**.{png,jpg}",
      "title": "Image #:counter",
      "params": {
        "byline": "Photo: Riona MacNamara / CC-BY-CA"
      }
    }
  ]
}

If you’ve copied the example site and you don’t want a blog section, or want to link to an external blog instead, just delete the blog subdirectory.

Working with top-level landing pages.

Docsy’s default page template has no left nav and is useful for creating a home page for your site or other “landing” type pages.

Customizing the example site pages

If you’ve copied the example site, you already have a simple site landing page in content/en/_index.html. This is made up of Docsy’s provided Hugo shortcode page blocks.

To customize the large landing image, which is in a cover block, replace the content/en/featured-background.jpg file in your project with your own image (it can be called whatever you like as long as it has background in the file name). You can remove or add as many blocks as you like, as well as adding your own custom content.

The example site also has an About page in content/en/项目简介/_index.html using the same Docsy template. Again, this is made up of page blocks, including another background image in content/en/项目简介/featured-background.jpg. As with the site landing page, you can replace the image, remove or add blocks, or just add your own content.

Building your own landing pages

If you’ve just used the theme, you can still use all Docsy’s provided page blocks (or any other content you want) to build your own landing pages in the same file locations.

Adding a community page

The community landing page template has boilerplate content that’s automatically filled in with the project name and community links specified in hugo.toml/hugo.yaml/hugo.json, providing your users with quick links to resources that help them get involved in your project. The same links are also added by default to your site footer.

[params.links]
# End user relevant links. These will show up on left side of footer and in the community page if you have one.
[[params.links.user]]
	name = "User mailing list"
	url = "https://example.org/mail"
	icon = "fa fa-envelope"
        desc = "参与讨论并从其他用户的回复中获取帮助"
[[params.links.user]]
	name ="Twitter"
	url = "https://example.org/twitter"
	icon = "fab fa-x-twitter"
        desc = "关注官方公众号获取最新消息!"
[[params.links.user]]
	name = "Stack Overflow"
	url = "https://example.org/stack"
	icon = "fab fa-stack-overflow"
        desc = "Practical questions and curated answers"
# Developer relevant links. These will show up on right side of footer and in the community page if you have one.
[[params.links.developer]]
	name = "GitHub"
	url = "https://github.com/quatm/quatm"
	icon = "fab fa-github"
        desc = "欢迎您在此施展才能、贡献才华!"
[[params.links.developer]]
	name = "Slack"
	url = "https://example.org/slack"
	icon = "fab fa-slack"
        desc = "Chat with other project developers"
[[params.links.developer]]
	name = "Developer mailing list"
	url = "https://example.org/mail"
	icon = "fa fa-envelope"
        desc = "Discuss development issues around the project"
params:
  links:
    user:
      - name: User mailing list
        url: 'https://example.org/mail'
        icon: fa fa-envelope
        desc: 参与讨论并从其他用户的回复中获取帮助
      - name: Twitter
        url: 'https://example.org/twitter'
        icon: fab fa-x-twitter
        desc: 关注官方公众号获取最新消息!
      - name: Stack Overflow
        url: 'https://example.org/stack'
        icon: fab fa-stack-overflow
        desc: Practical questions and curated answers
    developer:
      - name: GitHub
        url: 'https://github.com/quatm/quatm'
        icon: fab fa-github
        desc: 欢迎您在此施展才能、贡献才华!
      - name: Slack
        url: 'https://example.org/slack'
        icon: fab fa-slack
        desc: Chat with other project developers
      - name: Developer mailing list
        url: 'https://example.org/mail'
        icon: fa fa-envelope
        desc: Discuss development issues around the project
{
  "params": {
    "links": {
      "user": [
        {
          "name": "User mailing list",
          "url": "https://example.org/mail",
          "icon": "fa fa-envelope",
          "desc": "参与讨论并从其他用户的回复中获取帮助"
        },
        {
          "name": "Twitter",
          "url": "https://example.org/twitter",
          "icon": "fa-brands fa-x-twitter",
          "desc": "关注官方公众号获取最新消息!"
        },
        {
          "name": "Stack Overflow",
          "url": "https://example.org/stack",
          "icon": "fa-brands fa-stack-overflow",
          "desc": "Practical questions and curated answers"
        }
      ],
      "developer": [
        {
          "name": "GitHub",
          "url": "https://github.com/quatm/quatm",
          "icon": "fa-brands fa-github",
          "desc": "欢迎您在此施展才能、贡献才华!"
        },
        {
          "name": "Slack",
          "url": "https://example.org/slack",
          "icon": "fa-brands fa-slack",
          "desc": "Chat with other project developers"
        },
        {
          "name": "Developer mailing list",
          "url": "https://example.org/mail",
          "icon": "fa fa-envelope",
          "desc": "Discuss development issues around the project"
        }
      ]
    }
  }
}

If you’re creating your own site and want to add a page using this template, add a /技术交流/_index.md file in your content root directory. If you’ve copied the example site and don’t want a community page, just delete the /content/en/技术交流/ directory in your project repo.

Adding static content

You may want to serve some non-Hugo-built content along with your site: for example, if you have generated reference docs using Doxygen, Javadoc, or other doc generation tools.

To add static content to be served “as-is”, just add the content as a folder and/or files in your site’s static directory. When your site is deployed, content in this directory is served at the site root path. So, for example, if you have added content at /static/reference/cpp/, users can access that content at http://{server-url}/reference/cpp/ and you can link to pages in this directory from other pages at /reference/cpp/{file name}.

You can also use this directory for other files used by your project, including image files. You can find out more about serving static files, including configuring multiple directories for static content, in Static Files.

RSS feeds

Hugo will, by default, create an RSS feed for the home page and any section. For the main RSS feed you can control which sections to include by setting a site param in your hugo.toml/hugo.yaml/hugo.json. This is the default configuration:

[params]
rss_sections = ["blog"]
params:
  rss_sections: [blog]
{
  "params": {
    "rss_sections": [
      "blog"
      ]
  }
}

To disable all RSS feeds, add the following to your hugo.toml/hugo.yaml/hugo.json:

[params]
disableKinds = ["RSS"]
params:
  disableKinds: [RSS]
{
  "params": {
    "disableKinds": [
      "RSS"
      ]
  }
}

Sitemap

Hugo creates a sitemap.xml file for your generated site by default: for example, here’s the sitemap for this site.

You can configure the frequency with which your sitemap is updated, your sitemap filename, and the default page priority in your hugo.toml/hugo.yaml/hugo.json:

[sitemap]
  changefreq = "monthly"
  filename = "sitemap.xml"
  priority = 0.5
sitemap:
  changefreq: monthly
  filename: sitemap.xml
  priority: 0.5
{
  "sitemap": {
    "changefreq": "monthly",
    "filename": "sitemap.xml",
    "priority": 0.5
  }
}

To override any of these values for a given page, specify it in page frontmatter:

+++
title = "Adding Content"
linkTitle = "Adding Content"
weight = 1
description = '''
Add different types of content to your Docsy site.
'''
[sitemap]
priority = 1
+++
---
title: "Adding Content"
linkTitle: "Adding Content"
weight: 1
description: >
  Add different types of content to your Docsy site.  
sitemap:
  priority: 1.0
---
{
  "title": "Adding Content",
  "linkTitle": "Adding Content",
  "weight": 1,
  "description": "Add different types of content to your Docsy site.\n",
  "sitemap": {
    "priority": 1
  }
}

To learn more about configuring sitemaps, see Sitemap Template.

5.2 - Look and Feel

Customize colors, fonts, code highlighting, and more for your site.

By default, a site using Docsy has the theme’s default fonts, colors, and general look and feel. However, if you want your own color scheme (and you probably will!) you can very easily override the theme defaults with your own project-specific values - Hugo will look in your project files first when looking for information to build your site. And because [Docsy uses Bootstrap 5] and SCSS for styling, you can override just single values (such as project colors and fonts) in its special SCSS project variables file, or do more serious customization by creating your own styles.

Docsy also provides options for styling your code blocks, using either Chroma or Prism for highlighting.

Project style files

To customize your project’s look and feel, create your own version of the following Docsy placeholder files (note the _project*.scss suffixes) and place them inside your project’s assets/scss/ folder:

Colors and color themes

Site colors

To customize your site’s colors, add SCSS variable overrides to assets/scss/_variables_project.scss. For example, you can set the primary and secondary site colors as follows:

$primary: #390040;
$secondary: #a23b72;

Docsy has Bootstrap features such as gradient backgrounds ($enable-gradients) and shadows ($enable-shadows) enabled by default. These can also be toggled in your project variables file by setting the variables to false.

To add colors to or modify Bootstrap’s color maps, use assets/scss/_variables_project_after_bs.scss. For example:

$custom-colors: (
  'my-favorite-color': purple,
  'my-other-color': pink,
);

$theme-colors: map-merge($theme-colors, $custom-colors);

Learn how to modify maps, see Maps and loops and Adding theme colors.

Light/dark color themes

Docsy 0.10.0 supports light and dark mode color themes. To allow your website users to choose light/dark modes, enable the Docsy light/dark menu or create your own custom theme selector.

If your site uses Chroma for code highlighting, there are extra steps required so that code-block styles are compatible with light/dark mode:

For details, see Chroma for code highlighting.

Fonts

The theme uses Open Sans as its primary font. To disable Google Fonts and use a system font, set this SCSS variable in assets/scss/_variables_project.scss:

$td-enable-google-fonts: false;

To configure another Google Font:

$google_font_name: 'Open Sans';
$google_font_family: 'Open+Sans:300,300i,400,400i,700,700i';

Note that if you decide to go with a font with different weights (in the built-in configuration this is 300 (light), 400 (medium) and 700 (bold)), you also need to adjust the weight related variables, i.e. variables starting with $font-weight-.

CSS utilities

For documentation of available CSS utility classes, see the Bootstrap documentation. This theme adds very little on its own in this area. However, we have added some color state CSS classes that can be useful in a dynamic context:

  • .-bg-<color>
  • .-text-<color>

You can use these classes, for example, to style your text in an appropriate color when you don’t know if the primary color is dark or light, to ensure proper color contrast. They are also useful when you receive the color code as a shortcode parameter.

The value of <color> can be any of the color names, primary, white, dark, warning, light, success, 300, blue, orange etc.

When you use .-bg-<color>, the text colors will be adjusted to get proper contrast:

<div class="-bg-primary p-3 display-6">Background: Primary</div>
<div class="-bg-200 p-3 display-6">Background: Gray 200</div>
Background: Primary
Background: Gray 200

To only set the text color use .-text-<color>:

<div class="-text-blue pt-3 display-6">Text: Blue</div>
Text: Blue

Code highlighting with Chroma

As of Hugo 0.60+, you can choose from a range of code block highlight and color styles using Chroma. These styles are applied to your fenced code blocks. For details about code highlighting in Hugo using Chroma, see Syntax Highlighting.

Chroma style configuration

Hugo’s default Chroma style is monokai. To use another style, such as tango, add the following to your project configuration:

[markup]
  [markup.highlight]
      style = "tango"
markup:
  highlight:
    style: tango
{
  "markup": {
    "highlight": {
      "style": "tango"
    }
  }
}

For the complete list of available styles, see Chroma Style Gallery.

Light/dark code styles

Docsy’s default Chroma styles for light/dark mode are:

If you would like to use other styles, save the Hugo generated Chroma styles to the appropriate file:

Code blocks without a specified language

By default, highlighting is not applied to code blocks without a specified language. If you would like code highlighting to apply to all code blocks, even without a language, set markup.highlight.guessSyntax to true in your project’s configuration file.

Copy to clipboard

If you are using a Docsy 0.6.0 or later, code blocks show a “Copy to clipboard” button in the top right-hand corner. To disable this functionality, set disable_click2copy_chroma to true in your configuration file:

Code highlighting with Prism

Optionally, you can enable Prism syntax highlighting in your hugo.toml/hugo.yaml/hugo.json:

[params]
prism_syntax_highlighting = true
params:
  prism_syntax_highlighting: true
{
  "params": {
    "prism_syntax_highlighting": true
  }
}

When this option is enabled your site uses Prism instead of Chroma for code block highlighting.

Prism is a popular open source syntax highlighter which supports over 200 languages and various plugins.

Docsy includes JavaScript and CSS files for a basic Prism configuration, which supports:

  • Code blocks styled with the Prism Default theme
  • Copy to clipboard buttons on code blocks
  • Syntax highlighting for a number of common languages, as specified in the following Prism download link, Customize your download.

Code blocks with no language

By default, Prism code highlighting styles are not applied to code blocks without a specified language, instead you get Docsy’s default style of grey with black text. To apply Prism styling to code blocks with no language or a language not supported by Prism, specify none as the language after your triple backticks.

Extending Prism for additional languages or plugins

If the included Prism configuration is not sufficient for your requirements, and you want to use additional languages or plugins you can replace the included files with your own.

  1. Download your own Prism JS and CSS files from https://prismjs.com/download.html
  2. Replace the included Prism JS and CSS with the files you downloaded:
    • Copy the Javascript file to static/js/prism.js
    • Copy the CSS file to static/css/prism.css

Styling your project logo and name

The default Docsy navbar (.td-navbar) displays your site identity, consisting of the following:

  1. Your logo, which is included in the navbar as an inline SVG, styled by .td-navbar .navbar-brand svg. For the style details, see _nav.scss.

    To ensure your logo displays correctly, you may want to resize it and ensure that it doesn’t have height and width attributes so that its size is fully responsive. Override the default styling of .td-navbar .navbar-brand svg or (equivalently) .td-navbar .navbar-brand__logo as needed.

  2. Your project name, which is the site title. If you don’t want your project name to appear (for example, because your logo is or contains a wordmark), then add the following custom styling to your project’s styles:

    .td-navbar .navbar-brand__name {
      display: none;
    }
    

Light/dark mode menu

If you enable this feature, Docsy adds a menu to your navbar that lets users switch your site’s documentation page display between a default “light” mode, and a “dark” mode where the text is displayed in a light color on a dark background.

To enable the display of a light/dark mode menu in the navbar, set params.ui.showLightDarkModeMenu to true in your project’s configuration file. The dropdown menu appears at the right, immediately before the search box, if present.

[params]
[params.ui]
showLightDarkModeMenu = true
params:
  ui:
    showLightDarkModeMenu: true
{
  "params": {
    "ui": {
      "showLightDarkModeMenu": true
    }
  }
}

Translucent over cover images

For pages containing a blocks/cover shortcode, like most homepages, the navbar is translucent as long as the hero image hasn’t scrolled up past the navbar. For an example, see the About Docsy page. This initial translucent setting ensures that the hero image is maximally visible.

After the hero image has scrolled past the navbar, the navbar’s (opaque) background color is set – usually to the site’s primary color.

The text of navbar entries can be difficult to read with some hero images. In these cases, you can disable navbar translucency by setting the params.ui.navbar_translucent_over_cover_disable option to true in your site’s configuration file.

Tables

Docsy applies the following styles to all tables, through the class .td-table:

  • Bootstrap table styles:
    • .table
    • .table-striped
    • .table-responsive
  • display: block, which is necessary for tables to be responsive.

This styling configuration gives you responsive tables using Markdown only, without the need to wrap the table in a <div>. It does, however, mean that all your tables have display set to block. If you don’t want this, you can create your own custom styles for tables.

To render a table without Docsy styling, apply the .td-initial class to the table. From the resulting <table> style base, it is easier to apply your own custom styles (rather than trying to undo Docsy table styling), as is illustrated in the following example:

| Shape    | Number of sides |
| -------- | --------------- |
| Triangle | 3               |
| Square   | 4               |
{.td-initial .my-dark-table-style}

The example above uses Markdown attribute syntax, and might render like this:

ShapeNumber of sides
Triangle3
Square4

Customizing templates

Add code to head or before body end

If you need to add some code (CSS import, cookie consent, or similar) to the head section on every page, add the head-end.html partial to your project:

layouts/partials/hooks/head-end.html

And add the code you need in that file. Your partial code is automatically included just before the end of the theme partial head.html. The theme version of head-end.html is empty.

Similarly, if you want to add some code right before the body end, create your own version of the following file:

layouts/partials/hooks/body-end.html

Any code in this file is included automatically at the end of the theme partial scripts.html.

Both head.html and scripts.html are then used to build Docsy’s base page layout, which is used by all the other page templates:

<!doctype html>
<html lang="{{ .Site.Language.Lang }}" class="no-js">
  <head>
    {{ partial "head.html" . }}
  </head>
  <body class="td-{{ .Kind }}">
    <header>
      {{ partial "navbar.html" . }}
    </header>
    <div class="container-fluid td-default td-outer">
      <main role="main" class="td-main">
        {{ block "main" . }}{{ end }}
      </main>
      {{ partial "footer.html" . }}
    </div>
    {{ partialCached "scripts.html" . }}
  </body>
</html>

5.3 - Navigation and Menus

Customize site navigation for your Docsy site.

Docsy provides multiple built-in navigation features for your sites, including site menus, section menus, and page menus. This page shows you how they work and how to configure and customize them to meet your needs.

Top-level menu

The top level menu (the one that appears in the top navigation bar for the entire site) uses your site’s main menu. All Hugo sites have a main menu array of menu entries, accessible via the .Site.Menus site variable and populatable via page front matter or your site’s hugo.toml/hugo.yaml/hugo.json.

To add a page or section to this menu, add it to the site’s main menu in either hugo.toml/hugo.yaml/hugo.json or in the destination page’s front matter (in _index.md or _index.html for a section, as that’s the section landing page). For example, here’s how we added the Documentation section landing page to the main menu in this site:

+++
title = "Welcome to Docsy"
linkTitle = "Documentation"

[menu.main]
weight = 20
pre = "<i class='fa-solid fa-book'></i>"
+++
---
title: "Welcome to Docsy"
linkTitle: "Documentation"
menu:
  main:
    weight: 20
    pre: <i class='fa-solid fa-book'></i>
---
{
  "title": "Welcome to Docsy",
  "linkTitle": "Documentation",
  "menu": {
    "main": {
      "weight": 20,
      "pre": "<i class='fa-solid fa-book'></i>"
    }
  }
}

The menu is ordered from left to right by page weight. So, for example, a section index or page with weight: 30 would appear after the Documentation section in the menu, while one with weight: 10 would appear before it.

If you want to add a link to an external site to this menu, add it in hugo.toml/hugo.yaml/hugo.json, specifying the weight.

[[menu.main]]
    name = "GitHub"
    weight = 50
    url = "https://github.com/quatm/quatm/"
menu:
  main:
    - name: GitHub
      weight: 50
      url: 'https://github.com/quatm/quatm/'
{
  "menu": {
    "main": [
      {
        "name": "GitHub",
        "weight": 50,
        "url": "https://github.com/quatm/quatm/"
      }
    ]
  }
}

Adding icons to the top-level menu

As described in the Hugo docs, you can add icons to the top-level menu by using the pre and/or post parameter for main menu items defined in your site’s hugo.toml/hugo.yaml/hugo.json or via page front matter. For example, the following configuration adds the GitHub icon to the GitHub menu item, and a New! alert to indicate that this is a new addition to the menu.

[[menu.main]]
    name = "GitHub"
    weight = 50
    url = "https://github.com/quatm/quatm/"
    pre = "<i class='fa-brands fa-github'></i>"
    post = "<span class='alert'>New!</span>"
menu:
  main:
    - name: GitHub
      weight: 50
      url: 'https://github.com/quatm/quatm/'
      pre: <i class='fa-brands fa-github'></i>
      post: <span class='alert'>New!</span>
{
  "menu": {
    "main": [
      {
        "name": "GitHub",
        "weight": 50,
        "url": "https://github.com/quatm/quatm/",
        "pre": "<i class='fa-brands fa-github'></i>",
        "post": "<span class='alert'>New!</span>"
      }
    ]
  }
}

You can find a complete list of icons to use in the FontAwesome documentation. Docsy includes the free FontAwesome icons by default.

Adding a version drop-down

If you add some [params.versions] in hugo.toml, the Docsy theme adds a version selector drop down to the top-level menu.

You can find out more in the guide to versioning your docs.

Adding a language drop-down

If you configure more than one language in hugo.toml, the Docsy theme adds a language selector drop down to the top-level menu. Selecting a language takes the user to the translated version of the current page, or the home page for the given language.

You can find out more in Multi-language support.

Section menu

The section menu, as shown in the left side of the docs section, is automatically built from the content tree. Like the top-level menu, it is ordered by page or section index weight (or by page creation date if weight is not set), with the page or index’s Title, or linkTitle if different, as its link title in the menu. If a section subfolder has pages other than _index.md or _index.html, those pages will appear as a submenu, again ordered by weight. For example, here’s the metadata for this page showing its weight and title:

+++
title = "Navigation and Search"
linkTitle = "Navigation and Search"
date = 2017-01-05T00:00:00.000Z
weight = 3
description = '''
Customize site navigation and search for your Docsy site.
'''
+++
---
title: "Navigation and Search"
linkTitle: "Navigation and Search"
date: 2017-01-05
weight: 3
description: >
  Customize site navigation and search for your Docsy site.  
---
{
  "title": "Navigation and Search",
  "linkTitle": "Navigation and Search",
  "date": "2017-01-05T00:00:00.000Z",
  "weight": 3,
  "description": "Customize site navigation and search for your Docsy site.\n"
}

To hide a page or section from the left navigation menu, set toc_hide: true in the front matter.

To hide a page from the section summary on a docs section landing page, set hide_summary: true in the front matter. If you want to hide a page from both the TOC menu and the section summary list, you need to set both toc_hide and hide_summary to true in the front matter.

+++
title = "My Hidden Page"
weight = 99
toc_hide = true
hide_summary = true
description = '''
Page hidden from both the TOC menu and the section summary list.
'''
+++
---
title: "My Hidden Page"
weight: 99
toc_hide: true
hide_summary: true
description: >
  Page hidden from both the TOC menu and the section summary list.  
---
{
  "title": "My Hidden Page",
  "weight": 99,
  "toc_hide": true,
  "hide_summary": true,
  "description": "Page hidden from both the TOC menu and the section summary list.\n"
}

Section menu options

By default, the section menu shows the current section fully expanded all the way down. This may make the left nav too long and difficult to scan for bigger sites. Try setting site parameter ui.sidebar_menu_compact = true in hugo.toml.

With the compact menu (.ui.sidebar_menu_compact = true), only the current page’s ancestors, siblings and direct descendants are shown. You can use the optional parameter .ui.ul_show to set a desired menu depth to always be visible. For example, with .ui.ul_show = 1 the first menu level is always displayed.

As well as the completely expanded and compact menu options, you can also create a foldable menu by setting the site parameter ui.sidebar_menu_foldable = true in hugo.toml. The foldable menu lets users expand and collapse menu sections by toggling arrow icons beside the section parents in the menu.

On large sites (default: > 2000 pages) the section menu is not generated for each page, but cached for the whole section. The HTML classes for marking the active menu item (and menu path) are then set using JS. You can adjust the limit for activating the cached section menu with the optional parameter .ui.sidebar_cache_limit.

The tabbed pane below lists the menu section options you can define in your project [configuration file].

[params.ui]
sidebar_menu_compact = true
ul_show = 1
sidebar_menu_foldable = true
sidebar_cache_limit = 1000
params:
  ui:
    sidebar_menu_compact: true
    ul_show: 1
    sidebar_menu_foldable: true
    sidebar_cache_limit: 1000
{
  "params": {
    "ui": {
      "sidebar_menu_compact": true,
      "ul_show": 1,
      "sidebar_menu_foldable": true,
      "sidebar_cache_limit": 1000,
    }
  }
}

Add icons to the section menu

You can add icons to the section menu in the sidebar by setting the icon parameter in the page front matter (e.g. icon: fa-solid fa-screwdriver-wrench).

You can find a complete list of icons to use in the FontAwesome documentation. Docsy includes the free FontAwesome icons by default.

Out of the box, if you want to use icons, you should define icons for all items on the same menu level in order to ensure an appropriate look. If the icons are used in a different way, individual CSS adjustments are likely necessary.

By default the section menu is entirely generated from your section’s pages. If you want to add a manual link to this menu, such as a link to an external site or a page in a different section of your site, you can do this by creating a placeholder page file in the doc hierarchy with the appropriate weight and some special parameters in its metadata (frontmatter) to specify the link details.

To create a placeholder page, create a page file as usual in the directory where you want the link to show up in the menu, and add a manualLink parameter to its metadata. If a page has manualLink in its metadata, Docsy generates a link for it in the section menu for this page and in the section index (the list of the child pages of a section on a landing page - see description in the Docsy docs), but the link destination is replaced by the value of manualLink. The link text is the title (or linkTitle if set) of your placeholder page. You can optionally also set the title attribute of the link with the parameter manualLinkTitle and a link target with manualLinkTarget - for example if you want an external link to open in a new tab you can set the link target to _blank. Docsy automatically adds rel=noopener to links that open new tabs as a security best practice.

You can also use manualLink to add an additional cross reference to another existing page of your site. For internal links you can choose to use the parameter manualLinkRelref instead of manualLink to use the built-in Hugo function relref. If relref can’t find a unique page in your site, Hugo throws a error message.

Breadcrumb navigation links appear at the top of each page by default. To disable breadcrumb navigation, set site param ui.breadcrumb_disable = true in hugo.toml.

Breadcrumb navigation links are also shown for each item on the taxonomy results page (i.e. when you click one of the taxonomy labels, e.g. Tags/Categories). These breadcrumbs can be disabled in hugo.toml by setting site param ui.taxonomy_breadcrumb_disable = true.

The tabbed pane below lists the breadcrumb navigation options you can define in your project [configuration file].

[params.ui]
breadcrumb_disable = true
taxonomy_breadcrumb_disable = true
params:
  ui:
    breadcrumb_disable: true
    taxonomy_breadcrumb_disable: true
{
  "params": {
    "ui": {
      "breadcrumb_disable": true,
      "taxonomy_breadcrumb_disable": true
    }
  }
}

Docsy supports build-time generation of heading self links using Hugo’s render-heading.html hook.

To enable this feature in your project, define layouts/_default/_markup/render-heading.html as:

{{ template "_default/_markup/td-render-heading.html" . }}

The heading self-link anchor class is .td-heading-self-link, which you can customize for your project. By default, the heading self-link style has these defaults:

  • The self-link symbol is #.
  • The symbol is always visible on mobile and touch devices, otherwise it is only visible on hover or focus.

Your projects can also reuse (in your own custom heading render hook) or override the heading self-link template _default/_markup/_td-heading-self-link.html, which is defined in layouts/_default/_markup/td-render-heading.html.

5.4 - Search

Let users search your Docsy site with a choice of configurable search options.

Docsy offers multiple options that let your readers search your site content, so you can pick one that suits your needs. You can choose from:

  • Google Custom Search Engine (GCSE), the default option, which uses Google’s index of your public site to generate a search results page.
  • Algolia DocSearch, which uses Algolia’s indexing and search mechanism. Search results are displayed as a pop-up. Algolia DocSearch is free for public documentation sites.
  • Local search with Lunr, which uses Javascript to index and search your site without the need to connect to external services. This option doesn’t require your site to be public.

If you enable any of these search options in your project configuration file, a search box displays in the right of your top navigation bar. By default a search box also displays at the top of the section menu in the left navigation pane, which you can disable if you prefer, or if you’re using a search option that only works with the top search box.

By default, the search box appears in both the top navigation bar and at the top of the sidebar left navigation pane. If you don’t want the sidebar search box, set the site parameter sidebar_search_disable to true in hugo.toml/hugo.yaml/hugo.json:

[params.ui]
sidebar_search_disable = true
params:
  ui:
    sidebar_search_disable: true
{
  "params": {
    "ui": {
      "sidebar_search_disable": true
    }
  }
}

Configure search with a Google Custom Search Engine

By default Docsy uses a Google Custom Search Engine (GCSE) to search your site. To enable this feature, you’ll first need to make sure that you have built and deployed a production version of your site, as otherwise your site won’t be crawled and indexed.

  1. Create a Google Custom Search Engine for your deployed site by clicking New search engine on the Custom Search page and following the instructions. Make a note of the ID for your new search engine.

  2. Add any further configuration you want to your search engine using the Edit search engine options. In particular you may want to do the following:

    • Select Look and feel. Change from the default Overlay layout to Results only, as this option means your search results are embedded in your search page rather than appearing in a separate box. Click Save to save your changes.
    • Edit the default result link behavior so that search results from your site don’t open in a new tab. To do this, select Search Features - Advanced - Websearch Settings. In the Link Target field, type “_parent”. Click Save to save your changes.

Adding the search page

Once you have your search engine set up, you can add the feature to your site:

  1. Ensure you have a Markdown file in content/en/search.md (and one per other languages if needed) to display your search results. It only needs a title and layout: search, as in the following example:

    +++
    title = "Search Results"
    layout = "search"
    +++
    ---
    title: Search Results
    layout: search
    ---
    {
        "title": "Search Results",
        "layout": "search"
    }
  2. Add your Google Custom Search Engine ID to the site params in hugo.toml/hugo.yaml/hugo.json. You can add different values per language if needed.

    [params]
    # Google Custom Search Engine ID. Remove or comment out to disable search.
    gcs_engine_id = "011737558837375720776:fsdu1nryfng"
    params:
      gcs_engine_id: 011737558837375720776:fsdu1nryfng
    {
      "params": {
        "gcs_engine_id": "011737558837375720776:fsdu1nryfng"
      }
    }

If you don’t specify a Google Custom Search Engine ID for your project and haven’t enabled any other search options, the search box won’t appear in your site. If you’re using the default hugo.toml from the example site and want to disable search, just comment out or remove the relevant line.

Algolia DocSearch

As an alternative to GCSE, you can use Algolia DocSearch, which is free for public documentation sites. Docsy supports Algolia DocSearch v3.

Sign up for Algolia DocSearch

Complete the form at https://docsearch.algolia.com/apply. Proceed to the next step once you’ve received Algolia DocSearch parameters for your project.

Eager to test DocSearch?

Docsy defaults to the Algolia test-site parameters when none are provided. To enable search over the Algolia test, define params.search.algolia without any other fields, as outlined next.

Configure Algolia DocSearch

  1. Ensure that GCSE search is disabled.

  2. Add your project’s Algolia DocSearch parameters to hugo.toml/hugo.yaml/hugo.json, for example (using Algolia test values):

    [params.search.algolia]
    appId = "R2IYF7ETH7"
    apiKey = "599cec31baffa4868cae4e79f180729b"
    indexName = "docsearch"
    params:
      search:
        algolia:
          appId: R2IYF7ETH7
          apiKey: 599cec31baffa4868cae4e79f180729b
          indexName: docsearch
    {
      "params": {
        "search": {
          "algolia": {
            "appId": "R2IYF7ETH7",
            "apiKey": "599cec31baffa4868cae4e79f180729b",
            "indexName": "docsearch"
          }
        }
      }
    }

To learn more about Algolia DocSearch V3, see Getting started.

When you’ve completed these steps, Algolia search should be enabled on your site. Search results are displayed as a pop-up, so you don’t need to add any search results page.

Customizing Algolia templates

You can customize or disable Docsy’s default Algolia support by creating the following template files:

  • layouts/partials/algolia/head.html used by head.html to load Algolia DocSearch styles. It also issues a deprecation warning for params.algolia_docsearch.
  • layouts/partials/algolia/scripts.html used by scripts.html to load and configure Algolia DocSearch.

Leave either file empty to disable Docsy’s implementation.

Local search with Lunr

Lunr is a Javascript-based search option that lets you index your site and make it searchable without the need for external, server-side search services. This is a good option particularly for smaller or non-public sites.

To add Lunr search to your Docsy site:

  1. Enable local search in hugo.toml/hugo.yaml/hugo.json.

    [params]
    offlineSearch = true
    params:
      offlineSearch: true
    {
      "params": {
        "offlineSearch": true
      }
    }
  2. Remove or comment out any GCSE ID in hugo.toml/hugo.yaml/hugo.json and ensure Algolia DocSearch is set to false, as you can only have one type of search enabled. See Disabling GCSE search.

Once you’ve completed these steps, local search is enabled for your site and results appear in a drop down when you use the search box.

Changing the summary length of the local search results

You can customize the summary length by setting offlineSearchSummaryLength in hugo.toml/hugo.yaml/hugo.json.

#Enable offline search with Lunr.js
[params]
offlineSearch = true
offlineSearchSummaryLength = 200
params:
  offlineSearch: true
  offlineSearchSummaryLength: 200
{
  "params": {
    "offlineSearch": true,
    "offlineSearchSummaryLength": 200
  }
}

You can customize the maximum result count by setting offlineSearchMaxResults in hugo.toml/hugo.yaml/hugo.json.

[params]
offlineSearch = true
offlineSearchMaxResults = 25
params:
  offlineSearch: true
  offlineSearchMaxResults: 25
{
  "params": {
    "offlineSearch": true,
    "offlineSearchMaxResults": 25
  }
}

Changing the width of the local search results popover

The width of the search results popover will automatically widen according to the content.

If you want to limit the width, add the following scss into assets/scss/_variables_project.scss.

.td-offline-search-results {
  max-width: 460px;
}

Excluding pages from local search results

To exclude pages from local search results, add exclude_search: true to the the frontmatter of each page:

+++
title = "Index"
weight = 10
exclude_search = true
+++
---
title: "Index"
weight: 10
exclude_search: true
---
{
  "title": "Index",
  "weight": 10,
  "exclude_search": true
}

5.5 - Doc Versioning

Customize navigation and banners for multiple versions of your docs.

Depending on your project’s releases and versioning, you may want to let your users access previous versions of your documentation. How you deploy the previous versions is up to you. This page describes the Docsy features that you can use to provide navigation between the various versions of your docs and to display an information banner on the archived sites.

Adding a version drop-down menu

If you add some [params.versions] in hugo.toml/hugo.yaml/hugo.json, the Docsy theme adds a version selector drop down to the top-level menu. You specify a URL and a name for each version you would like to add to the menu, as in the following example:

# Add your release versions here
[[params.versions]]
  version = "master"
  url = "https://master.kubeflow.org"

[[params.versions]]
  version = "v0.2"
  url = "https://v0-2.kubeflow.org"

[[params.versions]]
  version = "v0.3"
  url = "https://v0-3.kubeflow.org"
params:
  versions:
    - version: master
      url: 'https://master.kubeflow.org'
    - version: v0.2
      url: 'https://v0-2.kubeflow.org'
    - version: v0.3
      url: 'https://v0-3.kubeflow.org'
{
  "params": {
    "versions": [
      {
        "version": "master",
        "url": "https://master.kubeflow.org"
      },
      {
        "version": "v0.2",
        "url": "https://v0-2.kubeflow.org"
      },
      {
        "version": "v0.3",
        "url": "https://v0-3.kubeflow.org"
      }
    ]
  }
}

Remember to add your current version so that users can navigate back!

The default title for the version drop-down menu is Releases. To change the title, change the site parameter version_menu in hugo.toml/hugo.yaml/hugo.json:

[params]
version_menu = "Releases"
params:
  version_menu: Releases
{
  "params": {
    "version_menu": "Releases"
  }
}

If you set the version_menu_pagelinks parameter to true, then links in the version drop-down menu point to the current page in the other version, instead of the main page. This can be useful if the document doesn’t change much between the different versions. Note that if the current page doesn’t exist in the other version, the link will be broken.

You can read more about Docsy menus in the guide to navigation and search.

Displaying a banner on archived doc sites

If you create archived snapshots for older versions of your docs, you can add a note at the top of every page in the archived docs to let readers know that they’re seeing an unmaintained snapshot and give them a link to the latest version.

For example, see the archived docs for Kubeflow v0.6:

A text box explaining that this is an unmaintained snapshot of the docs.
Figure 1. The banner on the archived docs for Kubeflow v0.6

To add the banner to your doc site, make the following changes in your hugo.toml/hugo.yaml/hugo.json file:

  1. Set the site parameter archived_version to true:

    [params]
    archived_version = true
    params:
      archived_version: true
    {
      "params": {
        "archived_version": true
      }
    }
  2. Set the site parameter version to the version of the archived doc set. For example, if the archived docs are for version 0.1:

    [params]
    version = "0.1"
    params:
      version: 0.1
    {
      "params": {
        "version": "0.1"
      }
    }
  3. Make sure that site parameter url_latest_version contains the URL of the website that you want to point readers to. In most cases, this should be the URL of the latest version of your docs:

    [params]
    url_latest_version = "https://your-latest-doc-site.com"
    params:
      url_latest_version: https://your-latest-doc-site.com
    {
      "params": {
        "url_latest_version": "https://your-latest-doc-site.com"
      }
    }

5.6 - Docsy Shortcodes

Use Docsy’s Hugo shortcodes to quickly build site pages.

Rather than writing all your site pages from scratch, Hugo lets you define and use shortcodes. These are reusable snippets of content that you can include in your pages, often using HTML to create effects that are difficult or impossible to do in simple Markdown. Shortcodes can also have parameters that let you, for example, add your own text to a fancy shortcode text box. As well as Hugo’s built-in shortcodes, Docsy provides some shortcodes of its own to help you build your pages.

Shortcode delimiters

As illustrated below, using the bracket styled shortcode delimiter, {{<...>}}, tells Hugo that the inner content is HTML/plain text and needs no further processing. By using the delimiter {{%...%}}, Hugo will treat the shortcode body as Markdown. You can use both styles in your pages.

Shortcode blocks

The theme comes with a set of custom Page Block shortcodes that can be used to compose landing pages, about pages, and similar.

These blocks share some common parameters:

height
A pre-defined height of the block container. One of min, med, max, full, or auto. Setting it to full will fill the Viewport Height, which can be useful for landing pages.
color
The block will be assigned a color from the theme palette if not provided, but you can set your own if needed. You can use all of Bootstrap’s color names, theme color names or a grayscale shade. Some examples would be primary, white, dark, warning, light, success, 300, blue, orange. This will become the background color of the block, but text colors will adapt to get proper contrast.

blocks/cover

The blocks/cover shortcode creates a landing page type of block that fills the top of the page.

{{< blocks/cover title="Welcome!" image_anchor="center" height="full" color="primary" >}}
<div class="mx-auto">
	<a class="btn btn-lg btn-primary me-3 mb-4" href="{{< relref "/docs" >}}">
		Learn More <i class="fa-solid fa-circle-right ms-2"></i>
	</a>
	<a class="btn btn-lg btn-secondary me-3 mb-4" href="https://example.org">
		Download <i class="fa-brands fa-github ms-2"></i>
	</a>
	<p class="lead mt-5">This program is now available in <a href="#">AppStore!</a></p>
	<div class="mx-auto mt-5">
		{{< blocks/link-down color="info" >}}
	</div>
</div>
{{< /blocks/cover >}}

Note that the relevant shortcode parameters above will have sensible defaults, but is included here for completeness.

ParameterDefaultDescription
titleThe main display title for the block.
image_anchor
heightSee above.
colorSee above.
bylineByline text on featured image.

To set the background image, place an image with the word “background” in the name in the page’s Page Bundle. For example, in our the example site the background image in the home page’s cover block is featured-background.jpg, in the same directory.

For available icons, see Font Awesome.

blocks/lead

The blocks/lead block shortcode is a simple lead/title block with centred text and an arrow down pointing to the next section.

{{% blocks/lead color="dark" %}}
TechOS is the OS of the future.

Runs on **bare metal** in the **cloud**!
{{% /blocks/lead %}}
ParameterDefaultDescription
heightautoSee Shortcode blocks
color.OrdinalSee Shortcode blocks

blocks/section

The blocks/section shortcode is meant as a general-purpose content container. It comes in two “flavors”, one for general content and one with styling more suitable for wrapping a horizontal row of feature sections.

The example below shows a section wrapping 3 feature sections.

{{< blocks/section color="dark" type="row" >}}
{{% blocks/feature icon="fa-lightbulb" title="Fastest OS **on the planet**!" %}}
The new **TechOS** operating system is an open source project. It is a new project, but with grand ambitions.
Please follow this space for updates!
{{% /blocks/feature %}}
{{% blocks/feature icon="fa-brands fa-github" title="Contributions welcome!" url="https://github.com/gohugoio/hugo" %}}
We do a [Pull Request](https://github.com/gohugoio/hugo/pulls) contributions workflow on **GitHub**. New users are always welcome!
{{% /blocks/feature %}}
{{% blocks/feature icon="fa-brands fa-x-twitter" title="Follow us on Twitter!" url="https://twitter.com/GoHugoIO" %}}
For announcement of latest features etc.
{{% /blocks/feature %}}
{{< /blocks/section >}}
ParameterDefaultDescription
heightSee above.
colorSee above.
typeSpecify “container” (the default) if you want a general container, or “row” if the section will contain columns – which must be immediate children.

blocks/feature

{{% blocks/feature icon="fa-brands fa-github" title="Contributions welcome!" url="https://github.com/gohugoio/hugo" %}}
We do a [Pull Request](https://github.com/gohugoio/hugo/pulls) contributions workflow on **GitHub**. New users are always welcome!
{{% /blocks/feature %}}
ParameterDefaultDescription
titleThe title to use.
urlThe URL to link to.
url_textThe language parameter value of ui_read_moreThe link text to use.
iconThe icon class to use.

The blocks/link-down shortcode creates a navigation link down to the next section. It’s meant to be used in combination with the other blocks shortcodes.

<div class="mx-auto mt-5">
	{{< blocks/link-down color="info" >}}
</div>
ParameterDefaultDescription
colorinfoSee above.

Shortcode helpers

alert

The alert shortcode creates an alert block that can be used to display notices or warnings.

{{% alert title="Warning" color="warning" %}}
This is a warning.
{{% /alert %}}

Renders to:

ParameterDefaultDescription
colorprimaryOne of the theme colors, eg primary, info, warning etc.

pageinfo

The pageinfo shortcode creates a text box that you can use to add banner information for a page: for example, letting users know that the page contains placeholder content, that the content is deprecated, or that it documents a beta feature.

{{% pageinfo color="info" %}}
This is placeholder content.
{{% /pageinfo %}}

Renders to:

This is placeholder content

ParameterDefaultDescription
colorprimaryOne of the theme colors, eg primary, info, warning etc.

imgproc

The imgproc shortcode finds an image in the current Page Bundle and scales it given a set of processing instructions.

{{% imgproc spruce Fill "400x450" %}}
Norway Spruce *Picea abies* shoot with foliage buds.
{{% /imgproc %}}

Use the syntax above if the inner content and/or the byline parameter of your shortcode is authored in markdown. In case of HTML content, use <> as innermost delimiters: {{< imgproc >}}<b>HTML</b> content{{< /imgproc >}}.

Norway Spruce Picea abies shoot with foliage buds.
Photo: Bjørn Erik Pedersen / CC-BY-SA

The example above has also a byline with photo attribution added. When using illustrations with a free license from WikiMedia and similar, you will in most situations need a way to attribute the author or licensor. You can add metadata to your page resources in the page front matter. The byline param is used by convention in this theme:

+++
[[resources]]
src = "**spruce*.jpg"

  [resources.params]
  byline = "*Photo*: Bjørn Erik Pedersen / CC-BY-SA"
+++
---
resources:
- src: "**spruce*.jpg"
  params:
    byline: "*Photo*: Bjørn Erik Pedersen / CC-BY-SA"
---
{
  "resources": [
    {
      "src": "**spruce*.jpg",
      "params": {
        "byline": "*Photo*: Bjørn Erik Pedersen / CC-BY-SA"
      }
    }
  ]
}
ParameterDescription
1The image filename or enough of it to identify it (we do Glob matching)
2Command. One of Fit, Resize, Fill or Crop. See Image Processing Methods.
3Processing options, e.g. 400x450 r180. See Image Processing Options.

swaggerui

You can place the swaggerui shortcode anywhere inside a page with the swagger layout; it renders Swagger UI using any OpenAPI YAML or JSON file as source. This file can be hosted anywhere you like, for example in your site’s root /static folder.

+++
title = "Pet Store API"
type = "swagger"
weight = 1
description = "Reference for the Pet Store API"
+++

{{< swaggerui src="/openapi/petstore.yaml" >}}
---
title: "Pet Store API"
type: swagger
weight: 1
description: Reference for the Pet Store API
---

{{< swaggerui src="/openapi/petstore.yaml" >}}
{
  "title": "Pet Store API",
  "type": "swagger",
  "weight": 1,
  "description": "Reference for the Pet Store API"
}

{{< swaggerui src="/openapi/petstore.yaml" >}}

You can customize Swagger UI’s look and feel by overriding Swagger’s CSS in themes/docsy/assets/scss/_swagger.scss.

redoc

The redoc shortcode uses the open-source Redoc tool to render reference API documentation from an OpenAPI YAML or JSON file. This can be hosted anywhere you like, for example in your site’s root /static folder, but you can use a URL as well, for example:

---
title: "Pet Store API"
type: docs
weight: 1
description: Reference for the Pet Store API
---

{{< redoc "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v2.0/yaml/petstore.yaml" >}}

iframe

With this shortcode you can embed external content into a Docsy page as an inline frame (iframe) - see: https://www.w3schools.com/tags/tag_iframe.asp

ParameterDefaultDescription
srcURL of external content
width100%Width of iframe
tryautoheighttrueIf true the shortcode tries to calculate the needed height for the embedded content using JavaScript, as described here: https://stackoverflow.com/a/14618068. This is only possible if the embedded content is on the same domain. Note that even if the embedded content is on the same domain, it depends on the structure of the content if the height can be calculated correctly.
stylemin-height:98vh; border:none;CSS styles for the iframe. min-height:98vh; is a backup if tryautoheight doesn’t work. border:none; removes the border from the iframe - this is useful if you want the embedded content to look more like internal content from your page.
sandboxfalseYou can switch the sandbox completely on by setting sandbox = true or allow specific functionality with the common values for the iframe parameter sandbox defined in the HTML standard.
nameiframe-nameSpecify the name of the iframe.
idiframe-idSets the ID of the iframe.
classOptional parameter to set the classes of the iframe.
subYour browser cannot display embedded frames. You can access the embedded page via the following link:The text displayed (in addition to the embedded URL) if the user’s browser can’t display embedded frames.

Tabbed panes

Sometimes it’s very useful to have tabbed panes when authoring content. One common use-case is to show multiple syntax highlighted code blocks that showcase the same problem, and how to solve it in different programming languages. As an example, the tabbed pane below shows the language-specific variants of the famous Hello world! program one usually writes first when learning a new programming language:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  puts("Hello World!");
  return EXIT_SUCCESS;
}
#include <iostream>

int main()
{
  std::cout << "Hello World!" << std::endl;
}
package main
import "fmt"
func main() {
  fmt.Printf("Hello World!\n")
}
class HelloWorld {
  static public void main( String args[] ) {
    System.out.println( "Hello World!" );
  }
}
fun main(args : Array<String>) {
    println("Hello, world!")
}
print "Hello world"
<?php
echo 'Hello World!';
?>
print("Hello World!")
puts "Hello World!"
object HelloWorld extends App {
  println("Hello world!")
}

The Docsy template provides two shortcodes tabpane and tab that let you easily create tabbed panes. To see how to use them, have a look at the following code block, which renders to a right aligned pane with one disabled and three active tabs:

{{< tabpane text=true right=true >}}
  {{% tab header="**Languages**:" disabled=true /%}}
  {{% tab header="English" lang="en" %}}
  ![Flag United Kingdom](flags/uk.png)
  Welcome!
  {{% /tab %}}
  {{< tab header="German" lang="de" >}}
    <b>Herzlich willkommen!</b>
    <img src="flags/de.png" alt="Flag Germany" style="float: right; padding: 0 0 0 0px">
  {{< /tab >}}
  {{% tab header="Swahili" lang="sw" %}}
  ![Flag Tanzania](flags/tz.png)
  **Karibu sana!**
  {{% /tab %}}
{{< /tabpane >}}

This code translates to the right aligned tabbed pane below, showing a Welcome! greeting in English, German or Swahili:

Flag United Kingdom Welcome!

Herzlich willkommen! Flag Germany

Flag Tanzania Karibu sana!

Shortcode details

Tabbed panes are implemented using two shortcodes: tabpane containing two or more nested tabs.

tabpane

The tabpane shortcode, which is the container element for the tabs, supports the following named parameters, all of which are optional:

  • lang: the default code-block language to use for all contained tabs
  • highlight: parameter passed on to the code-block highlight function, as described below
  • langEqualsHeader: set to true when header text matches the tab language.
  • persist: one of header, lang, or disabled
  • persistLang: deprecated, use persist instead
  • right: set to true if you want right-aligned tabs
  • text: set to true if the content of all contained tabs are text. Default is false and assumes the content is code.

The value of the optional parameters lang and highlight are passed on as second LANG and third OPTIONS arguments to Hugo’s built-in highlight function, which is used to render the code blocks of the individual tabs.

Tab selection is persisted by default. When unspecified, persist defaults to header when text=true or lang is set; otherwise persist defaults to lang. To disable tab persistence, set persist=disable.

tab

The tab shortcode represent the tabs you want to show. It supports the following named parameters, all of which are optional:

  • header: defines the tab’s header text. When omitted it defaults to text of the form “Tab n”. You can omit the parameter name if it is the only tab parameter:
    {{< tab "My tab header" >}} … {{< /tab >}}
    
  • lang: code-block language for code tabs
  • highlight: parameter passed on to the code-block highlight function
  • right: set to true in order to split tab panes into a left aligned and a right aligned tab groups. Specify right=true in the dividing tab. By using right=true more than once, you can even render multiple tab groups.
  • disabled: set to true to disable a tab.
  • text: set to true for text tabs. By default tabs are assumed to contain code.

For enabled tabs, there are two modes for content display, code representation and textual representation:

  • By default, the tab’s content is rendered as a code block. In order to get proper syntax highlighting, specify the named parameter lang –and optionally the parameter highlight– for each tab. Parameters set in the parent tabpane shortcode will be overwritten.
  • If the contents of your tabs should be rendered as text with different styles and optional images, specify text=true as parameter of your tab:

Reminder: If your content is markdown, use the percent sign % as delimiter for your tab shortcode, like this:

{{% tab %}} Your \*\*markdown\*\* content {{% /tab %}}

Card panes

When authoring content, it’s sometimes very useful to put similar text blocks or code fragments on card like elements, which can be optionally presented side by side. Let’s showcase this feature with the following sample card group which shows the first four Presidents of the United States:

George Washington
*1732     †1799
President: 1789 – 1797

PortraitGeorgeWashington

John Adams
* 1735     † 1826
President: 1797 – 1801

PortraitJohnAdams

Thomas Jefferson
* 1743     † 1826
President: 1801 – 1809

PortraitThomasJefferson

James Madison
* 1751     † 1836
President: 1809 – 1817

PortraitJamesMadison

Docsy supports creating such card panes via different shortcodes:

  • The cardpane shortcode which is the container element for the various cards to be presented.
  • The card shortcodes, with each shortcode representing an individual card. While cards are often presented inside a card group, a single card may stand on its own, too. A card shortcode can hold programming code, text, images or any other arbitrary kind of markdown or HTML markup as content. In case of programming code, cards provide automatic code-highlighting and other optional features like line numbers, highlighting of certain lines, ….

Shortcode card: textual content

Make use of the card shortcode to display a card. The following code sample demonstrates how to code a card element:

{{< card header="**Imagine**" title="Artist and songwriter: John Lennon" subtitle="Co-writer: Yoko Ono"
          footer="![SignatureJohnLennon](https://server.tld/…/signature.png 'Signature John Lennon')">}}
Imagine there's no heaven, It's easy if you try<br/>
No hell below us, above us only sky<br/>
Imagine all the people living for today…

{{< /card >}}

This code translates to the left card shown below, showing the lyrics of John Lennon’s famous song Imagine. A second explanatory card element to the right indicates and explains the individual components of a card:

Imagine
Artist and songwriter: John Lennon
Co-writer: Yoko Ono

Imagine there’s no heaven, It’s easy if you try
No hell below us, above us only sky
Imagine all the people living for today…

Imagine there’s no countries, it isn’t hard to do
Nothing to kill or die for, and no religion too
Imagine all the people living life in peace…

Imagine no possessions, I wonder if you can
No need for greed or hunger - a brotherhood of man
Imagine all the people sharing all the world…

You may say I’m a dreamer, but I’m not the only one
I hope someday you’ll join us and the world will live as one

Header: specified via named parameter Header
Card title: specified via named parameter title
Card subtitle: specified via named parameter subtitle

Content: inner content of the shortcode, this may be plain text or formatted text, images, videos, … . If your content is markdown, use the percent sign % as outermost delimiter of your card shortcode, your markup should look like {{% card %}}Your **markdown** content{{% /card %}}. In case of HTML content, use square brackets <> as outermost delimiters: {{< card >}}Your <b>HTML</b> content{{< /card >}}

While the main content of the card is taken from the inner markup of the card shortcode, the optional elements footer, header, title, and subtitle are all specified as named parameters of the shortcode.

Shortcode card: programming code

If you want to display programming code on your card, set the named parameter code of the card to true. The following sample demonstrates how to code a card element with the famous Hello world! application coded in C:

{{< card code=true header="**C**" lang="C" >}}
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  puts("Hello World!");
  return EXIT_SUCCESS;
}
{{< /card >}}

This code translates to the card shown below:

C

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  puts("Hello World!");
  return EXIT_SUCCESS;
}


If called with parameter code=true, the card shortcode can optionally hold the named parameters lang and/or highlight. The values of these optional parameters are passed on as second LANG and third OPTIONS arguments to Hugo’s built-in highlight function which is used to render the code block presented on the card.

Card groups

Displaying two ore more cards side by side can be easily achieved by putting them between the opening and closing elements of a cardpane shortcode. The general markup of a card group resembles closely the markup of a tabbed pane:

{{< cardpane >}}
  {{< card header="Header card 1" >}}
    Content card 1
  {{< /card >}}
  {{< card header="Header card 2" >}}
    Content card 2
  {{< /card >}}
  {{< card header="Header card 3" >}}
    Content card 3
  {{< /card >}}
{{< /cardpane >}}

Contrary to tabs, cards are presented side by side, however. This is especially useful it you want to compare different programming techniques (traditional vs. modern) on two cards, like demonstrated in the example above:

Java 5

File[] hiddenFiles = new File("directory_name")
  .listFiles(new FileFilter() {
    public boolean accept(File file) {
      return file.isHidden();
    }
  });
Java 8, Lambda expression

File[] hiddenFiles = new File("directory_name")
  .listFiles(File::isHidden);

Include external files

Sometimes there’s content that is relevant for several documents, or that is maintained in a file that is not necessarily a document. For situations like these, the readfile shortcode allows you to import the contents of an external file into a document.

Reuse documentation

In case you want to reuse some content in several documents, you can write said content in a separate file and include it wherever you need it.

For example, suppose you have a file called installation.md with the following contents:

## Installation

{{% alert title="Note" color="primary" %}}
Check system compatibility before proceeding.
{{% /alert %}}

1.  Download the installation files.

1.  Run the installation script

    `sudo sh install.sh`

1.  Test that your installation was successfully completed.

You can import this section into another document:

The following section explains how to install the database:

{{% readfile "installation.md" %}}

This is rendered as if the instructions were in the parent document. Hugo v0.101.0+ is required for imported files containing shortcodes to be rendered correctly.


The following section explains how to install the database:

Installation

  1. Download the installation files.

  2. Run the installation script

    sudo sh install.sh

  3. Test that your installation was successfully completed.


The parameter is the relative path to the file. Only relative paths under the parent file’s working directory are supported.

For files outside the current working directory you can use an absolute path starting with /. The root directory is the /content folder.

Include code files

Suppose you have an includes folder containing several code samples you want to use as part of your documentation. You can use readfile with some additional parameters:

To create a new pipeline, follow the next steps:

1.  Create a configuration file `config.yaml`:

    {{< readfile file="includes/config.yaml" code="true" lang="yaml" >}}

1.  Apply the file to your cluster `kubectl apply config.yaml`

This code automatically reads the content of includes/config.yaml and inserts it into the document. The rendered text looks like this:


To create a new pipeline, follow the next steps:

  1. Create a configuration file config.yaml:

    apiVersion: tekton.dev/v1beta1
        kind: Task
        metadata:
          name: hello
        spec:
          steps:
            - name: echo
              image: alpine
              script: |
                #!/bin/sh
                echo "Hello World"          
        
  2. Apply the file to your cluster kubectl apply config.yaml


The file parameter is the relative path to the file. Only relative paths under the parent file’s working directory are supported.

For files outside the current working directory you can use an absolute path starting with /. The root directory is the /content folder.

ParameterDefaultDescription
filePath of external file
codefalseBoolean value. If true the contents is treated as code
langplain textProgramming language

Error reporting

If the shortcode can’t find the specified file, the shortcode throws a compile error.

In the following example, Hugo throws a compile error if it can’t find includes/deploy.yml:

{{< readfile file="includes/deploy.yaml" code="true" lang="yaml" >}}

Alternately, Hugo you can display a message on the rendered page instead of throwing a compile error. Add draft="true" as a parameter. For example:

{{< readfile file="includes/deploy.yaml" code="true" lang="yaml" draft="true" >}}

Conditional text

The conditional-text shortcode allows you to show or hide parts of your content depending on the value of the buildCondition parameter set in your configuration file. This can be useful if you are generating different builds from the same source, for example, using a different product name. This shortcode helps you handle the minor differences between these builds.

{{% conditional-text include-if="foo" %}}
This text appears in the output only if `buildCondition = "foo" is set in your config file`.
{{% /conditional-text %}}
{{% conditional-text exclude-if="bar" %}}
This text does not appear in the output if `buildCondition = "bar" is set in your config file`.
{{% /conditional-text %}}

If you are using this shortcode, note that when evaluating the conditions, substring matches are matches as well. That means, if you set include-if="foobar", and buildcondition = "foo", you have a match!

5.7 - Logos and Images

Add and customize logos, icons, and images in your project.

By default, Docsy shows a site logo at the start of the navbar, that is, at the extreme left. Place your project’s SVG logo in assets/icons/logo.svg. This overrides the default Docsy logo in the theme.

If you don’t want a logo to appear in the navbar, then set site parameter navbar_logo to false in your project’s config:

[params.ui]
navbar_logo = false
params:
  ui:
    navbar_logo: false
{
  "params": {
    "ui": {
      "navbar_logo": false
    }
  }
}

For information about styling your logo, see Styling your project logo and name.

Use icons

Docsy includes the free FontAwesome icons by default, including logos for sites like GitHub and Stack Overflow. You can view all available icons in the FontAwesome documentation, including the FontAwesome version when the icon was added and whether it is available for free tier users. Check Docsy’s package.json and release notes for Docsy’s currently included version of FontAwesome.

You can add FontAwesome icons to your top-level menu, section menu, or anywhere in your text.

Add your favicons

The easiest way to do this is to create a set of favicons via http://cthedot.de/icongen (which lets you create a huge range of icon sizes and options from a single image) and/or https://favicon.io, and put them in your site project’s static/favicons directory. This will override the default favicons from the theme.

Note that https://favicon.io doesn’t create as wide a range of sizes as Icongen but does let you quickly create favicons from text: if you want to create text favicons you can use this site to generate them, then use Icongen to create more sizes (if necessary) from your generated .png file.

If you have special favicon requirements, you can create your own layouts/partials/favicons.html with your links.

Add images

Landing pages

Docsy’s blocks/cover shortcode make it easy to add large cover images to your landing pages. The shortcode looks for an image with the word “background” in the name inside the landing page’s Page Bundle - so, for example, if you’ve copied the example site, the landing page image in content/en/_index.html is content/en/featured-background.jpg.

You specify the preferred display height of a cover block container (and hence its image) using the block’s height parameter. For a full viewport height, use full:

{{< blocks/cover title="Welcome to the Docsy Example Project!" image_anchor="top" height="full" >}}
...
{{< /blocks/cover >}}

For a shorter image, as in the example site’s About page, use one of min, med, max or auto (the actual height of the image):

{{< blocks/cover title="About the Docsy Example" image_anchor="bottom" height="min" >}}
...
{{< /blocks/cover >}}

Other pages

To add inline images to other pages, use the imgproc shortcode. Alternatively, if you prefer, just use regular Markdown or HTML images and add your image files to your project’s static directory. You can find out more about using this directory in Adding static content.

Images used on this site

Images used as background images in this site are in the public domain and can be used freely. The porridge image in the example site is by iha31 from Pixabay.

5.8 - Print Support

Making it easier to print entire sections of documentation.

Individual documentation pages print well from most browsers as the layouts have been styled to omit navigational chrome from the printed output.

On some sites, it can be useful to enable a “print entire section” feature (as seen in this user guide). Selecting this option renders the entire current top-level section (such as Content and Customization for this page) with all of its child pages and sections in a format suited to printing, complete with a table of contents for the section.

To enable this feature, add the “print” output format in your site’s hugo.toml/hugo.yaml/hugo.json file for the “section” type:

[outputs]
section = [ "HTML", "RSS", "print" ]
outputs:
  section:
    - HTML
    - RSS
    - print
{
  "outputs": {
    "section": [
      "HTML",
      "RSS",
      "print"
    ]
  }
}

The site should then show a “Print entire section” link in the right hand navigation.

Further Customization

Disabling the ToC

To disable showing the the table of contents in the printable view, set the disable_toc param to true, either in the page front matter, or in hugo.toml/hugo.yaml/hugo.json:

+++

disable_toc = true

+++
---

disable_toc: true

---
{
  …,
  "disable_toc": true,
  
}
[params.print]
disable_toc = true
params:
  print:
    disable_toc: true
{
  "params": {
    "print": {
      "disable_toc": true
    }
  }
}

Layout hooks

A number of layout partials and hooks are defined that can be used to customize the printed format. These can be found in layouts/partials/print.

Hooks can be defined on a per-type basis. For example, you may want to customize the layouts of heading for “blog” pages vs “docs”. This can be achieved by creating layouts/partials/print/page-heading-<type>.html - eg. page-heading-blog.html. It defaults to using the page title and description as a heading.

Similarly, the formatting for each page can be customized by creating layouts/partials/print/content-<type>.html.

5.9 - Analytics, User Feedback, and SEO

Add Google Analytics tracking to your site, collect user feedback and learn about the page description meta tag.

Adding Analytics

The Docsy theme builds upon Hugo’s support for Google Analytics, which Hugo provides through internal templates. Once you set up analytics as described below, usage information for your site (such as page views) is sent to your Google Analytics account.

Prerequisites

You will need an analytics ID for your website before proceeding (technically it’s called a measurement ID or property ID but we’ll use the term “analytics ID” in this guide). If you don’t have one, see the How to get started section of Introducing Google Analytics 4 (GA4).

Setup

Enable Google Analytics by adding your project’s analytics ID to the site configuration file. For details, see Configure Google Analytics.

User Feedback

By default Docsy puts a “was this page helpful?” feedback widget at the bottom of every documentation page, as shown in Figure 1.

The user is presented with the text 'Was this page helpful?' followed
            by 'Yes' and 'No' buttons.
Figure 1. The feedback widget, outlined in red

After clicking Yes the user should see a response like Figure 2. You can configure the response text in your project’s configuration file.

After clicking 'Yes' the widget responds with 'Glad to hear it!
            Please tell us how we can improve.' and the second sentence is a link which,
            when clicked, opens GitHub and lets the user create an issue on the
            documentation repository.
Figure 2. An example Yes response

How is this data useful?

When you have a lot of documentation, and not enough time to update it all, you can use the “was this page helpful?” feedback data to help you decide which pages to prioritize. In general, start with the pages with a lot of pageviews and low ratings. “Low ratings” in this context means the pages where users are clicking No — the page wasn’t helpful — more often than Yes — the page was helpful. You can also study your highly-rated pages to develop hypotheses around why your users find them helpful.

In general, you can develop more certainty around what patterns your users find helpful or unhelpful if you introduce isolated changes in your documentation whenever possible. For example, suppose that you find a tutorial that no longer matches the product. You update the instructions, check back in a month, and the score has improved. You now have a correlation between up-to-date instructions and higher ratings. Or, suppose you study your highly-rated pages and discover that they all start with code samples. You find 10 other pages with their code samples at the bottom, move the samples to the top, and discover that each page’s score has improved. Since this was the only change you introduced on each page, it’s more reasonable to believe that your users find code samples at the top of pages helpful. The scientific method, applied to technical writing, in other words!

Setup

  1. Open your project’s Hugo configuration file.

  2. Set the response text that users see after clicking Yes or No.

    [params.ui.feedback]
    enable = true
    yes = 'Glad to hear it! Please <a href="https://github.com/USERNAME/REPOSITORY/issues/new">tell us how we can improve</a>.'
    no = 'Sorry to hear that. Please <a href="https://github.com/USERNAME/REPOSITORY/issues/new">tell us how we can improve</a>.'
    params:
      ui:
        feedback:
          enable: true
          'yes': >-
            Glad to hear it! Please <a href="https://github.com/USERNAME/REPOSITORY/issues/new">
            tell us how we can improve</a>.        
          'no': >-
            Sorry to hear that. Please <a href="https://github.com/USERNAME/REPOSITORY/issues/new">
            tell us how we can improve</a>.        
    {
      "params": {
        "ui": {
          "feedback": {
            "enable": true,
            "yes": "Glad to hear it! Please <a href=\"https://github.com/USERNAME/REPOSITORY/issues/new\"> tell us how we can improve</a>.",
            "no": "Sorry to hear that. Please <a href=\"https://github.com/USERNAME/REPOSITORY/issues/new\"> tell us how we can improve</a>."
          }
        }
      }
    }
  3. Save the edits to your configuration file.

By default, Docsy emits an event value of 100 when a user clicks “yes”. You can change this value by setting params.ui.feedback.max_value to a positive integer. Docsy uses 0 for “no” events.

Access the feedback data

Page feedback is reported to Google Analytics through events.

This section assumes basic familiarity with Google Analytics. For example, you should know how to check pageviews over a certain time range and navigate between accounts if you have access to multiple documentation sites.

  1. Open Google Analytics.
  2. Open Reports > Engagement > Events.
  3. Click page_helpful in the events table. If there is no page_helpful event, then none have been registered for the selected period. Adjust the period as necessary.

Note that you might be required to create a custom report if you’d like better visualize individual data points (per page) along with average values.

Disable feedback on a single page

Add the parameter hide_feedback to the page’s front matter and set it to true.

+++
hide_feedback = true
+++
---
hide_feedback: true
---
{
    "hide_feedback": true
}

Disable feedback on all pages

Set params.ui.feedback.enable to false in hugo.toml/hugo.yaml/hugo.json:

[params.ui.feedback]
enable = false
params:
  ui:
    feedback:
      enable: false
{
  "params": {
    "ui": {
      "feedback": {
        "enable": false
      }
    }
  }
}

Add a contact form with Fabform

You can create a contact form for your site and collect your form submissions at fabform.io. To use this feature, you first need to sign up for an account with Fabform. The following example shows how to add a simple form that collects the user’s email address to your site source:

<form action="https://fabform.io/f/{form-id}" method="post">
 <label for="email">Your Email</label>
 <input name="email" type="email">
 <button type="submit">Submit</button>
</form>

For more details, see Add a Hugo contact form in the Fabform documentation.

Search Engine Optimization meta tags

To learn how to optimize your site for SEO see, Search Engine Optimization (SEO) Starter Guide.

Google recommends using the description meta tag to tell search engines what your page is about. For each generated page, Docsy will set the content of the meta description by using the first of the following that is defined:

For the template code used to perform this computation, see layouts/partials/page-description.html.

Add more meta tags as needed to your project’s copy of the head-end.html partial. For details, see Customizing templates.

5.10 - Repository Links and other page information

Help your users interact with page source and view page-source information.

The Docsy docs and blog layouts include links for readers to edit the page or create issues for your docs or project via your site’s source repository. The current generated links for each docs or blog page are:

  • View page source: Brings the user to the page source in your docs repo.
  • Edit this page: Brings the user to an editable version of the page content in their fork (if available) of your docs repo. If the user doesn’t have a current fork of your docs repo, they are invited to create one before making their edit. The user can then create a pull request for your docs.
  • Create child page: Brings the user to a create new file form in their fork of your docs repo. The new file will be located as a child of the page they clicked the link on. The form will be pre-populated with a template the user can edit to create their page. You can change this by adding assets/stubs/new-page-template.md to your own project.
  • Create documentation issue: Brings the user to a new issue form in your docs repo with the name of the current page as the issue’s title.
  • Create project issue (optional): Brings the user to a new issue form in your project repo. This can be useful if you have separate project and docs repos and your users want to file issues against the project feature being discussed rather than your docs.

This page shows you how to configure these links.

Currently, Docsy supports only GitHub repository links “out of the box”. Since GitLab can handle the same link scheme, it should work as well. If you are using another repository such as Bitbucket and would like generated repository links, feel free to add a feature request or update our theme.

There are four site variables you can configure in hugo.toml/hugo.yaml/hugo.json to set up links, as well as one in your page metadata.

github_repo

The URL for your site’s source repository. This is used to generate the Edit this page, Create child page, and Create documentation issue links.

[params]
github_repo = "https://github.com/quatm/quatm"
params:
  github_repo: https://github.com/quatm/quatm
{
  "params": {
    "github_repo": "https://github.com/quatm/quatm"
  }
}

github_subdir (optional)

Specify a value here if your content directory is not in your repo’s root directory. For example, this site is in the userguide subdirectory of its repo. Setting this value means that your edit links will go to the right page.

[params]
github_subdir = "userguide"
params:
  github_subdir: userguide
{
  "params": {
    "github_subdir": "userguide"
  }
}

github_project_repo (optional)

Specify a value here if you have a separate project repo and you’d like your users to be able to create issues against your project from the relevant docs. The Create project issue link appears only if this is set.

[params]
github_project_repo = "https://github.com/quatm/quatm"
params:
  github_project_repo: https://github.com/quatm/quatm
{
  "params": {
    "github_project_repo": "https://github.com/quatm/quatm"
  }
}

github_branch (optional)

Specify a value here if you have would like to reference a different branch for the other github settings like Edit this page or Create project issue.

[params]
github_branch = "release"
params:
  github_branch: release
{
  "params": {
    "github_branch": "release"
  }
}

path_base_for_github_subdir (optional)

Suppose that the source files for all of the pages under content/some-section come from another repo, such as a git submodule. Add settings like these to the section’s index page so that the repository links for all pages in that section refer to the originating repo:

+++
title = "Some super section"
[cascade]
github_repo = "https://github.com/some-username/another-repo/"
github_subdir = "docs"
path_base_for_github_subdir = "content/some-section"

+++
---
title: Some super section
cascade:
  github_repo: https://github.com/some-username/another-repo/
  github_subdir: docs
  path_base_for_github_subdir: content/some-section

---
{
  "title": "Some super section",
  "cascade": {
    "github_repo": "https://github.com/some-username/another-repo/",
    "github_subdir": "docs",
    "path_base_for_github_subdir": "content/some-section"
  }
}

As an example, consider a page at the path content/some-section/subpath/some-page.md with github_branch globally set to main. The index page settings above will generate the following edit link for some-page.md:

https://github.com/some-username/another-repo/edit/main/开发文档/subpath/some-page.md

If you only have a single page originating from another repo, then omit the cascade key and write, at the top-level, the same settings as illustrated above.

If you’d like users to create project issues in the originating repo as well, then also set github_project_repo, something like this:

---
...
cascade:
  github_repo: &repo https://github.com/some-username/another-repo/
  github_project_repo: *repo
...
---
+++

[cascade]
github_repo = "https://github.com/some-username/another-repo/"
github_project_repo = "https://github.com/some-username/another-repo/"

+++
---

cascade:
  github_repo: &repo https://github.com/some-username/another-repo/
  github_project_repo: *repo

---
{
  "cascade": {
    "github_repo": "https://github.com/some-username/another-repo/",
    "github_project_repo": "https://github.com/some-username/another-repo/"
  }
}

The path_base_for_github_subdir setting is a regular expression, so you can use it even if you have a site with multiple languages for example:

+++

path_base_for_github_subdir = "content/\w+/some-section"

+++
---

path_base_for_github_subdir: content/\w+/some-section

---
{

  "path_base_for_github_subdir": "content/\w+/some-section"

}

In situations where a page originates from a file under a different name, you can specify from and to path-rename settings. Here’s an example where an index file is named README.md in the originating repo:

+++

github_repo = "https://github.com/some-username/another-repo/"
github_subdir = "docs"

[path_base_for_github_subdir]
from = "content/some-section/(.*?)/_index.md"
to = "$1/README.md"

+++
---

github_repo: https://github.com/some-username/another-repo/
github_subdir: docs
path_base_for_github_subdir:
  from: content/some-section/(.*?)/_index.md
  to: $1/README.md

---
{
  
  "github_repo": "https://github.com/some-username/another-repo/",
  "github_subdir": "docs",
  "path_base_for_github_subdir": {
    "from": "content/some-section/(.*?)/_index.md",
    "to": "$1/README.md"
  },
  
}

github_url (optional)

Specify a value for this in your page metadata to set a specific edit URL for this page, as in the following example:

+++
title = "Some page"
github_url = "https://github.com/some-username/another-repo/edit/main/README.md"

+++
---
title: Some page
github_url: https://github.com/some-username/another-repo/edit/main/README.md

---
{
  "title": "Some page",
  "github_url": "https://github.com/some-username/another-repo/edit/main/README.md",
  
}

This can be useful if you have page source files in multiple Git repositories, or require a non-GitHub URL. Pages using this value have Edit this page links only.

You can use CSS to selectively hide links. For example, add the following to your projects’s _styles_project.scss file to hide Create child page links from all pages (optionally with a !important modifier – not shown):

.td-page-meta__child { display: none; }

Each link kind has an associated unique class named .td-page-meta__KIND, as defined by the following table:

Link kindClass name
View page source.td-page-meta__view
Edit this page.td-page-meta__edit
Create child page.td-page-meta__child
Create documentation issue.td-page-meta__issue
Create project issue.td-page-meta__project-issue

Of course, you can also use these classes to give repository links unique styles for your project.

Last-modified page metadata

To have page-source metadata displayed at the bottom of documentation pages and blog posts, set the GitInfo configuration parameter to true, and ensure that params.github_repo is defined.

A last-modified page note looks something like this:

Last modified November 29, 2023: Release v0.8.0 preparation (#1756) (6bb4f99)

Once enabled site-wide, you can selectively hide last-modified notes in a page or section by declaring the following style (optionally with a !important modifier — not shown):

.td-page-meta__lastmod { display: none; }

5.11 - Taxonomy Support

Structure the content using taxonomies like tags, categories, labels.

Docsy supports Hugo’s Taxonomies (see: https://gohugo.io/content-management/taxonomies/) in its docs and blog section. You can see the default layout and can test the behavior of the generated links on this page.

Terminology

To understand the usage of taxonomies you should understand the following terminology:

Taxonomy
a categorization that can be used to classify content - e.g.: Tags, Categories, Projects, People
Term
a key within the taxonomy - e.g. within projects: Project A, Project B
Value
a piece of content assigned to a term - e.g. a page of your site, that belongs to a specific project

A example taxonomy for a movie website you can find in the official Hugo docs: https://gohugo.io/content-management/taxonomies/#example-taxonomy-movie-website

Parameters

There are various parameter to control the functionality of taxonomies in the project configuration file.

By default taxonomies for tags and categories are enabled in Hugo (see: https://gohugo.io/content-management/taxonomies/#default-taxonomies). In Docsy taxonomies are disabled by default in the hugo.toml/hugo.yaml/hugo.json:

disableKinds = ["taxonomy", "taxonomyTerm"]
disableKinds:
  - taxonomy
  - taxonomyTerm
{
  "disableKinds": [
    "taxonomy",
    "taxonomyTerm"
  ]
}

If you want to enable taxonomies in Docsy you have to delete (or comment out) this line in your project’s hugo.toml/hugo.yaml/hugo.json. Then the taxonomy pages for tags and categories will be generated by Hugo. If you want to use other taxonomies you have to define them in your configuration file. If you want to use beside your own taxonomies also the default taxonomies tags and categories, you also have to define them beside your own taxonomies. You need to provide both the plural and singular labels for each taxonomy.

With the following example you define a additional taxonomy projects beside the default taxonomies tags and categories:

[taxonomies]
tag = "tags"
category = "categories"
project = "projects"
taxonomies:
  tag: tags
  category: categories
  project: projects
{
  "taxonomies": {
    "tag": "tags",
    "category": "categories",
    "project": "projects"
  }
}

You can use the following parameters in your project’s hugo.toml/hugo.yaml/hugo.json to control the output of the assigned taxonomy terms for each article resp. page of your docs and/or blog section in Docsy or a “tag cloud” in Docsy’s right sidebar:

[params.taxonomy]
taxonomyCloud = ["projects", "tags"] # set taxonomyCloud = [] to hide taxonomy clouds
taxonomyCloudTitle = ["Our Projects", "Tag Cloud"] # if used, must have same length as taxonomyCloud
taxonomyPageHeader = ["tags", "categories"] # set taxonomyPageHeader = [] to hide taxonomies on the page headers
params:
  taxonomy:
    taxonomyCloud:
      - projects    # remove all entries
      - tags        # to hide taxonomy clouds
    taxonomyCloudTitle:   # if used, must have the same
      - Our Projects      # number of entries as taxonomyCloud
      - Tag Cloud
    taxonomyPageHeader:
      - tags        # remove all entries
      - categories  # to hide taxonomy clouds
{
  "params": {
    "taxonomy": {
      "taxonomyCloud": [
        "projects",
        "tags"
      ],
      "taxonomyCloudTitle": [
        "Our Projects",
        "Tag Cloud"
      ],
      "taxonomyPageHeader": [
        "tags",
        "categories"
      ]
    }
  }
}

The settings above would only show a taxonomy cloud for projects and tags (with the headlines “Our Projects” and “Tag Cloud”) in Docsy’s right sidebar and the assigned terms for the taxonomies tags and categories for each page.

To disable any taxonomy cloud you have to set the Parameter taxonomyCloud = [] resp. if you don’t want to show the assigned terms you have to set taxonomyPageHeader = [].

As default the plural label of a taxonomy is used as it cloud title. You can overwrite the default cloud title with taxonomyCloudTitle. But if you do so, you have to define a manual title for each enabled taxonomy cloud (taxonomyCloud and taxonomyCloudTitle must have the same length!).

If you don’t set the parameters taxonomyCloud resp. taxonomyPageHeader the taxonomy clouds resp. assigned terms for all defined taxonomies will be generated.

Partials

The by default used partials for displaying taxonomies are so defined, that you should be able to use them also easily in your own layouts.

taxonomy_terms_article

The partial taxonomy_terms_article shows all assigned terms of an given taxonomy (partial parameter taxo) of an article respectively page (partial parameter context, most of the time the current page or context .).

Example usage in layouts/开发文档/list.html for the header of each page in the docs section:

{{ $context := . }}
{{ range $taxo, $taxo_map := .Site.Taxonomies }}
  {{ partial "taxonomy_terms_article.html" (dict "context" $context "taxo" $taxo ) }}
{{ end }}

This will gave you for each in the current page (resp. context) defined taxonomy a list with all assigned terms:

<div class="taxonomy taxonomy-terms-article taxo-categories">
  <h5 class="taxonomy-title">Categories:</h5>
  <ul class="taxonomy-terms">
    <li><a class="taxonomy-term" href="//localhost:1313/categories/taxonomies/" data-taxonomy-term="taxonomies"><span class="taxonomy-label">Taxonomies</span></a></li>
  </ul>
</div>
<div class="taxonomy taxonomy-terms-article taxo-tags">
  <h5 class="taxonomy-title">Tags:</h5>
  <ul class="taxonomy-terms">
    <li><a class="taxonomy-term" href="//localhost:1313/tags/tagging/" data-taxonomy-term="tagging"><span class="taxonomy-label">Tagging</span></a></li>
    <li><a class="taxonomy-term" href="//localhost:1313/tags/structuring-content/" data-taxonomy-term="structuring-content"><span class="taxonomy-label">Structuring Content</span></a></li>
    <li><a class="taxonomy-term" href="//localhost:1313/tags/labelling/" data-taxonomy-term="labelling"><span class="taxonomy-label">Labelling</span></a></li>
  </ul>
</div>

taxonomy_terms_article_wrapper

The partial taxonomy_terms_article_wrapper is a wrapper for the partial taxonomy_terms_article with the only parameter context (most of the time the current page or context .) and checks the taxonomy parameters of your project’s hugo.toml/hugo.yaml/hugo.json to loop threw all listed taxonomies in the parameter taxonomyPageHeader resp. all defined taxonomies of your page, if taxonomyPageHeader isn’t set.

taxonomy_terms_cloud

The partial taxonomy_terms_cloud shows all used terms of an given taxonomy (partial parameter taxo) for your site (partial parameter context, most of the time the current page or context .) and with the parameter title as headline.

Example usage in partial taxonomy_terms_clouds for showing all defined taxonomies and its terms:

{{ $context := . }}
{{ range $taxo, $taxo_map := .Site.Taxonomies }}
  {{ partial "taxonomy_terms_cloud.html" (dict "context" $context "taxo" $taxo "title" ( humanize $taxo ) ) }}
{{ end }}

As an example this will gave you for following HTML markup for the taxonomy categories:

<div class="taxonomy taxonomy-terms-cloud taxo-categories">
  <h5 class="taxonomy-title">Cloud of Categories</h5>
  <ul class="taxonomy-terms">
    <li><a class="taxonomy-term" href="//localhost:1313/categories/category-1/" data-taxonomy-term="category-1"><span class="taxonomy-label">category 1</span><span class="taxonomy-count">3</span></a></li>
    <li><a class="taxonomy-term" href="//localhost:1313/categories/category-2/" data-taxonomy-term="category-2"><span class="taxonomy-label">category 2</span><span class="taxonomy-count">1</span></a></li>
    <li><a class="taxonomy-term" href="//localhost:1313/categories/category-3/" data-taxonomy-term="category-3"><span class="taxonomy-label">category 3</span><span class="taxonomy-count">2</span></a></li>
    <li><a class="taxonomy-term" href="//localhost:1313/categories/category-4/" data-taxonomy-term="category-4"><span class="taxonomy-label">category 4</span><span class="taxonomy-count">6</span></a></li>
  </ul>
</div>

taxonomy_terms_clouds

The partial taxonomy_terms_clouds is a wrapper for the partial taxonomy_terms_cloud with the only parameter context (most of the time the current page or context .) and checks the taxonomy parameters of your project’s hugo.toml/hugo.yaml/hugo.json to loop threw all listed taxonomies in the parameter taxonomyCloud resp. all defined taxonomies of your page, if taxonomyCloud isn’t set.

Multi language support for taxonomies

The taxonomy terms associated content gets only counted and linked WITHIN the language! The control parameters for the taxonomy support can also get assigned language specific.

5.12 - Diagrams and Formulae

Add generated diagrams and scientific formulae to your site.

Docsy has built-in support for a number of diagram creation and typesetting tools you can use to add rich content to your site, including \(\KaTeX\), Mermaid, Diagrams.net, PlantUML, and MarkMap.

\(\LaTeX\) support with \(\KaTeX\)

\(\LaTeX\) is a high-quality typesetting system for the production of technical and scientific documentation. Due to its excellent math typesetting capabilities, \(\TeX\) became the de facto standard for the communication and publication of scientific documents, especially if these documents contain a lot of mathematical formulae. Designed and mostly written by Donald Knuth, the initial version was released in 1978. Dating back that far, \(\LaTeX\) has pdf as its primary output target and is not particularly well suited for producing HTML output for the Web. Fortunately, with \(\KaTeX\) there exists a fast and easy-to-use JavaScript library for \(\TeX\) math rendering on the web, which was integrated into the Docsy theme.

With \(\KaTeX\) support enabled in Docsy, you can include complex mathematical formulae into your web page, either inline or centred on its own line. Since \(\KaTeX\) relies on server side rendering, it produces the same output regardless of your browser or your environment. Formulae can be shown either inline or in display mode:

Inline formulae

The following code sample produces a text line with three inline formulae:

When \\(a \ne 0\\), there are two solutions to \\(ax^2 + bx + c= 0\\) and they are \\(x = {-b \pm \sqrt{b^2-4ac} \over 2a}\\).

When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c= 0\) and they are \(x = {-b \pm \sqrt{b^2-4ac} \over 2a}\).

Formulae in display mode

The following code sample produces an introductory text line followed by a formula numbered as (1) residing on its own line:

The probability of getting \\(k\\) heads when flipping \\(n\\) coins is:
```math
\tag*{(1)} P(E) = {n \choose k} p^k (1-p)^{n-k}
```

The formula itself is written inside a GLFM math block. The above code fragment renders to:

The probability of getting \(k\) heads when flipping \(n\) coins is:

$$\tag*{(1)} P(E) = {n \choose k} p^k (1-p)^{n-k}$$

Activating and configuring \(\KaTeX\) support

Auto activation

As soon as you use a math code block on your page, support of \(\KaTeX\) is automatically enabled.

Manual activation (no math code block present or hugo 0.92 or lower)

If you want to use inline formulae and don’t have a math code block present in your page which triggers auto activation, you need to manually activate \(\KaTeX\) support. The easiest way to do so is to add a math attribute to the frontmatter of your page and set it to true:

+++
math = true
+++
---
math: true
---
{
  "math": true
}

If you use formulae in most of your pages, you can also enable sitewide \(\KaTeX\) support inside the Docsy theme. To do so update hugo.toml/hugo.yaml/hugo.json:

[params.katex]
enable = true
params:
  katex:
    enable: true
{
  "params": {
    "katex": {
      "enable": true
    }
  }
}

Additionally, you can customize various \(\KaTeX\) options inside hugo.toml/hugo.yaml/hugo.json, if needed:

[params.katex]
# enable/disable KaTeX support
enable = true
# Element(s) scanned by auto render extension. Default: document.body
html_dom_element = "document.body"

[params.katex.options]
# If true (the default), KaTeX will throw a ParseError when it encounters an
# unsupported command or invalid LaTeX. If false, KaTeX will render unsupported
# commands as text, and render invalid LaTeX as its source code with hover text
# giving the error, in the color given by errorColor.
throwOnError = false
errorColor = "#CD5C5C"

# This is a list of delimiters to look for math, processed in the same order as
# the list. Each delimiter has three properties:
#   left:    A string which starts the math expression (i.e. the left delimiter).
#   right:   A string which ends the math expression (i.e. the right delimiter).
#   display: Whether math in the expression should be rendered in display mode.
[[params.katex.options.delimiters]]
  left = "$$"
  right = "$$"
  display = true
[[params.katex.options.delimiters]]
  left = "$"
  right = "$"
  display = false
[[params.katex.options.delimiters]]
  left = "\\("
  right = "\\)"
  display = false
[[params.katex.options.delimiters]]
  left = "\\["
  right = "\\]"
  display = true
params:
  katex:
    enable: true  # enable/disable KaTeX support
    html_dom_element: document.body  # Element(s) scanned by auto render extension. Default: document.body
    options:

      # If true (the default), KaTeX will throw a ParseError when it encounters an
      # unsupported command or invalid LaTeX. If false, KaTeX will render unsupported
      # commands as text, and render invalid LaTeX as its source code with hover text
      # giving the error, in the color given by errorColor.
      throwOnError: false
      errorColor: '#CD5C5C'

      # This is a list of delimiters to look for math, processed in the same order as
      # the list. Each delimiter has three properties:
      #   left:    A string which starts the math expression (i.e. the left delimiter).
      #   right:   A string which ends the math expression (i.e. the right delimiter).
      #   display: Whether math in the expression should be rendered in display mode.
      delimiters:
        - left: $$
          right: $$
          display: true
        - left: $
          right: $
          display: false
        - left: \(
          right: \)
          display: false
        - left: \[
          right: \]
          display: true
{
  "params": {
    "katex": {
      "enable": true,
      "html_dom_element": "document.body",
      "options": {
        "throwOnError": false,
        "errorColor": "#CD5C5C",
        "delimiters": [
          {
            "left": "$$",
            "right": "$$",
            "display": true
          },
          {
            "left": "$",
            "right": "$",
            "display": false
          },
          {
            "left": "\\(",
            "right": "\\)",
            "display": false
          },
          {
            "left": "\\[",
            "right": "\\]",
            "display": true
          }
        ]
      }
    }
  }
}

For a complete list of options and their detailed description, have a look at the documentation of \({\KaTeX}\)’s Rendering API options and of \({\KaTeX}\)’s configuration options.

Display of Chemical Equations and Physical Units

mhchem is a \(\LaTeX\) package for typesetting chemical molecular formulae and equations. Fortunately, \(\KaTeX\) provides the mhchem extension that makes the mhchem package accessible when authoring content for the web. With mhchem extension enabled, you can easily include chemical equations into your page. An equation can be shown either inline or can reside on its own line. The following code sample produces a text line including a chemical equation:

*Precipitation of barium sulfate:* \\(\ce{SO4^2- + Ba^2+ -> BaSO4 v}\\)

Precipitation of barium sulfate: \(\ce{SO4^2- + Ba^2+ -> BaSO4 v}\)

More complex equations need to be displayed on their own line. Use a code block adorned with chem in order to achieve this:

```chem
\tag*{(2)} \ce{Zn^2+  <=>[+ 2OH-][+ 2H+]  $\underset{\text{amphoteric hydroxide}}{\ce{Zn(OH)2 v}}$  <=>[+ 2OH-][+ 2H+]  $\underset{\text{tetrahydroxozincate}}{\ce{[Zn(OH)4]^2-}}$}
```
$$\tag*{(2)} \ce{Zn^2+ <=>[+ 2OH-][+ 2H+] $\underset{\text{amphoteric hydroxide}}{\ce{Zn(OH)2 v}}$ <=>[+ 2OH-][+ 2H+] $\underset{\text{tetrahydroxozincate}}{\ce{[Zn(OH)4]^2-}}$}$$

Use of mhchem is not limited to the authoring of chemical equations, using the included \pu command, pretty looking physical units can be written with ease, too. The following code sample produces two text lines with four numbers plus their corresponding physical units:

* Scientific number notation: \\(\pu{1.2e3 kJ}\\) or \\(\pu{1.2E3 kJ}\\) \\
* Divisions: \\(\pu{123 kJ/mol}\\) or \\(\pu{123 kJ//mol}\\)
  • Scientific number notation: \(\pu{1.2e3 kJ}\) or \(\pu{1.2E3 kJ}\)
  • Divisions: \(\pu{123 kJ/mol}\) or \(\pu{123 kJ//mol}\)

For a complete list of options when authoring physical units, have a look at the section on physical units in the mhchem documentation.

Activating rendering support for chemical formulae

Auto activation

As soon as you use a chem code block on your page, rendering support for chemical equations is automatically enabled.

Manual activation (no chem code block present or hugo 0.92 or lower)

If you want to use chemical formulae inline and don’t have a chem code block present in your page which triggers auto activation, you need to manually activate rendering support for chemical formulae. The easiest way to do so is to add a chem attribute to the frontmatter of your page and set it to true:

+++
chem = true
+++
---
chem: true
---
{
  "chem": true
}

If you use formulae in most of your pages, you can also enable sitewide rendering support for chemical formulae inside the Docsy theme. To do so, enable mhchem inside your hugo.toml/hugo.yaml/hugo.json:

[params.katex]
enable = true

[params.katex.mhchem]
enable = true
params:
  katex:
    enable: true
    mhchem:
      enable: true
{
  "params": {
    "katex": {
      "enable": true,
      "mhchem": {
        "enable": true
      }
    }
  }
}

Diagrams with Mermaid

Mermaid is a Javascript library for rendering simple text definitions to useful diagrams in the browser. It can generate a variety of different diagram types, including flowcharts, sequence diagrams, class diagrams, state diagrams, ER diagrams, user journey diagrams, Gantt charts and pie charts.

With Mermaid support enabled in Docsy, you can include the text definition of a Mermaid diagram inside a code block, and it will automatically be rendered by the browser as soon as the page loads.

The great advantage of this is anyone who can edit the page can now edit the diagram - no more hunting for the original tools and version to make a new edit.

For example, the following defines a sequence diagram:

```mermaid
sequenceDiagram
    autonumber
    Docsy user->>Discussion board: Ask question
    Discussion board->>Community member: read question
    loop Different strategies
    Community member->>Test instance: Investigate issue raised
    end
    Note right of Community member: After hours of investigation:
    Test instance-->>Community member: Come up with solution
    Community member-->>Discussion board: Propose solution
    Discussion board-->>Docsy user: check proposed solution
    Docsy user->>Discussion board: Mark question as resolved
    Docsy user->>Docsy user: Being happy
```

which is automatically rendered to:

sequenceDiagram
    autonumber
    Docsy user->>Discussion board: Ask question
    Discussion board->>Community member: read question
    loop Different strategies
    Community member->>Test instance: Investigate issue raised
    end
    Note right of Community member: After hours of investigation:
    Test instance-->>Community member: Come up with solution
    Community member-->>Discussion board: Propose solution
    Discussion board-->>Docsy user: check proposed solution
    Docsy user->>Discussion board: Mark question as resolved
    Docsy user->>Docsy user: Being happy

Support of Mermaid diagrams is automatically enabled as soon as you use a mermaid code block on your page.

By default, docsy pulls in the latest officially released version of Mermaid at build time. If that doesn’t fit your needs, you can specify the wanted mermaid version inside your configuration file hugo.toml/hugo.yaml/hugo.json:

[params.mermaid]
version = "10.9.0"
params:
  mermaid:
    version: 10.9.0
{
  "params": {
    "mermaid": {
      "version": "10.9.0"
    }
  }
}

If needed, you can define custom settings for your diagrams, such as themes, padding in your hugo.toml/hugo.yaml/hugo.json.

[params.mermaid]
theme = "neutral"

[params.mermaid.flowchart]
diagramPadding = 6
params:
  mermaid:
    theme: neutral
    flowchart:
      diagramPadding: 6
{
  "params": {
    "mermaid": {
      "theme": "neutral",
      "flowchart": {
        "diagramPadding": 6
      }
    }
  }
}

See the Mermaid documentation for a list of defaults that can be overridden.

Settings can also be overridden on a per-diagram basis by making use of a frontmatter config block at the start of the diagram definition.

UML Diagrams with PlantUML

PlantUML is an alternative to Mermaid that lets you quickly create UML diagrams, including sequence diagrams, use case diagrams, and state diagrams. Unlike Mermaid diagrams, which are entirely rendered in the browser, PlantUML uses a PlantUML server to create diagrams. You can use the provided default demo server (not recommended for production use), or run a server yourself. PlantUML offers a wider range of image types than Mermaid, so may be a better choice for some use cases.

Diagrams are defined using a simple and intuitive language. (see PlantUML Language Reference Guide).

The following example shows a use case diagram:

```plantuml
participant participant as Foo
actor       actor       as Foo1
boundary    boundary    as Foo2
control     control     as Foo3
entity      entity      as Foo4
database    database    as Foo5
collections collections as Foo6
queue       queue       as Foo7
Foo -> Foo1 : To actor
Foo -> Foo2 : To boundary
Foo -> Foo3 : To control
Foo -> Foo4 : To entity
Foo -> Foo5 : To database
Foo -> Foo6 : To collections
Foo -> Foo7: To queue
```

Automatically renders to:

participant participant as Foo
actor       actor       as Foo1
boundary    boundary    as Foo2
control     control     as Foo3
entity      entity      as Foo4
database    database    as Foo5
collections collections as Foo6
queue       queue       as Foo7
Foo -> Foo1 : To actor
Foo -> Foo2 : To boundary
Foo -> Foo3 : To control
Foo -> Foo4 : To entity
Foo -> Foo5 : To database
Foo -> Foo6 : To collections
Foo -> Foo7: To queue

To enable/disable PlantUML, update hugo.toml/hugo.yaml/hugo.json:

[params.plantuml]
enable = true
params:
  plantuml:
    enable: true
{
  "params": {
    "plantuml": {
      "enable": true
    }
  }
}

Other optional settings are:

[params.plantuml]
enable = true
theme = "default"

# Set url to plantuml server
# default is http://www.plantuml.com/plantuml/svg/
svg_image_url = "https://www.plantuml.com/plantuml/svg/"

# By default the plantuml implementation uses <img /> tags to display UML diagrams.
# When svg is set to true, diagrams are displayed using <svg /> tags, maintaining functionality like links e.g.
# default = false
svg = true
params:
  plantuml:
    enable: true
    theme: default
    # Set url to plantuml server
    # default is http://www.plantuml.com/plantuml/svg/
    svg_image_url: 'https://www.plantuml.com/plantuml/svg/'
    # By default the plantuml implementation uses <img /> tags to display UML diagrams.
    # When svg is set to true, diagrams are displayed using <svg /> tags, maintaining functionality like links e.g.
    # default = false
    svg: true
{
  "params": {
    "plantuml": {
      "enable": true,
      "theme": "default",
      "svg_image_url": "https://www.plantuml.com/plantuml/svg/",
      "svg": true
    }
  }
}

MindMap support with MarkMap

MarkMap is a Javascript library for rendering simple text definitions to MindMap in the browser.

For example, the following defines a simple MindMap:

```markmap
# markmap

## Links

- <https://markmap.js.org/>
- [GitHub](https://github.com/gera2ld/markmap)

## Related

- [coc-markmap](https://github.com/gera2ld/coc-markmap)
- [gatsby-remark-markmap](https://github.com/gera2ld/gatsby-remark-markmap)

## Features

- links
- **inline** ~~text~~ *styles*
- multiline
  text
- `inline code`
-
    ```js
    console.log('code block');
    ```
- Katex - $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$
```

Automatically renders to:

# markmap

## Links

- <https://markmap.js.org/>
- [GitHub](https://github.com/gera2ld/markmap)

## Related

- [coc-markmap](https://github.com/gera2ld/coc-markmap)
- [gatsby-remark-markmap](https://github.com/gera2ld/gatsby-remark-markmap)

## Features

- links
- **inline** ~~text~~ *styles*
- multiline
  text
- `inline code`
-
    ```js
    console.log('code block');
    ```
- Katex - $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$

To enable/disable MarkMap, update hugo.toml/hugo.yaml/hugo.json:

[params.markmap]
enable = true
params:
  markmap:
    enable: true
{
  "params": {
    "markmap": {
      "enable": true
    }
  }
}

Diagrams with Diagrams.net

Diagrams.net (aka draw.io) provides a free and open source diagram editor that can generate a wider range of diagrams than Mermaid or PlantUML using a web or desktop editor.

SVG and PNG files exported with the tool contain the source code of the original diagram by default, which allows the diagrams.net site to import those images again for edit in the future. With draw.io enabled, Docsy will detect this and automatically add an Edit button over any image that can be edited using the online site.

Hover over the image below and click edit to instantly start working with it. Clicking the Save button will cause the edited diagram to be exported using the same filename and filetype, and downloaded to your browser.

As the diagram data is transported via the browser, the diagrams.net server does not need to access the content on your Docsy server directly at all.

Mouse over the above image and click the Edit button!

Mouse over the above image and click the Edit button!

To enable detection of diagrams, update hugo.toml/hugo.yaml/hugo.json:

[params.drawio]
enable = true
params:
  drawio:
    enable: true
{
  "params": {
    "drawio": {
      "enable": true
    }
  }
}

You can also deploy and use your own server for editing diagrams, in which case update the configuration to point to that server:

[params.drawio]
drawio_server = "https://app.mydrawioserver.example.com"
params:
  drawio:
    drawio_server: 'https://app.mydrawioserver.example.com'
{
  "params": {
    "drawio": {
      "drawio_server": "https://app.mydrawioserver.example.com"
    }
  }
}

6 - 常用硬件驱动模块

如何通过Quatm控制您的硬件。

已添加的硬件驱动

6.1 - Adwin驱动

如何通过Quatm控制Adwin。

quatm.drivers.adwin package

Submodules

quatm.drivers.adwin.adwin module

Class:

  • quatm.drivers.adwin.adwin.ADwinDummy

    class quatm.drivers.adwin.adwin.ADwinDummy(object):
        def Boot(self, s):
            pass
    
        def Data_Length(self, j):
            pass
    
        def Free_Mem(self, i):
            pass
    
        def Get_Par(self, j):
            pass
    
        def Load_Process(self, i):
            pass
    
        def Processor_Type(self):
            pass
    
        def SetData_Long(self, ArrayLong, i, j, l):
            pass
    
        def Set_Par(self, i, j):
            pass
    
        def Start_Process(self, i):
            pass
    
        def Test_Version(self):
            pass
    
        def Workload(self):
            pass
    
  • quatm.drivers.adwin.adwin.AdWinDriver(simulating=None)

    class quatm.drivers.adwin.adwin.AdWinDriver(object):
        def adwinStatus(self):
            pass
    
        def running(self):
            pass
    
        def setDAC(self, channel, value):
            pass
    
        def setTTL(self, channel, high):
            pass
    
        def set_allTTL(self, bitmask):
            pass
    
        def start(self, repetitions=1):
            pass
    
        def stop(self):
            pass
    
        def timetableMaxlength(self):
            pass
    
        def toBinary(self, dict_list):
            pass
    
        def uploadCommands(self, commands, binary=False, wait=True):
            pass
    

Exception:

  • quatm.drivers.adwin.adwin.AdWinDriverError(message)

    class quatm.drivers.adwin.adwin.AdWinDriverError(Exception):
        pass
    

quatm.drivers.adwin.client module

Class:

  • quatm.drivers.adwin.client.AdWinClient(experiment, simulating=None)

    class quatm.drivers.adwin.client.AdWinClient(object):
        def filter_cmdlist(self, combinetime=1e-08):
            pass
    
        def push(self, time, command, value, combinetime=1e-09):
            pass
    
        def start_realtime(self, processortime=0, repetitions=1):
            pass
    
        def stop(self):
            pass
    

quatm.drivers.adwin.units module

6.2 - blackfly驱动

如何通过Quatm控制blackfly。

quatm.drivers.blackfly package

Submodules

quatm.drivers.blackfly.bfly module

Class:

  • quatm.drivers.blackfly.bfly.Blackfly(serial)

    class quatm.drivers.blackfly.bfly.Blackfly(object):
        def __init__(self, serial):
            pass
    
        def getProps(self):
            pass
    
        def get_image(self):
            pass
    
        def setProps(self, props):
            pass
    
        def start(self, callback=None):
            pass
    
        def stop(self):
            pass
    
    • getProps(): Get all current properties (entries that can be configured) from the camera.

      • Returns: dict - Properties of the camera.
    • get_image(): Read image from camera.

      • Returns: Blackfly image. None in case of error.
    • setProps(props): Configure camera.

      • Args: props (dict) - Dictionary containing the properties. Keys correspond to functions called, the entries correspond to arguments.
      • Returns: props (dict) - The properties that have been set. May differ from the input in case of properties incompatible with the camera.
    • start(callback=None): Start capturing images.

    • stop(): Stop capturing images.

  • quatm.drivers.blackfly.bfly.Camserver(name, serial)

    class quatm.drivers.blackfly.bfly.Camserver(object):
        def __init__(self, name, serial):
            pass
    
        def generateImageIndex(self):
            pass
    
        def run(self):
            pass
    
        def sendimage(self, im):
            pass
    
        def updateBusInfo(self):
            pass
    
    • generateImageIndex(): In the current measurement, count the images. If the next run has started (either task, repetition or run changes), reset the counter (imgindex).

    • run(): Run loop running forever. Sends images from the camera to the imagestream and initiates reconfiguration of the camera in case properties have changed.

    • sendimage(im): Send Blackfly camera image via the imagestream. The image is converted to numpy array, additional information like binning, timestamp, etc., is added to a dictionary and both are sent to the imagestream.

      • Args: im - Blackfly image object.
      • Returns: None
    • updateBusInfo(): Detect cameras on the bus and update info in properties if new camera has been found.

  • quatm.drivers.blackfly.bfly.pc2

    class quatm.drivers.blackfly.bfly.pc2(object):
        pass
    
    • Dummy class in case driver is not installed.

Function:

  • quatm.drivers.blackfly.bfly.run(name)

    def quatm.drivers.blackfly.bfly.run(name):
        pass
    
    • Initialize a Camserver and run it.

6.3 - valon驱动

如何通过Quatm控制valon。

quatm.drivers.valon package

Submodules

[quatm.drivers.valon.VSerialPort3 module]

class quatm.drivers.valon.VSerialPort3.VSerialPort

Bases: serial.serialposix.Serial

  • lineGet()

  • Attributes:

    • portLineCount = 0
    • portLineIndex = 0
    • portLines = []
    • readAll()
    • writeline(text)

[quatm.drivers.valon.valon_quatm module]

class quatm.drivers.valon.valon_quatm.Valon_Driver

Bases: object

  • Attributes:
    • cwPanel = None
    • menuBar = None
    • sp = None
    • sendCommand(source, command, value)
      • Send command to valon
    • sendRaw(cmd)
    • set_frequency(freq=500, source=1)
      • Source: 1 or 2
      • Freq: Frequency in Hz

[quatm.drivers.valon.valon_prog module]

A separately running driver for the Valon, allows the (slow) Valon to receive commands without delaying the rest.

class quatm.drivers.valon.valon_prog.Valon_Standalone(name='Valon')

Bases: object

  • Standalone driver for the Valon frequency generator. Commands can be sent via the Commandhub and are processed in parallel to the experiment, thereby the experiment is not delayed by the Valon.

    • run()
  • function quatm.drivers.valon.valon_prog.run()

7 - 数据分析模块

如何分析内容并根据您的需求输出需要的数据。

quatm.analysis package

Submodules

quatm.analysis.bright_spots module

Detect bright spots such as ions in an image. We use skimage.features.blob_dog for bright spot detection.

Input:

  • Imagestream

Output:

  • Imagestream:
    • np.array: Mask containing ones on the locations where the bright spots are
    • dict: N_bright the number of bright spots detected
  • Datastream:
    • bloblist: the locations of the bright spots
    • dict: N_bright the number of bright spots detected

Properties:

  • imagestreams ([str]): Input streams
  • max_sigma (float): Parameter from blob_dog
  • threshold (float): Parameter from blob_dog

Hint: Use the output stream as a mask in the image monitor.

class quatm.analysis.bright_spots.BrightSpots(name)

Bases: object

run()

quatm.analysis.bright_spots.main_run(name)

quatm.analysis.crashit module

Simulate a crashed analysis routine.

quatm.analysis.gaussfit module

Perform a 1D Gaussian fit on a dataset.

Fit function: [ f(x) = \frac{A_0}{\sqrt{2\pi}\sigma} e^{\frac{-(x-\mu)^2}{2\sigma^2}} + C ]

Output: The output is a datastream containing a dictionary with the fit results and a 2D array containing the fitted curve.

Fit parameter nomenclature:

  • A0: ( A_0 )
  • sigma: ( \sigma )
  • pos: ( \mu )
  • offset: ( C )
  • height: ( \frac{A_0}{\sqrt{2\pi}\sigma} )

In older versions some of the parameters were named differently:

  • area: ( A_0 )
  • height: ( A_0 )

Format of the input datastream: The fit can handle two types of data:

  • 1D numpy.array (data.ndim == 1): the y-values are taken from the data, and the x values are a linear spaced index from 0 to ny.
  • 2D numpy.array:
    • x = data[0]
    • y = data[1]

Properties controlling the program:

  • datastreams: list of input datastreams

class quatm.analysis.gaussfit.Gaussfit(name)

Bases: object

run()

quatm.analysis.gaussfit.main_run(name)

quatm.analysis.imagedivider module

Handle absorption imaging data. According to Beer’s Law, light travelling through an atomic cloud is attenuated by:

[ I = I_0 e^{-n(x,y)\sigma} ]

where ( I_0 ) is the intensity before the cloud (Imaging beam without atoms) and ( I ) is the attenuated intensity (Image with atoms), ( \sigma ) is the absorption cross section, and ( n(x,y) ) is the column density of the atoms. Transforming this equation allows us to determine the column density of the atoms from the import two images.

[ n(x,y) = \frac{ln(I_0/I)}{\sigma} ]

where ( \sigma ) is given by:

[ N_{atoms} = \frac{ln(I_0/I)}{\frac{\sigma_0}{1+(2\Delta/\Gamma)^2}} ]

where effscale rescales the value from atoms per ( m^2 ) to atoms per pixel.

[ \sigma_0 = \frac{\hbar\omega\Gamma}{2 I_{sat}/C_2} ]

where ( \omega ) is the angular frequency of the laser, ( \Gamma ) is the linewidth of the transition in angular frequencies, ( I_{sat} ) is the saturation intensity in SI units, and ( C_2 ) is the Clebsh-Gordon coefficient for the dipole transition.

Properties:

  • imagestreams: input datastreams
  • imageWithAtoms: index of the image containing the image data with atoms (0 being the first image in each run)
  • imageWithoutAtoms: the image containing the image without atoms
  • absorptionCrossection: defaults to ( \sigma_0 )
  • detuning_rad: detuning of the imaging laser from resonance
  • linewidth_rad: linewidth of the transition

class quatm.analysis.imagedivider.ImageSlice(name)

Bases: object

  • C_2 = 0.6666666666666666
  • gamma = 36897377.3978814
  • h_bar = 1.0545716346179718e-34
  • isat = 25.4
  • omega = 2807325165778985.0
run()
  • sig0 = 1.4335384024006802e-13

quatm.analysis.imagedivider.main_run(name)

quatm.analysis.imageselector module

Select one single image per shot from the stream using the imgindex.

Input:

  • One image stream

Output:

  • Imagestream: the selected image

Properties:

  • imagestreams: ([str]) input image streams
  • SelectedImage: (int) the number of the image to be selected counting from 0.

class quatm.analysis.imageselector.ImageSlice(name)

Bases: object

run()

quatm.analysis.imageselector.main_run(name)

quatm.analysis.imageslice module

Create linear traces and small subregions from image stream.

![Imageslice]

Input:

  • Imagestream

Output:

  • colsum_ (datastream): summation in the direction of columns (use only row that lie within the region of interest. (gray area))
  • rowsum_ (datastream): summation along rows
  • colsumcut_, rowsumcut_: use only data within the region of interest
  • colint, rowint, colintcut, rowintcut: Perform numeric integration (which means the sum is multiplied by the metric pixel size)
  • (imagestream): send the image within the ROI

Properties:

  • cutimg: (bool) send the image inside the ROI
  • colsum: send the column sum
  • rowsum: send the sum over the rows
  • colsumcut, rowsumcut: (bool) send the corresponding data restricted to the region of interest
  • colint, rowint, colintcut, rowintcut: similar to the sum version but taking into account the scale. Therefore these versions can be treated as integrals

class quatm.analysis.imageslice.ImageSlice(name)

Bases: object

run()

quatm.analysis.imageslice.main_run(name)

7.1 - 事件分析模块

该代码定义了一些用于计算和处理物理实验数据的函数,包括计算概率、频率和数据过滤。代码还定义了一个事件函数字典 eventfunctions,其中包含了一些预定义的函数及其相关信息。这些函数主要用于统计分析和数据处理,特别是实验中测量的原子数量和频率。

代码概述

该代码定义了一些用于计算和处理物理实验数据的函数,包括计算概率、频率和数据过滤。代码还定义了一个事件函数字典 eventfunctions,其中包含了一些预定义的函数及其相关信息。这些函数主要用于统计分析和数据处理,特别是实验中测量的原子数量和频率。

依赖库

  • numpy:用于数值计算和数组操作。
  • scipy.constants:用于获取物理常数。
  • scipy.special:用于特殊函数的计算。
  • pytiamo.odt.utils:自定义工具库,用于计算 Wilson 误差。

物理常数

  • m_Li:锂原子的质量。
  • m_Ba:钡原子的质量。
  • kB:玻尔兹曼常数。

函数

P_n(data, args)

计算每个 xvalargs['n'] 的概率,并排除 args['x'] 中的值。

参数:

  • data:包含 x 和 y 值的数组。
  • args:包含 nx 的字典,n 是要计算的值,x 是要排除的值。

返回:

  • xvals:唯一的 x 值数组。
  • p:每个 x 值对应的概率。
  • [l, u]:每个概率的 Wilson 误差。
def P_n(data, args):
    n = float(args['n'])
    x = args['x']
    x = eval(x)
    if type(x) == tuple:
        x = list(x)
    else:
        x = [x]
    xvals = np.array(list(set(data[0])))
    yvals = [data[1][data[0] == i] for i in xvals]
    k = np.array([len(np.where(i==n)[0]) for i in yvals])
    N = np.array([len(i) for i in yvals])
    Nx = np.zeros(len(xvals))
    for j in x:
        Nx += np.array([len(np.where(i==j)[0]) for i in yvals])
    N = N - Nx
    p, l, u = ut.wilson_err(N, k)
    return xvals, p, [l,u]

freq(data, args)

计算每个 xvalargs['n'] 的频率和泊松误差。

参数:

  • data:包含 x 和 y 值的数组。
  • args:包含 n 的字典,n 是要计算的值。

返回:

  • xvals:唯一的 x 值数组。
  • yvals:每个 x 值对应的频率。
  • yerr:每个频率的泊松误差。
def freq(data, args):
    n = float(args['n'])
    xvals = np.array(list(set(data[0])))
    yvals = [data[1][data[0] == i] for i in xvals]
    yvals = np.array([len(np.where(i==n)[0]) for i in yvals])
    yerr = np.sqrt(yvals)
    return xvals, yvals, yerr

getFilter(data, n)

根据给定的值 n 过滤数据集,返回过滤后的数据。

参数:

  • data:包含 x 和 y 值的数组。
  • n:用于过滤数据的值。

返回:

  • filtdat:过滤后的数据数组。
def getFilter(data, n):
    dzip = [list(i) for i in zip(*data)]
    filt = filter(lambda d: d[1] == n, dzip)
    flist = list(filt)
    filtdat = [np.array(i) for i in zip(*flist)]
    return filtdat

事件函数字典 eventfunctions

包含预定义的事件函数及其相关信息,包括函数名称、公式、参数名和初始值。

eventfunctions = {
    '--None--': {
        'function_text': 'no Fitfunction',
        'arg_names': [],
        'start_values': [],
        'function': None
    },
    'P_n': {
        'name': 'P_n',
        'function_text': 'N_n/(N_tot-N_x)',
        'function': P_n,
        'arg_names': ['n', 'x'],
        'start_values': [1, 0]
    },
    'freq': {
        'name': 'freq',
        'function_text': 'N',
        'function': freq,
        'arg_names': ['n'],
        'start_values': [1]
    }
}

总结

该代码实现了一些用于物理实验数据处理的实用函数,包括计算概率、频率和数据过滤。事件函数字典 eventfunctions 提供了预定义的函数和其相关信息,方便在实验分析中使用。

7.2 - 表格组件

table_parameterItemtable_parameter 类扩展了 pyqtgraph 参数树的功能,使其能够以表格形式显示和编辑 NumPy 记录数组。通过注册自定义参数类型,这些类可以轻松地集成到现有的 pyqtgraph 应用程序中,提供灵活且强大的数据编辑功能。

概述

这个代码定义了一个用于编辑 NumPy 记录数组的自定义参数类型 table_parameter,并在 PyQt 环境中实现了一个表格小部件,用于显示和编辑记录数组的数据。

table_parameterItem

table_parameterItem 继承自 pTypes.WidgetParameterItem,是一个用于编辑 NumPy 记录数组的表格小部件。

主要方法

  • __init__(self, param, depth)

    • 初始化参数项,并隐藏小部件。
  • makeWidget(self)

    • 创建一个表格小部件 (QTableWidget)。
    • 获取初始值,并根据值的结构设置表格的行列数和标题。
    • 连接信号和槽,以便在表格内容更改时触发相应的操作。
  • value(self)

    • 获取表格当前的值,并返回一个 NumPy 记录数组。
    • 尝试从表格中读取数据并填充到 NumPy 数组中,如果失败则返回初始值。
  • setValue(self, arr)

    • 设置表格的值。
    • 根据提供的 NumPy 数组填充表格的每个单元格。
  • valueChanged(self, param, val, force=False)

    • 当参数值更改时调用,更新表格的显示内容。
    • 断开信号连接,更新表格值后重新连接信号,确保信号处理不会重复触发。

table_parameter

table_parameter 继承自 Parameter,用于管理和存储表格参数项的值。

主要方法

  • __init__(self, **opts)

    • 初始化参数项,传递其他参数选项。
  • setValue(self, value, blockSignal=None)

    • 设置参数项的值,并返回实际设置的值。
    • 在设置值之前断开信号连接,避免信号重复触发,设置完毕后重新连接信号。
  • valueIsDefault(self)

    • 判断当前值是否等于默认值。
    • 返回一个布尔值,表示当前值是否等于默认值。

registerParameterType 函数

使用 registerParameterType 函数将自定义参数类型 table_parameter 注册到参数树中,使其可以在参数树中使用。

使用场景

  • 该代码主要用于需要在图形用户界面中编辑和显示 NumPy 记录数组的场景。
  • 适用于科学计算、数据分析等需要处理大量数据的应用程序。
  • 提供了一种灵活的方式在 PyQt 应用程序中集成和使用表格参数项。

7.3 - 数据管理分析模块

这段代码实现了一个复杂的图形用户界面应用,用于科学实验数据的管理、分析和可视化。

主要功能和组件介绍

1. 数据存储管理 (H5StorageDataMgr)

  • 数据存储:通过HDF5文件格式保存和加载实验数据。
  • 数据订阅:管理数据流和图像流的订阅,确保在实验过程中捕获和存储所有相关数据。
  • 定时保存:定期自动保存数据,以防数据丢失。
  • 数据清理:在需要时清理当前加载的数据。

2. 图形用户界面 (H5StorageGui)

  • 标签页管理:包含选择数据、绘制数据和事件数据三个主要标签页,每个标签页对应不同的功能模块。
  • 数据选择和加载:允许用户选择数据文件和加载特定实验数据进行分析。
  • 保存和加载按钮:提供保存当前数据和从文件加载数据的功能。

3. 数据绘图 (H5DataPlotter)

  • 数据可视化:使用pyqtgraph和matplotlib库将实验数据绘制成图表,支持多种图形格式(如折线图、散点图等)。
  • 坐标轴选择:允许用户选择和配置x轴和y轴的数据源和显示方式。
  • 定期更新:定期检查并更新绘图数据,以确保图表反映最新的实验数据。
  • 数据导出:将绘制的图表导出为PDF或PNG格式文件。

4. 事件数据处理 (EventPlotter)

  • 事件分析:处理和绘制事件数据,例如离子存活率或损失率的概率或频率。
  • 自定义事件函数:用户可以选择和配置不同的事件函数来分析数据。
  • 保存事件数据:将事件分析结果保存为CSV或pickle文件,方便后续数据处理和分析。

交互功能和用户体验

  • 交互式控件:使用PyQt6提供交互式控件,如按钮、复选框、组合框和文本输入框,使用户能够方便地进行数据选择、配置和操作。
  • 动态更新:用户界面和绘图能够实时更新,确保用户始终看到最新的实验数据。
  • 多样化导出选项:支持将图表导出为不同格式,便于用户在报告和演示中使用。

辅助功能

  • 错误和信息处理:通过日志和弹窗显示错误信息和操作反馈,帮助用户及时了解系统状态和操作结果。
  • 数据过滤和处理:支持数据过滤和自定义处理函数,提供灵活的数据分析手段。

这个应用程序特别适合用于需要频繁收集、分析和可视化实验数据的科研环境。通过集成多种数据处理和绘图功能,它能够显著提高实验数据管理和分析的效率。

导入模块

代码导入了必要的模块和库,用于数据处理、图形绘制、图形用户界面(GUI)开发等。主要模块包括:

  • NumPySciPy:用于科学计算和数据处理。
  • matplotlibpyqtgraph:用于图形绘制。
  • PyQt6:用于构建图形用户界面。
  • pandas:用于数据处理和分析。

全局变量和常量定义

定义了一些物理常数,例如m_Li(锂原子质量)、m_Ba(钡原子质量)和kB(玻尔兹曼常数),这些常量用于后续的计算和拟合。

H5StorageGui 类

这是主界面类,继承自 BWidget。它包含了三个主要组件:

  1. H5StorageDataMgr:用于数据管理和存储。
  2. H5DataPlotter:用于数据的绘制和展示。
  3. EventPlotter:用于处理和绘制事件数据。

__init__ 方法

  • 初始化三个主要组件并将它们添加到标签页中。
  • 设置保存、加载和清除按钮,并配置定时器以定期保存数据。

H5StorageDataMgr 类

该类用于管理HDF5数据存储和加载。主要功能包括:

  • 选择数据存储目录。
  • 管理数据订阅。
  • 存储和加载数据文件。
  • 定期保存和更新数据。

__init__ 方法

  • 初始化数据管理器,设置数据存储路径和文件名。
  • 添加数据订阅编辑器,用于管理数据流和图像流。
  • 配置定时器以定期更新数据。

数据存储和加载

  • savetoFile 方法:将当前数据保存到HDF5文件中。
  • loadFromFile 方法:从HDF5文件中加载数据。
  • clear 方法:清除当前数据。

H5DataPlotter 类

用于绘制和展示数据。主要功能包括:

  • 设置坐标轴选择器。
  • 管理不同数据源。
  • 定期检查和更新数据。
  • 导出图形到PDF或PNG格式。

__init__ 方法

  • 初始化绘图窗口和数据选择器。
  • 设置坐标轴选择器和导出按钮。
  • 配置定时器以定期检查数据更新。

数据更新和绘制

  • checkForNewData 方法:定期检查是否有新数据,并更新绘图。
  • updateDatasources 方法:更新数据源列表。
  • update 方法:更新坐标轴选择器和绘图数据。
  • gen_export_plot 方法:生成用于导出的图形。
  • exportpngexportpdf 方法:导出图形到PNG和PDF格式。

EventPlotter 类

继承自 H5DataPlotter,用于处理和绘制事件数据。主要功能包括:

  • 设置和管理事件数据的坐标轴选择器。
  • 处理事件数据的计算和拟合。
  • 导出事件数据的图形。

__init__ 方法

  • 初始化事件绘图窗口和数据选择器。
  • 配置定时器以定期检查事件数据更新。

数据更新和绘制

  • updateData 方法:更新事件数据。
  • get_event_data 方法:获取和处理事件数据。
  • addFittingaddBinning 方法:添加数据拟合和分箱处理。
  • save_events 方法:保存事件数据。

EventYAxisWidget 类

继承自 YAxisWidget,用于事件数据的Y轴管理。主要功能包括:

  • 管理和更新Y轴数据。
  • 处理事件函数和参数。

updateData 方法

  • 更新Y轴数据和事件函数参数。
  • 处理和应用数据过滤器。

EventFuncWidget 类

用于设置事件函数和参数。主要功能包括:

  • 管理和选择事件函数。
  • 配置事件函数参数。

主要功能总结

  1. 数据管理:通过 H5StorageDataMgr 类实现,支持数据的存储、加载和定期保存。
  2. 数据绘制:通过 H5DataPlotter 类和 EventPlotter 类实现,支持数据和事件数据的绘制、更新和导出。
  3. 图形用户界面:通过 PyQt6 构建,支持用户交互、数据选择和配置。

7.4 - 数据流订阅管理

这段代码实现了能够动态订阅、显示和更新数据流的数据可视化界面。

PlotDataEditor

PlotDataEditor 类是一个管理数据或图像流订阅的小部件。它包含以下关键部分:

  • 初始化方法:接收属性对象和数据字典,设置布局,创建一个下拉菜单用于选择数据流。
  • 更新数据流列表:清空并重新填充下拉菜单中的数据流。
  • 更新数据通道:根据用户选择更新数据通道。

ScrollPlot

ScrollPlot 类继承自 pg.PlotItem,用于显示滚动数据图表。它的主要功能包括:

  • 初始化方法:设置图表属性,初始化数据缓冲区,创建数据流客户端和属性对象。
  • 初始化数据缓冲区:创建一个用于存储数据的数组。
  • 数据馈送方法:将新数据块添加到数据数组中。
  • 更新图表:根据数据数组更新图表显示。
  • 设置新数据:从数据流接收新数据,并调用数据馈送和图表更新方法。
  • 数据选择对话框:弹出一个对话框供用户选择数据流。
  • 订阅窗口:管理数据流订阅的对话框。
  • 配置窗口:弹出一个对话框供用户配置图表属性。

ScrollWindow

ScrollWindow 类继承自 BMainWindow,是应用程序的主窗口。它包含以下关键部分:

  • 初始化方法:创建主窗口和图形窗口,初始化多个 ScrollPlot 实例,并添加到窗口中。
  • 初始化图表:循环创建并添加 ScrollPlot 实例。
  • 数据馈送方法:将新数据块添加到数据数组中。
  • 更新图表:根据数据数组更新所有图表的显示。
  • 更新方法:定期调用数据馈送和图表更新方法。

main 函数

main 函数是程序的入口点,执行以下步骤:

  1. 创建一个 QApplication 实例。
  2. 创建并显示 ScrollWindow 实例。
  3. 启动应用程序事件循环。

主要功能和工作流程

  1. 数据订阅和显示PlotDataEditor 管理数据流订阅,ScrollPlot 显示订阅的数据,并定期更新图表。
  2. 用户交互:用户可以通过图形界面选择和配置数据流,更新图表显示。
  3. 定期更新:通过定时器定期检查和更新数据,实现滚动显示效果。

7.5 - 数据流订阅管理

SubscriptionEditor 类提供了一个直观的界面,用户可以方便地管理数据和图像流的订阅。通过灵活的属性管理和用户交互,确保用户能够轻松地添加、删除和更新订阅,从而适应不断变化的需求和数据源。

概述

这个代码定义了一个订阅编辑器 SubscriptionEditor 类,主要用于管理程序对数据流或图像流的订阅。在 PyQt 环境中,通过一个简单的图形用户界面,用户可以查看和修改当前的订阅列表。

SubscriptionEditor

SubscriptionEditor 类继承自 QWidget,用于管理数据或图像流的订阅。

主要方法和属性

  • 初始化方法 __init__

    • 接受参数:props(属性对象)、category(类别,例如 ‘Image’ 或 ‘Data’)、parent(父组件)、propprefix(属性前缀)、streamkey(流键)、fullList(全列表)。
    • 设置类的各种属性,并初始化图形界面组件,包括 QVBoxLayoutQListWidgetQComboBox
    • 调用 loadSubscriptions 方法加载当前的订阅,并调用 update_streamlist 方法更新可用的流列表。
    • 添加“添加”和“删除”按钮,并连接到相应的槽函数。
  • loadSubscriptions 方法

    • 从属性中加载当前的订阅列表,并将其显示在 QListWidget 中。
  • handle_property_changes 方法

    • 检查属性是否发生变化,如果发生变化则更新订阅列表,并发出 propertiesChanged 信号。
  • update_streamlist 方法

    • 更新 QComboBox 中可用的流列表。
    • 如果类别是 ‘List’,则使用全列表更新。
    • 否则,从属性中获取活动流,并计算每个流的时间差,并将其添加到 QComboBox 中。
  • add 方法

    • QComboBox 中选择的流添加到订阅列表中。
    • 检查流是否已经在订阅列表中,如果没有,则添加到 QListWidget 和属性中,并发出 subscriptionsChanged 信号。
  • deletemarked 方法

    • 删除 QListWidget 中选中的流。
    • 从属性中删除对应的流,并更新 QListWidget,最后发出 subscriptionsChanged 信号。

使用场景

  • 该代码主要用于需要管理数据或图像流订阅的应用程序。
  • 适用于需要动态调整订阅数据源的场景,例如科学计算、数据采集和监控等应用。
  • 提供了一种用户友好的方式,通过图形界面查看和修改订阅列表。

7.6 - 图表动态显示器

这个脚本可以用于需要实时监控和展示数据流的应用程序,例如科学实验、工业监控和实时数据分析等。用户可以通过 GUI 配置数据流的订阅和绘图属性,实时查看和分析数据变化。

概述

这个脚本使用 PyQt6 和 pyqtgraph 库创建了一个实时更新的绘图工具。工具订阅数据流并动态更新图表显示。核心组件包括 UpdatingPlot 类和 LivePlot 类。

主要组件

UpdatingPlot

UpdatingPlot 类继承自 pg.PlotItem,用于创建能够订阅数据流并实时更新的图表。

主要方法和属性
  • 初始化方法 __init__

    • 初始化数据客户端和属性客户端。
    • 设置绘图区域的上下文菜单,添加订阅和配置选项。
    • 启动定时器,每隔 10 毫秒调用 setnewData 方法更新数据。
  • setnewData 方法

    • 检查数据流中是否有新数据。
    • 处理新数据并更新曲线显示。
  • subscribe_window 方法

    • 创建并显示一个对话框,允许用户配置数据流订阅。
    • 更新订阅配置。
  • updateConfiguration 方法

    • 更新数据流订阅。
    • 清除旧的绘图,并为每个数据流创建新的曲线。
  • configureWindow 方法

    • 创建并显示一个对话框,允许用户配置绘图属性。
    • 更新绘图配置。

LivePlot

LivePlot 类继承自 QtWidgets.QWidget,用于创建包含 UpdatingPlot 图表的窗口。

主要方法和属性
  • 初始化方法 __init__

    • 初始化窗口布局,添加 UpdatingPlot 图表。
    • 设置窗口大小提示和显示配置。
  • sizeHint 方法

    • 返回窗口的大小提示。
  • setSizeHint 方法

    • 设置窗口的宽度和高度提示。

使用场景

这个脚本可以用于需要实时监控和展示数据流的应用程序,例如科学实验、工业监控和实时数据分析等。用户可以通过 GUI 配置数据流的订阅和绘图属性,实时查看和分析数据变化。

示例

下面是一个示例,展示如何使用 UpdatingPlotLivePlot 类:

def main(name):
    app = QtGui.QApplication([])
    camWin = LivePlot(name)
    camWin.show()
    sys.exit(app.exec())

if __name__ == '__main__':
    main('dummyname')

在这个示例中,main 函数创建一个 LivePlot 窗口并启动应用程序事件循环。运行此代码将显示一个包含实时更新图表的窗口。

关键功能

  • 实时数据更新:使用定时器定期检查数据流中的新数据并更新图表显示。
  • 动态配置:通过 GUI 配置数据流订阅和绘图属性,支持用户自定义设置。
  • 可扩展性:基于 PyQt6 和 pyqtgraph 构建,易于扩展和集成其他功能。

7.7 - 图形ROI管理器

这个类适用于需要在图形界面中显示和管理多个兴趣区域的应用程序,特别是那些需要通过中心属性类来通信和管理属性的场景。例如,科学实验中的图像处理和分析,实时监控中的区域选择和管理等。

概述

这个脚本定义了一个名为 zmq_ROI 的类,它继承自 pyqtgraph.ROI,并通过 BaLis 的中心属性类 Properties 来通信其属性。该类主要用于在图形界面中显示和管理一个兴趣区域(ROI),并实时更新其属性。

主要组件

zmq_ROI

zmq_ROI 类继承自 pg.ROI,用于创建一个可以通过属性类 Properties 来管理和通信其属性的兴趣区域。

属性和方法
  • 静态属性

    • roilist:存储所有 ROI 名称的列表。
    • p_pos:存储 ROI 的位置。
    • p_size:存储 ROI 的大小。
    • color:存储 ROI 的颜色。
  • 初始化方法 __init__

    • 初始化 ROI 的名称和属性。
    • 将 ROI 名称添加到 roilist 中(如果不存在)。
    • 设置 ROI 的位置和大小,并启动一个定时器,每隔 1000 毫秒调用 _publish_values 方法。
  • update_from_properties 方法

    • 从属性中更新 ROI 的颜色、位置和大小。
  • _publish_values 方法

    • 检查 ROI 的位置和大小是否发生变化。如果发生变化,则更新属性中的位置和大小。
    • 如果属性中有变化,则从属性中更新 ROI 的信息。

使用场景

这个类适用于需要在图形界面中显示和管理多个兴趣区域的应用程序,特别是那些需要通过中心属性类来通信和管理属性的场景。例如,科学实验中的图像处理和分析,实时监控中的区域选择和管理等。

示例

下面是一个使用 zmq_ROI 类的示例:

import pyqtgraph as pg
from PyQt6.QtWidgets import QApplication
import sys

def main():
    app = QApplication(sys.argv)
    win = pg.GraphicsLayoutWidget(show=True)
    view = win.addViewBox()
    view.setAspectLocked(True)
    img = pg.ImageItem()
    view.addItem(img)
    
    # 创建并添加 zmq_ROI 实例
    roi = zmq_ROI('exampleROI', pos=[50, 50], size=[100, 100])
    view.addItem(roi)
    
    # 显示窗口
    win.show()
    sys.exit(app.exec())

if __name__ == '__main__':
    main()

在这个示例中,main 函数创建一个包含图像和兴趣区域(ROI)的窗口。运行此代码将显示一个窗口,其中包含一个可拖动和调整大小的 ROI。

关键功能

  • 属性通信:通过 Properties 类管理和通信 ROI 的属性,使得多个 ROI 可以共享和实时更新其属性。
  • 定时更新:通过定时器定期检查和更新 ROI 的位置和大小。
  • 图形界面集成:集成到 pyqtgraph 中,提供强大的图形界面支持。

7.8 - 属性编辑器

这个代码实现了一个属性编辑器 GUI,用于管理和编辑属性树。

ScalableGroup 类

ScalableGroup 类是一个自定义的参数组,用于自动生成两个子参数,这两个子参数始终互为倒数。

初始化方法
  • __init__ 方法
    • 初始化参数组,并设置组类型、添加文本和添加列表。
    • 调用基类 GroupParameter 的初始化方法。
添加新参数方法
  • addNew 方法
    • 根据参数类型(字符串、浮点数或整数)添加新的子参数。
    • 设置新子参数的初始值和属性。

TreeEdit 类

TreeEdit 类用于从 Properties 类中提取信息并根据树视图进行格式化。

初始化方法
  • __init__ 方法
    • 初始化类实例,设置父类和子树路径。
    • 从属性对象中提取条目,并创建参数组。
    • 连接参数组的状态变化信号到 change 方法。
解析字典方法
  • _parsedict 方法
    • 将字典格式化为可以在树视图中查看的格式。
    • 根据不同的数据类型(整数、布尔、字符串、浮点数、列表、字典)创建相应的参数条目。
更改参数方法
  • change 方法
    • 处理树视图中的任何更改。
    • 根据参数类型和变化的数据更新属性对象。
更新方法
  • _update_update_whole_tree 方法
    • 更新树视图中选定条目或整个树视图。
    • 根据属性对象中的数据重新生成参数条目。

PropEdit 类

PropEdit 类是属性编辑器的主要 GUI 窗口,用于管理属性树。

初始化方法
  • __init__ 方法
    • 初始化类实例,设置子树路径。
    • 创建布局和参数树视图。
    • 添加更新、删除、保存和加载按钮,并连接相应的槽函数。
更新、保存、加载和删除方法
  • update 方法
    • 更新参数树视图。
  • save 方法
    • 将当前属性保存到文件。
  • load 方法
    • 从文件加载属性并更新参数树视图。
  • delete 方法
    • 删除当前选定的参数条目。

PropSelector 类

PropSelector 类是属性选择器 GUI,用于从属性树中选择和管理键列表。

初始化方法
  • __init__ 方法
    • 初始化类实例,设置子树路径。
    • 创建布局和参数树视图。
    • 添加选择和删除按钮,并连接相应的槽函数。
选择和删除方法
  • select 方法
    • 从参数树视图中选择当前条目并更新键列表。
  • updateKeys 方法
    • 更新键列表视图。
  • delete_marked 方法
    • 删除当前选定的键条目。

主函数

  • main 方法
    • 创建应用程序实例,设置窗口图标,创建并显示主窗口。
    • 进入应用程序事件循环。

代码逻辑

  1. 导入所需模块:导入标准库、第三方库和项目特定模块。
  2. 定义 ScalableGroup 类:自定义参数组,用于自动生成子参数。
  3. 定义 TreeEdit 类:从 Properties 类中提取信息并根据树视图进行格式化。
  4. 定义 PropEdit 类:属性编辑器的主要 GUI 窗口。
  5. 定义 PropSelector 类:属性选择器 GUI,用于选择和管理键列表。
  6. 定义主函数:创建并启动应用程序。
  7. 运行主程序:检查是否在交互模式下运行,如果不是,则运行主程序。

运行流程概述

  1. 启动应用程序:创建 QApplication 实例,并设置窗口图标。
  2. 创建 PropEdit 实例:初始化属性编辑器,并显示主窗口。
  3. 管理属性树:通过参数树视图和按钮与属性对象交互,更新、保存、加载和删除属性条目。
  4. 进入事件循环:应用程序进入事件循环,等待用户交互。

7.9 - 属性更新管理器

该代码实现了一个用于检查属性更新的 GUI 应用程序。通过 PropertiesChecker 类,用户可以定期检查属性是否更新,并在属性未更新时发出警报,使用了 PyQt6 的多种控件和信号槽机制来实现用户交互和数据更新。

PropertiesChecker 类

PropertiesChecker 类用于检查属性是否定期更新,并在属性未更新时发出警报。以下是该类的详细分析:

初始化方法
  • __init__ 方法
    • 初始化类实例,并设置初始状态或配置。
    • 创建两个 Properties 对象,用于检查属性的更新。
    • 初始化一个 QSoundEffect 对象,用于播放警报声音。
    • 调用 run 方法开始检查属性更新。
警报窗口方法
  • open_alert_window 方法
    • 创建并显示一个警报对话框,当属性未更新时调用。
    • 播放警报声音。
属性检查方法
  • run 方法
    • 使用一个无限循环定期检查属性是否更新。
    • 每隔一段时间设置和检查属性值。
    • 如果属性值未更新,则打印错误信息并显示警报窗口;否则,打印属性仍在更新的信息。

主函数

  • main 方法
    • 创建应用程序实例,设置窗口图标,创建并显示主窗口。
    • 进入应用程序事件循环。

代码逻辑

  1. 导入所需模块:导入标准库、第三方库和项目特定模块。
  2. 定义 PropertiesChecker 类:包含初始化方法、警报窗口方法和属性检查方法。
  3. 定义主函数:创建并启动应用程序。
  4. 运行主程序:检查是否在交互模式下运行,如果不是,则运行主程序。

运行流程概述

  1. 启动应用程序:创建 QApplication 实例,并设置窗口图标。
  2. 创建 PropertiesChecker 实例:初始化属性检查器,并开始检查属性更新。
  3. 检查属性更新:在 run 方法中,定期设置和检查属性值,并在属性未更新时发出警报。
  4. 显示警报窗口:当属性未更新时,显示警报对话框并播放警报声音。
  5. 进入事件循环:应用程序进入事件循环,等待用户交互。

7.10 - 数据/图像分析管理器

该代码实现了一个数据/图像分析管理器,通过图形用户界面(GUI)来启动、停止和配置分析脚本。使用PyQt6库来构建界面,包括树视图、按钮、文本框和下拉菜单。代码主要包括四个类:checkableModelTreeViewWidgetaddAnalysisWidgetAnalysisManager

类和方法

checkableModel

checkableModel 继承自 QtGui.QStandardItemModel,实现了一个可检查的模型。

方法:

  • test(self):测试方法(空实现)。

TreeViewWidget

TreeViewWidget 继承自 QWidget,实现了一个树视图组件,用于显示和管理分析任务。

方法:

  • __init__(self, props, parent=None):初始化树视图组件。

    • props:属性对象,用于存储和管理配置数据。
    • parent:父窗口。
    • 创建树视图和模型,并设置定时器定期更新任务状态。
  • createMailModel(self, parent):创建树视图模型。

    • 设置模型的列标题。
    • 连接模型的itemChanged信号到itchange方法。
  • itchange(self, item):处理模型项改变事件。

    • item:改变的模型项。
    • 根据项的检查状态,启动或停止相应的分析任务,并更新属性。
  • killVagabonding(self, pname, pargs):终止运行的孤立进程。

    • pname:程序名称。
    • pargs:程序参数。
    • 根据操作系统,查找并终止孤立进程。
  • startProcess(self, name):启动分析任务。

    • name:任务名称。
    • 终止同名任务后,启动新任务并记录进程对象。
  • endProcess(self, name):终止分析任务。

    • name:任务名称。
    • 如果任务在运行,则终止进程并记录日志。
  • updateStatus(self):更新任务状态。

    • 检查进程是否仍在运行,更新任务状态和视图。
  • addItem(self, direc, script, Filtername, active, category, streams):添加新任务到树视图。

    • direc:目录。
    • script:脚本名称。
    • Filtername:任务名称。
    • active:任务是否激活。
    • category:任务类别。
    • streams:数据流。
    • 创建新任务项并添加到模型中。
  • del_current(self):删除当前选中的任务。

    • 获取选中的任务项并删除相应的任务和进程。
  • configureCurrent(self):配置当前选中的任务。

    • 获取选中的任务项,打开属性编辑对话框进行配置。
  • __del__(self):析构函数,终止所有运行中的任务。

addAnalysisWidget

addAnalysisWidget 继承自 QWidget,实现了一个用于添加新分析任务的组件。

方法:

  • __init__(self, manager, parent=None):初始化添加分析任务组件。

    • manager:分析管理器对象。
    • parent:父窗口。
    • 创建布局、按钮、文本框和下拉菜单。
  • update_streamlist(self, category):更新数据流列表。

    • category:任务类别。
    • 根据选定的类别更新数据流下拉菜单。
  • addd(self):添加新任务。

    • 获取输入的信息,创建新任务,并添加到分析管理器中。

AnalysisManager

AnalysisManager 继承自 BWidget,实现了分析管理器,管理分析脚本的运行。

方法:

  • __init__(self, name='Analysis', parent=None):初始化分析管理器。

    • name:管理器名称,默认为’Analysis’。
    • parent:父窗口。
    • 设置属性和分析目录,初始化GUI。
  • initGUI(self):初始化GUI界面。

    • 创建添加分析任务组件和树视图组件,并设置布局。
    • 添加已有任务到树视图中。
  • delentry(self):删除当前选中的任务。

    • 调用树视图的del_current方法。
  • configureFilter(self):配置当前选中的任务。

    • 调用树视图的configureCurrent方法。

主函数

代码通过创建 QApplication 实例和 AnalysisManager 窗口来执行,并启动应用程序的主循环。

def main():
    app = QtWidgets.QApplication(sys.argv)
    icon = QtGui.QIcon()
    icon.addFile(iconpath + '/analysis.png')
    app.setWindowIcon(icon)
    Win = AnalysisManager()
    Win.setWindowTitle('Data/Image analysis manager')
    Win.show()
    sys.exit(app.exec())

代码执行

该代码通过命令行执行,创建一个AnalysisManager对象,并显示数据/图像分析管理器窗口。

7.11 - 数据/图像分析管理器

该代码定义了一些用于拟合和分析物理实验数据的数学函数。它包括一系列函数和常量,用于描述各种物理现象,例如多项式、指数衰减、高斯分布等。这些函数可以用于数据拟合和模型化实验结果。

常量定义

代码开始定义了一些常见的物理常数,用于后续计算。

  • m_Li:锂原子的质量
  • m_Ba:钡原子的质量
  • kB:玻尔兹曼常数

函数定义

这些函数用于拟合和分析实验数据,每个函数都有特定的用途和参数。

多项式函数

用于拟合线性和多项式数据。

  • pol1(p, x):一阶多项式
  • pol2(p, x):二阶多项式
  • pol10(p, x):十阶多项式

指数函数

用于描述指数增长和衰减现象。

  • exponential(p, x):指数函数
  • exponential_decay(p, x):指数衰减函数

扩展模型函数

用于描述复杂的物理现象,例如热云膨胀。

  • tof_temperature(p, x):热云膨胀模型
  • spatial_thermometry_scaled(p, x):空间测温模型

高斯函数

用于描述高斯分布和光束强度分布。

  • gaussian(p, x):高斯分布函数
  • gaussian_beam_intensity(p, x):高斯光束强度分布

洛伦兹函数

用于描述洛伦兹分布。

  • lorentzian(p, x):洛伦兹分布
  • lorentzian_cutoff(p, x):带截止的洛伦兹分布

其他函数

描述不同物理现象的函数。

  • sinc_profile(p, x):sinc函数
  • rabi_oscillation(p, x):拉比振荡
  • ac_stark_detuned_scattering(p, x):AC Stark失谐散射
  • saturation_parameter(p, x):饱和参数

拟合函数字典

这些函数被存储在一个字典中,可以根据需要进行调用。每个条目包含函数名称、函数公式、参数名称、初始值以及函数本身。

fitfunctions = {
    '--None--': {'function_text': 'no Fitfunction', 'par_names': [], 'startvalues': [], 'function': None},
    'linear': {'name': 'linear fit', 'function_text': 'a+b*x', 'par_names': ['a', 'b'], 'startvalues': [1, 0], 'function': pol1},
    'quadratic': {'name': 'quadratic fit', 'function_text': 'a+b*x+c*x^2', 'par_names': ['a', 'b', 'c'], 'startvalues': [1, 0, 0], 'function': pol2},
    'exponential': {'name': 'exponential', 'function_text': 'a+be^cx', 'par_names': ['a', 'b', 'c'], 'startvalues': [0, 1, 1], 'function': exponential},
    'tof_temperature': {'name': 'TOF_temperature', 'function_text': 'sqrt(sigma_0**2 + kB*T/m *(t-t0)**2)', 'par_names': ['sigma_0', 'T', 't0'], 'startvalues': [5e-6, 1.5e-6, 25e-6], 'function': tof_temperature},
    'spatial_thermometry_scaled': {'name': 'Spatial thermometry', 'function_text': 'sqrt(sigma_th^2 + sigma_psf^2)', 'par_names': ['T', 'sigma_psf'], 'startvalues': [360e-6, 10e-6], 'function': spatial_thermometry_scaled},
    'exponential_decay': {'name': 'exponential_decay', 'function_text': 'A*exp(-x/tau) + c', 'par_names': ['tau', 'A', 'c'], 'startvalues': [0.0003, 300e-6, 0.0], 'function': exponential_decay},
    'gaussian': {'name': 'gaussian', 'function_text': 'A0/(sqrt(2*pi)*sigma)*exp(-(x-mu)**2/2sigma**2) + c', 'par_names': ['mu', 'sigma', 'A0', 'c'], 'startvalues': [0, 1, 1, 0], 'function': gaussian},
    'lorentzian': {'name': 'lorentzian', 'function_text': 'A0 / (1 + (mu-x / (fwhm/2))**2) + c', 'par_names': ['mu', 'fwhm', 'A0', 'c'], 'startvalues': [318, 6, 18e3, 0], 'function': lorentzian},
    'sinc_profile': {'name': 'sinc_profile', 'function_text': 'A0 * sinc(b*(x-x0))**2 + c', 'par_names': ['x0', 'A0', 'b', 'c'], 'startvalues': [73.739e6, -2.3e4, 7e-4, 23e3], 'function': sinc_profile}
}

7.12 - 数据流图片流监视器

该代码使用 PyQt6 库构建了一个 GUI 应用,用于显示和编辑数据流、图像数据和相机属性。代码主要定义了一些自定义窗口小部件(widgets),包括参数显示框、图像数据框和相机属性框,并实现了上下文菜单、订阅管理和数据选择对话框等功能。

概要

该代码使用 PyQt6 库构建了一个 GUI 应用,用于显示和编辑数据流、图像数据和相机属性。代码主要定义了一些自定义窗口小部件(widgets),包括参数显示框、图像数据框和相机属性框,并实现了上下文菜单、订阅管理和数据选择对话框等功能。

主要类和功能

ParameterBox

该类继承自 BFrame,用于显示单个参数。它包括以下功能:

  • 初始化:设置框架样式、获取属性和数据流名称,并初始化显示标签。
  • 数据更新:使用定时器定期从数据流中获取新数据,并更新显示值。
  • 上下文菜单:右键单击时显示上下文菜单,包括订阅管理和数据选择功能。
  • 订阅管理:打开订阅管理窗口以编辑订阅。
  • 数据选择:打开数据选择对话框以选择要显示的数据。

ImageDataBox

该类继承自 BFrame,用于显示图像数据。它包括以下功能:

  • 初始化:设置框架样式、获取属性,并初始化显示框。
  • 上下文菜单:右键单击时显示上下文菜单,包括订阅管理功能。
  • 订阅管理:打开订阅管理窗口以编辑订阅。
  • 数据更新:通过设置新数据的方法更新显示框内容。

CamPropsBox

该类继承自 ImageDataBox,用于显示相机属性。它包括以下功能:

  • 初始化:获取相机名称和属性子树,并设置定时器定期更新数据。
  • 上下文菜单:右键单击时显示上下文菜单,包括属性和相机选择功能。
  • 属性窗口:打开属性选择窗口以编辑相机属性。
  • 相机选择窗口:打开相机选择窗口以选择要显示的相机。
  • 数据更新:根据当前相机和配置获取并显示相机属性。

DataBox

这是一个简单的用于显示标签和值的框,继承自 QWidget。它主要包括:

  • 初始化:设置布局,添加标签和值的显示。
  • 大小提示:返回组件的建议大小。

详细描述

ParameterBox

  • __init__ 方法

    • 初始化框架样式和宽度。
    • 获取参数属性和数据流名称。
    • 初始化显示标签和值标签,并设置布局。
    • 设置上下文菜单策略和定时器。
  • setNewData 方法

    • 检查数据流中是否有新数据。
    • 更新显示值。
  • openMenu 方法

    • 打开上下文菜单,包含订阅管理和数据选择选项。
  • dataSelectDialog 方法

    • 打开数据选择对话框,允许用户选择要显示的数据。
  • subscribe_window 方法

    • 打开订阅管理窗口,允许用户编辑订阅。
  • updateSubscription 方法

    • 更新数据流订阅。
  • updateDataLists 方法

    • 更新数据列表和显示标签。

ImageDataBox

  • __init__ 方法

    • 初始化框架样式和宽度。
    • 获取属性并初始化显示框。
    • 设置上下文菜单策略。
  • openMenu 方法

    • 打开上下文菜单,包含订阅管理选项。
  • subscribe_window 方法

    • 打开订阅管理窗口,允许用户编辑订阅。
  • dataSelectDialog 方法

    • 打开数据选择对话框,允许用户选择要显示的数据。
  • setNewData 方法

    • 更新显示框内容。

CamPropsBox

  • __init__ 方法

    • 获取相机名称和属性子树。
    • 设置定时器定期更新数据。
  • openMenu 方法

    • 打开上下文菜单,包含属性和相机选择选项。
  • props_window 方法

    • 打开属性选择窗口,允许用户编辑相机属性。
  • cams_window 方法

    • 打开相机选择窗口,允许用户选择相机。
  • setNewData 方法

    • 更新相机属性显示。

DataBox

  • __init__ 方法

    • 设置布局,添加标签和值显示。
  • sizeHint 方法

    • 返回组件的建议大小。

运行流程

  1. 创建 ParameterBoxImageDataBoxCamPropsBox 的实例。
  2. 定时器触发,调用 setNewData 方法从数据流中获取新数据并更新显示。
  3. 用户右键单击组件,显示上下文菜单。
  4. 用户选择订阅管理或数据选择选项,打开相应的对话框。
  5. 用户在对话框中编辑订阅或选择数据,更新组件显示。

7.13 - 数据流图片流监视器

该代码实现了一个基于 PyQt6 的应用程序,用于订阅和显示数据流或图像流。应用程序提供了一个可滚动的绘图窗口,用户可以通过多种交互方式来管理数据源和配置绘图属性。

功能介绍

该代码实现了一个基于 PyQt6 的应用程序,用于订阅和显示数据流或图像流。应用程序提供了一个可滚动的绘图窗口,用户可以通过多种交互方式来管理数据源和配置绘图属性。

代码结构

  1. 导入必要的模块和库
  2. 定义 PlotDataEditor
  3. 定义 ScrollPlot
  4. 定义 ScrollWindow
  5. 定义脚本入口

类:PlotDataEditor

功能介绍

PlotDataEditor 类是一个小部件,用于管理程序对数据流或图像流的订阅。

方法

  • __init__:初始化 PlotDataEditor 对象,设置布局和控件,更新可用流的列表。
    • 参数:props (属性对象)、data (初始数据字典)、category (流的类别)、parent (父对象)、preselect (预选择的流名称)。
  • update_streamlist:更新流选择框中的可用流列表。
  • updateDatachannel:更新选定的数据通道,并在父对象中设置相关属性。

类:ScrollPlot

功能介绍

ScrollPlot 类是一个绘图部件,用于订阅数据流并实时更新显示。

方法

  • __init__:初始化 ScrollPlot 对象,设置属性,订阅数据流,并配置绘图选项。
    • 参数:name (绘图的名称)、parent (父对象)。
  • initDataBuffer:初始化数据缓冲区,用于存储接收的数据。
  • feedData:将新数据块添加到数据缓冲区,并计算运行平均值(如果启用)。
  • clearPlot:清除绘图中的数据。
  • updatePlot:更新绘图,显示新的数据点和运行平均值。
  • updatePlotContent:更新绘图内容,删除当前内容以便显示新的数据。
  • updateTitle:更新绘图的标题。
  • updateSubscription:更新数据流的订阅,切换到新的数据流。
  • updateDataLists:更新数据列表和相关属性。
  • setnewData:接收新数据并更新绘图。
  • setScatterplot:设置散点图的绘图选项。
  • deletePlot:删除绘图并从属性中移除相关配置。
  • dataSelectDialog:打开数据选择对话框,用于选择新的数据源。
  • subscribe_window:打开订阅窗口,用于管理数据流的订阅。
  • configureWindow:打开配置窗口,用于修改绘图属性。
  • running_mean:静态方法,计算运行平均值。

类:ScrollWindow

功能介绍

ScrollWindow 类是主窗口类,包含多个滚动绘图,用于显示和管理数据流。

方法

  • __init__:初始化 ScrollWindow 对象,设置窗口和工具栏,并恢复之前保存的绘图。
    • 参数:name (窗口的名称)、parent (父对象)、n_plots (初始绘图数量)。
  • init_toolbar:初始化工具栏,添加操作按钮。
  • updateAllSubscriptions:更新所有绘图的订阅。
  • restorePlots:恢复之前保存的绘图。
  • addPlot:添加新绘图到窗口中。

脚本入口

功能介绍

脚本入口用于创建应用程序实例,显示主窗口并启动应用事件循环。

主要步骤

  1. 创建 QApplication 实例。
  2. 创建 ScrollWindow 实例。
  3. 显示主窗口。
  4. 启动应用事件循环。

总结

该代码实现了一个完整的 PyQt6 应用程序,用于管理和显示数据流。通过定义多个类和方法,用户可以方便地订阅数据流、配置绘图属性以及实时更新绘图。

7.14 - 数据实时监视器

该模块是一个用于在科学实验中实时绘制和分析数据的 PyQt6 控件。该控件集成了 pyqtgraph 库,用于高效地绘制和更新图表。

类:DataPlotterWidget

方法:__init__

功能:初始化 DataPlotterWidget 对象,设置属性和布局,启动定时器用于实时数据更新。

参数

  • axis_name:轴名称
  • prop_root:属性根路径
  • datastream_names:数据流名称列表
  • n_yaxis:Y轴数量
  • parent:父对象

主要步骤

  1. 初始化属性和数据管理器 (DataSummary)。
  2. 创建并设置网格布局 (QGridLayout)。
  3. 调用 buildPlotWidget 方法创建绘图小部件。
  4. 调用 buildDataSelector 方法创建数据选择器。
  5. 启动定时器,每20毫秒调用 checkForNewData 方法检查新数据。
方法:buildPlotWidget

功能:创建并设置绘图窗口和右键菜单。

主要步骤

  1. 创建 pyqtgraph 图形布局窗口 (GraphicsLayoutWidget)。
  2. 在窗口中添加绘图项 (PlotItem)。
  3. 添加右键菜单选项,通过 QAction 类实现。
方法:buildDataSelector

功能:创建并设置数据选择器界面。

主要步骤

  1. 创建数据选择器 (DataSelectorItem)。
  2. 创建 X轴选择器 (XAxisWidget) 和多个 Y轴选择器 (YAxisWidgetHelper)。
  3. 设置网格布局 (QGridLayout) 来管理数据选择器控件的排列和显示。
  4. 隐藏配置界面,默认不显示。
方法:toggleConfig

功能:切换配置界面的显示和隐藏状态。

主要步骤

  1. 根据 configVisible 变量的值显示或隐藏配置界面。
  2. 更新 configVisible 变量的值。
方法:setDataSource

功能:设置或更改数据源。

参数text - 数据源名称。

方法:checkForNewData

功能:检查是否有新数据,并更新图表。

主要步骤

  1. 调用 recvData 方法从数据源接收数据。
  2. 如果有新数据,更新 lastUpdate 时间戳。
  3. 调用 updateDatasourcesupdate 方法更新数据源和图表。
方法:updateDatasources

功能:检查并更新数据源列表。

主要步骤

  1. 创建一个新的数据源列表 sourcelist
  2. 如果数据源列表有变化,更新数据选择器中的数据源列表。
方法:update

功能:更新数据选择器中的可选数据字段,并更新图表。

主要步骤

  1. 从当前数据集中选择所有代表浮点数或整数的键。
  2. 更新数据选择器中的可选键列表。
  3. 调用 _updatePlotData 方法更新图表。
方法:_updatePlotData

功能:更新图表数据。

主要步骤

  1. 获取当前选中的 X轴字段。
  2. 调用每个 Y轴选择器的 updateData 方法更新数据。
方法:exportpdf

功能:导出图表为 PDF 文件。

主要步骤

  1. 创建一个 matplotlib 图表对象。
  2. 调用每个 Y轴选择器的 plotmpl 方法将数据绘制到图表上。
  3. 保存图表为 PDF 文件并使用查看器打开。
方法:clear

功能:清除数据。

主要步骤

  1. 调用数据管理器的 clear 方法清除数据。
  2. 移除所有图表项。
方法:plotData

功能:在图表中绘制数据。

参数

  • x:X轴数据
  • y:Y轴数据

主要步骤

  1. 创建一个 pg.PlotDataItem 对象并设置绘图样式。
  2. 将数据添加到图表项中并绘制。

类:YAxisWidgetHelper

方法:__init__

功能:初始化 YAxisWidgetHelper 对象,设置属性和布局。

参数

  • label:标签
  • plotter:数据绘图器对象
  • props:属性对象
  • plotitem:绘图项对象
  • parent:父对象

主要步骤

  1. 初始化 Y轴选择器,创建并设置布局和过滤器组合框。
  2. 创建并配置绘图项。
方法:updateYscale

功能:更新 Y轴缩放比例。

参数text - 缩放比例文本。

方法:createContextMenu

功能:创建上下文菜单。

参数position - 菜单位置。

主要步骤

  1. 创建菜单项用于添加过滤、分箱和拟合。
  2. 显示菜单并处理用户选择。
方法:_initPlot

功能:初始化绘图项。

主要步骤

  1. 创建并配置 pg.PlotDataItem 对象。
  2. 添加到绘图项中。
方法:configurePlot

功能:配置绘图样式。

主要步骤

  1. 设置绘图项的绘图样式。
  2. 如果有后续数据处理步骤,递归调用其配置方法。
方法:addBinning

功能:添加分箱处理步骤。

主要步骤

  1. 如果当前没有后续处理步骤,创建 BinningWidget 并添加到布局中。
  2. 更新数据。
方法:addFitting

功能:添加拟合处理步骤。

主要步骤

  1. 如果当前没有后续处理步骤,创建 FittingWidget 并添加到布局中。
  2. 更新数据。
方法:reevaluateData

功能:重新评估数据。

主要步骤

  1. 获取当前 X轴字段。
  2. 调用 updateData 方法更新数据。
方法:updateData

功能:更新数据。

参数xtext - X轴字段。

主要步骤

  1. 获取当前 Y轴字段。
  2. 从数据源获取数据并应用过滤器。
  3. 更新图表中的数据。
方法:plotmpl

功能:在 matplotlib 图表中绘制数据。

参数

  • axmatplotlib 图表轴对象。

主要步骤

  1. 将数据绘制到 matplotlib 图表轴中。
  2. 如果有后续数据处理步骤,递归调用其绘图方法。

7.15 - 图像查看器

该代码实现了一个基于 PyQt6 的图像查看器应用,名为 ImageWindow。这个应用包含一个中心图像显示区域和两个用于显示线图的侧边栏。用户可以通过该应用实时查看和分析图像数据,并调整图像的显示参数。

功能介绍

该代码实现了一个基于 PyQt6 的图像查看器应用,名为 ImageWindow。这个应用包含一个中心图像显示区域和两个用于显示线图的侧边栏。用户可以通过该应用实时查看和分析图像数据,并调整图像的显示参数。

代码结构

  • 导入必要的模块和库
  • 定义 ImageWindow
  • 定义主函数 main
  • 定义脚本入口

类:ImageWindow

简短功能介绍

ImageWindow 类是一个主窗口,包含一个图像显示区域和两个用于显示线图的侧边栏。此外,它还提供了一些工具栏和面板,用于调整图像显示参数和查看图像信息。

方法:__init__

功能:初始化 ImageWindow 对象,并设置窗口名称和父对象。

参数

  • name:窗口名称。
  • parent:父对象(可选)。

主要步骤

  1. 调用父类 BMainWindow 的构造函数。
  2. 初始化属性字段。
  3. 调用 initUI 方法初始化用户界面。

方法:initUI

功能:初始化用户界面,包括状态栏、图像显示区域和停靠窗口。

主要步骤

  1. 显示状态栏信息。
  2. 创建图像显示区域并设置为中心部件。
  3. 创建停靠窗口(Dock Widgets)。

方法:createDockWidgets

功能:创建用于显示线图、直方图和图像信息的停靠窗口。

主要步骤

  1. 创建顶部的线图停靠窗口并添加到主窗口。
  2. 创建右侧的线图停靠窗口并添加到主窗口。
  3. 创建左侧的直方图停靠窗口并添加到主窗口。
  4. 创建顶部的图像信息停靠窗口并添加到主窗口。

方法:update_min_max

功能:更新图像显示的最小和最大亮度值。

主要步骤

  1. 获取直方图的最小和最大亮度值。
  2. 更新属性中的最小和最大亮度值。

方法:get_tick_position

功能:获取直方图梯度的刻度位置。

主要步骤

  1. 获取直方图梯度的所有刻度位置。
  2. 计算并返回归一化的刻度位置。

方法:closeEvent

功能:在窗口关闭事件中保存当前图像的显示范围和刻度位置。

主要步骤

  1. 获取图像显示的 x 和 y 范围。
  2. 保存显示范围和刻度位置到属性中。
  3. 调用父类的关闭事件处理方法。

主函数:main

功能:创建并显示 ImageWindow 实例。

参数

  • name:窗口名称。

主要步骤

  1. 创建 QApplication 实例。
  2. 创建 ImageWindow 实例并设置窗口图标。
  3. 显示窗口。
  4. 启动应用事件循环。

脚本入口

功能:解析命令行参数并调用 main 函数。

主要步骤

  1. 检查是否以交互模式运行。
  2. 解析命令行参数获取程序实例名称。
  3. 调用 main 函数。

7.16 - 图像监视器

该代码实现了一个基于 PyQt6 的图像监控器应用,名为 ImageDisplay。这个应用能够接收并实时显示图像数据,并提供多种工具来调整和保存图像。用户可以通过该应用监控图像流,应用滤波器,调整显示参数,并保存当前图像。

功能介绍

该代码实现了一个基于 PyQt6 的图像监控器应用,名为 ImageDisplay。这个应用能够接收并实时显示图像数据,并提供多种工具来调整和保存图像。用户可以通过该应用监控图像流,应用滤波器,调整显示参数,并保存当前图像。

代码结构

  • 导入必要的模块和库
  • 定义 ImageDisplay
  • 定义主函数 main
  • 定义脚本入口

类:ImageDisplay

简短功能介绍

ImageDisplay 类是一个自更新的图像显示窗口,能够实时接收和显示图像数据,并提供多种工具和设置来调整图像显示效果。

方法:__init__

功能:初始化 ImageDisplay 对象,并设置窗口名称和父对象。

参数

  • name:窗口名称。
  • parent:父对象(可选)。

主要步骤

  1. 初始化属性字段。
  2. 创建并设置图像显示区域。
  3. 订阅图像流和掩码流。
  4. 设置图像显示和掩码显示的初始数据。
  5. 创建图像显示窗口和控件布局。
  6. 启动定时器以定期更新图像。

方法:sizeHint

功能:返回窗口的推荐大小。

返回值QtCore.QSize(800, 700)

方法:noise_filter

功能:应用噪声滤波器处理图像。

参数

  • img:待处理的图像数据。

主要步骤

  1. 将图像数据转换为绝对值。
  2. 应用双边滤波器和中值滤波器进行去噪处理。
  3. 返回处理后的图像。

方法:spot_detector

功能:检测图像中的亮点。

参数

  • img:待处理的图像数据。

主要步骤

  1. 将图像二值化,阈值为 _spot_level

方法:update_image

功能:定期更新图像显示。

主要步骤

  1. 检查是否有新图像数据。
  2. 接收并处理新图像数据。
  3. 更新图像显示。
  4. 更新图像掩码。

方法:update_mask

功能:更新图像掩码。

主要步骤

  1. 检查是否有新掩码数据。
  2. 接收并处理新掩码数据。
  3. 更新掩码显示。

方法:saveCurrentImage

功能:保存当前显示的图像为 PNG 文件。

主要步骤

  1. 构建文件路径,包含当前时间戳。
  2. 保存图像数据到文件。

方法:subscribe_window

功能:打开订阅窗口,用于选择图像流。

主要步骤

  1. 打开订阅窗口。
  2. 更新图像流订阅。

方法:subscribe_mask

功能:打开订阅窗口,用于选择掩码流。

主要步骤

  1. 打开订阅窗口。
  2. 更新掩码流订阅。

方法:_subscribe_win

功能:创建并显示订阅窗口。

参数

  • key:订阅的键。

主要步骤

  1. 创建对话框。
  2. 添加订阅编辑器到对话框。
  3. 显示对话框。

方法:configureWindow

功能:打开配置窗口,用于调整图像显示参数。

主要步骤

  1. 创建对话框。
  2. 添加属性编辑器到对话框。
  3. 显示对话框。

主函数:main

功能:创建并显示 ImageDisplay 实例。

参数

  • name:窗口名称。

主要步骤

  1. 创建 QApplication 实例。
  2. 创建 ImageDisplay 实例并设置窗口图标。
  3. 显示窗口。
  4. 启动应用事件循环。

脚本入口

功能:解析命令行参数并调用 main 函数。

主要步骤

  1. 检查是否以交互模式运行。
  2. 解析命令行参数获取程序实例名称。
  3. 调用 main 函数。

8 - 多语言支持

在您的实验控制中使用多种计算机语言。

If you’d like to provide site content in multiple languages, the Docsy theme and Hugo make it easy to both add your translated content and for your users to navigate between language versions.

Content and configuration

To add content in multiple languages, you first need to define the available languages in a languages section in your site configuration. Each language can have its own language-specific configuration. For example, the Docsy Example Site config specifies that it provides content in English and Norwegian, and that the language version visitors will see by default is English:

contentDir = "content/en"
defaultContentLanguage = "en"
defaultContentLanguageInSubdir = false
...
[languages]
[languages.en]
languageName ="English"
# Weight used for sorting.
weight = 1
[languages.en.params]
title = "Goldydocs"
description = "Docsy does docs"
[languages.no]
languageName ="Norsk"
contentDir = "content/no"
[languages.no.params]
title = "Goldydocs"
description = "Docsy er operativsystem for skyen"
time_format_default = "02.01.2006"
time_format_blog = "02.01.2006"
contentDir: content/en
defaultContentLanguage: en
defaultContentLanguageInSubdir: false

languages:
  en:
    languageName: English
    weight: 1 # used for sorting
    params:
      title: Docsy
      description: Docsy does docs
  'no':
    languageName: Norsk
    contentDir: content/no
    params:
      title: Docsy
      description: Docsy er operativsystem for skyen
      time_format_default: 02.01.2006
      time_format_blog: 02.01.2006
{
  "contentDir": "content/en",
  "defaultContentLanguage": "en",
  "defaultContentLanguageInSubdir": false,
  "languages": {
    "en": {
      "languageName": "English",
      "weight": 1,
      "params": {
        "title": "Docsy",
        "description": "Docsy does docs"
      }
  },
    "no": {
      "languageName": "Norsk",
      "contentDir": "content/no",
      "params": {
        "title": "Docsy",
        "description": "Docsy er operativsystem for skyen",
        "time_format_default": "02.01.2006",
        "time_format_blog": "02.01.2006"
      }
    }
  }
}

Any setting not defined in a [languages] block will fall back to the global value for that setting: so, for example, the content directory used for the site above will be content/en unless the user selects the Norwegian language option.

Once you’ve updated your site config, you create a content root directory for each language version in your source repo, such as content/en for English text, and add your content as usual. See the Hugo Docs on multi-language support for more information.

For adding multiple language versions of other site elements such as button text, see the internationalization bundles section below.

Selecting a language

If you configure more than one language in your configuration file, the Docsy theme adds a language selector drop down to the top-level menu. Selecting a language takes the user to the translated version of the current page, or the home page for the given language.

Internationalization bundles

All UI strings (text for buttons, repository links, etc.) are bundled inside /i18n in the theme, with a .toml file for each language.

If your chosen language isn’t currently in the theme and you create your own .toml file for all the common UI strings (for example, if you translate the UI text into Esperanto and create a copy of en.toml called eo.toml), we recommend you do this in the theme rather than in your own project. You can then open a pull request to contribute your translation to the Docsy community.

Create custom UI strings

If any of the Docsy theme UI strings in your chosen language aren’t suitable for your project, or if you need additional strings for your site, you can create your own project-specific internationalization file in your project’s /i18n directory. For example, if you want to override any of Docsy’s English-language strings, create your own /i18n/en.toml with just your custom strings. Any values you specify in this file will override the theme versions, while the remaining strings will come from the theme’s corresponding internationalization bundle.

9 - 实验框架部署

实验框架部署。

There are multiple possible options for deploying a Hugo site, including Netlify, Firebase Hosting, Bitbucket with Aerobatic, and more; you can read about them all in Hosting and Deployment. Hugo also makes it easy to deploy your site locally for quick previews of your content.

Serving your site locally

Depending on your deployment choice you may want to serve your site locally during development to preview content changes. To serve your site locally:

  1. Ensure you have an up to date local copy of your site files cloned from your repo.

  2. Ensure you have the tools described in Prerequisites and installation installed on your local machine, including postcss-cli (you’ll need it to generate the site resources the first time you run the server).

  3. Run the hugo server command in your site root. By default your site will be available at http://localhost:1313.

Now that you’re serving your site locally, Hugo will watch for changes to the content and automatically refresh your site. If you have more than one local git branch, when you switch between git branches the local website reflects the files in the current branch.

Build environments and indexing

By default, Hugo sites built with hugo (rather than served locally with hugo server) have the Hugo build environment production. Deployed Docsy sites with production builds can be indexed by search engines, including Google Custom Search Engines. Production builds also have optimized JavaScript and CSS for live deployment (for example, minified JS rather than the more legible original source).

If you do not want your deployed site to be indexed by search engines (for example if you are still developing your live site), or if you want to build a development version of your site for offline analysis, you can set your Hugo build environment to something else such as development (the default for local deploys with hugo server), test, or another environment name of your choice.

The simplest way to set this is by using the -e flag when specifying or running your hugo command, as in the following example:

hugo -e development

Deployment with Netlify

We recommend using Netlify as a particularly simple way to serve your site from your Git provider (GitHub, GitLab, or BitBucket), with continuous deployment, previews of the generated site when you or your users create pull requests against the doc repo, and more. Netlify is free to use for Open Source projects, with premium tiers if you require greater support.

Before deploying with Netlify, make sure that you’ve pushed your site source to your chosen GitHub (or other provider) repo, following any setup instructions in Using the theme.

Then follow the instructions in Host on Netlify to set up a Netlify account (if you don’t have one already) and authorize access to your GitHub or other Git provider account. Once you’re logged in:

  1. Click New site from Git.

  2. Click your chosen Git provider, then choose your site repo from your list of repos.

  3. In the Deploy settings page:

    1. Specify your Build command. The exact build command depends on how you have chosen to use Docsy:
      • If you are using Docsy as a Git submodule, specify cd themes/docsy && git submodule update -f --init && cd ../.. && hugo. You need to specify this rather than just hugo so that Netlify can use the theme’s submodules.
      • If you are using Docsy as a Hugo module or NPM package, you can just specify hugo.
    2. Click Show advanced.
    3. In the Advanced build settings section, click New variable.
    4. Specify NODE_VERSION as the Key for the new variable, and set its Value to the latest LTS version of node.js (minimum recommended version: v20.x).
    5. In the Advanced build settings section, click New variable.
    6. Specify HUGO_VERSION as the Key for the new variable, and set its Value to the latest version of Hugo (minimum recommended version: 0.125.4).
    7. In the Advanced build settings section, click New variable again.
    8. Specify GO_VERSION as the Key for the new variable, and set its Value to the latest version of Go (minimum recommended version: 1.21).

    If you don’t want your site to be indexed by search engines, you can add an environment flag to your build command to specify a non-production environment, as described in Build environments and indexing.

  4. Click Deploy site.

Alternatively, you can follow the same instructions but specify your Deploy settings in a netlify.toml file in your repo rather than in the Deploy settings page. You can see an example of this in the Docsy theme repo (though note that the build command here is a little unusual because the Docsy user guide is inside the theme repo).

If you have an existing deployment you can view and update the relevant information by selecting the site from your list of sites in Netlify, then clicking Site settings - Build and deploy. Ensure that Ubuntu Focal 20.04 is selected in the Build image selection section - if you’re creating a new deployment this is used by default. You need to use this image to run the extended version of Hugo.

Deployment on GitHub Pages

If your repo is hosted on GitHub, a simple option is to serve your site with GitHub Pages. GitHub Pages lets you create project, user, and organization sites; for a project site, your site URL will be http(s)://<username>.github.io/<repository_name>, custom domains are also supported. GitHub Pages come with continuous deployment using GitHub actions, while the marketplace for actions has useful tools for spell and link checking, deploy previews, and more. Using your existing GitHub account, you can start by using the free plan for publicly available repositories, with premium tiers available for business use cases.

The Docsy example site repo provides a workflow file that you can use when deploying to GitHub Pages. If you used the example site as template for your new site as described here, you may already have this file in your repo, if not the instructions below show you how to create your own workflow file.

Before deploying on GitHub Pages, make sure that you’ve pushed your site source to your chosen GitHub repo, following any setup instructions in Using the theme.

  1. With GitHub Pages, a site is published to the branch gh-pages and served from there by default. You must create this branch first, either in the GitHub web interface or via command line (at the root of your local repo clone):

    $ git checkout -b gh-pages
    Switched to a new branch 'gh-pages'
    
  2. Push this local branch to your repo:

    $ git push --set-upstream origin gh-pages
     details omitted …
     * [new branch]      new -> new
    branch 'gh-pages' set up to track 'origin/gh-pages'.
    
  3. Switch back to the main (or work) branch of your repo:

    $ git checkout main
    Switched to branch 'main'
    
  4. Check if you already have the workflow file .github/workflows/deploy-github-pages.yml in your repo. If this file doesn’t exist, do the following:

    1. Create a new empty workflow file from the root of your repo, as follows:

      $ mkdir -p .github/workflows
      $ touch .github/workflows/deploy-github-pages.yml
      
    2. Open the file in an editor of your choice, paste in the code below, and save the file:

      name: Deployment to GitHub Pages
      
      on:
        workflow_dispatch:
        push:
          branches:
            - main  # <-- specify the branch you want to deploy from
        pull_request:
      
      env:
        REPO_NAME: ${{ github.event.repository.name }}
        REPO_OWNER: ${{ github.repository_owner }}
      
      jobs:
        deploy:
          runs-on: ubuntu-22.04
          concurrency:
            group: ${{ github.workflow }}-${{ github.ref }}
          steps:
            - uses: actions/checkout@v4
              with:
                fetch-depth: 0         # Fetch all history for .GitInfo and .Lastmod
      
            - name: Setup Hugo
              uses: peaceiris/actions-hugo@v3
              with:
                hugo-version: '0.125.5'
                extended: true
      
            - name: Setup Node
              uses: actions/setup-node@v4
              with:
                node-version: '20'
                cache: 'npm'
                cache-dependency-path: '**/package-lock.json'
      
            - run: npm ci
            - run: hugo --baseURL https://${REPO_OWNER}.github.io/${REPO_NAME} --minify
      
            - name: Deploy
              uses: peaceiris/actions-gh-pages@v4
              if: ${{ github.ref == 'refs/heads/main' }} # <-- specify same branch as above here
              with:
                github_token: ${{ secrets.GITHUB_TOKEN }}
      
    3. Add the file to the staging area, commit your change and push the change to your remote GitHub repo:

      $ git add .github/workflows/deploy-github-pages.yml
      $ git commit -m "Adding workflow file for site deployment"
      $ git push origin
      
  5. In your browser, make sure you are logged into your GitHub account. In your repo Settings, select Pages.

    1. Under Build and deployment, select Deploy from a branch in the source dropdown.

    2. From the branch dropdown, select gh-page as branch where the site is built from.

    3. From the folder dropdown, select /(root) as root directory.

That’s it! Your deployment workflow for your site is configured.

Any future push to the branch specified in your workflow file will now trigger the action workflow defined in the workflow file. Additionally, you can trigger the deployment manually by using GitHub web UI.

Once you push to your repo, you can see the progress of the triggered workflow in the Actions tab of the the GitHub web UI:

URL 'Repo actions': https://github.com/<username>/<repository_name>/actions

After the first successful deployment, a new environment github-pages is added to your repo. This is shown at the right of your repo main view (below Releases and Packages). When you click on this environment, a list of deployments is displayed:

URL 'Repo deployments': https://github.com/<username>/<repository_name>/deployments/

You can find out more in Hosting on GitHub in the Hugo documentation.

For advanced use cases, the hugo-action used inside the workflow file has more configuration options, which are well documented.

Deployment with Amazon S3 + Amazon CloudFront

There are several options for publishing your web site using Amazon Web Services, as described in this blog post. This section describes the most basic option, deploying your site using an S3 bucket and activating the CloudFront CDN (content delivery network) to speed up the delivery of your deployed contents.

  1. After your registration at AWS, create your S3 bucket, connect it with your domain, and add it to the CloudFront CDN. This blog post has all the details and provides easy to follow step-by-step instructions for the whole procedure.

  2. Download and install the latest version 2 of the AWS Command Line Interface (CLI). Then configure your CLI instance by issuing the command aws configure (make sure you have your AWS Access Key ID and your AWS Secret Access Key at hand):

    $ aws configure
    AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
    AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
    Default region name [None]: eu-central-1
    Default output format [None]:
    
  3. Check the proper configuration of your AWS CLI by issuing the command aws s3 ls, this should output a list of your S3 bucket(s).

  4. Inside your hugo.toml/hugo.yaml/hugo.json, add a [deployment] section like this one:

    [deployment]
    [[deployment.targets]]
    name = "aws"
    URL = "s3://www.your-domain.tld"
    cloudFrontDistributionID = "E9RZ8T1EXAMPLEID"
    deployment:
      targets:
        - name: aws
          URL: 's3://www.your-domain.tld'
          cloudFrontDistributionID: E9RZ8T1EXAMPLEID
    {
      "deployment": {
        "targets": [
          {
            "name": "aws",
            "URL": "s3://www.your-domain.tld",
            "cloudFrontDistributionID": "E9RZ8T1EXAMPLEID"
          }
        ]
      }
    }
  5. Run the command hugo --gc --minify to render the site’s assets into the public/ directory of your Hugo build environment.

  6. Use Hugo’s built-in deploy command to deploy the site to S3:

    hugo deploy
    Deploying to target "aws" (www.your-domain.tld)
    Identified 77 file(s) to upload, totaling 5.3 MB, and 0 file(s) to delete.
    Success!
    Invalidating CloudFront CDN...
    Success!
    

    As you can see, issuing the hugo deploy command automatically invalidates your CloudFront CDN cache.

  7. That’s all you need to do! From now on, you can easily deploy to your S3 bucket using Hugo’s built-in deploycommand!

For more information about the Hugo deploy command, including command line options, see this synopsis. In particular, you may find the --maxDeletes int option or the --force option (which forces upload of all files) useful.

If S3 does not meet your needs, consider AWS Amplify Console. This is a more advanced continuous deployment (CD) platform with built-in support for the Hugo static site generator. A starter can be found in Hugo’s official docs.

10 - Quatm更新

保持您的Quatm框架的最新状态。

We hope to continue to make improvements to the theme along with the Docsy community. If you have cloned the example site (or are otherwise using the theme as a Hugo Module or Git submodule), you can easily update the Docsy theme in your site yourself. If you have cloned the theme itself into your own project you can also update, though you may need to resolve merge conflicts.

Updating Docsy means that your site will build using the latest version of Docsy at HEAD and include all the new commits or changes that have been merged since the point in time that you initially added the Docsy submodule, or last updated. Updating won’t affect any modifications that you made in your own project to override the Docsy look and feel, as your overrides don’t modify the theme itself. For details about what has changed in the theme since your last update, see the list of Docsy commits.

If you have been using the theme as a Git submodule, you can also update your site to use Docsy as a Hugo Module. This is the latest and simplest way to pull in a Hugo theme from its repository. If you’re not ready to migrate to Hugo Modules yet, don’t worry, your site will still work and you can continue to update your submodule as before.

10.1 - Update your Docsy Hugo Module

Update your Docsy theme to the latest version using Hugo Modules.

When using the Docsy theme as a Hugo Module, updating your theme is really easy.

At the command prompt, change to the root directory of your existing site.

cd /path/to/my-existing-site

Then invoke hugo’s module get subcommand with the update flag:

hugo mod get -u github.com/google/docsy

Hugo automatically pulls in the latest theme version. That’s it, your update is done!

10.2 - Update Docsy without Hugo Modules

Update the Docsy theme to the latest version using submodules or git pull.

If you aren’t using Hugo Modules, depending on how you chose to install Docsy on your existing site, use one of the following two procedures to update your theme.

Update your Docsy submodule

If you are using the Docsy theme as a submodule in your project, here’s how you update the submodule:

  1. Navigate to the root of your local project, then run:

    git submodule update --remote
    
  2. Add and then commit the change to your project:

    git add themes/
    git commit -m "Updating theme submodule"
    
  3. Push the commit to your project repo. For example, run:

    git push origin master
    

Route 2: Update your Docsy clone

If you cloned the Docsy theme into the themes folder in your project, then you use the git pull command:

  1. Navigate to the themes directory in your local project:

    cd themes
    
  2. Ensure that origin is set to https://github.com/quatm/quatm.git:

    git remote -v
    
  3. Update your local clone:

    git pull origin master
    

If you have made any local changes to the cloned theme, you must manually resolve any merge conflicts.

10.3 - Migrate to Hugo Modules

Convert an existing site to use Docsy as a Hugo Module

TL;DR: Conversion for the impatient expert

Run the following from the command line:

cd /path/to/my-existing-site
hugo mod init github.com/me-at-github/my-existing-site
hugo mod get github.com/google/docsy@v0.10.0
sed -i '/theme = \["docsy"\]/d' config.toml
mv config.toml hugo.toml
cat >> hugo.toml <<EOL
[module]
proxy = "direct"
[[module.imports]]
path = "github.com/google/docsy"
EOL
hugo server
cd  my-existing-site
hugo mod init github.com/me-at-github/my-existing-site
hugo mod get github.com/google/docsy@v0.10.0
findstr /v /c:"theme = [\"docsy\"]" config.toml > hugo.toml
(echo [module]^

proxy = "direct"^

[[module.imports]]^

path = "github.com/google/docsy")>>hugo.toml
hugo server

Detailed conversion instructions

Import the Docsy theme module as a dependency of your site

At the command prompt, change to the root directory of your existing site.

cd /path/to/my-existing-site

Only sites that are Hugo Modules themselves can import other Hugo Modules. Turn your existing site into a Hugo Module by running the following command from your site directory, replacing github.com/me/my-existing-site with your site repository:

hugo mod init github.com/me/my-existing-site

This creates two new files, go.mod for the module definitions and go.sum which holds the checksums for module verification.

Next declare the Docsy theme module as a dependency for your site.

hugo mod get github.com/google/docsy@v0.10.0

This command adds the docsy theme module to your definition file go.mod.

Update your config file

In your hugo.toml/hugo.yaml/hugo.json file, update the theme setting to use Hugo Modules. Find the following line:

theme = ["docsy"]
theme: docsy
"theme": "docsy"

Change this line to:

theme = ["github.com/google/docsy"]
theme:
  - github.com/google/docsy
"theme": [
  "github.com/google/docsy"
]

Alternatively, you can omit this line altogether and replace it with the settings given in the following snippet:

[module]
  proxy = "direct"
  # uncomment line below for temporary local development of module
  # replacements = "github.com/google/docsy -> ../../docsy"
  [module.hugoVersion]
    extended = true
    min = "0.73.0"
  [[module.imports]]
    path = "github.com/google/docsy"
    disable = false
module:
  proxy: direct
  hugoVersion:
    extended: true
    min: 0.73.0
  imports:
    - path: github.com/google/docsy
      disable: false
    - path: github.com/google/docsy/dependencies
      disable: false
{
  "module": {
    "proxy": "direct",
    "hugoVersion": {
      "extended": true,
      "min": "0.73.0"
    },
    "imports": [
      {
        "path": "github.com/google/docsy",
        "disable": false
      },
      {
        "path": "github.com/google/docsy/dependencies",
        "disable": false
      }
    ]
  }
}

You can find details of what these configuration settings do in the Hugo modules documentation. Depending on your environment you may need to tweak them slightly, for example by adding a proxy to use when downloading remote modules.

Check validity of your configuration settings

To make sure that your configuration settings are correct, run the command hugo mod graph which prints a module dependency graph:

hugo mod graph
hugo: collected modules in 1092 ms
github.com/me/my-existing-site github.com/google/docsy@v0.10.0
github.com/google/docsy@v0.10.0 github.com/twbs/bootstrap@v5.2.3+incompatible
github.com/google/docsy@v0.10.0 github.com/FortAwesome/Font-Awesome@ v0.0.0-20230802202706-f0c25837a3fe

Make sure that three lines with dependencies docsy, bootstrap and Font-Awesome are listed. If not, please double check your config settings.

Clean up your repository

Since your site now uses Hugo Modules, you can remove docsy from the themes directory, as instructed below. First, change to the root directory of your site:

cd /path/to/my-existing-site

Previous use of Docsy theme as git clone

Simply remove the subdirectory docsy inside your themes directory:

rm -rf themes/docsy

Previous use of Docsy theme as git submodule

If your Docsy theme was installed as submodule, use git’s rm subcommand to remove the subdirectory docsy inside your themes directory:

git rm -rf themes/docsy

You are now ready to commit your changes to your repository:

git commit -m "Removed docsy git submodule"

11 - 使用范例

一些使用Quatm框架的案例。

One of the best ways to see what Docsy can do, and learn how to configure a site with it, is to see some real projects. In addition to our provided Docsy Example Project, there are several live sites already using the theme. Please add your own examples once you’ve got a production site up and running with Docsy!

Docsy theme examples

Example sites that have low to no customization:

SiteRepo
This Docsy documentation sitehttps://github.com/quatm/quatm
“Goldydocs” - a Docsy example sitehttps://github.com/quatm/quatm-example
https://www.kubeflow.org/https://github.com/kubeflow/website
https://agones.dev/site/https://github.com/googleforgames/agones/tree/main/site
https://googlecontainertools.github.io/kpt/https://github.com/GoogleContainerTools/kpt/tree/main/docs
Navidrome Music Serverhttps://github.com/navidrome/website
https://docs.agilebase.co.uk/https://github.com/okohll/abdocs
https://jvmperf.net/https://github.com/cchesser/java-perf-workshop
gRPChttps://github.com/grpc/grpc.io
tekton.devhttps://github.com/tektoncd
fluxcd.iohttps://github.com/fluxcd/website
Graphvizhttps://gitlab.com/graphviz/graphviz.gitlab.io
Cloudpodshttps://github.com/yunionio/docs
Seleniumhttps://github.com/SeleniumHQ/seleniumhq.github.io
fission.iohttps://github.com/fission/fission.io
Stroomhttps://github.com/gchq/stroom-docs
OpenTelemetryhttps://github.com/open-telemetry/opentelemetry.io
CloudWeGohttps://github.com/cloudwego/cloudwego.github.io
etcdhttps://github.com/etcd-io/website
protobuf.devhttps://github.com/protocolbuffers/protocolbuffers.github.io
Layer5 Docshttps://github.com/layer5io/docs
Apache Parquethttps://parquet.apache.org
YMCA Website Serviceshttps://github.com/YCloudYUSA/yusaopeny_docs

Customized Docsy examples

Example sites that include a moderate to high amount of customization:

SiteRepo
Apache Airflowhttps://github.com/apache/airflow-site/
Docsy Mostly Docshttps://github.com/gwatts/mostly开发文档/
Kuberneteshttps://github.com/kubernetes/website
XLThttps://github.com/Xceptance/xlt-documentation
Daprhttps://github.com/dapr/docs

12 - 代码贡献指南

如何对Quatm项目贡献您的智慧

Quatm是一个开源项目,我们热爱并欢迎大家提交补丁和贡献,以使Quatm及其文档变得更好。

贡献Quatm

Quatm主要托管在 https://github.com/quatm/Quatm,考虑到地缘政治不确定的因素,我们使用部署在中国大陆境内的私有Git服务器 https://git.shopping/quatm/Quatm 对项目进行镜像备份。

贡献者许可协议

在您参与对本项目的贡献时,除非在有书面协议的例外情况下,您(或您的雇主)保留对您的贡献的版权,并自动给予我们使用和重新分发您的贡献作为项目一部分的权限。具体细节请参考本项目的贡献者许可协议

代码审核

所有提交,包括项目成员的提交,都需要经过审核。我们使用GitHub的拉取请求(pull request)进行代码审核。有关如何使用拉取请求的更多信息,请查阅 GitHub帮助

社区准则

在交流讨论中,请遵循 Quatm社区准则

创建问题

如果您想在Quatm中看到某些功能(或者发现某些功能没有按预期工作),但您不确定如何自己修复,请创建一个 issue。您也可以通过社交媒体直接与我们联系。

13 - 可选功能

可选的教程与指南,根据您的需求进一步开发更为个性化的框架。

Use this section to learn about some of the best practices around creating technical documentation with Docsy.

13.1 - Hugo Content Tips

Tips for authoring content for your Docsy-themed Hugo site.

Docsy is a theme for the Hugo static site generator. If you’re not already familiar with Hugo this page provides some useful tips and potential gotchas for adding and editing content for your site. Feel free to add your own!

Linking

By default, regular relative URLs in links are left unchanged by Hugo (they’re still relative links in your site’s generated HTML), hence some hardcoded relative links like [relative cross-link](../../peer-folder/sub-file.md) might behave unexpectedly compared to how they work on your local file system. You may find it helpful to use some of Hugo’s built-in link shortcodes to avoid broken links in your generated site. For example a {{< ref "filename.md" >}} link in Hugo will actually find and automatically link to your file named filename.md.

Note, however, that ref and relref links don’t work with _index or index files (for example, this site’s content landing page): you’ll need to use regular Markdown links to section landing or other index pages. Specify these links relative to the site’s root URL, for example: /开发文档/adding-content/.

Learn more about linking.

13.2 - Organizing Your Content

Optional guidance and recommendations on how to organize your documentation site.

If you have a look at our Example Site, you’ll see that we’ve organized the Documentation section into a number of subsections, each with some recommendations about what you might put in that section.

Do I need to use this structure?

Absolutely not! The site structure in the Example Site was created to meet the needs of large docsets for large products with lots of features, potential tasks, and reference elements. For a simpler docset (like this one!), it’s fine to just structure your docs around specific features that your users need to know about. Even for larger documentation sets, you may find that the structure isn’t useful “as is”, or that you don’t need to use all the section types.

We do recommend that (as we’ve done here) you provide at least:

  • An Overview of the product (either on the docs landing page or a separate Overview page) that tells the user why they should be interested in your project.
  • A Getting Started page.
  • Some Examples.

You may also want to create some tasks/how-tos for your project’s features. Feel free to copy this Docsy user guide site or even just the docs section instead if you like this simpler structure better.

Learn more about how Hugo and Docsy use folders and other files to organize your site.

Why this structure?

We based the Example Site structure on our own experiences creating (and using) large documentation sets for different types of project and on user research carried out on some of our bigger sites. In user studies we saw that users cared most about and immediately looked for a Get Started or Getting Started section (so they could, well, get started), and some examples to explore and copy, so we made those into prominent top-level doc sections in our site. Users also wanted to find “recipes” that they could easily look up to perform specific tasks and put together to create their own applications or projects, so we suggest that you add this kind of content as Tasks. Other content types such as conceptual docs, reference docs, and end-to-end tutorials are less important for all doc sets, particularly for smaller projects. We emphasize in our Example Site that these sections are optional.

We hope to improve the Example Site structure further as we learn more about how users interact with technical documentation, particularly for Open Source projects.

Writing style guide

This guide and the example site just address how to organize your documentation content into pages and sections. For some guidance on how to organize and write the content in each page, we recommend the Google Developer Documentation Style Guide, particularly the Style Guide Highlights.