Example #1
0
def test_valid_args(tmp_environ):
    if os.path.isdir("pairef_valid_args"):
        # Preparation - clean rests from previously examined test that
        # has been interrupted
        shutil.rmtree("pairef_valid_args")
    arguments = "--HKLIN " + str(config("mdm2_merged.mtz")) + \
        " --XYZIN " + str(config("mdm2_1-60A.pdb")) + \
        " -i 1.6" + \
        " -r " + RES_SHELLS_GOOD + \
        " -p valid_args" + \
        " -t"
    cp = run(arguments)
    expected_stdout_1 = """
 __   _  ___ __  ___ ___
 )_) /_)  )  )_) )_  )_
/   / / _(_ / \ (__ (

automatic PAIRed REFinement protocol
"""
# run date and time: ...
    expected_stdout_2 = """
Please cite: "Paired refinement under the control of PAIREF"
M. Maly, K. Diederichs, J. Dohnalek, P. Kolenko (2020) IUCrJ 7

Command line arguments: """ + arguments + """

Program has been executed with following input parameters:
"""
    expected_stdout_2 += " * XYZIN: " + str(config("mdm2_1-60A.pdb")) + "\n"
    expected_stdout_2 += " * HKLIN: " + str(config("mdm2_merged.mtz")) + "\n"
    expected_stdout_2 += """ * Project name: valid_args
 * Resolution shells: 1.55,1.50,1.45,1.40,1.35,1.30
 * Light-testing mode (REFMAC5 will not be executed).

"""
    expected_stdout_2 += "Resolution of the merged diffraction data " + \
        str(config("mdm2_merged.mtz")) + ": 61.93-1.25 A"
    expected_stdout_2 += """
Manual setting of initial high resolution limit will be used: 1.60 A.
High resolution diffraction limits: 1.55 A, 1.50 A, 1.45 A, 1.40 A, 1.35 A, 1.30 A
"""
    expected_stdout_2 += \
        " * Data with FreeRflag set 0 will be excluded during refinement.\n"
    # expected_stdout_2 += "\n"
    # expected_stdout_2 += "Current working directory: " \
    #     "" + tempfile.gettempdir() + "/pairef_valid_args\n"
    # expected_stdout_2 += \
    #     "------> RESULTS AND THE CURRENT STATUS OF CALCULATIONS ARE LISTED" \
    #     " IN A HTML LOG FILE " + tempfile.gettempdir() + \
    #     "/pairef_valid_args/PAIREF_valid_args.html\n\n"
    stdout_all = cp.stdout.splitlines(True)
    stdout_1 = "".join(stdout_all[:6])
    stdout_2 = "".join(stdout_all[9:-4])
    # stdout_2 = "".join(stdout_all[9:])
    assert stdout_1 == expected_stdout_1
    assert stdout_2 == expected_stdout_2
    assert os.path.isdir("pairef_valid_args")
    shutil.rmtree("pairef_valid_args")
    assert cp.returncode == 0
    assert not cp.stderr
Example #2
0
    def __init__(self, config_file, kafka_config_file, verbose):
        self.logger = helper.setup_logging(self.__class__.__name__, verbose)

        self.db_connection = DBConnection(verbose)
        self.kafka_consumer = None

        self.kafka_params = helper.config(kafka_config_file)
        self.db_params = helper.config(config_file, "db")
        self.params = helper.config(config_file)
Example #3
0
def test_file_not_exists(tmp_environ):
    cp = run("--HKLIN " + str(config("foo.mtz")) + ""
             " --XYZIN " + str(config("mdm2_1-60A.pdb")) + ""
             " -i 2" + ""
             " -r " + RES_SHELLS_GOOD + ""
             " -p file_not_exists")
    assert cp.returncode != 0
    # assert not cp.stdout
    # assert cp.stderr == help + "\ncctbx.python -m pairef: error: " \
    #     "The file " + str(config("foo.mtz")) + " does not exist!\n"
    assert cp.stderr == "error: " \
        "The file " + str(config("foo.mtz")) + " does not exist!\n"
Example #4
0
def test_invalid_res_shells_setting(tmp_environ,
                                    res_init, res_shells, error_message):
    if os.path.isdir("pairef_bad_res_shells_setting"):
        # Preparation - clean rests from previously examined test that
        # has been interrupted
        shutil.rmtree("pairef_bad_res_shells_setting")
    cp = run("--HKLIN " + str(config("mdm2_merged.mtz")) + ""
             " --XYZIN " + str(config("mdm2_1-60A.pdb")) + ""
             " -i " + res_init + ""
             " -r " + res_shells + ""
             " -p bad_res_shells_setting" + ""
             " -t")
    assert cp.returncode != 0
    # assert not cp.stdout
    assert cp.stderr == error_message
Example #5
0
def test_matplotlib_bar(tmp_environ):
    shutil.copy2(config("A_R-values.csv"), tempfile.gettempdir())
    args = AttrDict()
    args.project = "A"
    args.complete_cross_validation = False
    matplotlib_bar(args, values="R-values")
    assert os.path.isfile("A_R-values.png")
    os.remove("A_R-values.csv")
    os.remove("A_R-values.png")
Example #6
0
def test_write_log_html(tmp_environ):
    versions_dict = {"refmac_version": "N/A", "pairef_version": "N/A"}
    args = AttrDict()
    args.xyzin = "fake.pdb"
    args.hklin = "fake.mtz"
    args.hklin_unmerged = "fake.HKL"
    args.libin = "fake.mtz"
    args.comin = "fake.com"
    args.tlsin = "fake.tls"
    args.defin = None
    args.phenix = None
    args.project = "A"
    args.ncyc = 11
    args.weight = None
    args.tlsin_keep = None
    args.tls_ncyc = None
    args.flag = 0
    args.add_to_bfactor = None
    args.complete_cross_validation = False
    args.no_modification = None
    args.prerefinement_ncyc = None
    args.reset_bfactor = None
    args.add_to_bfactor = None
    args.set_bfactor = None
    args.shake_sites = None
    args.constant_grid = None
    shutil.copy2(config("A_R-values.csv"), tempfile.gettempdir())
    shells_ready_with_res_init = (1.8, 1.7, 1.6)
    shells = (1.8, 1.7, 1.6, 1.5)
    flag_sets = range(20)
    htmlfilename_in_progress = write_log_html(shells,
                                              shells_ready_with_res_init, args,
                                              versions_dict, flag_sets)
    assert os.path.isfile(htmlfilename_in_progress)
    with open(htmlfilename_in_progress, "r") as htmlfile_in_progress:
        htmlfile_in_progress_content = htmlfile_in_progress.read()
    assert "Calculations are still in progress" in htmlfile_in_progress_content
    assert "</html>" in htmlfile_in_progress_content
    os.remove(htmlfilename_in_progress)

    htmlfilename_done = write_log_html(shells,
                                       shells,
                                       args,
                                       versions_dict,
                                       flag_sets,
                                       done=True)
    assert os.path.isfile(htmlfilename_done)
    with open(htmlfilename_done, "r") as htmlfile_done:
        htmlfile_done_content = htmlfile_done.read()
    assert "Calculations are still in progress" not in htmlfile_done_content
    assert "</html>" in htmlfile_done_content
    os.remove(htmlfilename_done)
    os.remove("A_R-values.csv")
Example #7
0
def handle_expired_error(e):
    try:
        identify = e.get(helper.config('JWT_IDENTITY_CLAIM', 'identify'), None)
        claims = e.get(helper.config('JWT_USER_CLAIMS', {}))

        response = TokenExpired('Access token expired.').to_response()
        response.headers['Authorization'] = create_access_token(identify, user_claims=claims)

        query = g.get('query', None)

        if query is not None:
            expired_data = json.loads(response.get_data())

            pre_script = expired_data.get('script', '')
            sub_script = '$scope.term.retry(\'%s\', \'%s\', %s)' \
                         % (query.app, query.command, '[\'' + '\',\''.join(query.arguments) + '\']')

            expired_data['script'] = pre_script + sub_script

            response.set_data(json.dumps(expired_data))

        return response
    except Exception as be:
        return TokenDiscarded(str(be)).to_response()
Example #8
0
def test_matplotlib_line_Rgap(tmp_environ):
    shutil.copy2(config("NK_Rgap.csv"), tempfile.gettempdir())
    matplotlib_line(
        shells=(1.8),
        project="NK",
        statistics="Rgap",
        n_bins_low=10,
        title="$\it{R}_{\mathrm{free}}-"
        "\it{R}_{\mathrm{work}}$",
        multiscale=False,
        # title=r"$\it{R}_{\mathrm{free}}-"
        # r"\it{R}_{\mathrm{work}}$", multiscale=False,
        filename_suffix="Rgap")
    assert os.path.isfile("NK_Rgap.png")
    os.remove("NK_Rgap.csv")
    os.remove("NK_Rgap.png")
Example #9
0
def test_matplotlib_line_Rvalues(tmp_environ, statistics, title,
                                 filename_suffix, pngfile):
    files_in = [
        "NK_R00_1-80A.csv", "NK_R00_1-70A.csv", "NK_R00_1-60A.csv",
        "NK_R00_1-50A.csv"
    ]
    for f in files_in:
        shutil.copy2(config(f), tempfile.gettempdir())
    matplotlib_line(shells=(1.8, 1.7, 1.6, 1.5),
                    project="NK",
                    statistics=statistics,
                    n_bins_low=10,
                    title=title,
                    multiscale=False,
                    filename_suffix=filename_suffix)
    assert os.path.isfile(pngfile)
    files = files_in + [pngfile]
    for f in files:
        os.remove(f)
Example #10
0
        '--rouge_only',
        help='Only compute ROUGE scores, without writing summaries',
        action='store_true')
    parser.add_argument(
        '--ind_rouge_scores',
        help='Compute individual ROUGE scores for significance testing',
        action='store_true')
    args = parser.parse_args()

    # Load vocab file
    logging.info("Opening vocab file: {}".format(args.vocab_file))
    with open(args.vocab_file, 'rb') as f:
        vocab = pickle.load(f, encoding='latin1')

    # Set up configs
    config(args, vocab)

    # Create directories if needed
    args.ref_dir = os.path.join(args.data_dir, 'ref')
    args.hyp_dir = os.path.join(args.data_dir, 'model')
    args.article_dir = os.path.join(args.data_dir, 'articles')
    if not os.path.exists(args.ref_dir):
        raise ValueError(
            "Please create reference summary directory, named 'ref'.")
    if not os.path.exists(args.article_dir):
        raise ValueError("Please create article directory, named 'articles'.")
    if not os.path.exists(args.hyp_dir): os.mkdir(args.hyp_dir)

    if args.rouge_only: compute_rouge(args)
    elif args.ind_rouge_scores: write_rouge_scores(args)
    else: make_summaries(args)
from helper import run_ok, config, user, pr_labels

RADIOACTIVE_WASE = '\n'.join([
    f'  PR https://github.com/{user}/filabel-testrepo2/pull/{num} - OK'
    for num in reversed(range(1, 111 + 1))
]) + '\n'
RADIOACTIVE_WASE_ADD = RADIOACTIVE_WASE.replace('\n', '\n    + danger\n')
RADIOACTIVE_WASE_DEL = RADIOACTIVE_WASE.replace('\n', '\n    - danger\n')

auth = config("auth.real.cfg")


def test_radioactive_waste_empty():
    cp = run_ok(f'--config-labels "{config("labels.empty.cfg")}" '
                f'--config-auth "{auth}" '
                f'{user}/filabel-testrepo2')

    assert '\n' + cp.stdout == f'''
REPO {user}/filabel-testrepo2 - OK
{RADIOACTIVE_WASE}'''
    assert pr_labels('filabel-testrepo2', 1) == []
    assert pr_labels('filabel-testrepo2', 42) == []
    assert pr_labels('filabel-testrepo2', 110) == []


def test_radioactive_waste_add():
    cp = run_ok(f'--config-labels "{config("labels.radiation.cfg")}" '
                f'--config-auth "{auth}" '
                f'{user}/filabel-testrepo2')

    assert '\n' + cp.stdout == f'''
Example #12
0
import shutil
from pairef.commons import twodec, twodecname, fourdec, extract_from_file
from helper import run, config


@pytest.mark.parametrize(
    ["value_in", "value_twodec", "value_twodecname", "value_fourdec"],
    [(2, "2.00", "2-00", "2.0000"), (0.617, "0.62", "0-62", "0.6170")])
def test_twodec_twodecname_fourdec(value_in, value_twodec, value_twodecname,
                                   value_fourdec):
    assert twodec(value_in) == value_twodec
    assert twodecname(value_in) == value_twodecname
    assert fourdec(value_in) == value_fourdec


filename = config("lysozyme_1-40A.log")
filename_fake = config("foo")
searched_stats = "Resolution limits"
searched_Rfree = "Free R factor"
table_stats_i = """Resolution limits                    =     39.355     1.402
Number of used reflections           =      21761
Percentage observed                  =    97.1541
Percentage of free reflections       =     5.0028
Overall R factor                     =     0.2103
Free R factor                        =     0.2236
Average Fourier shell correlation    =     0.9155
AverageFree Fourier shell correlation=     0.9072
Overall weighted R factor            =     0.2013
Free weighted R factor               =     0.2116
Overall weighted R2 factor           =     0.2598
Free weighted R2 factor              =     0.2707
Example #13
0
class MWindow(QWidget, Ui_MWindow):


    # MDMailer Class handles everything except graphics
    mdm = None

    # recipientsWindow
    recWin = recipientsWindow()

    Mail_Thread = QThread()
    config = helper.config()

    send_signal = pyqtSignal()

    export_pdf_act = None


    def __init__(self, parent=None):
        super().__init__(parent)


        # construct MDMailer with server Info
        self.mdm = MDMailer_(self.config.get_email(),
                             self.config.get_smtp(),
                             self.config.get_port(),
                             self.config.get_username(),
                             self.config.get_password())




        # Connect Stuff here ...
        self.mdtext.textedit.textChanged.connect(self.compile)
        self.send_btn.pressed.connect(self.send)
        self.add_att_btn.pressed.connect(self.add_att)
        self.send_signal.connect(self.mdm.send)
        self.mdm.finished_sending.connect(self.reenable_send)
        self.mdm.progress2.connect(self.progress_bar.setMaximum)
        self.mdm.progress1.connect(self.progress_bar.setValue)
        self.multi_rec_btn.pressed.connect(self.open_recipientsWindow)
        self.recWin.ready.connect(self.get_recipients)

        del_att_short = QShortcut(QKeySequence(Qt.Key_Delete), self.attachments)
        del_att_short.activated.connect(self.del_att)

        self.export_pdf_act = QShortcut(QKeySequence("Ctrl+E"), self)

        self.export_pdf_act.activated.connect(self.export_pdf)

        self.stylesheet = """
        .QPushButton {
            background-color: #4CAF50;
            border: none;
            color: white;
            padding: 5px 11px;
            text-align: center;
            text-decoration: none;
            font-size: 16px;
            }
        .QPushButton:hover {
            background-color: #555;
            border: none;
            color: white;
            padding: 5px 11px;
            text-align: center;
            text-decoration: none;
            font-size: 16px;
            }
        .QLineEdit {
            background-color: #ddd;
            font-size: 16px;
            border-radius: 0px;
            }
        .QPlainTextEdit {
            background-color: #fff;
            font-size: 16px;
            border-radius: 0px;
            }
        .QFileDialog:QPushButton {
            background-color: #4CAF50;
            border: none;
            color: white;
            padding: 5px 11px;
            text-align: center;
            text-decoration: none;
            font-size: 16px;
            }
        .QListWidget {
            background-color: #fff;
            font-size: 16px;
            }
        .QProgressBar {
            color: #FFFFFF;
            border: none;
            padding: 0px 0px;
            margin: -3px;
            border-radius: 0px;
            }
        .QProgressBar:chunk {
            background-color: #4CAF50;
            border: none;
            padding: 0px 0px;
            margin: 0px;
            border-radius: 0px;
            }
        """

        self.setStyleSheet(self.stylesheet)

        self.Mail_Thread.start()
        self.mdm.moveToThread(self.Mail_Thread)

    # Show html from plain text
    def compile(self):

        cursor = self.mdtext.textedit.textCursor()
        cursor.movePosition(9, 1)


        md_text_plain = self.mdtext.textedit.toPlainText()

        md_text_plain = self.show_code_inline(md_text_plain)

        html_c = self.mdm.get_html(md_text_plain, self.subject_edit.text())

        scroll = self.html_view.page().mainFrame().scrollPosition()

        max_y = self.html_view.page().mainFrame().scrollBarMaximum(2)

        end = False
        if scroll.y() == max_y:
            end = True

        self.html_view.setHtml(html_c)

        if end:
            scroll.setY(self.html_view.page().mainFrame().scrollBarMaximum(2))

        self.html_view.page().mainFrame().setScrollPosition(scroll)

    # Send Mail
    def send(self):
        self.mdm.mail_text = self.show_code_inline(self.mdtext.textedit.toPlainText())
        self.mdm.subject = self.subject_edit.text()
        to = self.to_edit.text()

        if to != "":
            rec = [to]
            self.mdm.rec = rec
        else:
            if self.mdm.rec == [""]:
                msg_box = QMessageBox()
                msg_box.setIcon(QMessageBox.Information)
                msg_box.setWindowTitle("No valid E-Mail address found")
                msg_box.setInformativeText("No valid E-Mail address found")

        files = []
        for i in range(self.attachments.count()):
            files.append(str(self.attachments.item(i).data(3)))

        for i in re.findall(r"<att>?\(([^\)]*)\)", self.mdm.mail_text):
            files.append(str(i))

        re.sub(r"<att>?\(([^\)]*)\)", "", self.mdm.mail_text)

        self.mdm.files = files

        #self.mdm.send_mail(mail_text, subject, rec, files=files)
        self.send_signal.emit()
        self.send_signal.disconnect()

    def add_att(self):
        fd = QFileDialog()
        files = fd.getOpenFileNames()

        for f in files[0]:
            item = QListWidgetItem()
            item.setData(3, f)
            item.setText(os.path.basename(f))
            self.attachments.addItem(item)

    def del_att(self):

        for item in self.attachments.selectedItems():
            tmp = self.attachments.takeItem(self.attachments.row(item))
            del tmp

    def open_recipientsWindow(self):
        self.recWin.show()

    def get_recipients(self):
        self.mdm.rec = self.recWin.get_recipients()
        self.recWin.close()

    @pyqtSlot()
    def reenable_send(self):
        self.send_signal.connect(self.mdm.send)

    def show_code_inline(self, text):
        incs = re.findall(r"(<inc>?\[([^\]]*)\]\(([^\)]*)\))", text)

        for inc in incs:
            filename = None
            for i in range(self.attachments.count()):
                if str(self.attachments.item(i).data(2)) == inc[1]:
                    filename = self.attachments.item(i).data(3)
                    break

            if not filename:
                if os.path.isfile(inc[1]):
                    filename = inc[1]
                else:
                    continue

            lines = re.search(r'\blines="([ ]*[\d]+[ ]*-[ ]*[\d]+[ ]*)"', inc[2])

            with open(filename, 'r') as file:
                code = file.read()

            if lines:
                opts = inc[2].replace(lines[0], "")

                lines = lines[1].split("-")

                code = "\n".join(code.splitlines()[int(lines[0]) - 1:int(lines[1])])


            else:
                opts = inc[2]

            if ("no_code" not in opts):
                code = "~~~ " + opts + "\n" + code + "\n~~~"
            text = text.replace(inc[0], code)


        return text

    def export_pdf(self):

        filename, t = QFileDialog.getSaveFileName(None, "Export to PDF", ".pdf", "pdf (*.pdf)")

        if filename == "":
            return

        html = self.html_view.page().mainFrame().toHtml()

        pdfkit.from_string(html, filename)
Example #14
0
import flask
import importlib

from helper import env, config, user


config_env = config('web_secret.cfg')
config_env_nosecret = config('web_nosecret.cfg')


def _import_app():
    import committee
    importlib.reload(committee)  # force reload (config could change)
    if hasattr(committee, 'app'):
        return committee.app
    elif hasattr(committee, 'create_app'):
        return committee.create_app(None)
    else:
        raise RuntimeError(
            "Can't find a Flask app. "
            "Either instantiate `committee.app` variable "
            "or implement `committee.create_app(dummy)` function. "
            "See https://flask.palletsprojects.com/en/1.1.x/patterns/appfactories/"
            "for additional information."
        )


def _test_app():
    app = _import_app()
    app.config['TESTING'] = True
    return app.test_client()
    def test_integration_quick_mdm2(tmp_environ):
        print("\nPerforming a quick integration test using mdm2 demo data"
              ", please wait...\n")
        if os.path.isdir(dir_project):
            # Preparation - clean rests from previously examined test that
            # has been interrupted
            shutil.rmtree(dir_project)
        arguments = "--HKLIN " + str(config("mdm2_merged.mtz")) + \
            " --XYZIN " + str(config("mdm2_1-60A.pdb")) + \
            " -u " + hklin_unmerged + " -i 1.6 -r 1.55,1.5 -p test_quick_mdm2"
        cp = run(arguments)
        assert cp.returncode == 0
        # assert not cp.stderr

        expected_stdout_1 = """
 __   _  ___ __  ___ ___
 )_) /_)  )  )_) )_  )_
/   / / _(_ / \ (__ (

automatic PAIRed REFinement protocol
version: """ + str(__version__) + "\n"
        # run date and time: ...

        expected_stdout_2 = """
Please cite: "Paired refinement under the control of PAIREF"
M. Maly, K. Diederichs, J. Dohnalek, P. Kolenko (2020) IUCrJ 7

Command line arguments: """ + arguments + """

Program has been executed with following input parameters:
"""
        expected_stdout_2 += " * XYZIN: " + str(config("mdm2_1-60A.pdb")) + "\n"
        expected_stdout_2 += " * HKLIN: " + str(config("mdm2_merged.mtz")) + "\n"
        expected_stdout_2 += " * HKLIN unmerged: " + hklin_unmerged + "\n"
        expected_stdout_2 += """ * Project name: test_quick_mdm2
 * Resolution shells: 1.55,1.5

"""
        expected_stdout_2 += "Resolution of the merged diffraction data " + \
            str(config("mdm2_merged.mtz")) + ": 61.93-1.25 A\n"
        expected_stdout_2 += "Resolution of the unmerged diffraction data " + \
            hklin_unmerged + ": 61.90-1.24 A"
        expected_stdout_2 += """
Manual setting of initial high resolution limit will be used: 1.60 A.
High resolution diffraction limits: 1.55 A, 1.50 A
"""
        expected_stdout_2 += \
        " * Data with FreeRflag set 0 will be excluded during refinement.\n"

        expected_stdout_3 = """Refinement using REFMAC5:

   * Calculating initial statistics at 1.60 A resolution...
       Collecting statistics from logfiles...

   * Refining using data up to 1.55 A resolution...
       Running command:
       refmac5 HKLIN mdm2_merged.mtz XYZIN test_quick_mdm2_R00_1-60A.pdb HKLOUT test_quick_mdm2_R00_1-55A.mtz XYZOUT test_quick_mdm2_R00_1-55A.pdb LIBOUT test_quick_mdm2_R00_1-55A.cif
       Calculating statistics of the refined structure model... . . .
       Collecting statistics from logfiles...
       Updating graphs...
       Preliminary suggested cutoff: 1.XX A

   * Refining using data up to 1.50 A resolution...
       Running command:
       refmac5 HKLIN mdm2_merged.mtz XYZIN test_quick_mdm2_R00_1-55A.pdb HKLOUT test_quick_mdm2_R00_1-50A.mtz XYZOUT test_quick_mdm2_R00_1-50A.pdb LIBOUT test_quick_mdm2_R00_1-50A.cif
       Calculating statistics of the refined structure model... . . . .
       Collecting statistics from logfiles...
       Updating graphs...
       Preliminary suggested cutoff: 1.XX A

     * Calculating merging statistics... . . . . . . . .
       Using labels=I,SIGI

Suggested cutoff: 
"""
        stdout_all = cp.stdout.splitlines(True)
        assert "Preliminary suggested cutoff:" in stdout_all[43]
        stdout_all[43] = "       Preliminary suggested cutoff: 1.XX A\n"
        assert "Preliminary suggested cutoff:" in stdout_all[51]
        stdout_all[51] = "       Preliminary suggested cutoff: 1.XX A\n"
        stdout_1 = "".join(stdout_all[:7])
        stdout_2 = "".join(stdout_all[9:27])
        stdout_3 = "".join(stdout_all[32:57])
        assert stdout_1 == expected_stdout_1
        assert stdout_2 == expected_stdout_2
        assert stdout_3 == expected_stdout_3
        assert "1.60 A" in stdout_all[57]

        assert os.path.isdir(dir_project)
        os.chdir(dir_project)

        with open("PAIREF_out.log", "r") as stdout_logfile:
            stdout_log = stdout_logfile.readlines()
        assert "Preliminary suggested cutoff:" in stdout_log[43]
        stdout_log[43] = "       Preliminary suggested cutoff: 1.XX A\n"
        assert "Preliminary suggested cutoff:" in stdout_log[51]
        stdout_log[51] = "       Preliminary suggested cutoff: 1.XX A\n"
        print("STDOUT:\n" + cp.stdout)
        stdout_log_1 = "".join(stdout_log[:7])
        stdout_log_2 = "".join(stdout_log[9:27])
        stdout_log_3 = "".join(stdout_log[32:57])
        assert stdout_log_1 == expected_stdout_1
        assert stdout_log_2 == expected_stdout_2
        assert stdout_log_3 == expected_stdout_3
        assert "1.60 A" in stdout_log[57]

        files_out = \
            ["mdm2_1-60A.pdb",
             "mdm2_merged.mtz",
             "mdm2_unmerged.mtz",
             "PAIREF_cutoff.txt",
             "PAIREF_out.log",
             "PAIREF_test_quick_mdm2.html",
             "styles.css",
             "test_quick_mdm2_1-60A.pdb",
             "test_quick_mdm2_CCfree.png",
             "test_quick_mdm2_CC.png",
             "test_quick_mdm2_CCwork.png",
             "test_quick_mdm2_Comp_Mult.png",
             "test_quick_mdm2_Intensities.png",
             "test_quick_mdm2_merging_stats.csv",
             "test_quick_mdm2_No_reflections.png",
             "test_quick_mdm2_No_work_free_reflections.png",
             "test_quick_mdm2_Optical_resolution.csv",
             "test_quick_mdm2_Optical_resolution.png",
             "test_quick_mdm2_R00_1-50A_comparison_at_1-50A.log",
             "test_quick_mdm2_R00_1-50A_comparison_at_1-50A.mtz",
             "test_quick_mdm2_R00_1-50A_comparison_at_1-55A.log",
             "test_quick_mdm2_R00_1-50A_comparison_at_1-55A.mtz",
             "test_quick_mdm2_R00_1-50A_comparison_at_1-55A_prev_pair.log",
             "test_quick_mdm2_R00_1-50A_comparison_at_1-55A_prev_pair.mtz",
             "test_quick_mdm2_R00_1-50A_comparison_at_1-60A.log",
             "test_quick_mdm2_R00_1-50A_comparison_at_1-60A.mtz",
             "test_quick_mdm2_R00_1-50A.csv",
             "test_quick_mdm2_R00_1-50A.log",
             "test_quick_mdm2_R00_1-50A.mmcif",
             "test_quick_mdm2_R00_1-50A.mtz",
             "test_quick_mdm2_R00_1-50A.pdb",
             # "test_quick_mdm2_R00_1-50A_sfcheck.log",
             # "test_quick_mdm2_R00_1-50A_sfcheck.out",
             # "test_quick_mdm2_R00_1-50A_sfcheck.ps",
             # "test_quick_mdm2_R00_1-50A_sfcheck.xml",
             "test_quick_mdm2_R00_1-50A_stats_vs_cycle.png",
             "test_quick_mdm2_R00_1-55A_comparison_at_1-55A.log",
             "test_quick_mdm2_R00_1-55A_comparison_at_1-55A.mtz",
             "test_quick_mdm2_R00_1-55A_comparison_at_1-60A.log",
             "test_quick_mdm2_R00_1-55A_comparison_at_1-60A.mtz",
             "test_quick_mdm2_R00_1-55A_comparison_at_1-60A_prev_pair.log",
             "test_quick_mdm2_R00_1-55A_comparison_at_1-60A_prev_pair.mtz",
             "test_quick_mdm2_R00_1-55A.csv",
             "test_quick_mdm2_R00_1-55A.log",
             "test_quick_mdm2_R00_1-55A.mmcif",
             "test_quick_mdm2_R00_1-55A.mtz",
             "test_quick_mdm2_R00_1-55A.pdb",
             # "test_quick_mdm2_R00_1-55A_sfcheck.log",
             # "test_quick_mdm2_R00_1-55A_sfcheck.out",
             # "test_quick_mdm2_R00_1-55A_sfcheck.ps",
             # "test_quick_mdm2_R00_1-55A_sfcheck.xml",
             "test_quick_mdm2_R00_1-55A_stats_vs_cycle.png",
             "test_quick_mdm2_R00_1-60A_comparison_at_1-60A.log",
             "test_quick_mdm2_R00_1-60A_comparison_at_1-60A.mtz",
             "test_quick_mdm2_R00_1-60A.csv",
             "test_quick_mdm2_R00_1-60A.log",
             "test_quick_mdm2_R00_1-60A.mmcif",
             "test_quick_mdm2_R00_1-60A.mtz",
             "test_quick_mdm2_R00_1-60A.pdb",
             # "test_quick_mdm2_R00_1-60A_sfcheck.log",
             # "test_quick_mdm2_R00_1-60A_sfcheck.out",
             # "test_quick_mdm2_R00_1-60A_sfcheck.ps",
             # "test_quick_mdm2_R00_1-60A_sfcheck.xml",
             "test_quick_mdm2_R00_Rgap.csv",
             "test_quick_mdm2_R00_R-values.csv",
             "test_quick_mdm2_Rfree.png",
             "test_quick_mdm2_Rgap.csv",
             "test_quick_mdm2_Rgap.png",
             "test_quick_mdm2_Rmerge_Rmeas_Rpim.png",
             "test_quick_mdm2_R-values.csv",
             "test_quick_mdm2_R-values.png",
             "test_quick_mdm2_Rwork.png"]
        for f in files_out:
            assert os.path.isfile(f)

        # Rfree decrease?
        # with open("test_quick_mdm2_R-values.csv", "r") as csvfile:
        #     csvfile_lines = csvfile.readlines()
        #     lines = [1, 2]
        #     for line in lines:
        #         assert float(csvfile_lines[line].split()[6]) < 0
        # But CC* is lower than CCwork so suggested cutoff should be 1.60 A
        with open("PAIREF_cutoff.txt", "r") as result:
            assert result.read() == "1.60"

        assert filecmp.cmp("test_quick_mdm2_R-values.csv",
                           "test_quick_mdm2_R00_R-values.csv")
        assert filecmp.cmp("test_quick_mdm2_Rgap.csv",
                           "test_quick_mdm2_R00_Rgap.csv")
        assert filecmp.cmp("test_quick_mdm2_R00_1-60A.log",
                           "test_quick_mdm2_R00_1-60A_comparison_at_1-60A.log")
        assert filecmp.cmp("test_quick_mdm2_R00_1-60A.mtz",
                           "test_quick_mdm2_R00_1-60A_comparison_at_1-60A.mtz")
        with open("PAIREF_test_quick_mdm2.html", "r") as htmlfile:
            htmlfile_content = htmlfile.read()
        assert "Calculations are still in progress" not in htmlfile_content
        assert "</html>" in htmlfile_content

        # Clean up
        os.chdir("..")
        shutil.rmtree(dir_project)