├── .github
└── workflows
│ └── release.yml
├── .gitignore
├── .image-config.json
├── CellProfiler-Analyst.py
├── LICENSE
├── Properties_README.txt
├── README.md
├── cpa
├── CreateMasterTableWizard.py
├── Integration.mathematica
├── PlateMapBrowser.bat
├── PlateMapBrowser.command
├── __init__.py
├── _classifier.c
├── boxplot.py
├── change_malloc_zone.c
├── classifier.py
├── colorbarpanel.py
├── columnfilter.py
├── cpaprefs.py
├── cpatool.py
├── datamodel.py
├── datatable.py
├── dbconnect.py
├── density.py
├── dimensionreduction.py
├── dirichletintegrate.py
├── errors.py
├── fastgentleboosting.py
├── fastgentleboostingmulticlass.py
├── fastgentleboostingworkermulticlass.py
├── gating.py
├── generalclassifier.py
├── guiutils.py
├── helpmenu.py
├── histogram.py
├── hypergeom.py
├── icons
│ ├── __init__.py
│ ├── boxplot.png
│ ├── brightness.png
│ ├── classifier.png
│ ├── cpa.icns
│ ├── cpa.ico
│ ├── cpa_128.png
│ ├── cpa_32.png
│ ├── data_grid.png
│ ├── density.png
│ ├── dimensionality.png
│ ├── filter.png
│ ├── filter.psd
│ ├── filter_16.psd
│ ├── filter_new.png
│ ├── gate.png
│ ├── gate.psd
│ ├── gate_16.psd
│ ├── gate_new.png
│ ├── gate_tool.png
│ ├── gate_tool.psd
│ ├── histogram.png
│ ├── image_gallery.png
│ ├── image_viewer.png
│ ├── lasso.png
│ ├── lasso_tool.png
│ ├── normalize.png
│ ├── pixelclassifier.png
│ ├── platemapbrowser.png
│ ├── scatter.png
│ ├── staticimage.png
│ ├── timelapse.png
│ ├── timelapse.psd
│ └── zoom.png
├── imagecontrolpanel.py
├── imagegallery.py
├── imagelist.py
├── imagepanel.py
├── imagereader.py
├── imagetile.py
├── imagetilesizer.py
├── imagetools.py
├── imageviewer.py
├── incell.py
├── logistic_normal_scoring.py
├── multiclasssql.py
├── multiclasssql_legacy.py
├── mysql_plugins
│ ├── classifier_narrow.c
│ └── classify.c
├── normalizationtool.py
├── normalize.py
├── parseperkinelmer.py
├── per_image to per_object.py
├── pilfix.py
├── platemappanel.py
├── plateviewer.py
├── polyafit.py
├── properties.py
├── querymaker.py
├── scatter.py
├── scoreall.py
├── scoreall_manual_validation.py
├── scoredialog.py
├── shell.py
├── singleton.py
├── sortbin.py
├── sqltools.py
├── tableviewer.py
├── tests
│ ├── 32-bit-grayscale.tif
│ ├── __init__.py
│ ├── test.py
│ ├── test2.py
│ ├── test_datamodel.py
│ ├── test_dbconnect.py
│ ├── test_imagereader.py
│ ├── test_multiclasssql.py
│ ├── test_properties.py
│ ├── test_properties_old_filter.properties
│ ├── test_pylab.py
│ ├── test_sqltools.py
│ ├── test_sqltools_old_filter.properties
│ ├── testclassifier.py
│ ├── testdbconnect.py
│ ├── testimagereader.py
│ ├── testscoring.py
│ └── threadingexample.py
├── tilecollection.py
├── trainingset.py
├── tsne.py
├── updatechecker.py
├── util
│ ├── __init__.py
│ ├── frozen_version.py
│ └── version.py
└── utils.py
├── distribution
├── macos
│ ├── CellProfiler-Analyst.spec
│ ├── Info.plist
│ ├── Makefile
│ ├── add-osx-certificate.sh
│ ├── entitlements.plist
│ └── osx-codesign.sh
└── windows
│ ├── CellProfiler-Analyst.iss
│ └── CellProfiler-Analyst.spec
├── docs
├── LICENSE
├── Makefile
├── README.md
├── build
│ └── doctrees
│ │ ├── 0_introduction.doctree
│ │ ├── 10_histogram_plot.doctree
│ │ ├── 11_density_plot.doctree
│ │ ├── 12_boxplot.doctree
│ │ ├── 13_workspaces.doctree
│ │ ├── 14_image_gallery.doctree
│ │ ├── 15_normalization_tool.doctree
│ │ ├── 1_preliminary_requirements.doctree
│ │ ├── 2_installation.doctree
│ │ ├── 3_properties_file.doctree
│ │ ├── 4_cpa_interface.doctree
│ │ ├── 5_classifier.doctree
│ │ ├── 6_table_viewer.doctree
│ │ ├── 7_image_viewer.doctree
│ │ ├── 8_plate_viewer.doctree
│ │ ├── 9_scatter_plot.doctree
│ │ ├── environment.pickle
│ │ └── index.doctree
└── source
│ ├── 0_introduction.rst
│ ├── 10_histogram_plot.rst
│ ├── 11_density_plot.rst
│ ├── 12_boxplot.rst
│ ├── 13_workspaces.rst
│ ├── 14_image_gallery.rst
│ ├── 15_normalization_tool.rst
│ ├── 16_dimensionality_reduction.rst
│ ├── 17_FAQ.rst
│ ├── 1_preliminary_requirements.rst
│ ├── 2_installation.rst
│ ├── 3_properties_file.rst
│ ├── 4_cpa_interface.rst
│ ├── 5_classifier.rst
│ ├── 6_table_viewer.rst
│ ├── 7_image_viewer.rst
│ ├── 8_plate_viewer.rst
│ ├── 9_scatter_plot.rst
│ ├── __init__.py
│ ├── conf.py
│ ├── index.rst
│ ├── manual.pdf
│ └── static
│ ├── 01_01.jpg
│ ├── 01_02.jpg
│ ├── 03_01.jpg
│ ├── 03_02.jpg
│ ├── 04_01.jpg
│ ├── 04_02.jpg
│ ├── 04_03.jpg
│ ├── 04_04.jpg
│ ├── 05_00.jpg
│ ├── 05_01.jpg
│ ├── 05_02.jpg
│ ├── 05_03.jpg
│ ├── 05_04.jpg
│ ├── 05_04b.jpg
│ ├── 05_05.jpg
│ ├── 05_06.jpg
│ ├── 05_06b.jpg
│ ├── 05_07.jpg
│ ├── 05_08.jpg
│ ├── 05_09.jpg
│ ├── 05_09a.jpg
│ ├── 05_09b.jpg
│ ├── 05_10.jpg
│ ├── 05_11.jpg
│ ├── 05_11b.jpg
│ ├── 05_12.jpg
│ ├── 05_13.jpg
│ ├── 05_14.jpg
│ ├── 05_15.jpg
│ ├── 05_16.jpg
│ ├── 05_17.jpg
│ ├── 05_18.jpg
│ ├── 05_19.jpg
│ ├── 05_20.jpg
│ ├── 05_a.jpg
│ ├── 05_b.jpg
│ ├── 05_e.jpg
│ ├── 05_f.jpg
│ ├── 05_y.jpg
│ ├── 05_z.jpg
│ ├── 06_01.jpg
│ ├── 06_02.jpg
│ ├── 06_04.jpg
│ ├── 07_01.jpg
│ ├── 07_02.jpg
│ ├── 07_03.jpg
│ ├── 07_pic1.jpg
│ ├── 08_00.jpg
│ ├── 08_001.jpg
│ ├── 08_01.jpg
│ ├── 08_02.jpg
│ ├── 08_03.jpg
│ ├── 08_04.jpg
│ ├── 08_05.jpg
│ ├── 08_06.jpg
│ ├── 08_08.jpg
│ ├── 08_09.jpg
│ ├── 08_10.jpg
│ ├── 08_11.jpg
│ ├── 08_13.jpg
│ ├── 08_14.jpg
│ ├── 08_15.jpg
│ ├── 08_16.jpg
│ ├── 08_x.jpg
│ ├── 08_y.jpg
│ ├── 08_z.jpg
│ ├── 09_01.jpg
│ ├── 09_02.jpg
│ ├── 09_z.jpg
│ ├── 10_01.jpg
│ ├── 11_01.jpg
│ ├── 12_01.jpg
│ ├── 14_01.jpg
│ ├── 15_01.jpg
│ ├── 16_01.jpg
│ ├── 5_c.jpg
│ └── 5_d.jpg
├── manual
└── cpa_manual.doc
├── requirements.txt
└── setup.py
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: create-release
2 | on:
3 | push:
4 | # branches: [ master ]
5 | tags:
6 | - "*"
7 |
8 | jobs:
9 | build:
10 | name: build
11 | runs-on: ${{ matrix.os }}
12 | steps:
13 | - if: ${{ matrix.os == 'windows-2019' }}
14 | uses: actions/cache@v2
15 | with:
16 | path: ~\AppData\Local\pip\Cache
17 | key: ${{ runner.os }}-pip-${{ hashFiles('setup.py') }}
18 | restore-keys: |
19 | ${{ runner.os }}-pip-
20 | - if: ${{ matrix.os == 'macos-10.15' }}
21 | uses: actions/cache@v2
22 | with:
23 | path: ~/Library/Caches/pip
24 | key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
25 | restore-keys: |
26 | ${{ runner.os }}-pip-
27 | - uses: actions/checkout@v2
28 | - uses: actions/setup-python@v2
29 | with:
30 | architecture: x64
31 | python-version: ${{ matrix.python-version }}
32 | - uses: actions/setup-java@v1
33 | with:
34 | java-version: '14.0.1' # The JDK version to make available on the path.
35 | java-package: jdk
36 | architecture: x64
37 | - run: |
38 | pip install --upgrade pip setuptools wheel
39 | pip install numpy
40 | pip install pyinstaller==4.3
41 | - env:
42 | LDFLAGS: -L/usr/local/opt/openssl/lib
43 | CERTIFICATE_OSX_APPLICATION: ${{ secrets.CERTIFICATE_OSX_APPLICATION }}
44 | CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
45 | if: ${{ matrix.os == 'macos-10.15' }}
46 | run: |
47 | sed -i '' 's/4.0.0/3.0.4/' Info.plist
48 | brew install mysql
49 | git clone https://github.com/CellProfiler/python-javabridge.git
50 | cd python-javabridge/
51 | git checkout print
52 | pip install -e .
53 | cd ..
54 | make
55 | chmod +x add-osx-certificate.sh && ./add-osx-certificate.sh
56 | chmod +x osx-codesign.sh && ./osx-codesign.sh
57 | ditto -ck --keepParent --rsrc --sequesterRsrc ./dist/CellProfiler-Analyst.app ./dist/CellProfiler-Analyst-macOS-3.0.4.zip
58 | working-directory: ./distribution/macos
59 | - env:
60 | JDK_HOME: C:\hostedtoolcache\windows\jdk\14.0.1\x64
61 | if: ${{ matrix.os == 'windows-2019' }}
62 | run: |
63 | pip install cython
64 | pip install --editable .
65 | - if: ${{ matrix.os == 'windows-2019' }}
66 | run: |
67 | pyinstaller distribution/windows/CellProfiler-Analyst.spec
68 | iscc /dMyAppVersion="3.0.4" "distribution/windows/CellProfiler-Analyst.iss"
69 | - if: ${{ matrix.os == 'macos-10.15' }}
70 | uses: actions/upload-artifact@v1
71 | with:
72 | name: CellProfiler-Analyst-macOS-3.0.4.zip
73 | path: ./distribution/macos/dist/CellProfiler-Analyst-macOS-3.0.4.zip
74 | - if: ${{ matrix.os == 'windows-2019' }}
75 | uses: actions/upload-artifact@v2
76 | with:
77 | name: CellProfiler-Analyst-Windows-3.0.4.exe
78 | path: ./distribution/windows/Output/CellProfiler-Analyst-Windows-3.0.4.exe
79 | strategy:
80 | matrix:
81 | os: [macos-10.15, windows-2019]
82 | python-version: [ "3.8" ]
83 | upload:
84 | name: upload
85 | needs: build
86 | runs-on: ubuntu-latest
87 | steps:
88 | - uses: actions/checkout@v2
89 | - env:
90 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
91 | id: create_release
92 | uses: actions/create-release@v1
93 | with:
94 | draft: true
95 | prerelease: true
96 | release_name: ${{ github.ref }}
97 | tag_name: ${{ github.ref }}
98 | - uses: actions/download-artifact@v1
99 | with:
100 | name: CellProfiler-Analyst-macOS-3.0.4.zip
101 | path: ./
102 | - uses: actions/download-artifact@v1
103 | with:
104 | name: CellProfiler-Analyst-Windows-3.0.4.exe
105 | path: ./
106 | - env:
107 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
108 | uses: actions/upload-release-asset@v1
109 | with:
110 | asset_content_type: application/zip
111 | asset_name: CellProfiler-Analyst-macOS-3.0.4.zip
112 | asset_path: /home/runner/work/CellProfiler-Analyst/CellProfiler-Analyst/CellProfiler-Analyst-macOS-3.0.4.zip
113 | upload_url: ${{ steps.create_release.outputs.upload_url }}
114 | - env:
115 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
116 | uses: actions/upload-release-asset@v1
117 | with:
118 | asset_content_type: application/exe
119 | asset_name: CellProfiler-Analyst-Windows-3.0.4.exe
120 | asset_path: /home/runner/work/CellProfiler-Analyst/CellProfiler-Analyst/CellProfiler-Analyst-Windows-3.0.4.exe
121 | upload_url: ${{ steps.create_release.outputs.upload_url }}
122 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/.DS_Store
2 | **/Thumbs.db
3 | *.dll
4 | *.exe
5 | *.jar
6 | *.pdb
7 | *.pyc
8 | *.pyd
9 | *.so
10 | *\#
11 | *~
12 | *.egg
13 | .eggs/
14 | build
15 | dist
16 | output
17 | /cpa/_description.py
18 | /cpa/version.iss
19 | /images
20 | **/.idea
21 | .vscode
22 | .*.swp
23 | /docs/build/html
24 |
--------------------------------------------------------------------------------
/.image-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "storePath": "/images",
3 | "wwwRoot": "/",
4 | "grammars": {
5 | "Markdown": {
6 | "url": ""
7 | },
8 | "GitHub Markdown": {
9 | "url": ""
10 | },
11 | "HTML": {
12 | "url": "
"
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The BSD 3-Clause License
2 |
3 | Copyright © 2003 - 2024 Broad Institute, Inc. All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright notice,
9 | this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright
12 | notice, this list of conditions and the following disclaimer in the
13 | documentation and/or other materials provided with the distribution.
14 |
15 | 3. Neither the name of the Broad Institute, Inc. nor the names of its
16 | contributors may be used to endorse or promote products derived from
17 | this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED “AS IS.” BROAD MAKES NO EXPRESS OR IMPLIED
20 | REPRESENTATIONS OR WARRANTIES OF ANY KIND REGARDING THE SOFTWARE AND
21 | COPYRIGHT, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE, CONFORMITY WITH ANY DOCUMENTATION,
23 | NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT
24 | DISCOVERABLE. IN NO EVENT SHALL BROAD, THE COPYRIGHT HOLDERS, OR CONTRIBUTORS
25 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO PROCUREMENT OF SUBSTITUTE
27 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF, HAVE REASON TO KNOW, OR IN
31 | FACT SHALL KNOW OF THE POSSIBILITY OF SUCH DAMAGE.
32 |
33 | If, by operation of law or otherwise, any of the aforementioned warranty
34 | disclaimers are determined inapplicable, your sole remedy, regardless of the
35 | form of action, including, but not limited to, negligence and strict
36 | liability, shall be replacement of the software with an updated version if one
37 | exists.
38 |
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 | -----------------
5 |
6 | | **`Version`** | **`Documentation`** | **`Forum`** |
7 | |---------------|----------------|-----------------|
8 | | [](https://cellprofileranalyst.org/releases) | [](https://cellprofiler-manual.s3.amazonaws.com/CellProfiler-Analyst-3.0.0/index.html) | [](https://forum.image.sc/tag/cellprofiler-analyst) |
9 |
10 | **CellProfiler Analyst** allows interactive exploration and analysis of data,
11 | particularly from high-throughput, image-based experiments. Included is a
12 | supervised machine learning system which can be trained to recognize complex
13 | and subtle phenotypes, for automatic scoring of millions of cells.
14 |
15 |
16 |

17 |
18 |
19 | ## Learn more about CellProfiler Analyst
20 | This is the developer site for CellProfiler Analyst.
21 | The regular home page for CellProfiler Analyst is here: https://cellprofileranalyst.org/
22 |
23 | ## Installation
24 |
25 | Download [CellProfiler Analyst](https://cellprofileranalyst.org/releases)
26 |
27 | When running from source, CellProfiler Analyst requires [JDK 1.8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) to be installed (not just JRE).
28 | Check the Java path.
29 |
30 | Please note that this is the development branch of CPA and it will be updated on regular basis.
31 |
32 | Find all releases [here](https://cellprofileranalyst.org/previously-released-versions-cellprofiler-analyst).
33 |
34 | For a head start, download example dataset here: [Example Dataset for CPA (zipped)](http://d1zymp9ayga15t.cloudfront.net/content/Examplezips/cpa_2.0_example.zip)
35 |
36 | ## Developer build
37 |
38 | Building CPA on your machine requires CellProfiler dependencies. Check the wiki
39 | for more detailed installation instructions.
40 |
41 | * Pandas
42 | * Seaborn
43 | * Scikit-learn
44 | * Python-Javabridge
45 | * Verlib
46 | * Python-bioformats
47 |
48 | ## Documentation
49 |
50 | > https://cellprofileranalyst.org/manuals
51 |
52 | ## Wiki
53 |
54 | > https://github.com/CellProfiler/CellProfiler-Analyst/wiki
55 |
56 | ## Forum
57 |
58 | CellProfiler Analyst development is discussed on the CellProfiler Forum
59 | list.
60 |
61 | > https://forum.image.sc/tag/cellprofiler-analyst/
62 |
63 | ## How to file new issues
64 |
65 | Please attach sufficient information to reproduce the bug. For many
66 | bugs, it is appropriate to attach a properties file, a training set,
67 | or a screenshot.
68 |
69 | ## How to cite
70 |
71 | *David Dao, Adam N Fraser, Jane Hung, Vebjorn Ljosa, Shantanu Singh and Anne E Carpenter*
72 | __[CellProfiler Analyst: interactive data exploration, analysis and classification of large biological image sets][bioinformatics]__
73 | Bioinformatics (2016) doi:10.1093/bioinformatics/btw390
74 |
75 | *Thouis R Jones, In Han Kang, Douglas B Wheeler, Robert A Lindquist, Adam Papallo, David M Sabatini, Polina Golland and Anne E Carpenter*
76 | __[CellProfiler Analyst: data exploration and analysis software for complex image-based screens][bmc]__
77 | BMC Bioinformatics (2008) doi:10.1186/1471-2105-9-482
78 |
79 |
80 | [bioinformatics]: http://bioinformatics.oxfordjournals.org/content/early/2016/07/24/bioinformatics.btw390
81 | [bmc]: https://bmcbioinformatics.biomedcentral.com/articles/10.1186/1471-2105-9-482
82 |
83 |
84 | ## Contributors
85 |
86 | David Dao, Adam Fraser, David Stirling, Pearl Ryder, Beth Cimini, Vebjorn Ljosa, Thouis R. Jones, Jane Hung, Shantanu Singh, Mark Bray, Lee Kamentsky, Anne Carpenter
87 |
88 | ## Kudos
89 |
90 | David Logan, Allen Goodman, Alison Kozol, Mohammad Hossein Rohban
91 |
92 | *Copyright 2021, The Broad Institute of MIT and Harvard.
93 | Distributed under the BSD license.*
94 |
--------------------------------------------------------------------------------
/cpa/Integration.mathematica:
--------------------------------------------------------------------------------
1 | FullSimplify[Integrate[PDF[BetaDistribution[s*a,s*b],x]*CDF[BetaDistribution[a,b],x],{x,0,1}], {a>0,b>0,b \[NotElement] Integers, s>1}]
2 |
3 |
4 | In[1]:= Integrate[PDF[BetaDistribution[c,d],x]*CDF[BetaDistribution[a,b],x],{x,0,1},Assumptions->{a>0,b>0,c>0,d>0}]
5 |
6 | Out[1]= (Gamma[a] Gamma[a + c] Gamma[d]
7 |
8 | > HypergeometricPFQRegularized[{a, 1 - b, a + c}, {1 + a, a + c + d}, 1])
9 |
10 | > / (Beta[a, b] Beta[c, d])
11 |
12 | http://functions.wolfram.com/HypergeometricFunctions/HypergeometricPFQRegularized/02/0001/MainEq1.gif
13 |
14 |
15 | Integrate[PDF[BetaDistribution[111.52056534719972, 0.31516669716616263],x]*CDF[BetaDistribution[90.520565347199721, 0.31516669716616263],x],{x,0,1}]
16 |
17 |
18 | Integrate[PDF[BetaDistribution[a+c,b+d],x]*CDF[BetaDistribution[a,b],x],{x,0,1},Assumptions->{a>0,b>0,c>=0,d>=0,(c+d)>0,c in Integers, d in Integers}]
19 |
20 |
21 | A useful identity:
22 | HypergeometricPFQ[{a, b, c}, {d, a - 1}, 1] == ((Gamma[d] Gamma[d - b
23 | - c])/(Gamma[d - b] Gamma[d - c])) (1 - (b c)/((a - 1) (1 + b + c -
24 | d))) /; Re[d - b - c] > 1
25 |
26 |
27 | Combined with:
28 | (a_i - 1) F = (a_i - a_j - 1) F(a_i - 1) + a_j F(a_i - 1, a_j + 1)
29 |
30 |
31 | FullSimplify[Integrate[w^(-1-c) Hypergeometric2F1[a+c,1-d, a+c+b, 1/w], {w,1,Infinity}], {a>0, b>0, c>0, d>0}]
32 | FullSimplify[Integrate[w^(a-1) Hypergeometric2F1[a+c,1-b, a+c+d, w], {w,0,1}], {a>0, b>0, c>0, d>0}]
33 |
34 | FullSimplify[Integrate[p^(b+d-1) (1-p)^(c+b-1) AppellF1[b, a+b+c+d-2, 1-a, b+c, 1-p, 1-p^2], {p, 0, 1}], {a>0, b>0, c>0, d>0}]
--------------------------------------------------------------------------------
/cpa/PlateMapBrowser.bat:
--------------------------------------------------------------------------------
1 | cd /d %~dp0
2 | python plateviewer.py
--------------------------------------------------------------------------------
/cpa/PlateMapBrowser.command:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | cd `dirname $0`
3 |
4 | python plateviewer.py
5 |
6 |
--------------------------------------------------------------------------------
/cpa/__init__.py:
--------------------------------------------------------------------------------
1 | from cpa.util.version import __version__
2 |
3 | from . import properties, util
4 | from . import dbconnect
5 |
6 | p = properties.Properties()
7 | db = dbconnect.DBConnect()
8 |
--------------------------------------------------------------------------------
/cpa/_classifier.c:
--------------------------------------------------------------------------------
1 | /* _classifier.c - */
2 |
3 | // Compile (for testing) with:
4 | // python setup.py build_ext -i
5 |
6 | #include "sqlite3.h"
7 | #include "Python.h"
8 | #include "numpy/arrayobject.h"
9 | #include
10 |
11 | #define MAX_STUMPS 100 // Default limit for sqlite3
12 | #define MAX_CLASSES 100
13 |
14 | static struct {
15 | int num_classes;
16 | int num_stumps;
17 | double thresholds[MAX_STUMPS];
18 | double stump_weights_a[MAX_STUMPS][MAX_CLASSES];
19 | double stump_weights_b[MAX_STUMPS][MAX_CLASSES];
20 | int valid;
21 | } classifier_data;
22 |
23 | #define TYPE_ERROR(str, fail_label) {PyErr_SetString(PyExc_TypeError, (str)); goto fail_label;}
24 | #define VALUE_ERROR(str, fail_label) {PyErr_SetString(PyExc_ValueError, (str)); goto fail_label;}
25 |
26 | static PyObject *setup_classifier(PyObject *self, PyObject *args)
27 | {
28 | PyObject *weak_learners;
29 | PyArrayObject *wl_array;
30 | int i, j;
31 |
32 | if (! PyArg_ParseTuple(args, "O", &weak_learners))
33 | TYPE_ERROR("one argument required", fail_1);
34 |
35 | wl_array = (PyArrayObject *) PyArray_FROM_OTF(weak_learners, NPY_DOUBLE, NPY_IN_ARRAY);
36 | if (! wl_array)
37 | return NULL;
38 |
39 | if (wl_array->nd != 2)
40 | TYPE_ERROR("argument must be 2D array of floats (or convertable to same)", fail_2);
41 |
42 | if ((PyArray_DIM(wl_array, 1) % 2) == 0)
43 | TYPE_ERROR("argument must have an odd dimenions along axis 1", fail_2);
44 |
45 | classifier_data.num_stumps = PyArray_DIM(wl_array, 0);
46 | classifier_data.num_classes = PyArray_DIM(wl_array, 1) / 2;
47 |
48 | if (classifier_data.num_stumps > MAX_STUMPS)
49 | VALUE_ERROR("maximum number of stumps (100) exceeded.", fail_2);
50 |
51 | for (i = 0; i < classifier_data.num_stumps; i++) {
52 | classifier_data.thresholds[i] = * (double *) PyArray_GETPTR2(wl_array, i, 0);
53 |
54 | for (j = 0; j < classifier_data.num_classes; j++) {
55 | classifier_data.stump_weights_a[i][j] = * (double *) PyArray_GETPTR2(wl_array, i, 1 + j);
56 | classifier_data.stump_weights_b[i][j] = * (double *) PyArray_GETPTR2(wl_array, i, 1 + classifier_data.num_classes + j);
57 | }
58 | }
59 |
60 | classifier_data.valid = 1;
61 |
62 | Py_DECREF(wl_array);
63 | Py_INCREF(Py_None);
64 | return Py_None;
65 |
66 | fail_2:
67 | Py_DECREF(wl_array);
68 | fail_1:
69 | return NULL;
70 | }
71 |
72 | static void c_classifier(sqlite3_context* context, int argc, sqlite3_value** argv)
73 | {
74 | int stumps[MAX_STUMPS], i, j;
75 | double best_score = -3 * classifier_data.num_stumps;
76 | int best_class = 0;
77 |
78 | if (! classifier_data.valid) {
79 | sqlite3_result_error(context, "setup_classifier() must be called before using classifier() in SQL.", -1);
80 | return;
81 | }
82 |
83 | if (argc != classifier_data.num_stumps) {
84 | sqlite3_result_error(context, "The number of arguments to classifier() must be the same as the number passed to setup_classifier()", -1);
85 | return;
86 | }
87 |
88 | // compute the stumps
89 | for (i = 0; i < argc; i++) {
90 | stumps[i] = sqlite3_value_double(argv[i]) > classifier_data.thresholds[i];
91 | }
92 |
93 | // compute the scores
94 | for (i = 0; i < classifier_data.num_classes; i++) {
95 | double score = 0.0;
96 | for (j = 0; j < classifier_data.num_stumps; j++)
97 | score += stumps[j] ? classifier_data.stump_weights_a[j][i] : classifier_data.stump_weights_b[j][i];
98 | if (score > best_score) {
99 | best_score = score;
100 | best_class = i;
101 | }
102 | }
103 |
104 | sqlite3_result_int(context, best_class + 1);
105 | }
106 |
107 |
108 | // NB: this will blow up if the pysqlite_Connection structure changes.
109 | // This is just the first few bytes of the structure, so we can get the db.
110 | typedef struct
111 | {
112 | PyObject_HEAD
113 | sqlite3* db;
114 | } pysqlite_Connection;
115 |
116 | static PyObject* create_classifier_function(PyObject* self, PyObject* args)
117 | {
118 | int rc;
119 | pysqlite_Connection *conn;
120 |
121 | if (!PyArg_ParseTuple(args, "O", &conn))
122 | return NULL;
123 |
124 | if (SQLITE_VERSION_NUMBER >= 3006020)
125 | sqlite3_initialize();
126 | rc = sqlite3_create_function(conn->db, "classifier", -1, SQLITE_UTF8, NULL, c_classifier, NULL, NULL);
127 |
128 | if (rc != SQLITE_OK) {
129 | return NULL;
130 | } else {
131 | Py_INCREF(Py_None);
132 | return Py_None;
133 | }
134 | }
135 |
136 | static PyMethodDef ClassifierMethods[] = {
137 | {"setup_classifier", setup_classifier, METH_VARARGS, "Set up a run of the classifier function"},
138 | {"create_classifier_function", create_classifier_function, METH_VARARGS, "Create the C classifier function on a connection."},
139 | {NULL, NULL, 0, NULL}
140 | };
141 |
142 |
143 | #ifdef __cplusplus
144 | extern "C"
145 | #endif
146 | PyMODINIT_FUNC init_classifier(void)
147 | {
148 | PyObject *m;
149 |
150 | classifier_data.valid = 0;
151 |
152 | m = Py_InitModule("_classifier", ClassifierMethods);
153 | import_array();
154 |
155 | if (m == NULL)
156 | return;
157 | }
158 |
--------------------------------------------------------------------------------
/cpa/change_malloc_zone.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | void *(*system_malloc)(malloc_zone_t *zone, size_t size);
6 | void (*system_free)(malloc_zone_t *zone, void *ptr);
7 |
8 | #define KEEP_SIZE 4096
9 | #define KEEP_NUM 100
10 | static void* keep_list[KEEP_NUM];
11 | static void** tail;
12 |
13 |
14 | void *mymalloc(malloc_zone_t *zone, size_t size)
15 | {
16 | if (size >= KEEP_SIZE) { // big?
17 | if (tail > keep_list) { // available?
18 | void **entry;
19 | for (entry = tail - 1; entry >= keep_list; entry--) {
20 | if (zone->size(zone, *entry) >= size) {
21 | void *retval = *entry;
22 | tail--;
23 | *entry = *tail;
24 | //fprintf(stderr, "fulfill %d w/ %d, %d on list\n", size, zone->size(zone, *entry), keep_list - tail);
25 | return retval;
26 | }
27 | }
28 | }
29 | }
30 |
31 | // fprintf(stderr, "malloc %d\n", size);
32 | return system_malloc(zone, size);
33 | }
34 |
35 | void myfree(malloc_zone_t *zone, void *ptr)
36 | {
37 | size_t sz = zone->size(zone, ptr);
38 | if (sz >= KEEP_SIZE) { // big?
39 | if ((tail - keep_list) < KEEP_NUM) { // space available?
40 | *tail = ptr;
41 | tail++;
42 | //fprintf(stderr, "kept %d, %d on list\n", sz, keep_list - tail);
43 | return;
44 | }
45 | }
46 | // fprintf(stderr, "free %d\n", sz);
47 | system_free(zone, ptr);
48 | }
49 |
50 | void setup()
51 | {
52 | malloc_zone_t * zone = malloc_default_zone();
53 |
54 | tail = keep_list;
55 | system_malloc = zone->malloc;
56 | zone->malloc = mymalloc;
57 | system_free = zone->free;
58 | zone->free = myfree;
59 | }
60 |
61 | void teardown()
62 | {
63 | malloc_zone_t * zone = malloc_default_zone();
64 |
65 | while (tail > keep_list) {
66 | tail--;
67 | system_free(zone, *tail);
68 | }
69 |
70 | zone->malloc = system_malloc;
71 | zone->free = system_free;
72 | }
73 |
--------------------------------------------------------------------------------
/cpa/cpaprefs.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 | CHECK_FOR_UPDATES = 'CheckForUpdates'
4 | CHECKFORNEWVERSIONS = 'CheckForNewVersions'
5 | SKIPVERSION = 'SkipVersion'
6 |
7 | def get_config():
8 | try:
9 | config = wx.Config.Get(False)
10 | except wx.PyNoAppError:
11 | app = wx.App(0)
12 | config = wx.Config.Get(False)
13 | if not config:
14 | wx.Config.Set(wx.Config('CellProfilerAnalyst','BroadInstitute','CellProfilerAnalystLocal.cfg','CellProfilerAnalystGlobal.cfg',wx.CONFIG_USE_LOCAL_FILE))
15 | config = wx.Config.Get()
16 | return config
17 |
18 | def get_check_new_versions():
19 | if not get_config().Exists(CHECKFORNEWVERSIONS):
20 | # should this check for whether we can actually save preferences?
21 | return True
22 | return get_config().ReadBool(CHECKFORNEWVERSIONS)
23 |
24 | def set_check_new_versions(val):
25 | old_val = get_check_new_versions()
26 | get_config().WriteBool(CHECKFORNEWVERSIONS, bool(val))
27 | # If the user turns on version checking, they probably don't want
28 | # to skip versions anymore.
29 | if val and (not old_val):
30 | set_skip_version(0)
31 |
32 | def get_skip_version():
33 | if not get_config().Exists(SKIPVERSION):
34 | return 0
35 | return get_config().ReadInt(SKIPVERSION)
36 |
37 | def set_skip_version(ver):
38 | get_config().WriteInt(SKIPVERSION, ver)
39 |
40 | def get_check_update():
41 | if not get_config().Exists(CHECK_FOR_UPDATES):
42 | return "Never"
43 | return get_config().Read(CHECK_FOR_UPDATES)
44 |
45 |
46 | def get_check_update_bool():
47 | if not get_config().Exists(CHECK_FOR_UPDATES):
48 | return True
49 | update_str = get_config().Read(CHECK_FOR_UPDATES)
50 | if update_str == "Disabled":
51 | return False
52 | else:
53 | return True
54 |
55 |
56 | def set_check_update(val):
57 | if str(val) == "False":
58 | val = "Disabled"
59 | elif str(val) == "True":
60 | val = "Never"
61 | get_config().Write(CHECK_FOR_UPDATES, val)
62 |
--------------------------------------------------------------------------------
/cpa/cpatool.py:
--------------------------------------------------------------------------------
1 | '''
2 | '''
3 | import wx
4 |
5 | class CPATool(object):
6 | '''Any tool or visualization whose state may be saved and recalled from a
7 | series of settings and corresponding values.'''
8 | def __init__(self):
9 | # Set the name of the tool based on the class name. A subclass can
10 | # override this by declaring a tool_name attribute in the class
11 | # definition
12 | if 'tool_name' not in self.__dict__:
13 | self.tool_name = self.__class__.__name__
14 |
15 | def save_settings(self):
16 | '''Override this method when defining a new tool or visualization.
17 |
18 | save_settings is called when saving a workspace to file.
19 |
20 | returns a dictionary mapping setting names to values encoded as strings
21 | '''
22 | raise NotImplementedError
23 |
24 | def load_settings(self, settings):
25 | '''Override this method when defining a new tool or visualization.
26 |
27 | load_settings is called when loading a workspace from file.
28 |
29 | settings - a dictionary mapping setting names to values encoded as
30 | strings.
31 | '''
32 | raise NotImplementedError
33 |
--------------------------------------------------------------------------------
/cpa/errors.py:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | def show_exception_as_dialog(type, value, tb, raisefurther=True):
5 | """Exception handler that show a dialog."""
6 | import traceback
7 | import wx
8 |
9 | # if tb:
10 | # print((traceback.format_tb(tb)))
11 |
12 | if isinstance(value, ClearException):
13 | wx.MessageBox(value, value.heading, wx.OK | wx.ICON_ERROR)
14 | else:
15 | from wx.lib.dialogs import ScrolledMessageDialog
16 | lines = ['An error occurred in the program:\n']
17 | lines += traceback.format_exception_only(type, value)
18 | lines += ['\nTraceback (most recent call last):\n']
19 | if tb:
20 | lines += traceback.format_tb(tb)
21 | dlg = ScrolledMessageDialog(None, "".join(lines), 'Error', style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
22 | dlg.ShowModal()
23 | if raisefurther:
24 | raise value
25 |
26 |
27 | class ClearException(Exception):
28 | """
29 | AN exception where what happened is so clear that it is
30 | unnecessary to show a stack trace.
31 |
32 | """
33 | def __init__(self, message, heading='Error', *args, **kwargs):
34 | super(ClearException, self).__init__(message, *args, **kwargs)
35 | self.heading = heading
36 |
37 |
38 |
--------------------------------------------------------------------------------
/cpa/fastgentleboostingworkermulticlass.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Worker script called from FastGentleBoosting.py.
4 |
5 | from sys import stdin, stdout, stderr, argv
6 | from numpy import *
7 |
8 | def train_weak_learner(labels, weights, values):
9 | ''' For a multiclass training set, with C classes and N examples,
10 | finds the optimal weak learner in O(M * N logN) time.
11 | Optimality is defined by Eq. 7 of Torralba et al., 'Sharing visual
12 | features...', 2007, IEEE PAMI.
13 |
14 | We differ from Torralba et al. in two ways:
15 | - we do not share a's and b's between classes
16 | - we always solve for the complete set of examples, regardless of label
17 |
18 | Labels should be 1 and -1, only.
19 | label_matrix and weights are NxC.
20 | values is Nx1
21 | '''
22 |
23 | global order, s_values, s_labels, s_weights, s_weights_times_labels, num_a, den_a, a, b, sless0, sgrtr0, w_below_neg, w_below_pos, w_above_neg, w_above_pos, J
24 |
25 | # Sort labels and weights by values (AKA possible thresholds). By
26 | # default, argsort is not stable, so the results will vary
27 | # slightly with the number of workers. Add kind="mergesort" to
28 | # get a stable sort, which avoids this.
29 | order = argsort(values)
30 | s_values = values[order]
31 | s_labels = labels[order, :]
32 | s_weights = weights[order, :]
33 |
34 | # useful subfunction
35 | num_examples = labels.shape[0]
36 | def tilesum(a):
37 | return tile(sum(a, axis=0), (num_examples, 1))
38 |
39 | # Equations 9 and 10 of Torralba et al.
40 | s_weights_times_labels = s_weights * s_labels
41 | num_a = (tilesum(s_weights_times_labels) - cumsum(s_weights_times_labels, axis=0))
42 | den_a = (tilesum(s_weights) - cumsum(s_weights, axis=0))
43 | den_a[den_a <= 0.0] = 1.0 # avoid div by zero
44 | a = num_a / den_a
45 | b = cumsum(s_weights_times_labels, axis=0) / cumsum(s_weights, axis=0)
46 |
47 | # We need, at each index, the total weights below and above,
48 | # separated by positive and negative label. Below includes the
49 | # current index
50 | sless0 = (s_labels < 0)
51 | sgrtr0 = (s_labels > 0)
52 | w_below_neg = cumsum(s_weights * sless0, axis=0)
53 | w_below_pos = cumsum(s_weights * sgrtr0, axis=0)
54 | w_above_neg = tilesum(s_weights * sless0) - w_below_neg
55 | w_above_pos = tilesum(s_weights * sgrtr0) - w_below_pos
56 |
57 | # Now evaluate the error at each threshold.
58 | # (see Equation 7, and note that we're assuming -1 and +1 for entries in the label matrix.
59 | J = w_below_neg * ((-1 - b)**2) + w_below_pos * ((1 - b)**2) + w_above_neg * ((-1 - a)**2) + w_above_pos * ((1 - a)**2)
60 | J = J.sum(axis=1)
61 |
62 | # Find index of least error
63 | idx = argmin(J)
64 |
65 | # make sure we're at the top of this thresh
66 | while (idx+1 < len(s_values)) and (s_values[idx] == s_values[idx + 1]):
67 | idx += 1
68 |
69 | # return the threshold at that index
70 | return s_values[idx], J[idx], a[idx, :].copy(), b[idx, :].copy()
71 |
72 | def train_classifier(labels, values, iterations):
73 | # make sure these are arrays (not matrices)
74 | labels = array(labels)
75 | values = array(values)
76 |
77 | num_examples = labels.shape[0]
78 |
79 | learners = []
80 | weights = ones(labels.shape)
81 | output = zeros(labels.shape)
82 | for n in range(iterations):
83 | best_error = float(Infinity)
84 |
85 | for feature_idx in range(values.shape[1]):
86 | val, err, a, b = train_weak_learner(labels, weights, values[:, feature_idx])
87 | if err < best_error:
88 | best_error = err
89 | best_idx = feature_idx
90 | best_val = val
91 | best_a = a
92 | best_b = b
93 |
94 | delta = values[:, best_idx] > best_val
95 | delta.shape = (len(delta), 1)
96 | feature_thresh_mask = tile(delta, (1, labels.shape[1]))
97 | output = output + feature_thresh_mask * tile(best_a, (num_examples, 1)) + (1 - feature_thresh_mask) * tile(best_b, (num_examples, 1))
98 | weights = exp(- output * labels)
99 | weights = weights / sum(weights)
100 | err = sum((output * labels) <= 0)
101 | return
102 |
103 | def myfromfile(stream, type, sh):
104 | if len(sh) == 2:
105 | tot = sh[0] * sh[1]
106 | else:
107 | tot = sh[0]
108 | result = fromfile(stream, type, tot)
109 | result.shape = sh
110 | return result
111 |
112 | def doit():
113 | testing = False
114 | n, ncols = myfromfile(stdin, int32, (2,))
115 | num_classes = myfromfile(stdin, int32, (1,))[0]
116 | values = myfromfile(stdin, float32, (n, ncols))
117 | label_matrix = myfromfile(stdin, int32, (n, num_classes))
118 |
119 | while True:
120 | # It would be cleaner to tell the worker we're done by just
121 | # closing the stream, but numpy does strange things (prints
122 | # error message, signals MemoryError) when myfromfile cannot
123 | # read as many bytes as expected.
124 | if stdin.readline() == "done\n":
125 | return
126 | weights = myfromfile(stdin, float32, (n, num_classes))
127 |
128 | best = float(Infinity)
129 | for column in range(ncols):
130 | colvals = values[:, column]
131 | # print >>stderr, "WORK", column, label_matrix, weights, colvals
132 | thresh, err, a, b = train_weak_learner(label_matrix, weights, colvals)
133 | if err < best:
134 | best = err
135 | bestvals = (err, column, thresh, a, b)
136 |
137 | err, column, thresh, a, b = bestvals
138 | array([err, column, thresh], float32).tofile(stdout)
139 | a.astype(float32).tofile(stdout)
140 | b.astype(float32).tofile(stdout)
141 | stdout.flush()
142 |
143 |
144 |
145 | if __name__ == '__main__':
146 | try:
147 | import dl
148 | h = dl.open('change_malloc_zone.dylib')
149 | h.call('setup')
150 | except:
151 | pass
152 | if len(argv) != 1:
153 | import cProfile
154 | cProfile.runctx("doit()", globals(), locals(), "worker.cprof")
155 | else:
156 | try: # Use binary I/O on Windows
157 | import msvcrt, os
158 | try:
159 | msvcrt.setmode(stdin.fileno(), os.O_BINARY)
160 | except:
161 | stderr.write("Couldn't deal with stdin\n")
162 | pass
163 | try:
164 | msvcrt.setmode(stdout.fileno(), os.O_BINARY)
165 | stderr.write("Couldn't deal with stdout\n")
166 | except:
167 | pass
168 | except ImportError:
169 | pass
170 | doit()
171 | try:
172 | h.call('teardown')
173 | except:
174 | pass
175 |
--------------------------------------------------------------------------------
/cpa/helpmenu.py:
--------------------------------------------------------------------------------
1 | import wx
2 | import cpa
3 | import cpa.icons
4 | from cpa.updatechecker import check_update
5 | from cpa.util.version import display_version, __version__
6 |
7 |
8 | def _on_check_update(self):
9 | check_update(self, force=True)
10 |
11 | def _on_about(self):
12 | ''' Shows a message box with the version number etc.'''
13 | shift = wx.GetKeyState(wx.WXK_SHIFT)
14 | ctrl = wx.GetKeyState(wx.WXK_CONTROL)
15 |
16 | if shift or ctrl:
17 | import logging
18 | import os
19 | import sys
20 | import javabridge
21 | logging.info("\n\nDEBUG - CPA Java State is as follows:")
22 |
23 | # Hold ctrl only: change CP_JAVA_HOME
24 | if ctrl and not shift:
25 | cd = wx.DirDialog(None, message="Choose new CP_JAVA_HOME",
26 | defaultPath=os.getcwd(), name="Set JAVA location")
27 | if cd.ShowModal() == wx.ID_OK:
28 | newdir = cd.GetPath()
29 | os.environ["CP_JAVA_HOME"] = newdir
30 | logging.info(f"Set CP_JAVA_HOME to {str(newdir)}")
31 |
32 | if 'CP_JAVA_HOME' in os.environ:
33 | logging.info(f"CP_JAVA_HOME is {os.environ['CP_JAVA_HOME']}")
34 | else:
35 | logging.info("CP_JAVA_HOME is not set")
36 | if 'JAVA_HOME' in os.environ:
37 | logging.info(f"JAVA_HOME is {os.environ['JAVA_HOME']}")
38 | else:
39 | logging.info("JAVA_HOME is not set")
40 | logging.info(f"Current working directory is {os.getcwd()}")
41 | logging.info(f"Python is running from {sys.prefix}")
42 | logging.info(f"Core Python install is at {sys.base_prefix}")
43 | logging.info(f"Javabridge java search returned {javabridge.locate.find_javahome()}")
44 | # Shift and ctrl/cmd held - test the VM. You'll need to restart CPA after since the VM can't be restarted.
45 | if shift and ctrl:
46 | try:
47 | logging.warning("Attempting to start Javabridge")
48 | javabridge.start_vm(run_headless=True)
49 | logging.warning("VM started successfully")
50 | javabridge.kill_vm()
51 | logging.warning("Shut down test vm. You'll need to RESTART CPA to use it again")
52 | except Exception as e:
53 | logging.info(f"Javabridge test failed")
54 | logging.info(e)
55 |
56 | message = ('CellProfiler Analyst was developed at The Broad Institute\n'
57 | 'Imaging Platform and is distributed under the\n'
58 | 'BSD 3-Clause License.')
59 | from wx.adv import AboutBox, AboutDialogInfo
60 | info = AboutDialogInfo()
61 | info.SetIcon(cpa.icons.get_cpa_icon())
62 | info.SetName('CellProfiler Analyst (%s)'%(str(display_version) or 'unknown revision'))
63 | info.SetDescription(message)
64 | info.AddDeveloper('David Dao')
65 | info.AddDeveloper('Adam Fraser')
66 | info.AddDeveloper('Jane Hung')
67 | info.AddDeveloper('Thouis (Ray) Jones')
68 | info.AddDeveloper('Vebjorn Ljosa')
69 | info.AddDeveloper('David Stirling')
70 | info.SetWebSite('cellprofileranalyst.org')
71 | AboutBox(info)
72 |
73 | def make_help_menu(frame, main=False, manual_url="index.html"):
74 | help_version = __version__.rsplit('.', 1)[0]
75 | manual_url = f"https://cellprofiler-manual.s3.amazonaws.com/CellProfiler-Analyst-{help_version}/{manual_url}"
76 | helpMenu = wx.Menu()
77 | def on_manual(self):
78 | import webbrowser
79 | webbrowser.open(manual_url)
80 |
81 | frame.Bind(wx.EVT_MENU, on_manual,
82 | helpMenu.Append(-1, item='Online manual'))
83 | if main:
84 | frame.Bind(wx.EVT_MENU, _on_check_update,
85 | helpMenu.Append(-1, item='Check for updates', helpString='Check for new versions'))
86 | frame.Bind(wx.EVT_MENU, _on_about,
87 | helpMenu.Append(-1, item='About', helpString='About CellProfiler Analyst'))
88 | return helpMenu
89 |
90 | if __name__ == '__main__':
91 | app = wx.App()
92 | frame = wx.Frame(None, title='Test help menu')
93 | menu_bar = wx.MenuBar()
94 | menu_bar.Append(make_help_menu(frame), 'Help')
95 | frame.SetMenuBar(menu_bar)
96 | frame.Show()
97 | app.MainLoop()
98 |
99 |
--------------------------------------------------------------------------------
/cpa/hypergeom.py:
--------------------------------------------------------------------------------
1 | # CellProfiler is distributed under the GNU General Public License,
2 | # but this file is licensed under the more permissive BSD license.
3 | # See the accompanying file LICENSE for details.
4 |
5 | from scipy.special import gamma, hyp2f1, gammaln
6 | from numpy import *
7 | import pdb
8 |
9 | def pochdivgamma(a, b, iterations):
10 | out = zeros(iterations, float64)
11 | out[0] = 1.0 / gamma(b)
12 | out[1:] = (a + arange(iterations-1).astype(float64)) / (b + arange(iterations-1).astype(float64))
13 | return cumprod(out)
14 |
15 | def hyper3F2regularizedZ1(a1, a2, a3, b1, b2):
16 | '''the regularized hypergeometric function 3(F^~)2(a,b,z) with z=1.
17 | The terms are grouped under the assumption that the arguments will be:
18 | {a, 1-b, a+c} and {1+a, a+c+d} w/ a,b,c,d >= 0, in which case the
19 | groupings result in terms all <= 1 (after enough iterations)'''
20 |
21 | iterations = int(max(-2*a1, -2*a2, -2*a3, 100))
22 |
23 | a1b1term = pochdivgamma(a1, b1, iterations)
24 | a3b2term = pochdivgamma(a3, b2, iterations)
25 | a2kterm = pochdivgamma(a2, 1, iterations)
26 | termprod = a1b1term * a3b2term * a2kterm
27 |
28 | pdb.set_trace()
29 |
30 | return sum(termprod), abs(termprod[-1])
31 |
32 |
33 | def pochdivpoch(a, b, iterations):
34 | out = zeros(iterations, float64)
35 | out[0] = 1.0
36 | out[1:] = (a + arange(iterations-1).astype(float128)) / (b + arange(iterations-1).astype(float128))
37 | return cumprod(out)
38 |
39 |
40 | def pochdivpochgen(a, b):
41 | 'generates 100 terms at a time of pochhammer(a)/pochhammer(b)'
42 | count = 0
43 | oldval = 0.0
44 | out = zeros(101, float64)
45 | out[0] = 1
46 | while True:
47 | out[1:] = (a + arange(count,count+100,dtype=float64)) / (b + arange(count,count+100,dtype=float64))
48 | out = cumprod(out)
49 | yield out[1:]
50 | out[0] = out[-1]
51 | count += 100
52 |
53 | def hyper3F2Z1(a1, a2, a3, b1, b2, tol=1e-15):
54 | '''the hypergeometric function 3(F^~)2(a,b,z) with z=1.
55 | The terms are grouped under the assumption that the arguments will be:
56 | {a, 1-b, a+c} and {1+a, a+c+d} w/ a,b,c,d >= 0, in which case the
57 | groupings result in terms all < 1 (after enough iterations)'''
58 |
59 | a1b1terms = pochdivpochgen(a1, b1)
60 | a3b2terms = pochdivpochgen(a3, b2)
61 | a2kterms = pochdivpochgen(a2, 1)
62 |
63 | terms = []
64 | while True:
65 | termprod = next(a1b1terms) * next(a3b2terms) * next(a2kterms)
66 | terms.append(termprod)
67 | if abs(termprod[-1]) < tol:
68 | break
69 |
70 | # sum in reverse, for better accuracy
71 | terms.reverse()
72 | # print 'L', len(terms)
73 | return 1.0+sum([sum(t[::-1]) for t in terms]), terms[0][-1]
74 |
75 |
76 | def hyp2f1mine(a, b, c):
77 | 'hyp2f1 from scipy gives nan if any of the arguments are too large'
78 | return exp(gammaln(c) + gammaln(c-a-b) - gammaln(c - a) - gammaln(c - b))
79 |
80 | def hyper3F2aZ1(a1, a2, a3, b2, tol=1e-10):
81 | '''same has hyper3F2Z1 but with b1 = a1+1'''
82 |
83 | if (a2 > -2):
84 | # force a2 no higher than -2
85 | # use identity for hypergeom F:
86 | # (ai - 1) * F = (ai - aj - 1) * F(ai -1) + aj * F(ai-1, aj+1)
87 | # in this case, i = 2, j = 1
88 | toladjust = tol / max(1, abs((a2 - a1 - 1) / (a2 - 1)))
89 | temp = ((a2 - a1 -1) * hyper3F2aZ1(a1, a2 - 1, a3, b2, tol=toladjust) + a1 * hyp2f1mine(a2 - 1, a3, b2)) / (a2 - 1)
90 | return temp
91 | if (a2 < -10):
92 | # force a2 no lower than -10
93 | # use identity for hypergeom F:
94 | # (ai - aj) * F = ai * F(ai + 1) - aj * F(aj + 1)
95 | # in this case, i = 1, j = 2
96 | # no adjustment for tolerance because a1 > 0, a2 < 0
97 |
98 | a2new = arange(a2, -9)
99 | A = [a1 * hyp2f1mine(a2n, a3, b2) for a2n in a2new]
100 | B = a2new
101 | C = (a1 - a2new)
102 | # compute last entry
103 | B[-1] = a2new[-1] * hyper3F2aZ1(a1, a2new[-1]+1, a3, b2)
104 | for idx in arange(len(B)-1, 0, -1):
105 | B[idx-1] *= (A[idx] - B[idx]) / C[idx]
106 |
107 | # temp = (a1 * hyp2f1mine(a2, a3, b2) - a2 * hyper3F2aZ1(a1, a2 + 1, a3, b2)) / (a1 - a2)
108 | return (A[0] - B[0]) / C[0]
109 | else:
110 | return hyper3F2Z1(a1, a2, a3, a1+1, b2, tol=tol)[0]
111 |
--------------------------------------------------------------------------------
/cpa/icons/__init__.py:
--------------------------------------------------------------------------------
1 | import wx
2 | import os.path
3 | import sys
4 |
5 | # Old code used to scan the icons directory and report everything into global variables on startup.
6 | # As of wx4 this is no longer valid, since the app has to launch first.
7 | # So now we'll call icons when needed and cache them in a dictionary.
8 | # We could convert to wx.Bitmap before storage, but there must be some reason the original
9 | # stored everything as wx.Image, right?
10 |
11 | icon_cache = {}
12 |
13 | def get_icon(name):
14 | if name in icon_cache:
15 | return icon_cache[name]
16 | else:
17 | dir = __path__[0]
18 | icon_cache[name] = wx.Image(os.path.join(dir, name + ".png"))
19 | return icon_cache[name]
20 |
21 | def get_cpa_icon(size=None):
22 | '''The CellProfiler Analyst icon as a wx.Icon'''
23 | icon = wx.Icon()
24 | if size == None and sys.platform.startswith('win'):
25 | icon.CopyFromBitmap(wx.Bitmap(get_icon("cpa_32")))
26 | else:
27 | icon.CopyFromBitmap(wx.Bitmap(get_icon("cpa_128")))
28 | return icon
29 |
--------------------------------------------------------------------------------
/cpa/icons/boxplot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/boxplot.png
--------------------------------------------------------------------------------
/cpa/icons/brightness.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/brightness.png
--------------------------------------------------------------------------------
/cpa/icons/classifier.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/classifier.png
--------------------------------------------------------------------------------
/cpa/icons/cpa.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/cpa.icns
--------------------------------------------------------------------------------
/cpa/icons/cpa.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/cpa.ico
--------------------------------------------------------------------------------
/cpa/icons/cpa_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/cpa_128.png
--------------------------------------------------------------------------------
/cpa/icons/cpa_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/cpa_32.png
--------------------------------------------------------------------------------
/cpa/icons/data_grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/data_grid.png
--------------------------------------------------------------------------------
/cpa/icons/density.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/density.png
--------------------------------------------------------------------------------
/cpa/icons/dimensionality.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/dimensionality.png
--------------------------------------------------------------------------------
/cpa/icons/filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/filter.png
--------------------------------------------------------------------------------
/cpa/icons/filter.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/filter.psd
--------------------------------------------------------------------------------
/cpa/icons/filter_16.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/filter_16.psd
--------------------------------------------------------------------------------
/cpa/icons/filter_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/filter_new.png
--------------------------------------------------------------------------------
/cpa/icons/gate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/gate.png
--------------------------------------------------------------------------------
/cpa/icons/gate.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/gate.psd
--------------------------------------------------------------------------------
/cpa/icons/gate_16.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/gate_16.psd
--------------------------------------------------------------------------------
/cpa/icons/gate_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/gate_new.png
--------------------------------------------------------------------------------
/cpa/icons/gate_tool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/gate_tool.png
--------------------------------------------------------------------------------
/cpa/icons/gate_tool.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/gate_tool.psd
--------------------------------------------------------------------------------
/cpa/icons/histogram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/histogram.png
--------------------------------------------------------------------------------
/cpa/icons/image_gallery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/image_gallery.png
--------------------------------------------------------------------------------
/cpa/icons/image_viewer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/image_viewer.png
--------------------------------------------------------------------------------
/cpa/icons/lasso.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/lasso.png
--------------------------------------------------------------------------------
/cpa/icons/lasso_tool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/lasso_tool.png
--------------------------------------------------------------------------------
/cpa/icons/normalize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/normalize.png
--------------------------------------------------------------------------------
/cpa/icons/pixelclassifier.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/pixelclassifier.png
--------------------------------------------------------------------------------
/cpa/icons/platemapbrowser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/platemapbrowser.png
--------------------------------------------------------------------------------
/cpa/icons/scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/scatter.png
--------------------------------------------------------------------------------
/cpa/icons/staticimage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/staticimage.png
--------------------------------------------------------------------------------
/cpa/icons/timelapse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/timelapse.png
--------------------------------------------------------------------------------
/cpa/icons/timelapse.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/timelapse.psd
--------------------------------------------------------------------------------
/cpa/icons/zoom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/icons/zoom.png
--------------------------------------------------------------------------------
/cpa/imagelist.py:
--------------------------------------------------------------------------------
1 |
2 | import logging
3 | import wx
4 | import numpy as np
5 | from .properties import Properties
6 | from .dbconnect import *
7 | from . import imagetools
8 |
9 | p = Properties()
10 | db = DBConnect()
11 |
12 | class ImageListCtrl(wx.ListCtrl):
13 | def __init__(self, parent, imkeys):
14 | wx.ListCtrl.__init__(self, parent, -1,
15 | style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
16 |
17 | self.set_key_list(imkeys)
18 |
19 | self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
20 |
21 | def set_key_list(self, imkeys):
22 | self.imkeys = imkeys
23 |
24 | if len(self.imkeys) > 0:
25 | columns_of_interest = well_key_columns(p.image_table)
26 | if len(columns_of_interest) > 0:
27 | columns_of_interest = ','+','.join(columns_of_interest)
28 | self.data = db.execute('SELECT %s%s FROM %s WHERE %s'%(
29 | UniqueImageClause(),
30 | columns_of_interest,
31 | p.image_table,
32 | GetWhereClauseForImages(imkeys)))
33 | self.cols = image_key_columns() + well_key_columns()
34 | else:
35 | self.data = np.array(self.imkeys)
36 | self.cols = image_key_columns()
37 | else:
38 | self.data = []
39 | self.cols = []
40 |
41 | self.data.sort()
42 |
43 | for i, col in enumerate(self.cols):
44 | self.InsertColumn(i, col)
45 | self.SetColumnWidth(i, 150)
46 | self.SetItemCount(len(imkeys))
47 |
48 | def OnItemActivated(self, event):
49 | imkey = self.imkeys[event.m_itemIndex]
50 | f = imagetools.ShowImage(tuple(imkey), p.image_channel_colors, self.GrandParent or self.Parent)
51 | f.Raise()
52 |
53 | def OnGetItemText(self, row, col):
54 | return str(self.data[row][col])
55 |
56 |
57 | class ImageListFrame(wx.Frame):
58 | def __init__(self, parent, imkeys, **kwargs):
59 | wx.Frame.__init__(self, parent, -1, **kwargs)
60 |
61 | sizer = wx.BoxSizer(wx.VERTICAL)
62 | self.imlist = ImageListCtrl(self, imkeys)
63 | sizer.Add(self.imlist, 1, wx.EXPAND)
64 |
65 | self.SetSizer(sizer)
66 | self.SetAutoLayout(True)
67 |
68 |
69 |
70 | if __name__ == "__main__":
71 | app = wx.App()
72 | logging.basicConfig(level=logging.DEBUG,)
73 |
74 | if not p.show_load_dialog():
75 | print('Props file required')
76 | sys.exit()
77 |
78 | ilf = ImageListFrame(None, db.execute('SELECT %s from %s'%(UniqueImageClause(), p.image_table)))
79 | ilf.Show()
80 |
81 | app.MainLoop()
82 |
--------------------------------------------------------------------------------
/cpa/imagepanel.py:
--------------------------------------------------------------------------------
1 | import wx
2 | from . import imagetools
3 | from .properties import Properties
4 |
5 | p = Properties()
6 |
7 | class ImagePanel(wx.Panel):
8 | '''
9 | ImagePanels are wxPanels that display a wxBitmap and store multiple
10 | image channels which can be recombined to mix different bitmaps.
11 | '''
12 | def __init__(self, images, channel_map, parent,
13 | scale=1.0, brightness=1.0, contrast=None, display_whole_image=False):
14 | """
15 | images -- list of numpy arrays
16 | channel_map -- list of strings naming the color to map each channel
17 | onto, e.g., ['red', 'green', 'blue']
18 | parent -- parent window to the wx.Panel
19 | scale -- factor to scale image by
20 | brightness -- factor to scale image pixel intensities by
21 |
22 | """
23 | self.chMap = channel_map
24 | self.toggleChMap = channel_map[:]
25 | self.images = images
26 |
27 | # Displayed bitmap
28 | self.bitmap = imagetools.MergeToBitmap(images,
29 | chMap = channel_map,
30 | scale = scale,
31 | brightness = brightness,
32 | contrast = contrast,
33 | display_whole_image = display_whole_image)
34 |
35 | max_size = 1000
36 | sizex = min(max_size, self.bitmap.Size[0])
37 | sizey = min(max_size, self.bitmap.Size[1])
38 | wx.Panel.__init__(self, parent, wx.NewId(), size=(sizex, sizey))
39 |
40 | self.scale = scale
41 | self.brightness = brightness
42 | self.contrast = contrast
43 | self.selected = False
44 | self.display_whole_image = display_whole_image
45 |
46 | self.Bind(wx.EVT_PAINT, self.OnPaint)
47 |
48 | def OnPaint(self, evt):
49 | self.SetClientSize((self.bitmap.Width, self.bitmap.Height))
50 | dc = wx.PaintDC(self)
51 | dc.Clear()
52 | dc.DrawBitmap(self.bitmap, 0, 0)
53 | # Outline the whole image
54 | if self.selected:
55 | dc.SetPen(wx.Pen("WHITE",1))
56 | dc.SetBrush(wx.Brush("WHITE", style=wx.TRANSPARENT))
57 | dc.DrawRectangle(0,0,self.bitmap.Width,self.bitmap.Height)
58 | return dc
59 |
60 | def UpdateBitmap(self):
61 | self.bitmap = imagetools.MergeToBitmap(self.images,
62 | chMap = self.chMap,
63 | brightness = self.brightness,
64 | scale = self.scale,
65 | contrast = self.contrast,
66 | display_whole_image = self.display_whole_image)
67 | self.Refresh()
68 | self.Update()
69 |
70 |
71 | def MapChannels(self, chMap):
72 | ''' Recalculates the displayed bitmap for a new channel-color map. '''
73 | self.chMap = chMap
74 | self.UpdateBitmap()
75 |
76 | def SetScale(self, scale):
77 | if scale != self.scale:
78 | self.scale = scale
79 | self.UpdateBitmap()
80 | self.SetClientSize((self.bitmap.Width, self.bitmap.Height))
81 |
82 | def SetBrightness(self, brightness):
83 | if brightness != self.brightness:
84 | self.brightness = brightness
85 | self.UpdateBitmap()
86 |
87 | def SetContrastMode(self, mode):
88 | self.contrast = mode
89 | self.UpdateBitmap()
90 |
91 |
92 |
--------------------------------------------------------------------------------
/cpa/imagetilesizer.py:
--------------------------------------------------------------------------------
1 | '''
2 | Special sizer for organizing image tiles.
3 | '''
4 |
5 | import wx
6 | import math
7 |
8 | class ImageTileSizer(wx.Sizer):
9 | def __init__(self):
10 | wx.Sizer.__init__(self)
11 |
12 | def pitch(self):
13 | # get sizes of all tiles
14 | children = self.GetChildren()
15 | if len(children) == 0:
16 | return None
17 | else:
18 | maxi_w = 0
19 | maxi_h = 0
20 | for child in children:
21 | size = child.GetSize()
22 | add = 2 * child.GetBorder()
23 | maxi_w = max(maxi_w, size.GetWidth() + add)
24 | maxi_h = max(maxi_h, size.GetHeight() + add)
25 | return wx.Size(maxi_w, maxi_h)
26 |
27 | def CalcMin(self):
28 | n = len(self.GetChildren())
29 | if n > 0:
30 | width = self.GetContainingWindow().GetClientSize().GetWidth()
31 | self.columns = max(1, width // self.pitch().x)
32 | self.rows = math.ceil(1.0 * n / self.columns)
33 | pitch = self.pitch()
34 | return wx.Size(self.columns * pitch.x, self.rows * pitch.y)
35 | else:
36 | return wx.Size(0,0)
37 |
38 | def RecalcSizes(self):
39 | self.CalcMin()
40 | origin = self.GetPosition()
41 | pitch = self.pitch()
42 | for k, item in enumerate(self.GetChildren()):
43 | i = k // self.columns
44 | j = k % self.columns
45 | pos = origin + wx.Point(j * pitch.x, i * pitch.y)
46 | item = self.GetChildren()[i * self.columns + j]
47 | border = item.GetBorder()
48 | item.SetDimension(pos+wx.Point(border, border), item.GetSize())
49 |
--------------------------------------------------------------------------------
/cpa/mysql_plugins/classifier_narrow.c:
--------------------------------------------------------------------------------
1 | /*
2 | * classifier_narrow.c
3 | *
4 | * Compile with:
5 | * gcc -Wall -fPIC -c `mysql_config --cflags` classifier_narrow.c
6 | * gcc -o classifier_narrow.so -shared classifier_narrow.o
7 | *
8 | * To add this function to mysql, compile it to classifier_narrow.so,
9 | * put it in a directory on the LD_LIBRARY_PATH for mysql, and execute
10 | * this statement within mysql:
11 | *
12 | * CREATE FUNCTION classifier_narrow RETURNS INTEGER SONAME 'classifier_narrow.so';
13 | *
14 | */
15 |
16 | #include
17 | #include
18 | #include
19 |
20 | #if defined(WIN32) || defined(MS_WINDOWS) || defined(WINDOWS)
21 | #else
22 | //typedef unsigned long long ulonglong;
23 | //typedef long long longlong;
24 | #endif /*__WIN__*/
25 |
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include // To get strmov()
32 |
33 | my_bool classifier_narrow_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
34 | {
35 | int num_stumps, num_classes, i;
36 |
37 | // Classifier function can't return null.
38 | initid->maybe_null = 0;
39 |
40 | if ((args->arg_count < 4) || (args->args[0] == NULL) || (args->arg_type[0] != INT_RESULT)) {
41 | strcpy(message, "Requires at least 6 arguments, the first of which is a constant integer.");
42 | return 1; // fail
43 | }
44 |
45 | num_stumps = *((longlong*) args->args[0]);
46 | if (num_stumps <= 0) {
47 | strcpy(message, "First argument must be positive.");
48 | return 1; // fail
49 | }
50 |
51 | num_classes = ((args->arg_count - 3) / num_stumps) - 2;
52 |
53 | if ((args->arg_count - 3) != (num_stumps * (num_classes + 2))) {
54 | strcpy(message, "Mismatch in argument number");
55 | return 1; // fail
56 | }
57 |
58 | int *stumps = (int *)malloc(sizeof(int) * (num_stumps + 1));
59 | stumps[0] = num_stumps;
60 | initid->ptr = (char *)stumps;
61 | if (!(initid->ptr)) {
62 | strcpy(message,"Couldn't allocate memory");
63 | return 1; // fail
64 | }
65 |
66 | // set the argument types we want
67 | for (i = 1; i < args->arg_count; i++)
68 | args->arg_type[i] = REAL_RESULT;
69 |
70 | return 0; // success
71 | }
72 |
73 | void classifier_narrow_deinit(UDF_INIT *initid)
74 | {
75 | if (initid->ptr)
76 | free(initid->ptr);
77 | }
78 |
79 | void classifier_narrow_clear(UDF_INIT *initid, char *is_null, char *error)
80 | {
81 | int *stumps = (int *)(initid->ptr);
82 | int num_stumps = stumps[0];
83 | memset(stumps + 1, 0, num_stumps * sizeof(int));
84 | }
85 |
86 | #define get_arg(idx) ((args->args[idx] == NULL) ? 0.0 : *((double *) args->args[idx]))
87 |
88 | void classifier_narrow_add(UDF_INIT *initid, UDF_ARGS *args,
89 | char *is_null, char *error)
90 | {
91 | int num_stumps = *((longlong *)args->args[0]);
92 | int feature_id = *((longlong *)args->args[args->arg_count - 2]);
93 | double feature_value = get_arg(args->arg_count - 1);
94 | double threshold;
95 | int *stumps = (int *)(initid->ptr);
96 | int stump, i;
97 |
98 | /* Which feature is this row for? */
99 | for (stump = 0; stump < num_stumps; stump++) {
100 | i = *((longlong *)args->args[stump + 1]);
101 | if (i == feature_id)
102 | break;
103 | }
104 | if (stump == num_stumps)
105 | return; /* This row is for a feature the classifier does not use. */
106 |
107 | threshold = get_arg(1 + num_stumps + stump);
108 | stumps[stump + 1] = feature_value > threshold;
109 | }
110 |
111 | /* Used by older version of MySQL. */
112 | void classifier_narrow_reset(UDF_INIT *initid, UDF_ARGS *args,
113 | char *is_null, char *error)
114 | {
115 | classifier_narrow_clear(initid, is_null, error);
116 | classifier_narrow_add(initid, args, is_null, error);
117 | }
118 |
119 | longlong classifier_narrow(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
120 | char *error)
121 | {
122 | longlong class;
123 | double best_score;
124 | int num_stumps = *((longlong*) args->args[0]);
125 | int num_classes = ((args->arg_count - 1) / num_stumps) - 2;
126 | int *stumps = (int *) (initid->ptr);
127 | int offset, i, k;
128 |
129 | // weights start at this offset.
130 | offset = 1 + 2 * num_stumps;
131 | for (k = 0; k < num_classes; k++) {
132 | double temp_score = 0.0;
133 | for (i = 0; i < num_stumps; i++) {
134 | temp_score += get_arg(offset + i) * stumps[i + 1];
135 | }
136 | if ((k == 0) || (temp_score > best_score)) {
137 | best_score = temp_score;
138 | class = k;
139 | }
140 | offset += num_stumps;
141 | }
142 |
143 | return class;
144 | }
145 |
--------------------------------------------------------------------------------
/cpa/mysql_plugins/classify.c:
--------------------------------------------------------------------------------
1 |
2 | /* classify.c - */
3 |
4 | // To add this function to mysql, compile it to classify.so, put it in a
5 | // directory on the LD_LIBRARY_PATH for mysql, and execute this statement
6 | // within mysql:
7 | // mysql> CREATE FUNCTION classifier RETURNS INTEGER SONAME 'classify.so';
8 |
9 |
10 |
11 | #include
12 | #include
13 |
14 | #if defined(WIN32) || defined(MS_WINDOWS) || defined(WINDOWS)
15 | #else
16 | typedef unsigned long long ulonglong;
17 | typedef long long longlong;
18 | #endif /*__WIN__*/
19 |
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include // To get strmov()
26 |
27 | my_bool classifier_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
28 | {
29 | int num_stumps, num_classes, i;
30 |
31 | // Classifier function can't return null.
32 | initid->maybe_null = 0;
33 |
34 | if ((args->arg_count < 4) || (args->args[0] == NULL) || (args->arg_type[0] != INT_RESULT)) {
35 | strcpy(message, "Requires at least 4 arguments, the first of which is a constant integer.");
36 | return 1; // fail
37 | }
38 |
39 | num_stumps = *((longlong*) args->args[0]);
40 | if (num_stumps <= 0) {
41 | strcpy(message, "First argument must be positive.");
42 | return 1; // fail
43 | }
44 |
45 | num_classes = ((args->arg_count - 1) / num_stumps) - 2;
46 |
47 | if ((args->arg_count - 1) != (num_stumps * (num_classes + 2))) {
48 | strcpy(message, "Mismatch in argument number");
49 | return 1; // fail
50 | }
51 |
52 | initid->ptr = (char *) malloc(sizeof (int) * num_stumps);
53 | if (!(initid->ptr)) {
54 | strcpy(message,"Couldn't allocate memory");
55 | return 1; // fail
56 | }
57 |
58 | // set the argument types we want
59 | for (i = 1; i < args->arg_count; i++)
60 | args->arg_type[i] = REAL_RESULT;
61 |
62 | return 0; // success
63 | }
64 |
65 | void classifier_deinit(UDF_INIT *initid)
66 | {
67 | if (initid->ptr)
68 | free(initid->ptr);
69 | }
70 |
71 | longlong classifier(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
72 | char *error)
73 | {
74 | longlong class;
75 | double best_score;
76 | int num_stumps = *((longlong*) args->args[0]);
77 | int num_classes = ((args->arg_count - 1) / num_stumps) - 2;
78 | int *stumps = (int *) (initid->ptr);
79 | int offset, i, k;
80 |
81 | #define get_arg(idx) ((args->args[idx] == NULL) ? 0.0 : *((double *) args->args[idx]))
82 |
83 | // evaluate stumps
84 | for (i = 0; i < num_stumps; i++) {
85 | stumps[i] = get_arg(i + 1) > get_arg(i + 1 + num_stumps);
86 | }
87 |
88 | // weights start at this offset.
89 | offset = 1 + 2 * num_stumps;
90 | for (k = 0; k < num_classes; k++) {
91 | double temp_score = 0.0;
92 | for (i = 0; i < num_stumps; i++) {
93 | temp_score += get_arg(offset + i) * stumps[i];
94 | }
95 | if ((k == 0) || (temp_score > best_score)) {
96 | best_score = temp_score;
97 | class = k;
98 | }
99 | offset += num_stumps;
100 | }
101 |
102 | return class;
103 | }
104 |
--------------------------------------------------------------------------------
/cpa/normalize.py:
--------------------------------------------------------------------------------
1 | from scipy.ndimage import median_filter, uniform_filter
2 | import numpy as np
3 | import logging
4 |
5 |
6 | G_EXPERIMENT = "Experiment"
7 | G_PLATE = "Plate"
8 | G_QUADRANT = "Plate Quadrant"
9 | G_WELL_NEIGHBORS = "Well Neighbors"
10 | G_CONSTANT = "Constant"
11 |
12 | M_MEDIAN = "Median"
13 | M_MEAN = "Mean"
14 | M_MODE = "Mode"
15 | M_NEGCTRL = "Negative Control" # DMSO Standardization
16 | M_ZSCORE = "Z score"
17 |
18 | W_SQUARE = "Square"
19 | W_MEANDER = "Linear (meander)"
20 |
21 | # Parameter names for do_normalization_step
22 | P_GROUPING = 'grouping'
23 | P_AGG_TYPE = 'aggregate_type'
24 | P_WIN_SIZE = 'win_size'
25 | P_WIN_TYPE = 'win_type'
26 | P_CONSTANT = 'constant'
27 |
28 | def do_normalization_step(input_data, grouping, aggregate_type, win_size, win_type, constant):
29 | '''Apply a single normalization step
30 | input_data -- a numpy array of raw data to normalize. This array MUST be in the same
31 | shape as your plate data if you are applying a spatially dependent
32 | grouping.
33 | returns a 2-tuple containing an array of normalized values and an array of
34 | the normalization factors
35 | '''
36 | #assert input_data.ndim==2 or grouping in (G_CONSTANT, G_EXPERIMENT)
37 |
38 | if grouping == G_EXPERIMENT:
39 | output_data = do_normalization(input_data, aggregate_type)
40 |
41 | elif grouping == G_PLATE:
42 | output_data = do_normalization(input_data, aggregate_type)
43 |
44 | elif grouping == G_QUADRANT:
45 | all_quadrants = [
46 | # upper left
47 | (np.arange(input_data.shape[0]) % 2 == 0, np.arange(input_data.shape[1]) % 2 == 0),
48 | # upper right
49 | (np.arange(input_data.shape[0]) % 2 == 0, np.arange(input_data.shape[1]) % 2 != 0),
50 | # lower left
51 | (np.arange(input_data.shape[0]) % 2 != 0, np.arange(input_data.shape[1]) % 2 == 0),
52 | # lower right
53 | (np.arange(input_data.shape[0]) % 2 != 0, np.arange(input_data.shape[1]) % 2 != 0) ]
54 | output_data = input_data.copy()
55 | for quad in all_quadrants:
56 | ixgrid = np.ix_(quad[0],quad[1])
57 | output_data[ixgrid] = do_normalization(input_data[ixgrid], aggregate_type)
58 |
59 | elif grouping == G_WELL_NEIGHBORS:
60 | if win_type == W_SQUARE:
61 | output_data = square_filter_normalization(input_data, aggregate_type, win_size)
62 | elif win_type == W_MEANDER:
63 | output_data = linear_filter_normalization(input_data, aggregate_type, win_size)
64 |
65 | elif grouping == G_CONSTANT:
66 | output_data = do_normalization(input_data, constant)
67 | else:
68 | raise ValueError('Programming Error: Unknown normalization type supplied.')
69 |
70 | return output_data
71 |
72 | def square_filter_normalization(data, aggregate_type, win_size):
73 | '''
74 | '''
75 | # Filter locally, for staining variation
76 | if aggregate_type == M_MEDIAN:
77 | normalization_values = median_filter(data, (win_size, win_size))
78 | elif aggregate_type == M_MEAN:
79 | normalization_values = uniform_filter(data, (win_size, win_size))
80 | else:
81 | raise ValueError('Programming Error: Unknown window type supplied.')
82 |
83 | try:
84 | res = data / normalization_values
85 | except:
86 | logging.error("Division by zero, replace value with 0")
87 | res = 0
88 |
89 |
90 | def linear_filter_normalization(data, aggregate_type, win_size):
91 | '''
92 | '''
93 | # Filter linearly (assumes FormatPlateData reordered plate-data to account for meandering)
94 | if aggregate_type == M_MEDIAN:
95 | normalization_values = median_filter(data.flatten(), win_size).reshape(data.shape)
96 | elif aggregate_type == M_MEAN:
97 | normalization_values = uniform_filter(data.flatten(), win_size).reshape(data.shape)
98 | else:
99 | raise ValueError('Programming Error: Unknown window type supplied.')
100 |
101 | try:
102 | res = data / normalization_values
103 | except:
104 | logging.error("Division by zero, replace value with 0")
105 | res = 0
106 |
107 | return res
108 |
109 | def do_normalization(data, aggregate_type_or_const):
110 | '''
111 | data -- meat and potatoes
112 | aggregate_type_or_const -- specify an aggregation type or a numeric constant
113 | to divide by
114 | '''
115 | if aggregate_type_or_const == M_NEGCTRL:
116 | normalization_value = 1 # Keep data the same
117 | elif aggregate_type_or_const == M_MEDIAN:
118 | normalization_value = np.median(data.flatten())
119 | elif aggregate_type_or_const == M_MEAN:
120 | normalization_value = np.mean(data.flatten())
121 | elif aggregate_type_or_const == M_MODE:
122 | import scipy.ndimage
123 | # Use histogram function with values a bit removed from saturation
124 | robust_min = 0.02 * (np.max(data) - np.min(data)) + np.min(data)
125 | robust_max = 0.98 * (np.max(data) - np.min(data)) + np.min(data)
126 | nbins = 256
127 | h = scipy.ndimage.histogram(data.flatten(), robust_min, robust_max, nbins)
128 | index = np.argmax(h)
129 | normalization_value = np.min(data) + float(index)/float(nbins-1)*(np.max(data) - np.min(data))
130 | elif type(aggregate_type_or_const) in (float, int):
131 | normalization_value = aggregate_type_or_const
132 |
133 | try:
134 | res = data / normalization_value
135 | except:
136 | logging.error("Division by zero, replace value with 0!")
137 | res = 0
138 |
139 | return res
140 |
--------------------------------------------------------------------------------
/cpa/pilfix.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import PIL.Image
3 |
4 | try:
5 | import PIL.Hdf5StubImagePlugin
6 | except:
7 | logging.info("No HDF5StubImagePlugin")
8 | try:
9 | import PIL.FitsStubImagePlugin
10 | except:
11 | logging.info("No PIL.FitsStubImagePlugin")
12 | try:
13 | import PIL.SunImagePlugin
14 | except:
15 | logging.info("No PIL.SunImagePlugin")
16 | try:
17 | import PIL.GbrImagePlugin
18 | except:
19 | logging.info("No PIL.GbrImagePlugin")
20 | try:
21 | import PIL.PngImagePlugin
22 | except:
23 | logging.info("No PIL.PngImagePlugin")
24 | try:
25 | import PIL.MicImagePlugin
26 | except:
27 | logging.info("No PIL.MicImagePlugin")
28 | try:
29 | import PIL.FpxImagePlugin
30 | except:
31 | logging.info("No PIL.FpxImagePlugin")
32 | try:
33 | import PIL.PcxImagePlugin
34 | except:
35 | logging.info("No PIL.PcxImagePlugin")
36 | try:
37 | import PIL.ImImagePlugin
38 | except:
39 | logging.info("No PIL.ImImagePlugin")
40 | try:
41 | import PIL.SpiderImagePlugin
42 | except:
43 | logging.info("No PIL.SpiderImagePlugin")
44 | try:
45 | import PIL.PsdImagePlugin
46 | except:
47 | logging.info("No PIL.PsdImagePlugin")
48 | try:
49 | import PIL.BufrStubImagePlugin
50 | except:
51 | logging.info("No PIL.BufrStubImagePlugin")
52 | try:
53 | import PIL.SgiImagePlugin
54 | except:
55 | logging.info("No PIL.SgiImagePlugin")
56 | try:
57 | import PIL.McIdasImagePlugin
58 | except:
59 | logging.info("No PIL.McIdasImagePlugin")
60 | try:
61 | import PIL.XpmImagePlugin
62 | except:
63 | logging.info("No PIL.XpmImagePlugin")
64 | try:
65 | import PIL.BmpImagePlugin
66 | except:
67 | logging.info("No PIL.BmpImagePlugin")
68 | try:
69 | import PIL.TgaImagePlugin
70 | except:
71 | logging.info("No PIL.TgaImagePlugin")
72 | try:
73 | import PIL.PalmImagePlugin
74 | except:
75 | logging.info("No PIL.PalmImagePlugin")
76 | try:
77 | import PIL.XVThumbImagePlugin
78 | except:
79 | logging.info("No PIL.XVThumbImagePlugin")
80 | try:
81 | import PIL.GribStubImagePlugin
82 | except:
83 | logging.info("No PIL.GribStubImagePlugin")
84 | try:
85 | import PIL.ArgImagePlugin
86 | except:
87 | logging.info("No PIL.ArgImagePlugin")
88 | try:
89 | import PIL.PdfImagePlugin
90 | except:
91 | logging.info("No PIL.PdfImagePlugin")
92 | try:
93 | import PIL.ImtImagePlugin
94 | except:
95 | logging.info("No PIL.ImtImagePlugin")
96 | try:
97 | import PIL.GifImagePlugin
98 | except:
99 | logging.info("No PIL.GifImagePlugin")
100 | try:
101 | import PIL.CurImagePlugin
102 | except:
103 | logging.info("No PIL.CurImagePlugin")
104 | try:
105 | import PIL.WmfImagePlugin
106 | except:
107 | logging.info("No PIL.WmfImagePlugin")
108 | try:
109 | import PIL.MpegImagePlugin
110 | except:
111 | logging.info("No PIL.MpegImagePlugin")
112 | try:
113 | import PIL.IcoImagePlugin
114 | except:
115 | logging.info("No PIL.IcoImagePlugin")
116 | try:
117 | import PIL.TiffImagePlugin
118 | except:
119 | logging.info("No PIL.TiffImagePlugin")
120 | try:
121 | import PIL.PpmImagePlugin
122 | except:
123 | logging.info("No PIL.PpmImagePlugin")
124 | try:
125 | import PIL.MspImagePlugin
126 | except:
127 | logging.info("No PIL.MspImagePlugin")
128 | try:
129 | import PIL.EpsImagePlugin
130 | except:
131 | logging.info("No PIL.EpsImagePlugin")
132 | try:
133 | import PIL.JpegImagePlugin
134 | except:
135 | logging.info("No PIL.JpegImagePlugin")
136 | try:
137 | import PIL.PixarImagePlugin
138 | except:
139 | logging.info("No PIL.PixarImagePlugin")
140 | try:
141 | import PIL.PcdImagePlugin
142 | except:
143 | logging.info("No PIL.PcdImagePlugin")
144 | try:
145 | import PIL.IptcImagePlugin
146 | except:
147 | logging.info("No PIL.IptcImagePlugin")
148 | try:
149 | import PIL.XbmImagePlugin
150 | except:
151 | logging.info("No PIL.XbmImagePlugin")
152 | try:
153 | import PIL.DcxImagePlugin
154 | except:
155 | logging.info("No PIL.DcxImagePlugin")
156 | try:
157 | import PIL.IcnsImagePlugin
158 | except:
159 | logging.info("No PIL.IcnsImagePlugin")
160 | try:
161 | import PIL.FliImagePlugin
162 | except:
163 | logging.info("No PIL.FliImagePlugin")
164 |
--------------------------------------------------------------------------------
/cpa/querymaker.py:
--------------------------------------------------------------------------------
1 |
2 | import logging
3 | import wx
4 | import sys
5 | from .properties import Properties
6 | from . import tableviewer
7 | from . import dbconnect
8 | import numpy as np
9 |
10 | # TODO: Wrap queries in "SELECT * FROM () LIMIT 1000, offset"
11 | # and write a TableData subclass to feed rows to the TableViewer.
12 | class QueryMaker(wx.Frame):
13 | '''Super-simple interface for making queries directly to the database and
14 | displaying results using TableViewer. Results are pulled straight into
15 | memory, so this shouldn't be used to fetch large result sets.
16 | '''
17 | def __init__(self, parent, size=(400,250), **kwargs):
18 | wx.Frame.__init__(self, parent, -1, size=size, title='Query Maker', **kwargs)
19 | panel = wx.Panel(self)
20 | self.query_textctrl = wx.TextCtrl(panel, -1, size=(-1,-1), style=wx.TE_MULTILINE)
21 | self.execute_btn = wx.Button(panel, -1, 'execute')
22 |
23 | sizer = wx.BoxSizer(wx.VERTICAL)
24 | panel.SetSizer(sizer)
25 | sizer.Add(self.query_textctrl, 1, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 10)
26 | button_sizer = wx.BoxSizer(wx.HORIZONTAL)
27 | sizer.Add(button_sizer, 0, wx.EXPAND)
28 |
29 | button_sizer.AddStretchSpacer()
30 | button_sizer.Add(self.execute_btn, 0, wx.ALL, 10)
31 |
32 | self.query_textctrl.Bind(wx.EVT_KEY_UP, self. on_enter)
33 | self.execute_btn.Bind(wx.EVT_BUTTON, self.on_execute)
34 |
35 | def on_enter(self, evt):
36 | '''Execute query on Cmd+Enter'''
37 | if evt.CmdDown() and evt.GetKeyCode() == wx.WXK_RETURN:
38 | self.on_execute()
39 | evt.Skip()
40 |
41 | def on_execute(self, evt=None):
42 | '''Run the query and show the results in a TableViewer'''
43 | db = dbconnect.DBConnect()
44 | q = self.query_textctrl.Value
45 | try:
46 | res = db.execute(q)
47 | if res is None or len(res) == 0:
48 | logging.info('Query successful. No Data to return.')
49 | return
50 | res = np.array(db.execute(q))
51 | colnames = db.GetResultColumnNames()
52 | grid = tableviewer.TableViewer(self, title='query results')
53 | grid.table_from_array(res, colnames)
54 | grid.Show()
55 | logging.info('Query successful')
56 | except Exception as e:
57 | logging.error('Query failed:')
58 | logging.error(e)
59 |
60 |
61 | if __name__ == "__main__":
62 | app = wx.App()
63 | logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
64 |
65 | p = Properties()
66 | # Load a properties file if passed in args
67 | if len(sys.argv) > 1:
68 | propsFile = sys.argv[1]
69 | p.LoadFile(propsFile)
70 | else:
71 | if not p.show_load_dialog():
72 | print('Query Maker requires a properties file. Exiting.')
73 | # necessary in case other modal dialogs are up
74 | wx.GetApp().Exit()
75 | sys.exit()
76 |
77 | QueryMaker(None).Show()
78 |
79 | app.MainLoop()
80 |
81 |
--------------------------------------------------------------------------------
/cpa/scoredialog.py:
--------------------------------------------------------------------------------
1 |
2 | import wx
3 |
4 | class ScoreDialog(wx.Dialog):
5 | """
6 | A dialog that prompts the user for group and filter, and whether or not
7 | to calculate/report enrichment values.
8 | """
9 | def __init__(self, parent, groups, filters, enrichments=True):
10 | """Groups and filters are lists. Each item in the list is
11 | either a (key, value) pair or a non-tuple value (e.g., a
12 | string). In the latter case, str(value) is used as the key."""
13 | wx.Dialog.__init__(self, parent, -1, "Score all cells")
14 |
15 | def key_value(item):
16 | if isinstance(item, tuple):
17 | return item
18 | else:
19 | return (item, str(item))
20 |
21 | self.groups = list(map(key_value, groups))
22 | self.filters = list(map(key_value, filters))
23 |
24 | self.groups_lb = wx.ListBox(self, choices=[v for k,v in self.groups])
25 | self.groups_lb.SetSelection(0)
26 | self.filters_lb = wx.ListBox(self, choices=[v for k,v in self.filters])
27 | self.filters_lb.SetSelection(0)
28 | self._wants_enrichments = wx.CheckBox(self, -1, 'Report enrichments?')
29 | self._wants_enrichments.SetValue(enrichments)
30 |
31 | vbox = wx.BoxSizer(wx.VERTICAL)
32 | vbox.Add(wx.StaticText(self, -1, 'Grouping method:'), 0)
33 | vbox.Add(self.groups_lb, 1, wx.EXPAND)
34 | vbox.Add(wx.StaticText(self, -1, 'Filter:'), 0, wx.TOP, 5)
35 | vbox.Add(self.filters_lb, 1, wx.EXPAND)
36 | vbox.Add(self._wants_enrichments)
37 | vbox.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0,
38 | wx.TOP | wx.ALIGN_CENTER, 5)
39 | hbox = wx.BoxSizer(wx.HORIZONTAL)
40 | hbox.Add(vbox, 1, wx.EXPAND | wx.ALL, 10)
41 | self.SetSizer(hbox)
42 | self.Centre()
43 |
44 | @property
45 | def group(self):
46 | """Return the key of the selected group."""
47 | return self.groups[self.groups_lb.GetSelections()[0]][0]
48 |
49 | @property
50 | def filter(self):
51 | """Return the key of the selected filter."""
52 | return self.filters[self.filters_lb.GetSelections()[0]][0]
53 |
54 | @property
55 | def wants_enrichments(self):
56 | """Return whether the user checked the "Report enrichments?" box."""
57 | return self._wants_enrichments.Value
58 |
59 |
60 | if __name__ == "__main__":
61 | app = wx.App()
62 | d = ScoreDialog(None, [str(a) for a in range(15)],
63 | [(None, 'None'), 'Untreated', 'HRG'])
64 | if d.ShowModal() == wx.ID_OK:
65 | print('a')
66 | print(("Group:", repr(d.group)))
67 | print(("Filter:", repr(d.filter)))
68 | print(((d.wants_enrichments and 'Wants' or 'Does not want') + ' enrichments'))
69 | d.Destroy()
70 |
--------------------------------------------------------------------------------
/cpa/shell.py:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | '''
3 | Load a properties file, then start a shell with certain local
4 | variables exposed.
5 | '''
6 |
7 |
8 | import code
9 | import sys
10 | from optparse import OptionParser
11 | import cpa
12 | import cpa.properties
13 | import cpa.dbconnect
14 |
15 | parser = OptionParser("usage: %prog [options] [PROPERTIES-FILE [COMMAND]]")
16 | options, args = parser.parse_args()
17 |
18 | if len(args) > 0:
19 | cpa.properties.LoadFile(sys.argv[1])
20 |
21 | variables = {'cpa': cpa}
22 |
23 | if len(args) == 2:
24 | interpreter = code.InteractiveInterpreter(locals=variables)
25 | interpreter.runsource(sys.argv[2])
26 | else:
27 | code.interact(local=variables)
28 |
--------------------------------------------------------------------------------
/cpa/singleton.py:
--------------------------------------------------------------------------------
1 | '''
2 | This Singleton metaclass ensures that only one instance of a
3 | class can be created. Subsequent calls to make that class will
4 | return the original instance. In Python 3, specify metaclass=Singleton
5 | to use this functionality.
6 |
7 | If you absolutely must re-create a singleton, use the forget() method
8 | to delete the original instance. A new instance will then be created
9 | on the next class call.
10 |
11 | This version was put together to replace a more complex Python 2 singleton
12 | class that no longer works in Python 3. Good luck!
13 | '''
14 |
15 | class Singleton(type):
16 | _instances = {}
17 | def __call__(cls, *args, **kwargs):
18 | if cls not in cls._instances:
19 | cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
20 | return cls._instances[cls]
21 |
22 | def forget(cls):
23 | if cls in cls._instances:
24 | del cls._instances[cls]
25 |
26 |
--------------------------------------------------------------------------------
/cpa/tests/32-bit-grayscale.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/tests/32-bit-grayscale.tif
--------------------------------------------------------------------------------
/cpa/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/cpa/tests/__init__.py
--------------------------------------------------------------------------------
/cpa/tests/test.py:
--------------------------------------------------------------------------------
1 | import wx
2 | from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg, NavigationToolbar2WxAgg
3 | from matplotlib.backends.backend_wx import _load_bitmap
4 | import matplotlib as mpl
5 |
6 |
7 | app = wx.App()
8 | f = wx.Frame(None)
9 | fig = mpl.figure.Figure()
10 | p = FigureCanvasWxAgg(f, -1, fig)
11 |
12 | toolbar = NavigationToolbar2WxAgg(p)
13 | toolbar.Hide()
14 |
15 | #toolbar constants
16 | TBFLAGS = (wx.TB_HORIZONTAL|wx.TB_TEXT)
17 | tsize = (24,24)
18 | tb = f.CreateToolBar(TBFLAGS)
19 |
20 | _NTB2_HOME = wx.NewId()
21 | _NTB2_BACK = wx.NewId()
22 | _NTB2_FORWARD = wx.NewId()
23 | _NTB2_PAN = wx.NewId()
24 | _NTB2_ZOOM = wx.NewId()
25 | _NTB2_SAVE = wx.NewId()
26 | _NTB2_SUBPLOT = wx.NewId()
27 |
28 | tb.AddSimpleTool(_NTB2_HOME, _load_bitmap('home.png'), 'Home', 'Reset original view')
29 | tb.AddSimpleTool(_NTB2_BACK, _load_bitmap('back.png'), 'Back', 'Back navigation view')
30 | tb.AddSimpleTool(_NTB2_FORWARD, _load_bitmap('forward.png'), 'Forward', 'Forward navigation view')
31 |
32 | tb.AddCheckTool(_NTB2_PAN, "", _load_bitmap('move.png'), shortHelp='Pan')
33 | tb.AddCheckTool(_NTB2_ZOOM, "", _load_bitmap('zoom_to_rect.png'), shortHelp='Zoom')
34 |
35 | tb.AddSeparator()
36 | tb.AddSimpleTool(_NTB2_SUBPLOT, _load_bitmap('subplots.png'), 'Configure subplots', 'Configure subplot parameters')
37 | tb.AddSimpleTool(_NTB2_SAVE, _load_bitmap('filesave.png'), 'Save', 'Save plot contents to file')
38 |
39 | f.Bind(wx.EVT_TOOL, toolbar.home, id=_NTB2_HOME)
40 | f.Bind(wx.EVT_TOOL, toolbar.forward, id=_NTB2_FORWARD)
41 | f.Bind(wx.EVT_TOOL, toolbar.back, id=_NTB2_BACK)
42 | f.Bind(wx.EVT_TOOL, toolbar.zoom, id=_NTB2_ZOOM)
43 | f.Bind(wx.EVT_TOOL, toolbar.pan, id=_NTB2_PAN)
44 | f.Bind(wx.EVT_TOOL, toolbar.configure_subplots, id=_NTB2_SUBPLOT)
45 | f.Bind(wx.EVT_TOOL, toolbar.save_figure, id=_NTB2_SAVE)
46 |
47 | tb.Realize()
48 | f.Show()
49 | f.Close()
50 | app.MainLoop()
--------------------------------------------------------------------------------
/cpa/tests/test2.py:
--------------------------------------------------------------------------------
1 |
2 | # Fancy-pants method for getting a where clause that groups adjacent image keys
3 | # using "BETWEEN X AND Y" ... unfortunately this usually takes far more
4 | # characters than using "ImageNumber IN (X,Y,Z...)" since we don't run into
5 | # queries asking for consecutive image numbers very often (except when we do it
6 | # deliberately). It is also slower than the "IN" method unless the ImageNumbers
7 | # come in a smaller list of consecutive groups.
8 | #
9 | # ...still, this may be very useful since it is notably faster when ImageNumbers
10 | # are consecutive.
11 |
12 | def get_where_clause_for_images(keys, is_sorted=False):
13 | '''
14 | takes a list of keys and returns a (hopefully) short where clause that
15 | includes those keys.
16 | '''
17 | def in_sequence(k1,k2):
18 | if len(k1)>1:
19 | if k1[:-1] != k2[:-1]:
20 | return False
21 | return k1[-1]==(k2[-1]-1)
22 |
23 | def optimize_for_query(keys, is_sorted=False):
24 | if not is_sorted:
25 | keys.sort()
26 | groups = []
27 | in_run = False
28 | for i in range(len(keys)):
29 | if i == len(keys)-1:
30 | if in_run:
31 | groups[-1] += [keys[i]]
32 | else:
33 | groups += [[keys[i]]]
34 | break
35 | if in_run:
36 | if in_sequence(keys[i], keys[i+1]):
37 | continue
38 | else:
39 | groups[-1] += [keys[i]]
40 | in_run = False
41 | else:
42 | if in_sequence(keys[i], keys[i+1]):
43 | in_run = True
44 | groups += [[keys[i]]]
45 | return groups
46 |
47 | groups = optimize_for_query(keys)
48 | wheres = []
49 | for k in groups:
50 | if len(k)==1:
51 | wheres += ['%s=%s'%(col,value) for col, value in zip(object_key_columns(), k[0])]
52 | else:
53 | # expect 2 keys: the first and last of a contiguous run
54 | first, last = k
55 | if p.table_id:
56 | wheres += ['(%s=%s AND %s BETWEEN %s and %s)'%
57 | (p.table_id, first[0], p.image_id, first[1], last[1])]
58 | else:
59 | wheres += ['(%s BETWEEN %s and %s)'%
60 | (p.image_id, first[0], last[0])]
61 | return ' OR '.join(wheres)
--------------------------------------------------------------------------------
/cpa/tests/test_datamodel.py:
--------------------------------------------------------------------------------
1 | from mock import patch
2 | import unittest
3 | import cpa.datamodel
4 |
5 | class PopulatePlateMapsTestCase(unittest.TestCase):
6 |
7 | def setUp(self):
8 | self.dm = cpa.datamodel.DataModel()
9 | self.p = cpa.datamodel.p
10 |
11 | @patch('cpa.datamodel.db')
12 | def test_well_format_A01(self, db):
13 | db.execute.return_value = [('A01',), ('P24',), ('b9',)]
14 | self.p.well_format = 'A01'
15 | self.p.plate_shape = (16, 24)
16 | self.dm.populate_plate_maps()
17 |
18 | @patch('cpa.datamodel.db')
19 | def test_well_format_123(self, db):
20 | db.execute.return_value = [('0',), ('01',), ('123',), ('12345',)]
21 | self.p.well_format = '123'
22 | self.p.plate_shape = (1, 20)
23 | self.dm.populate_plate_maps()
24 |
25 | def test_unknown_well_format(self):
26 | for value in [None, '', 'abc', 'AA1']:
27 | self.p.well_format = value
28 | self.assertRaises(ValueError, lambda: self.dm.populate_plate_maps())
29 |
30 | @patch('cpa.datamodel.db')
31 | def test_A01_over_52_rows(self, db):
32 | # Need at least one well to trigger the code.
33 | db.execute.return_value = [('A01',),]
34 | self.p.well_format = 'A01'
35 | self.p.plate_shape = (53, 1)
36 | self.assertRaises(ValueError, lambda: self.dm.populate_plate_maps())
37 |
38 |
39 | class GetWellPositionFromName(unittest.TestCase):
40 | def setUp(self):
41 | self.dm = cpa.datamodel.DataModel()
42 | self.set_plate_map()
43 |
44 | def set_plate_map(self):
45 | self.dm.plate_map = {'A01': (0, 0)}
46 | self.dm.rev_plate_map = {(0, 0): 'A01'}
47 |
48 | def clear_plate_map(self):
49 | self.dm.plate_map = {}
50 | self.dm.rev_plate_map = {}
51 |
52 | @patch.object(cpa.datamodel.DataModel, 'populate_plate_maps')
53 | def test_forward_missing(self, populate_plate_maps):
54 | populate_plate_maps.side_effect = self.set_plate_map
55 | self.clear_plate_map()
56 | row, col = self.dm.get_well_position_from_name('A01')
57 | populate_plate_maps.assert_called_with()
58 | self.assertEqual((row, col), (0, 0))
59 |
60 | @patch.object(cpa.datamodel.DataModel, 'populate_plate_maps')
61 | def test_reverse_missing(self, populate_plate_maps):
62 | populate_plate_maps.side_effect = self.set_plate_map
63 | self.clear_plate_map()
64 | name = self.dm.get_well_name_from_position((0, 0))
65 | populate_plate_maps.assert_called_with()
66 | self.assertEqual(name, 'A01')
67 |
68 | def test_forward_present(self):
69 | self.assertEqual(self.dm.get_well_position_from_name('A01'),
70 | (0, 0))
71 |
72 | def test_reverse_present(self):
73 | self.assertEqual(self.dm.get_well_name_from_position((0, 0)),
74 | 'A01')
75 |
76 | def test_forward_absent(self):
77 | self.assertRaises(KeyError, lambda: self.dm.get_well_position_from_name('B01'))
78 |
79 | def test_reverse_absent(self):
80 | self.assertRaises(KeyError, lambda: self.dm.get_well_name_from_position((1, 0)))
81 |
--------------------------------------------------------------------------------
/cpa/tests/test_dbconnect.py:
--------------------------------------------------------------------------------
1 | import threading
2 | from mock import patch, Mock
3 | import unittest
4 | import cpa.dbconnect
5 |
6 |
7 | class ExecuteTestCase(unittest.TestCase):
8 |
9 | def setUp(self):
10 | self.p = cpa.dbconnect.p
11 | self.db = cpa.dbconnect.DBConnect()
12 | cursor = Mock()
13 | connID = threading.currentThread().getName()
14 | self.db.connections[connID] = Mock()
15 | self.db.cursors[connID] = cursor
16 |
17 | def test_args_to_sqlite(self):
18 | self.p.db_type = 'SQLite'
19 | self.assertRaises(TypeError, lambda: self.db.execute('query', 'args'))
20 |
21 |
22 | class CheckColnameUserTestCase(unittest.TestCase):
23 | def setUp(self):
24 | self.db = cpa.dbconnect.DBConnect()
25 | self.p = cpa.dbconnect.p
26 | self.p.image_table = 'Per_Image'
27 | self.p.object_table = 'Per_Object'
28 | self.f = cpa.dbconnect._check_colname_user
29 |
30 | def test_not_user_image(self):
31 | self.assertRaises(ValueError, lambda: self.f(self.p, 'Per_Image', 'foo'))
32 |
33 | def test_user_image(self):
34 | self.f(self.p, 'Per_Image', 'User_foo')
35 |
36 | def test_not_user_object(self):
37 | self.assertRaises(ValueError, lambda: self.f(self.p, 'Per_Object', 'foo'))
38 |
39 | def test_user_object(self):
40 | self.f(self.p, 'Per_Object', 'usEr_foo')
41 |
42 | def test_not_user_other(self):
43 | self.f(self.p, 'MetadataTable', 'foo')
44 |
45 |
46 | class AppendColumnTestCase(unittest.TestCase):
47 | def setUp(self):
48 | self.db = cpa.dbconnect.DBConnect()
49 | self.p = cpa.dbconnect.p
50 | self.p.image_table = 'Per_Image'
51 | self.p.object_table = 'Per_Object'
52 |
53 | def test_blank_name(self):
54 | self.assertRaises(ValueError, lambda: self.db.AppendColumn('FooTable', '', 'TEXT'))
55 |
56 | def test_start_number(self):
57 | self.assertRaises(ValueError, lambda: self.db.AppendColumn('FooTable', '1s', 'TEXT'))
58 |
59 | def test_symbol(self):
60 | self.assertRaises(ValueError, lambda: self.db.AppendColumn('FooTable', 'foo$bar', 'TEXT'))
61 |
62 |
63 | class UpdateWellsTestCase(unittest.TestCase):
64 | def setUp(self):
65 | self.db = cpa.dbconnect.DBConnect()
66 | self.p = cpa.dbconnect.p
67 | self.p.image_table = 'Per_Image'
68 | self.p.object_table = 'Per_Object'
69 | self.p.well_id = 'Well'
70 |
71 | def test_double_quote(self):
72 | with patch.object(self.db, 'execute') as execute:
73 | self.assertRaises(ValueError, lambda: self.db.UpdateWells("Per_Image", "User_BarColumn", 'baz"quux', [('A01',)]))
74 |
75 | def test_single_quote(self):
76 | with patch.object(self.db, 'execute') as execute:
77 | self.assertRaises(ValueError, lambda: self.db.UpdateWells("Per_Image", "User_BarColumn", "baz'quux", [('A01',)]))
78 |
79 | def test_backtick(self):
80 | with patch.object(self.db, 'execute') as execute:
81 | self.assertRaises(ValueError, lambda: self.db.UpdateWells("Per_Image", "User_BarColumn", "baz`quux", [('A01',)]))
82 |
83 | def test_null(self):
84 | with patch.object(self.db, 'execute') as execute:
85 | self.db.UpdateWells("Per_Image", "User_BarColumn", None, [('A01',)])
86 | execute.assert_called_with('UPDATE Per_Image SET User_BarColumn=NULL WHERE Well IN ("A01")')
87 |
88 | def test_string(self):
89 | with patch.object(self.db, 'execute') as execute:
90 | self.db.UpdateWells("Per_Image", "User_BarColumn", "baz", [('A01',)])
91 | execute.assert_called_with('UPDATE Per_Image SET User_BarColumn="baz" WHERE Well IN ("A01")')
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/cpa/tests/test_imagereader.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import cpa.imagereader
3 |
--------------------------------------------------------------------------------
/cpa/tests/test_multiclasssql.py:
--------------------------------------------------------------------------------
1 | import mock
2 | from unittest import TestCase
3 | import cpa.multiclasssql
4 |
5 | class WhereClausesTestCase(TestCase):
6 | def _where_clauses(self, imkeys):
7 | p = mock.Mock()
8 | p.table_id = None
9 | p.image_id = 'ImageNumber'
10 | p.object_table = 'Per_Object'
11 | dm = mock.Mock()
12 | filter_name = None
13 | dm.GetAllImageKeys = lambda x: imkeys
14 | return cpa.multiclasssql._where_clauses(p, dm, filter_name)
15 |
16 | def test_2(self):
17 | result = self._where_clauses([(2,), (1,)])
18 | print(result)
19 | assert result == ['(1 = 1)']
20 |
21 | def test_5(self):
22 | result = self._where_clauses([(5,), (4,), (3,), (2,), (1,)])
23 | assert result == ['(Per_Object.ImageNumber <= 5)']
24 |
25 |
26 |
--------------------------------------------------------------------------------
/cpa/tests/test_properties.py:
--------------------------------------------------------------------------------
1 | import os.path
2 | import cpa
3 |
4 | # Issue #24
5 | # def test_old_filter():
6 | # fn = os.path.join(os.path.dirname(__file__),
7 | # 'test_properties_old_filter.properties')
8 | # cpa.properties.LoadFile(fn)
9 |
10 |
--------------------------------------------------------------------------------
/cpa/tests/test_pylab.py:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | import PIL.Image as Image
5 | import pylab
6 | import numpy as np
7 |
8 |
9 | pylab.figure()
10 |
11 | #im = Image.open("/Users/afraser/Pizzabarn.jpg")
12 | #ivals = np.array(im.getdata())
13 | #ivals = ivals.reshape((im.size[1], im.size[0], 3))
14 | #pylab.imshow(ivals[:,:,1], cmap=pylab.cm.gray, aspect='auto')
15 | #pylab.axis('tight')
16 | #pylab.axis('off')
17 | #pylab.subplots_adjust(0.,0.,1.,1.)
18 |
19 | a = np.ones(1000)
20 | a = a.reshape((100,10))
21 | pylab.imshow(a)
22 |
23 | pylab.show()
24 |
--------------------------------------------------------------------------------
/cpa/tests/test_sqltools.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from mock import patch, Mock
3 | import threading
4 | import os.path
5 | import cpa
6 |
7 |
8 | class TestOldFilter(unittest.TestCase):
9 | def setUp(self):
10 | fn = os.path.join(os.path.dirname(__file__),
11 | 'test_sqltools_old_filter.properties')
12 | p = cpa.properties.Properties()
13 | p.load_file(fn)
14 | self.db = cpa.dbconnect.DBConnect()
15 | cursor = Mock()
16 | connID = threading.currentThread().getName()
17 | self.db.connections[connID] = Mock()
18 | self.db.cursors[connID] = cursor
19 |
20 |
21 | def test_get_tables(self):
22 | p = cpa.properties.Properties()
23 | filter = p._filters['MCF7wt']
24 | with patch.object(cpa.db, 'execute') as execute:
25 | with patch.object(cpa.db, 'GetResultColumnNames') as GetResultColumnNames:
26 | execute.return_value = [(1, 'SIMPLE', 'Morphology_Per_Image', 'ALL', None, None, None, None, 107760, 'Using where')]
27 | GetResultColumnNames.return_value = ['id', 'select_type', 'table', 'type', 'possible_keys', 'key', 'key_len', 'ref', 'rows', 'Extra']
28 | tables = filter.get_tables()
29 | self.assertEqual(tables, set(['Morphology_Per_Image']))
30 |
--------------------------------------------------------------------------------
/cpa/tests/testclassifier.py:
--------------------------------------------------------------------------------
1 | import cpa.dbconnect
2 | from cpa.datatable import DataGrid
3 | from cpa.datamodel import DataModel
4 | from cpa.imagecontrolpanel import ImageControlPanel
5 | from cpa.properties import Properties
6 | from cpa.scoredialog import ScoreDialog
7 | import cpa.sortbin
8 | from cpa.tilecollection import EVT_TILE_UPDATED
9 | from cpa.trainingset import TrainingSet
10 | from io import StringIO
11 | import cpa.fastgentleboostingmulticlass
12 | import cpa.imagetools
13 | import cpa.multiclasssql
14 | import cpa.polyafit
15 | import numpy
16 | import os
17 | import wx
18 | from cpa.classifier import *
19 |
20 |
21 | import time
22 | if __name__ == "__main__":
23 | app = wx.App()
24 |
25 | p = Properties()
26 | db = dbconnect.DBConnect()
27 | dm = DataModel()
28 |
29 | # props = '/Volumes/imaging_analysis/2007_10_19_Gilliland_LeukemiaScreens/Screen3_1Apr09_run3/2007_10_19_Gilliland_LeukemiaScreens_Validation_v2_AllBatches_DuplicatesFiltered_FullBarcode_testSinglePlate.properties'
30 | # ts = '/Volumes/imaging_analysis/2007_10_19_Gilliland_LeukemiaScreens/Screen3_1Apr09_run3/trainingvalidation3b.txt'
31 | props = '../Properties/nirht_area_test.properties'
32 | ts = '/Users/afraser/Desktop/MyTrainingSet.txt'
33 | p.LoadFile(props)
34 | classifier = Classifier(p)
35 | classifier.Show(True)
36 | classifier.LoadTrainingSet(ts)
37 | time.sleep(3)
38 | classifier.TrainClassifier()
39 | classifier.ScoreAll()
40 |
41 | app.MainLoop()
--------------------------------------------------------------------------------
/cpa/tests/testimagereader.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from cpa.imagereader import ImageReader
3 | from cpa.properties import Properties
4 |
5 | p = Properties()
6 |
7 | # fake-up some props
8 | p._filename = '../../CPAnalyst_test_data/test_images/'
9 | p.image_channel_colors = ['red','green','blue','none','none','none']
10 | p.object_name = ['cell', 'cells']
11 | p.image_names = ['', '', '']
12 | p.image_id = 'ImageNumber'
13 |
14 | ir = ImageReader()
15 |
16 | class TestImageReader(unittest.TestCase):
17 |
18 | def test_tif1(self):
19 | # TIF RGB, 8-bit, PackBits encoding
20 | fds = ['color.tif']
21 | images = ir.ReadImages(fds)
22 | assert len(images) == 3
23 | for im in images:
24 | assert 0. <= im.min() <= im.max() <= 1.
25 | assert im.shape == (512, 512)
26 |
27 | def test_tif2(self):
28 | # 2 RGB TIFS
29 | fds = ['color.tif','color.tif']
30 | images = ir.ReadImages(fds)
31 | assert len(images) == 6
32 | for im in images:
33 | assert 0. <= im.min() <= im.max() <= 1.
34 | assert im.shape == (512, 512)
35 |
36 | def test_tif3(self):
37 | # Buzz buam TIF 8-bit uncompressed
38 | fds = ['01_POS002_D.TIF',
39 | '01_POS002_F.TIF',
40 | '01_POS002_R.TIF']
41 | images = ir.ReadImages(fds)
42 | assert len(images) == 3
43 | for im in images:
44 | assert 0. <= im.min() <= im.max() <= 1.
45 | assert im.shape == (1006, 1000)
46 |
47 | def test_tif4(self):
48 | # TIF 8-bit PackBits encoding
49 | fds = ['AS_09125_050116030001_D03f00d0.tif',
50 | 'AS_09125_050116030001_D03f00d1.tif',
51 | 'AS_09125_050116030001_D03f00d2.tif',]
52 | images = ir.ReadImages(fds)
53 | assert len(images) == 3
54 | for im in images:
55 | assert 0. <= im.min() <= im.max() <= 1.
56 | assert im.shape == (512, 512)
57 |
58 | def test_tif5(self):
59 | # TIFs from Neurospheres project
60 | fds = ['PANDORA_100324070001_P14f00d0.TIF',
61 | 'PANDORA_100324070001_P14f00d1.TIF',]
62 | images = ir.ReadImages(fds)
63 | assert len(images) == 2
64 | for im in images:
65 | assert 0. <= im.min() <= im.max() <= 1.
66 | assert im.shape == (512, 512)
67 |
68 | def test_jpg1(self):
69 | # JPG
70 | fds = ['30-2A1b.jpg']
71 | images = ir.ReadImages(fds)
72 | assert len(images) == 3
73 | for im in images:
74 | assert 0. <= im.min() <= im.max() <= 1.
75 | assert im.shape == (1200, 1600)
76 |
77 | def test_dib(self):
78 | # Cellomics dibs
79 | fds = ['AS_09125_050116030001_D03f00d0.DIB',
80 | 'AS_09125_050116030001_D03f00d1.DIB',
81 | 'AS_09125_050116030001_D03f00d2.DIB',]
82 | images = ir.ReadImages(fds)
83 | assert len(images) == 3
84 | for im in images:
85 | assert 0. <= im.min() <= im.max() <= 1.
86 | assert im.shape == (512, 512)
87 |
88 | def test_png(self):
89 | # PNG
90 | fds = ['AS_09125_050116000001_A01f00d0.png',
91 | 'AS_09125_050116000001_A01f00d1.png',
92 | 'AS_09125_050116000001_A01f00d2.png',]
93 | images = ir.ReadImages(fds)
94 | assert len(images) == 3
95 | for im in images:
96 | assert 0. <= im.min() <= im.max() <= 1.
97 | assert im.shape == (512, 512)
98 |
99 | def test_mixed(self):
100 | # READ different image types into same channel set
101 | fds = ['AS_09125_050116030001_D03f00d0.DIB',
102 | 'AS_09125_050116030001_D03f00d1.tif',
103 | 'AS_09125_050116000001_A01f00d2.png',]
104 | images = ir.ReadImages(fds)
105 | assert len(images) == 3
106 | for im in images:
107 | assert 0. <= im.min() <= im.max() <= 1.
108 | assert im.shape == (512, 512)
109 |
110 | if __name__ == "__main__":
111 | unittest.main()
--------------------------------------------------------------------------------
/cpa/tests/threadingexample.py:
--------------------------------------------------------------------------------
1 | import time
2 | from threading import *
3 | import wx
4 |
5 | # Button definitions
6 | ID_START = wx.NewId()
7 | ID_STOP = wx.NewId()
8 |
9 | # Define notification event for thread completion
10 | EVT_RESULT_ID = wx.NewId()
11 |
12 | def EVT_RESULT(win, func):
13 | """Define Result Event."""
14 | win.Connect(- 1, - 1, EVT_RESULT_ID, func)
15 |
16 | class ResultEvent(wx.PyEvent):
17 | """Simple event to carry arbitrary result data."""
18 | def __init__(self, data):
19 | """Init Result Event."""
20 | wx.PyEvent.__init__(self)
21 | self.SetEventType(EVT_RESULT_ID)
22 | self.data = data
23 |
24 | # Thread class that executes processing
25 | class WorkerThread(Thread):
26 | """Worker Thread Class."""
27 | def __init__(self, notify_window):
28 | """Init Worker Thread Class."""
29 | Thread.__init__(self)
30 | self._notify_window = notify_window
31 | self._want_abort = 0
32 | # This starts the thread running on creation, but you could
33 | # also make the GUI thread responsible for calling this
34 | self.start()
35 |
36 | def run(self):
37 | """Run Worker Thread."""
38 | # This is the code executing in the new thread. Simulation of
39 | # a long process (well, 10s here) as a simple loop - you will
40 | # need to structure your processing so that you periodically
41 | # peek at the abort variable
42 | for i in range(10):
43 | time.sleep(1)
44 | if self._want_abort:
45 | # Use a result of None to acknowledge the abort (of
46 | # course you can use whatever you'd like or even
47 | # a separate event type)
48 | wx.PostEvent(self._notify_window, ResultEvent(None))
49 | return
50 | # Here's where the result would be returned (this is an
51 | # example fixed result of the number 10, but it could be
52 | # any Python object)
53 | wx.PostEvent(self._notify_window, ResultEvent(10))
54 |
55 | def abort(self):
56 | """abort worker thread."""
57 | # Method for use by main thread to signal an abort
58 | self._want_abort = 1
59 |
60 | # GUI Frame class that spins off the worker thread
61 | class MainFrame(wx.Frame):
62 | """Class MainFrame."""
63 | def __init__(self, parent, id):
64 | """Create the MainFrame."""
65 | wx.Frame.__init__(self, parent, id, 'Thread Test')
66 |
67 | # Dumb sample frame with two buttons
68 | wx.Button(self, ID_START, 'Start', pos=(0, 0))
69 | wx.Button(self, ID_STOP, 'Stop', pos=(0, 50))
70 | self.status = wx.StaticText(self, - 1, '', pos=(0, 100))
71 |
72 | self.Bind(wx.EVT_BUTTON, self.OnStart, id=ID_START)
73 | self.Bind(wx.EVT_BUTTON, self.OnStop, id=ID_STOP)
74 |
75 | # Set up event handler for any worker thread results
76 | EVT_RESULT(self, self.OnResult)
77 |
78 | # And indicate we don't have a worker thread yet
79 | self.worker = None
80 |
81 | def OnStart(self, event):
82 | """Start Computation."""
83 | # Trigger the worker thread unless it's already busy
84 | if not self.worker:
85 | self.status.SetLabel('Starting computation')
86 | self.worker = WorkerThread(self)
87 |
88 | def OnStop(self, event):
89 | """Stop Computation."""
90 | # Flag the worker thread to stop if running
91 | if self.worker:
92 | self.status.SetLabel('Trying to abort computation')
93 | self.worker.abort()
94 |
95 | def OnResult(self, event):
96 | """Show Result status."""
97 | if event.data is None:
98 | # Thread aborted (using our convention of None return)
99 | self.status.SetLabel('Computation aborted')
100 | else:
101 | # Process results here
102 | self.status.SetLabel('Computation Result: %s' % event.data)
103 | # In either event, the worker is done
104 | self.worker = None
105 |
106 | class MainApp(wx.App):
107 | """Class Main App."""
108 | def OnInit(self):
109 | """Init Main App."""
110 | self.frame = MainFrame(None, - 1)
111 | self.frame.Show(True)
112 | self.SetTopWindow(self.frame)
113 | return True
114 |
115 | if __name__ == '__main__':
116 | app = MainApp(0)
117 | app.MainLoop()
118 |
119 |
--------------------------------------------------------------------------------
/cpa/tsne.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # tsne.py
4 | #
5 | # Implementation of t-SNE in Python. The implementation was tested on Python 2.5.1, and it requires a working
6 | # installation of NumPy. The implementation comes with an example on the MNIST dataset. In order to plot the
7 | # results of this example, a working installation of matplotlib is required.
8 | # The example can be run by executing: ipython tsne.py -pylab
9 | #
10 | #
11 | # Created by Laurens van der Maaten on 20-12-08.
12 | # Copyright (c) 2008 Tilburg University. All rights reserved.
13 |
14 | import numpy as np
15 |
16 | def Hbeta(D = np.array([]), beta = 1.0):
17 | """Compute the perplexity and the P-row for a specific value of the precision of a Gaussian distribution."""
18 |
19 | # Compute P-row and corresponding perplexity
20 | P = np.exp(-D.copy() * beta);
21 | sumP = sum(P);
22 | H = np.log(sumP) + beta * np.sum(D * P) / sumP;
23 | P = P / sumP;
24 | return H, P;
25 |
26 |
27 | def x2p(X = np.array([]), tol = 1e-5, perplexity = 30.0):
28 | """Performs a binary search to get P-values in such a way that each conditional Gaussian has the same perplexity."""
29 |
30 | # Initialize some variables
31 | print("Computing pairwise distances...")
32 | (n, d) = X.shape;
33 | sum_X = np.sum(np.square(X), 1);
34 | D = np.add(np.add(-2 * np.dot(X, X.T), sum_X).T, sum_X);
35 | P = np.zeros((n, n));
36 | beta = np.ones((n, 1));
37 | logU = np.log(perplexity);
38 |
39 | # Loop over all datapoints
40 | for i in range(n):
41 |
42 | # Print progress
43 | if i % 500 == 0:
44 | print(("Computing P-values for point ", i, " of ", n, "..."))
45 |
46 | # Compute the Gaussian kernel and entropy for the current precision
47 | betamin = -np.inf;
48 | betamax = np.inf;
49 | Di = D[i, np.concatenate((np.r_[0:i], np.r_[i+1:n]))];
50 | (H, thisP) = Hbeta(Di, beta[i]);
51 |
52 | # Evaluate whether the perplexity is within tolerance
53 | Hdiff = H - logU;
54 | tries = 0;
55 | while np.abs(Hdiff) > tol and tries < 50:
56 |
57 | # If not, increase or decrease precision
58 | if Hdiff > 0:
59 | betamin = beta[i];
60 | if betamax == np.inf or betamax == -np.inf:
61 | beta[i] = beta[i] * 2;
62 | else:
63 | beta[i] = (beta[i] + betamax) / 2;
64 | else:
65 | betamax = beta[i];
66 | if betamin == np.inf or betamin == -np.inf:
67 | beta[i] = beta[i] / 2;
68 | else:
69 | beta[i] = (beta[i] + betamin) / 2;
70 |
71 | # Recompute the values
72 | (H, thisP) = Hbeta(Di, beta[i]);
73 | Hdiff = H - logU;
74 | tries = tries + 1;
75 |
76 | # Set the final row of P
77 | P[i, np.concatenate((np.r_[0:i], np.r_[i+1:n]))] = thisP;
78 |
79 | # Return final P-matrix
80 | print(("Mean value of sigma: ", np.mean(np.sqrt(1 / beta))))
81 | return P;
82 |
83 |
84 | def pca(X = np.array([]), no_dims = 50):
85 | """Runs PCA on the NxD array X in order to reduce its dimensionality to no_dims dimensions."""
86 |
87 | print("Preprocessing the data using PCA...")
88 | (n, d) = X.shape;
89 | X = X - np.tile(np.mean(X, 0), (n, 1));
90 | (l, M) = np.linalg.eig(np.dot(X.T, X));
91 | Y = np.dot(X, M[:,0:no_dims]);
92 | np.testing.assert_array_almost_equal(np.imag(Y), np.zeros(Y.shape))
93 | return np.real(Y);
94 |
95 |
96 | def tsne(X = np.array([]), no_dims = 2, initial_dims = 50, perplexity = 30.0):
97 | """Runs t-SNE on the dataset in the NxD array X to reduce its dimensionality to no_dims dimensions.
98 | The syntaxis of the function is Y = tsne.tsne(X, no_dims, perplexity), where X is an NxD NumPy array."""
99 |
100 | # Check inputs
101 | if X.dtype != "float64":
102 | print("Error: array X should have type float64.");
103 | return -1;
104 | #if no_dims.__class__ != "": # doesn't work yet!
105 | # print "Error: number of dimensions should be an integer.";
106 | # return -1;
107 |
108 | # Initialize variables
109 | X = pca(X, initial_dims);
110 | (n, d) = X.shape;
111 | max_iter = 1000;
112 | initial_momentum = 0.5;
113 | final_momentum = 0.8;
114 | eta = 500;
115 | min_gain = 0.01;
116 | Y = np.random.randn(n, no_dims);
117 | dY = np.zeros((n, no_dims));
118 | iY = np.zeros((n, no_dims));
119 | gains = np.ones((n, no_dims));
120 |
121 | # Compute P-values
122 | P = x2p(X, 1e-5, perplexity);
123 | P = P + np.transpose(P);
124 | P = P / np.sum(P);
125 | P = P * 4; # early exaggeration
126 | P = np.maximum(P, 1e-12);
127 |
128 | # Run iterations
129 | for iter in range(max_iter):
130 |
131 | # Compute pairwise affinities
132 | sum_Y = np.sum(np.square(Y), 1);
133 | num = 1 / (1 + np.add(np.add(-2 * np.dot(Y, Y.T), sum_Y).T, sum_Y));
134 | num[list(range(n)), list(range(n))] = 0;
135 | Q = num / np.sum(num);
136 | Q = np.maximum(Q, 1e-12);
137 |
138 | # Compute gradient
139 | PQ = P - Q;
140 | for i in range(n):
141 | dY[i,:] = np.sum(np.tile(PQ[:,i] * num[:,i], (no_dims, 1)).T * (Y[i,:] - Y), 0);
142 |
143 | # Perform the update
144 | if iter < 20:
145 | momentum = initial_momentum
146 | else:
147 | momentum = final_momentum
148 | gains = (gains + 0.2) * ((dY > 0) != (iY > 0)) + (gains * 0.8) * ((dY > 0) == (iY > 0));
149 | gains[gains < min_gain] = min_gain;
150 | iY = momentum * iY - eta * (gains * dY);
151 | Y = Y + iY;
152 | Y = Y - np.tile(np.mean(Y, 0), (n, 1));
153 |
154 | # Compute current value of cost function
155 | if (iter + 1) % 10 == 0:
156 | C = np.sum(P * np.log(P / Q));
157 | print(("Iteration ", (iter + 1), ": error is ", C))
158 |
159 | # Stop lying about P-values
160 | if iter == 100:
161 | P = P / 4;
162 |
163 | # Return solution
164 | return Y;
165 |
166 |
167 | if __name__ == "__main__":
168 | import pylab
169 | print("Run Y = tsne.tsne(X, no_dims, perplexity) to perform t-SNE on your dataset.")
170 | print("Running example on 2,500 MNIST digits...")
171 | X = np.loadtxt("mnist2500_X.txt");
172 | labels = np.loadtxt("mnist2500_labels.txt");
173 | Y = tsne(X, 2, 50, 20.0);
174 | pylab.scatter(Y[:,0], Y[:,1], 20, labels);
175 |
--------------------------------------------------------------------------------
/cpa/updatechecker.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import logging
3 | import requests
4 | import wx
5 |
6 | from . import __version__ as current_version
7 | from .cpaprefs import get_check_update, get_check_update_bool, set_check_update
8 |
9 |
10 | def check_update(origin, force=False, event=True):
11 | if not force and not check_date():
12 | return
13 | if event:
14 | parent = origin.GetEventObject().GetWindow()
15 | else:
16 | parent = origin
17 | try:
18 | response = requests.get("https://api.github.com/repos/cellprofiler/cellprofiler-analyst/releases/latest", timeout=0.25)
19 | except:
20 | response = False
21 | message = "CellProfiler-Analyst was unable to connect to GitHub to check for updates"
22 | if response:
23 | status = response.status_code
24 | response = response.json()
25 | if status == 200 and 'tag_name' in response:
26 | latest = response['tag_name']
27 | latest = tuple(map(int, (latest.split("."))))
28 | current = tuple(map(int, (current_version.split("."))))
29 | if current < latest:
30 | body_text = response['body']
31 | if len(body_text) > 1000:
32 | body_text = body_text[:1000] + "..."
33 | elif len(body_text) == 0:
34 | body_text = "No information available"
35 | logging.info(f"An update for CellProfiler-Analyst is available ({response['tag_name']})")
36 | show_message(parent, response['tag_name'], body_text)
37 | return
38 | else:
39 | message = "CellProfiler-Analyst is up-to-date"
40 | if get_check_update() != "Disabled":
41 | set_check_update(datetime.date.today().strftime("%Y%m%d"))
42 | elif status == 200:
43 | message = "Unable to read data from GitHub, API may have changed."
44 | else:
45 | message = "Invalid response from GitHub server, site may be down."
46 | if force:
47 | # User explicitly asked for a check, display a popup even with no available updates.
48 | dlg = wx.MessageDialog(
49 | parent,
50 | message,
51 | caption="Check for updates",
52 | style=wx.ICON_INFORMATION | wx.OK,
53 | )
54 | dlg.ShowModal()
55 | else:
56 | logging.info(message)
57 |
58 |
59 | def show_message(parent, version, blurb):
60 | message = f"""A new CellProfiler-Analyst release is available:\n\nVersion {version}\n
61 | Would you like to visit the download page?"""
62 | dlg = wx.RichMessageDialog(
63 | parent,
64 | message,
65 | caption="CellProfiler-Analyst Update Available",
66 | style=wx.YES_NO | wx.CENTRE | wx.ICON_INFORMATION,
67 | )
68 | dlg.ShowDetailedText(f"Release Notes:\n{blurb}")
69 | dlg.ShowCheckBox("Check for updates on startup", checked=get_check_update_bool())
70 | response = dlg.ShowModal()
71 | if response == wx.ID_YES:
72 | wx.LaunchDefaultBrowser("https://cellprofileranalyst.org/releases")
73 | if not dlg.IsCheckBoxChecked():
74 | set_check_update("Disabled")
75 | else:
76 | set_check_update(datetime.date.today().strftime("%Y%m%d"))
77 |
78 |
79 | def check_date():
80 | last_checked = get_check_update()
81 | if last_checked == "Disabled":
82 | # Updating is disabled
83 | return False
84 | elif last_checked == "Never":
85 | return True
86 | today = datetime.date.today()
87 | last_checked = datetime.datetime.strptime(last_checked, "%Y%m%d").date()
88 | if (last_checked - today).days >= 7:
89 | return True
90 | else:
91 | return False
--------------------------------------------------------------------------------
/cpa/util/frozen_version.py:
--------------------------------------------------------------------------------
1 | # MANUAL
2 | version_string = '2.2.1'
--------------------------------------------------------------------------------
/cpa/util/version.py:
--------------------------------------------------------------------------------
1 | '''version.py - Version fetching and comparison.
2 |
3 | CellProfiler Analyst is distributed under the GNU General Public License,
4 | but this file is licensed under the more permissive BSD license.
5 | See the accompanying file LICENSE for details.
6 |
7 | Copyright (c) 2003-2009 Massachusetts Institute of Technology
8 | Copyright (c) 2009-2021 Broad Institute
9 |
10 | All rights reserved.
11 |
12 | Please see the AUTHORS file for credits.
13 |
14 | Website: http://www.cellprofileranalyst.org
15 | '''
16 |
17 |
18 | import re
19 | import sys
20 | import os.path
21 |
22 | _cached_description = None
23 |
24 | __version__ = '3.0.4' # Version used by update checker, must be in format "N.N.N"
25 | _sub_version = '' # Use this to tag release candidates, betas, etc.
26 |
27 | display_version = __version__ + _sub_version
28 |
29 | def _get_description():
30 | """Get description from git or file system.
31 |
32 | If we're not frozen and this is a git repository, try to get the
33 | description by running ``git describe``, then store it in
34 | javabridge/_description.py. Otherwise, try to load the description
35 | from that file. If both methods fail, quietly return None.
36 |
37 | """
38 | global _cached_description
39 | git_description = None
40 | if (not hasattr(sys, 'frozen') and
41 | os.path.exists(os.path.join(os.path.dirname(__file__), '..', '..',
42 | '.git'))):
43 | import subprocess
44 | try:
45 | git_description = subprocess.Popen(['git', 'describe', '--long'],
46 | stdout=subprocess.PIPE).communicate()[0].strip()
47 | except:
48 | pass
49 |
50 | description_file = os.path.join(os.path.dirname(__file__), '..',
51 | '_description.py')
52 | if os.path.exists(description_file):
53 | with open(description_file) as f:
54 | cached_description_line = f.read().strip()
55 | try:
56 | # From http://stackoverflow.com/a/3619714/17498
57 | _cached_description = re.search(r"^__description__ = ['\"]([^'\"]*)['\"]",
58 | cached_description_line, re.M).group(1)
59 | except:
60 | raise RuntimeError("Unable to find description in %s" % description_file)
61 | else:
62 | _cached_description = None
63 |
64 | if git_description and git_description != _cached_description:
65 | with open(description_file, 'w') as f:
66 | print('__description__ = "%s"' % git_description, file=f)
67 |
68 | return git_description or _cached_description
69 |
70 | def _parse_description(description):
71 | if description is None:
72 | return None
73 | m = re.match('(.*)-(\d+)-g([0-9a-f]+)$', description)
74 | if m is None:
75 | return None
76 | else:
77 | return m.groups()
78 |
79 | def get_commit(_description=_get_description()):
80 | tag, additional, commit = _parse_description(_description)
81 | return commit
82 |
83 | if __name__ == '__main__':
84 | if len(sys.argv) == 2:
85 | description = sys.argv[1]
86 | elif len(sys.argv) == 1:
87 | description = _get_description()
88 | else:
89 | print("Usage: %s [DESCRIPTION]" % os.path.basename(sys.argv[0]), file=sys.stderr)
90 | sys.exit(64) # EX_USAGE
91 | print('Description:', description)
92 | print('Version:', __version__)
93 | print('Commit:', get_commit(description))
94 |
--------------------------------------------------------------------------------
/cpa/utils.py:
--------------------------------------------------------------------------------
1 |
2 | class Observable:
3 | '''Mixin for objects that need to be observed by other objects.'''
4 | _observers = None
5 | def addobserver(self, observer):
6 | if not self._observers:
7 | self._observers = []
8 | self._observers.append(observer)
9 |
10 | def removeobserver(self, observer):
11 | if self._observers and observer in self._observers:
12 | self._observers.remove(observer)
13 |
14 | def notify(self, event):
15 | for o in self._observers or ():
16 | o(event)
17 |
18 |
19 | class ObservableDict(dict, Observable):
20 | def __setitem__(self, key, value):
21 | dict.__setitem__(self, key, value)
22 | self.notify((key, value))
23 |
24 | def __delitem__(self, key):
25 | dict.__delitem__(self, key)
26 | self.notify((key, None))
27 |
28 | def pop(self, key):
29 | v = dict.pop(self, key)
30 | self.notify((key, None))
31 | return v
32 |
33 | def clear(self):
34 | dict.clear(self)
35 | self.notify(None)
36 |
37 |
38 | # AutoSave
39 | import threading
40 | from functools import wraps
41 |
42 | def delay(delay=0.):
43 | """
44 | Decorator delaying the execution of a function for a while.
45 | """
46 | def wrap(f):
47 | @wraps(f)
48 | def delayed(*args, **kwargs):
49 | timer = threading.Timer(delay, f, args=args, kwargs=kwargs)
50 | timer.start()
51 | return delayed
52 | return wrap
--------------------------------------------------------------------------------
/distribution/macos/CellProfiler-Analyst.spec:
--------------------------------------------------------------------------------
1 | # -*- mode: python ; coding: utf-8 -*-
2 |
3 | import os
4 | import os.path
5 |
6 | import PyInstaller.compat
7 | import PyInstaller.utils.hooks
8 |
9 | binaries = []
10 |
11 | block_cipher = None
12 |
13 | datas = []
14 |
15 | datas += PyInstaller.utils.hooks.collect_data_files("bioformats")
16 | datas += PyInstaller.utils.hooks.collect_data_files("javabridge")
17 |
18 | datas += [
19 | ("../../cpa/icons/*", "cpa/icons"),
20 | ]
21 |
22 | for subdir, dirs, files in os.walk(os.environ["JAVA_HOME"]):
23 | if 'Contents/' in subdir:
24 | if len(subdir.split('Contents/')) >1:
25 | _, subdir_split = subdir.split('Contents/')
26 | for file in files:
27 | datas += [(os.path.join(subdir, file), subdir_split)]
28 |
29 | hiddenimports = []
30 |
31 | hiddenimports += PyInstaller.utils.hooks.collect_submodules('sklearn.utils')
32 | hiddenimports += ['cmath']
33 |
34 | excludes = []
35 |
36 | excludes += [
37 | "PyQt5.QtGui",
38 | "PyQt5.QtCore",
39 | "PyQt4.QtGui",
40 | "PyQt4.QtCore",
41 | "PySide.QtGui",
42 | "PySide.QtCore",
43 | "PyQt5",
44 | "PyQt4",
45 | "PySide",
46 | "PySide2",
47 | "FixTk",
48 | "tcl",
49 | "tk",
50 | "_tkinter",
51 | "tkinter",
52 | "Tkinter"
53 | ]
54 |
55 |
56 | a = Analysis(['../../CellProfiler-Analyst.py'],
57 | pathex=['CellProfiler-Analyst'],
58 | binaries=binaries,
59 | datas=datas,
60 | excludes=excludes,
61 | hiddenimports=hiddenimports,
62 | hookspath=[],
63 | runtime_hooks=[],
64 | win_no_prefer_redirects=False,
65 | win_private_assemblies=False,
66 | cipher=block_cipher)
67 |
68 | libpng_pathname = PyInstaller.utils.hooks.get_homebrew_path("libpng")
69 | libpng_pathname = os.path.join(libpng_pathname, "lib", "libpng16.16.dylib")
70 |
71 | java_pathname = os.path.join(os.environ["JAVA_HOME"], "lib/libjava.dylib")
72 | a.binaries += [
73 | ("libpng16.16.dylib", libpng_pathname, "BINARY"),
74 | ("libjava.dylib", java_pathname, "BINARY")
75 | ]
76 |
77 | exclude_binaries = [
78 | ('libpng16.16.dylib', '/usr/local/lib/python3.8/site-packages/matplotlib/.dylibs/libpng16.16.dylib', 'BINARY'),
79 | ]
80 |
81 | a.binaries = [binary for binary in a.binaries if binary not in exclude_binaries]
82 |
83 | pyz = PYZ(
84 | a.pure,
85 | a.zipped_data,
86 | cipher=block_cipher
87 | )
88 |
89 | exe = EXE(
90 | pyz,
91 | a.scripts,
92 | exclude_binaries=True,
93 | name="cpanalyst",
94 | debug=True,
95 | strip=False,
96 | upx=True,
97 | console=False
98 | )
99 |
100 | coll = COLLECT(
101 | exe,
102 | a.binaries,
103 | a.zipfiles,
104 | a.datas,
105 | icon="../../cpa/icons/cpa.icns",
106 | name="CellProfiler-Analyst.app"
107 | )
108 |
109 | app = BUNDLE(
110 | coll,
111 | name="CellProfiler-Analyst.app",
112 | icon="../../cpa/icons/cpa.icns",
113 | bundle_identifier=None
114 | )
--------------------------------------------------------------------------------
/distribution/macos/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleDisplayName
8 | CellProfiler-Analyst
9 | CFBundleExecutable
10 | MacOS/cpanalyst
11 | CFBundleIconFile
12 | cpa.icns
13 | CFBundleIdentifier
14 | org.cellprofiler.CellProfiler-Analyst
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | CellProfiler-Analyst
19 | CFBundleVersion
20 | 4.0.0
21 | CFBundleShortVersionString
22 | 4.0.0
23 | LSApplicationCategoryType
24 |
25 | CFBundleDocumentTypes
26 |
27 |
28 | CFBundleTypeExtensions
29 |
30 | workspace
31 |
32 | CFBundleTypeIconFile
33 | cpa.icns
34 | CFBundleTypeName
35 | CellProfiler-Analyst Workspace
36 | CFBundleTypeRole
37 | Editor
38 |
39 |
40 | LSEnvironment
41 |
42 | JAVA_HOME
43 | ./Contents
44 |
45 | NSHighResolutionCapable
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/distribution/macos/Makefile:
--------------------------------------------------------------------------------
1 | MAKEFLAGS += --warn-undefined-variables
2 |
3 | SHELL := bash
4 |
5 | .DEFAULT_GOAL := dist/CellProfiler-Analyst.app
6 |
7 | .DELETE_ON_ERROR:
8 |
9 | .SHELLFLAGS := -eu -o pipefail -c
10 |
11 | .SUFFIXES:
12 |
13 | CellProfiler-Analyst:
14 | git clone https://github.com/CellProfiler/CellProfiler-Analyst.git
15 |
16 | cd $@
17 |
18 | .PHONY: dependencies
19 | dependencies: CellProfiler-Analyst
20 | pip3 install --editable CellProfiler-Analyst --upgrade
21 |
22 | dist/CellProfiler-Analyst.app: CellProfiler-Analyst dependencies Info.plist
23 | pyinstaller --noconfirm CellProfiler-Analyst.spec
24 |
25 | cp $(word 3, $^) $@/Contents
26 |
27 | cp entitlements.plist $@/Contents/MacOS
28 |
29 | .PHONY: clean
30 | clean:
31 | if [ -d CellProfiler-Analyst ]; then rm -rf CellProfiler-Analyst; fi
32 |
33 | if [ -d build ]; then rm -rf build; fi
34 |
35 | if [ -d dist ]; then rm -rf build; fi
36 |
37 | if [ CellProfiler.dmg ]; then rm -rf CellProfiler.dmg; fi
38 |
--------------------------------------------------------------------------------
/distribution/macos/add-osx-certificate.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | KEY_CHAIN=build.keychain
4 | CERTIFICATE_P12=certificate.p12
5 |
6 | # Recreate the certificate from the secure environment variable
7 | echo $CERTIFICATE_OSX_APPLICATION | base64 --decode > $CERTIFICATE_P12
8 |
9 | #create a keychain
10 | security create-keychain -p actions $KEY_CHAIN
11 |
12 | # Make the keychain the default so identities are found
13 | security default-keychain -s $KEY_CHAIN
14 |
15 | # Unlock the keychain
16 | security unlock-keychain -p actions $KEY_CHAIN
17 |
18 | security import $CERTIFICATE_P12 -k $KEY_CHAIN -P $CERTIFICATE_PASSWORD -T /usr/bin/codesign;
19 |
20 | security set-key-partition-list -S apple-tool:,apple: -s -k actions $KEY_CHAIN
21 |
22 | # remove certs
23 | rm -fr *.p12
24 |
25 |
26 |
--------------------------------------------------------------------------------
/distribution/macos/entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.cs.allow-jit
6 |
7 | com.apple.security.cs.allow-unsigned-executable-memory
8 |
9 | com.apple.security.cs.disable-executable-page-protection
10 |
11 | com.apple.security.cs.allow-dyld-environment-variables
12 |
13 | com.apple.security.cs.disable-library-validation
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/distribution/macos/osx-codesign.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | cd ./dist/CellProfiler-Analyst.app/Contents/Resources
4 | sudo rm -r Home/legal/
5 | sudo codesign --timestamp -s "Apple Development: alicelucas93@gmail.com (P6D4NCA4CT)" Home/lib/server/classes.jsa
6 | find . -type f | xargs -I file codesign --timestamp -f -s "Apple Development: alicelucas93@gmail.com (P6D4NCA4CT)" file
7 | cd ../MacOS
8 | find . -type f | xargs -I file sudo codesign --timestamp -f -s "Apple Development: alicelucas93@gmail.com (P6D4NCA4CT)" file
9 | codesign --timestamp -f -s "Apple Development: alicelucas93@gmail.com (P6D4NCA4CT)" _elementtree.cpython-38-darwin.so
10 | codesign --entitlements entitlements.plist --timestamp -o runtime -s "Apple Development: alicelucas93@gmail.com (P6D4NCA4CT)" ./cpanalyst
11 | cd ..
12 | codesign --timestamp -s "Apple Development: alicelucas93@gmail.com (P6D4NCA4CT)" Info.plist
13 |
14 |
15 |
--------------------------------------------------------------------------------
/distribution/windows/CellProfiler-Analyst.iss:
--------------------------------------------------------------------------------
1 | ; Script generated by the Inno Script Studio Wizard.
2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
3 |
4 | #define MyAppName "CellProfiler-Analyst"
5 | #define MyAppPublisher "Broad Institute"
6 | #define MyAppURL "http:\\cellprofileranalyst.org"
7 | #define MyAppExeName "CellProfiler-Analyst.exe"
8 |
9 | [Setup]
10 | ; NOTE: The value of AppId uniquely identifies this application.
11 | ; Do not use the same AppId value in installers for other applications.
12 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
13 | AppId={{9A310638-495F-4817-9AC1-6094DD90E821}
14 | AppName={#MyAppName}
15 | AppVersion={#MyAppVersion}
16 | ;AppVerName={#MyAppName} {#MyAppVersion}
17 | AppPublisher={#MyAppPublisher}
18 | AppPublisherURL={#MyAppURL}
19 | AppSupportURL={#MyAppURL}
20 | AppUpdatesURL={#MyAppURL}
21 | DefaultDirName={pf64}\{#MyAppName}
22 | DefaultGroupName={#MyAppName}
23 | LicenseFile=..\..\LICENSE
24 | OutputBaseFilename=CellProfiler-Analyst-Windows-{#MyAppVersion}
25 | Compression=lzma
26 | SolidCompression=yes
27 | DisableDirPage=no
28 |
29 | [Languages]
30 | Name: "english"; MessagesFile: "compiler:Default.isl"
31 |
32 | [Tasks]
33 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
34 |
35 | [Files]
36 | Source: "D:\a\CellProfiler-Analyst\CellProfiler-Analyst\dist\CellProfiler-Analyst\CellProfiler-Analyst.exe"; DestDir: "{app}"; Flags: ignoreversion
37 | Source: "D:\a\CellProfiler-Analyst\CellProfiler-Analyst\dist\CellProfiler-Analyst\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
38 | Source: "C:\hostedtoolcache\windows\jdk\14.0.1\x64\*"; DestDir: "{app}\java"; Flags: recursesubdirs
39 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files
40 |
41 | [Icons]
42 | Name: "{commonprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
43 | Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
44 |
45 | [Run]
46 | Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
47 |
--------------------------------------------------------------------------------
/distribution/windows/CellProfiler-Analyst.spec:
--------------------------------------------------------------------------------
1 | # -*- mode: python ; coding: utf-8 -*-
2 |
3 | import os
4 | import os.path
5 |
6 | import PyInstaller.compat
7 | import PyInstaller.utils.hooks
8 |
9 | binaries = []
10 |
11 | block_cipher = None
12 |
13 | datas = []
14 |
15 | datas += PyInstaller.utils.hooks.collect_data_files("bioformats")
16 | datas += PyInstaller.utils.hooks.collect_data_files("javabridge")
17 |
18 | datas += [
19 | ("../../cpa/icons/*", "cpa/icons"),
20 | ]
21 |
22 | hiddenimports = []
23 |
24 | hiddenimports += PyInstaller.utils.hooks.collect_submodules('sklearn.utils')
25 |
26 | a = Analysis(['../../CellProfiler-Analyst.py'],
27 | pathex=['CellProfiler-Analyst'],
28 | binaries=binaries,
29 | datas=datas,
30 | hiddenimports=hiddenimports,
31 | hookspath=[],
32 | runtime_hooks=[],
33 | excludes=[],
34 | win_no_prefer_redirects=False,
35 | win_private_assemblies=False,
36 | cipher=block_cipher,
37 | noarchive=False)
38 | pyz = PYZ(a.pure, a.zipped_data,
39 | cipher=block_cipher)
40 | exe = EXE(pyz,
41 | a.scripts,
42 | [],
43 | exclude_binaries=True,
44 | name='CellProfiler-Analyst',
45 | debug=False,
46 | bootloader_ignore_signals=False,
47 | strip=False,
48 | upx=True,
49 | icon='../../cpa/icons/cpa.ico',
50 | console=False )
51 | coll = COLLECT(exe,
52 | a.binaries,
53 | a.zipfiles,
54 | a.datas,
55 | strip=False,
56 | upx=True,
57 | upx_exclude=[],
58 | name='CellProfiler-Analyst')
59 |
--------------------------------------------------------------------------------
/docs/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016, David Dao
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of CPA-docs nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = build
9 |
10 | # Internal variables.
11 | PAPEROPT_a4 = -D latex_paper_size=a4
12 | PAPEROPT_letter = -D latex_paper_size=letter
13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
14 | # the i18n builder cannot share the environment and doctrees with the others
15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
16 |
17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
18 |
19 | help:
20 | @echo "Please use \`make ' where is one of"
21 | @echo " html to make standalone HTML files"
22 | @echo " dirhtml to make HTML files named index.html in directories"
23 | @echo " singlehtml to make a single large HTML file"
24 | @echo " pickle to make pickle files"
25 | @echo " json to make JSON files"
26 | @echo " htmlhelp to make HTML files and a HTML help project"
27 | @echo " qthelp to make HTML files and a qthelp project"
28 | @echo " devhelp to make HTML files and a Devhelp project"
29 | @echo " epub to make an epub"
30 | @echo " latexmake to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
31 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
32 | @echo " text to make text files"
33 | @echo " man to make manual pages"
34 | @echo " texinfo to make Texinfo files"
35 | @echo " info to make Texinfo files and run them through makeinfo"
36 | @echo " gettext to make PO message catalogs"
37 | @echo " changes to make an overview of all changed/added/deprecated items"
38 | @echo " linkcheck to check all external links for integrity"
39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
40 |
41 | clean:
42 | -rm -rf $(BUILDDIR)/*
43 |
44 | html:
45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
46 | @echo
47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
48 |
49 | dirhtml:
50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
51 | @echo
52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
53 |
54 | singlehtml:
55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
56 | @echo
57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
58 |
59 | pickle:
60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
61 | @echo
62 | @echo "Build finished; now you can process the pickle files."
63 |
64 | json:
65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
66 | @echo
67 | @echo "Build finished; now you can process the JSON files."
68 |
69 | htmlhelp:
70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
71 | @echo
72 | @echo "Build finished; now you can run HTML Help Workshop with the" \
73 | ".hhp project file in $(BUILDDIR)/htmlhelp."
74 |
75 | qthelp:
76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
77 | @echo
78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SphinxRTDthemedemo.qhcp"
81 | @echo "To view the help file:"
82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SphinxRTDthemedemo.qhc"
83 |
84 | devhelp:
85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
86 | @echo
87 | @echo "Build finished."
88 | @echo "To view the help file:"
89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/SphinxRTDthemedemo"
90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SphinxRTDthemedemo"
91 | @echo "# devhelp"
92 |
93 | epub:
94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
95 | @echo
96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
97 |
98 | latex:
99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
100 | @echo
101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
103 | "(use \`make latexpdf' here to do that automatically)."
104 |
105 | latexpdf:
106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
107 | @echo "Running LaTeX files through pdflatex..."
108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
110 |
111 | text:
112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
113 | @echo
114 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
115 |
116 | man:
117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
118 | @echo
119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
120 |
121 | texinfo:
122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
123 | @echo
124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
125 | @echo "Run \`make' in that directory to run these through makeinfo" \
126 | "(use \`make info' here to do that automatically)."
127 |
128 | info:
129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
130 | @echo "Running Texinfo files through makeinfo..."
131 | make -C $(BUILDDIR)/texinfo info
132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
133 |
134 | gettext:
135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
136 | @echo
137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
138 |
139 | changes:
140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
141 | @echo
142 | @echo "The overview file is in $(BUILDDIR)/changes."
143 |
144 | linkcheck:
145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
146 | @echo
147 | @echo "Link check complete; look for any errors in the above output " \
148 | "or in $(BUILDDIR)/linkcheck/output.txt."
149 |
150 | doctest:
151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
152 | @echo "Testing of doctests in the sources finished, look at the " \
153 | "results in $(BUILDDIR)/doctest/output.txt."
154 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # CPA-docs
2 |
3 | Manual for CellProfiler Analyst 3.0
4 |
5 | ## How to build
6 |
7 | ```bash
8 |
9 | pip install sphinx_rtd_theme
10 | make html
11 | cd build/html
12 | python -m SimpleHTTPServer .
13 |
14 | ```
15 |
16 |
--------------------------------------------------------------------------------
/docs/build/doctrees/0_introduction.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/0_introduction.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/10_histogram_plot.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/10_histogram_plot.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/11_density_plot.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/11_density_plot.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/12_boxplot.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/12_boxplot.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/13_workspaces.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/13_workspaces.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/14_image_gallery.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/14_image_gallery.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/15_normalization_tool.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/15_normalization_tool.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/1_preliminary_requirements.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/1_preliminary_requirements.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/2_installation.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/2_installation.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/3_properties_file.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/3_properties_file.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/4_cpa_interface.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/4_cpa_interface.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/5_classifier.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/5_classifier.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/6_table_viewer.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/6_table_viewer.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/7_image_viewer.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/7_image_viewer.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/8_plate_viewer.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/8_plate_viewer.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/9_scatter_plot.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/9_scatter_plot.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/environment.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/environment.pickle
--------------------------------------------------------------------------------
/docs/build/doctrees/index.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/build/doctrees/index.doctree
--------------------------------------------------------------------------------
/docs/source/0_introduction.rst:
--------------------------------------------------------------------------------
1 | ============
2 | Introduction
3 | ============
4 |
5 | CellProfiler Analyst (CPA) provides tools for classifying biological images and exploring and visualizing multidimensional data (particularly from high-throughput experiments) that has been extracted from companion image analysis software CellProfiler.
6 |
7 | CellProfiler Analyst’s primary tools:
8 |
9 | * **Image Gallery** displays (full and cell) images with a variety of filter options and can be used interactively with other tools.
10 |
11 | * **Classifier** enables cell and field-of-view-level classification of multiple phenotypes using popular supervised machine learning models.
12 |
13 | * **Plate Viewer** displays data according to the spatial layout of the experiment, such as a multi-well plate or microarray.
14 |
15 | * **Scatter Plot**, **Histogram**, and **Density Plot** display numerical data.
16 |
17 | * **Table Viewer** displays numerical and text data in a spreadsheet format, where data points can be clicked to display images.
18 |
19 | * **Normalization Tool** creates a new datatable with normalized and feature-selected columns.
20 |
21 | The CellProfiler project is based at the Broad Institute Imaging Platform. It was started by `Anne E. Carpenter `_ and `Thouis (Ray) Jones `_
22 | in the laboratories of David M. Sabatini and Polina Golland at the Whitehead Institute for Biomedical Research and MIT's CSAIL. CellProfiler Analyst is tested on MacOS 10.15, 11.2, Windows 7 and 10, and to a lesser extent Linux. Running the software from Linux currently requires use of the source code, which is beyond the scope of this document.
23 |
24 | CellProfiler Analyst is distributed under the BSD-3 Clause (see LICENSE.txt).
25 |
--------------------------------------------------------------------------------
/docs/source/10_histogram_plot.rst:
--------------------------------------------------------------------------------
1 | =================
2 | X. Histogram Plot
3 | =================
4 |
5 | Launch **Histogram Plot** from the main CPA interface by clicking the button in the toolbar. This
6 | tool allows you to create histogram plots from the numeric columns in your tables.
7 |
8 | To use the **Histogram Plot**, simply select the table whose columns you would like to plot from
9 | the table dropdown. Then select a single measurement from that table in the x-axis dropdown
10 | (only numeric columns will be available). You can also enter the number of bins to use. The filter
11 | dropdown can be used to select filters defined in your properties file to limit the points being
12 | plotted. Finally, click the **Update Chart** button to view the plot.
13 |
14 | Once data is plotted, you can use the tools provided in the toolbar at the top of the window to
15 | explore the plot. Going backwards from right to left, the tools are as follows:
16 |
17 | - **Save**: Clicking this will give you choices for saving the plot as an image.
18 |
19 | * **Zoom-to-rect**: This tool may be toggled on and off. When it is on, you can use the mouse to click and drag a rectangle to zoom in on. The extents of the rectangle will become the new extents of the axes. Use the Back button (below) to zoom back out.
20 |
21 | - **Pan**: This tool may also be toggled. When on, you can use the mouse to pan the axes by clicking and dragging.
22 |
23 | * **Forward** and **Back**: These 2 buttons will redo and undo the zooming and panning actions 38 that you make
24 |
25 | - **Home**: This will reset the view to the way it was after Update Chart was pressed.
26 |
27 | .. figure:: static/10_01.jpg
28 | :align: center
29 |
30 | Using the Histogram Plot to view the distribution of the Nuclei_Intensity_DNA_IntegratedIntensity measurement, with the x-axis displayed in the log space. The distribution appears to be bimodal, each peak representing an accumulation of cells in different stages of mitosis.
31 |
--------------------------------------------------------------------------------
/docs/source/11_density_plot.rst:
--------------------------------------------------------------------------------
1 | ================
2 | XI. Density Plot
3 | ================
4 |
5 | Launch **Density Plot** from the main CPA interface by clicking the button in the toolbar. This tool
6 | will allow you create density plots from the numeric columns in your tables.
7 |
8 | To use the **Density Plot**, simply select the table whose columns you would like to plot from the
9 | table dropdown. Then select the measurements you would like to plot from that table in the xaxis
10 | and y-axis dropdowns (only numeric columns will be available). To view an axis in the log
11 | scale, choose **log** from the x-scale or y-scale dropdown. You may also enter the grid size to use
12 | for binning the data. The grid size is similar to the bins input in the histogram plot except that it
13 | 39
14 | is applied along both dimensions, so a grid size of 50 would yield 50x50 points. The filter
15 | dropdown can be used to select filters defined in your properties file to limit the points being
16 | plotted. Finally, click the **Update Chart** button to view the plot. With the plot displayed, you can
17 | change the color map by selecting different maps from the color map dropdown.
18 |
19 | Once data is plotted, you can use the tools provided in the toolbar at the top of the window to
20 | explore the plot. Going backwards from right to left, the tools are as follows:
21 |
22 | .. figure:: static/11_01.jpg
23 | :align: center
24 |
25 | A density plot of Nuclei_Intensity_DNA_IntegratedIntensity versus Nuclei_AreaShape_Area with log axes, log color scale, and a grid size of 100.
26 |
27 | - **Save**: Clicking this will give you choices for saving the plot as an image.
28 |
29 | * **Zoom-to-rect**: This tool may be toggled on and off. When it is on, you can use the mouse to click and drag a rectangle to zoom in on. The extents of the rectangle will become the new extents of the axes. Use the Back button (below) to zoom back out.
30 |
31 | - **Pan**: This tool may also be toggled. When on, you can use the mouse to pan the axes by clicking and dragging.
32 |
33 | * **Forward** and **Back**: These 2 buttons will redo and undo the zooming and panning actions that you make
34 |
35 | - **Home**: This will reset the view to the way it was after Update Chart was pressed.
36 |
37 | .. note::
38 | Update may take a long time for large databases. We are working to improve this performance in later releases.
39 |
--------------------------------------------------------------------------------
/docs/source/12_boxplot.rst:
--------------------------------------------------------------------------------
1 | =============
2 | XII. Box Plot
3 | =============
4 |
5 | Launch **Box Plot** from the main CPA interface by clicking the button in the toolbar. This tool will
6 | allow you create box and whisker plots from the numeric columns in your tables.
7 |
8 | To use the **Box Plot**, simply select the table whose column(s) you would like to plot from the
9 | table dropdown. Then select the measurement you would like to plot from that table in the x-axis
10 | dropdown (only numeric columns will be available). To plot multiple measurements against the
11 | same y-axis, click the **Select Multiple** button to the right of the x-axis dropdown. You will be
12 | presented with a checklist of columns to include in the plot. The filter dropdown can be used to
13 | select filters defined in your properties file to limit the points being plotted. Finally, click the
14 | **Update Chart** button to view the plot.
15 |
16 | The bottom and top of the box represent the 25th and 75th percentile of the data, with the median
17 | value represented by a horizontal red line. The whiskers on the top and bottom extend to the
18 | most extreme data point within 1.5 times the upper and lower quartiles. Outliers are
19 | represented individually with “+” shapes.
20 |
21 | Once data is plotted, you can use the tools provided in the toolbar at the top of the window to
22 | explore the plot. Going backwards from right to left, the tools are as follows:
23 |
24 | * **Save**: Clicking this will give you choices for saving the plot as an image.
25 |
26 | - **Zoom-to-rect**: This tool may be toggled on and off. When it is on, you can use the mouse to click and drag a rectangle to zoom in on. The extents of the rectangle will become the new extents of the axes. Use the Back button (below) to zoom back out.
27 |
28 | * **Pan**: This tool may also be toggled. When on, you can use the mouse to pan the axes by clicking and dragging.
29 |
30 | - **Forward** and **Back**: These 2 buttons will redo and undo the zooming and panning actions that you make
31 |
32 | * **Home**: This will reset the view to the way it was after Update Chart was pressed.
33 |
34 | .. figure:: static/12_01.jpg
35 | :align: center
36 |
37 | A box plot of Nuclei_AreaShape_Area.
38 |
--------------------------------------------------------------------------------
/docs/source/13_workspaces.rst:
--------------------------------------------------------------------------------
1 | ================
2 | XIII. Workspaces
3 | ================
4 |
5 | **Workspaces** in CPA are a way of saving the state of your plots so they can be reopened later
6 | and even applied as a template to new datasets.
7 |
8 | Suppose you are performing quality control on a biological screen in which new plates (or
9 | slides) are imaged every week. The way you process and perform quality control on each new
10 | plate is largely the same. For example, you first run a CellProfiler pipeline producing various QC
11 | measures such as focus scores and stain intensities. Then, in CPA, you want to create (for
12 | example) a DNA content histogram and a scatterplot of Measurement_X vs. Measurement_Y
13 | while filtering for your controls. You also display Measurement_Z in P**late Viewer** to look for
14 | wells that may be out of focus. All of these plots can be saved in a workspace file by CPA, and
15 | 42
16 | applied to new data later.
17 |
18 | To create a workspace, simply open and configure the plots that you wish to save. Then choose
19 | **File > Save workspace** from the CPA file menu. The file that you save will contain configuration
20 | details for all of the currently open plots (Note: Table Viewer and Classifier do not yet support
21 | saving configurations). These same plots can be reopened in CPA by choosing **File > Load
22 | workspace** from the CPA file menu when the same properties file is used. To apply the
23 | workspace to a new dataset, simply open CPA with a different properties file that points to your
24 | other data, then choose **File > Load workspace** from the CPA file menu. CPA will try to apply
25 | the same settings to all of the plots that were open while using your new data.
26 |
27 | **Warning**: If you save a histogram plot of per_image.Measurement_X in a workspace
28 | and try to open the workspace with a dataset that doesn’t have a Measurement_X
29 | column in it’s per_image table, CPA will simply use the first measurement in your
30 | per_image table instead.
31 |
--------------------------------------------------------------------------------
/docs/source/14_image_gallery.rst:
--------------------------------------------------------------------------------
1 | ==================
2 | XIV. Image Gallery
3 | ==================
4 | Image Gallery provides a convenient gridview allowing an overview of images from the entire experiment. A variety of options are provided to filter images based on experiment-specific metadata, e.g., gene name, compound treatments, etc. Multiple filters can be combined to refine the search. Images can be displayed as a custom-sized thumbnail or in full resolution, and the color assigned to each channel in the image can be customized to highlight structures of interest. Individual segmented cells can be viewed for each image, and can be dragged and dropped into the Classifier window.
5 |
6 | Image Gallery consists of a menu bar, an area for the image gallery area, and an area for the objects of segmented image. In the menu bar, you can choose what image you want to fetch. You can choose a range of images based on image ID from the experiment or a filter, all images from the experiment or a filter, or an individual image based on image ID. Once the selection is made, click **Fetch** to load the relevant images.
7 |
8 | For each image loaded in the image gallery area, right-click to show the options.
9 | - Select **View full images of selected** or double-click an individual tile to show the object in the context of the image from which it was drawn. This launches the **Image Viewer** tool (section V).
10 | - **Select all/Deselect all** (``ctrl+A/ctrl+D``) selects/deselects all tiles in the bin so they can be dragged and dropped together.
11 | - **Invert selection** (``ctrl+I``) to invert your selection (that is, select all non-selected tiles in the current bin and deselect all selected tiles).
12 | - **Remove selected** (``Delete``) removes the selected tiles from the current bin.
13 | - **Fetch all objects from image** populates the objects of segmented image area below with all objects belonging to the selected image(s).
14 |
15 | Images loaded in the area for the objects of segmented image have the same right-click options except for **Fetch all objects from image**. Tiles in this area can be dragged and dropped into the Classifier.
16 |
17 | .. figure:: static/14_01.jpg
18 | :align: center
19 |
20 | Image Gallery
--------------------------------------------------------------------------------
/docs/source/15_normalization_tool.rst:
--------------------------------------------------------------------------------
1 | =======================
2 | XV. Normalization Tool
3 | =======================
4 |
5 | .. figure:: static/15_01.jpg
6 | :align: center
7 |
8 | Normalization Tool
--------------------------------------------------------------------------------
/docs/source/16_dimensionality_reduction.rst:
--------------------------------------------------------------------------------
1 | =============================
2 | XVI. Dimensionality Reduction
3 | =============================
4 |
5 | Click the **Reduction** button in the main CPA interface toolbar to launch the Dimensionality Reduction tool. This tool
6 | will allow you to perform several reduction methods and visualise the results as a scatter plot.
7 |
8 | .. figure:: static/16_01.jpg
9 | :align: center
10 |
11 | Dimensionality Reduction Tool
12 |
13 | Dimensionality reduction condenses large numbers of measurements into a more managable number of components, this can
14 | help to visualise results and identify clusters of objects and outliers.
15 |
16 | To use the **Dimensionality Reduction Plot**, select a reduction method from the available choices and click
17 | **Update Chart**. The different methods are explained further in the sections below. CPA will normalise measurements
18 | before applying these methods.
19 |
20 | The x- and y-axis dropdowns can be used to switch between display of different components on each axis. Click
21 | **Update Chart** after making a selection to display the data.
22 |
23 | Displaying "Scores" will show the positions of individual objects from your dataset. Hovering over a
24 | point will display a key for that object in the toolbar. A key of (4, 14) would mean Image #4, Object #14. Some
25 | reduction methods will have the option to display "Loadings", for which the average position of each original
26 | measurement column will be shown on the new axes. Hovering over a loading point will display the measurement name.
27 |
28 | Filters can be used to restrict which objects will be displayed on the resulting plot. Note that, due to the nature of
29 | these reduction methods, data from all objects from a dataset will be used to perform the initial reduction.
30 |
31 | In the toolbar, you'll also find the **lasso tool**. Activating this will allow you to draw a selection polygon onto
32 | the current plot. Any points within the polygon will be considered as selected. Right-clicking on a plot with an
33 | active selection will produce a popup menu with options to visualise the highlighted objects. If you have a Classifier
34 | tool open, you'll also see the option to *send the selected objects directly to the classifier*.
35 |
36 | Reduction Methods
37 | *****************
38 |
39 | - **Principal Component Analysis (PCA)**: PCA attempts to generate a series of features which capture the variance of the original dataset. Measurements which vary in the same manner are collapsed towards a single new measurement, termed a *Principal Component*. On the resulting axis labels, CPA will also display the proportion of the original variance which is explained by each principal component. Components are sorted by their contribution to variance, so PC1 will always be the most significant feature.
40 |
41 | - **Singular Value Decomposition (SVD)**: SVD is very similar to PCA, but does not center the data before processing. This can be much faster and more memory efficient than PCA when working with very large datasets, but a trade-off is that the resulting components will not be ordered by significance (i.e. PC1 may not be the most important feature).
42 |
43 | - **Gaussian Random Projection (GRP)**: This method reduces the dimensionality of the dataset by projecting samples into fewer dimensions while preserving the pairwise distances between them. The random matrix used for projection is generated using a gaussian distribution.
44 |
45 | - **Sparse Random Projection (SRP)**: Similar to GRP, but uses a sparse matrix instead of a gaussian one. This can be more memory efficient with large datasets.
46 |
47 | - **Factor Analysis (FA)**: Like PCA, Factor Analysis generates a series of components which describe the variance of the dataset. However, with FA the variance in each direction within the input space can be modelled independently.
48 |
49 | - **Feature Agglomeration (FAgg)**: This method utilises hierarchical clustering to group together features that behave similarly. The generated clusters can then be treated like components
50 |
51 | - **t-Distributed Stochastic Neighbor Embedding (t-SNE)**: t-SNE helps to visualise high dimensional data by giving individual datapoints a coordinate on a 2D map, on which similar points are placed close together. The resulting clusters can help to visualise different object types within a dataset.
52 |
53 |
--------------------------------------------------------------------------------
/docs/source/17_FAQ.rst:
--------------------------------------------------------------------------------
1 | =======================
2 | XVII. FAQ
3 | =======================
4 |
5 | Q1: I automatically correct images in my CP pipeline and save the corrected images to perform the analysis on them. However CPA opens the uncorrected images. I can't change the settings in the CPA properties file, and the path to the corrected images is not stored in the database (the corrected images are stored in the input folder but they have a different name).
6 | From https://forum.image.sc/t/path-to-aligned-images-in-cpa/16850
7 |
8 | A1: In the SaveImages module for the corrected images, check the box near the end of the settings that says "Record the file and path information to the saved image?" That setting is where the path gets input into the database and then into your properties file.
--------------------------------------------------------------------------------
/docs/source/1_preliminary_requirements.rst:
--------------------------------------------------------------------------------
1 | ================================
2 | I. Preliminary data requirements
3 | ================================
4 |
5 | CPA requires access to the following data sources:
6 |
7 | - An image table and an object table containing measurements and metadata
8 |
9 | These may reside in a MySQL or SQLite database or in a set of comma-separated value (CSV) files. A MySQL database is recommended, though you may need to consult with your local information technology staff to set up a database server. See section II.B for more information. The tables must contain a few datacolumns needed by CellProfiler Analyst to access images and data properly, such as an Image ID column to link the per-image and per-object tables, file path and file name columns to specify where images are stored, and X, Y location columns to specify where each object resides within the image. These configuration details are specified in a properties file. Note: if image classification is specified in the properties file, an object table is not required. See section III.
10 |
11 | - The images that were analyzed to generate the above-mentioned Table Viewers
12 |
13 | These can be stored either locally or remotely and accessed via HTTP. The directory structure does not matter as long as the file paths stored in the image table point to the correct images.
14 | Throughout CPA, the term image is meant to include all image data associated with an analyzed field-of-view. An image in this sense usually includes several individual monochromatic images that show the different wavelengths (channels) as well as images that show outlines of identified objects. You can specify any number of image channels (including, for example, outlines of objects that resulted from image processing) by adding path and filename columns to the image table of your database for each channel.
15 | CPA currently requires image files to be monochromatic; several individual channels can be combined into a color image for viewing within the software.
16 | CPA currently supports the following image file types: BMP, CUR, DCX, Cellomics DIB, FLI, FLC, FPX, GBR, GD, GIF, ICO, IM, IMT, IPTC/NAA, JPG/JPEG, MCIDAS, MIC, MSP, PCD, PCX, PIXAR, PNG, PPM, PSD, SGI, SPIDER, TGA, TIF/TIFF, WAL, XBM, XPM, XV Thumbnails.
17 |
18 | .. note::
19 | While designed for high-throughput, image-based biological experiments, CellProfiler Analyst is also useful for the exploration of other multi-dimensional data sets, particularly when data points are linked to images.
20 |
21 | I.A Example image table
22 | =======================
23 |
24 | The image table requires one column for a unique image ID and a pair of columns for each channel represented in the images: one column for the image path, and one column for the image file name (which may include some part of the path to the image, such as the subdirectory that contains the file). These columns do not need to have specific names; you will indicate which column names correspond to image ID, image path, and image filename when configuring the properties file. The remaining columns can contain measurements and metadata about each image.
25 |
26 | .. note::
27 | While MySQL and SQLite support diverse column names, CPA will not handle column names that contain commas. In general, we advise that you use only alphanumeric characters and underscores in the names of your table columns.
28 |
29 | An image table for an experiment involving cells imaged for GFP and Hoechst would have two channels and would look something like this:
30 |
31 | .. figure:: static/01_01.jpg
32 | :align: center
33 |
34 | I.B Example object table
35 | =========================
36 |
37 | The object table requires four columns: a foreign key image ID column that corresponds to the image ID in the image table, a unique object ID column, a column for the object x-location, and a column for the object y-location. CPA expects the location columns to correspond to the x-y pixel coordinates of the objects’ centroids; the corresponding column names that are produced by CellProfiler depend on the name of the objects; for example, if nuclei were measured, the column names would be Nuclei_Location_Center_X and Nuclei_Location_Center_Y. Again, these columns do not need to have specific names; you indicate which column names correspond to these functionalities when configuring the properties file. Additional columns in this table typically contain measurements for each object, but are completely up to the user.
38 |
39 | .. note::
40 | While MySQL and SQLite support diverse column names, CPA will not handle column names that contain commas. In general, we advise that you use only alphanumeric characters and underscores in the names of your table columns.
41 |
42 | An object table for an experiment involving cells imaged for GFP and Hoechst would have two channels and would look something like this:
43 |
44 | .. figure:: static/01_02.jpg
45 | :align: center
46 |
--------------------------------------------------------------------------------
/docs/source/2_installation.rst:
--------------------------------------------------------------------------------
1 | ====================================
2 | II. Installation and getting started
3 | ====================================
4 |
5 | CPA releases
6 | ============
7 |
8 | All CellProfiler-Analyst releases can be found `here `_
9 |
10 | II.A Mac OS
11 | =============
12 |
13 | Copy CellProfiler-Analyst.app to /Applications.
14 |
15 | II.B Windows
16 | ==============
17 |
18 | Run the setup.exe to install CPA and create shortcuts.
19 |
20 | II.C Using the example dataset
21 | ==============================
22 |
23 | Download the CPA example dataset from http://cellprofileranalyst.org/ or `this link `_ and unzip it to create the cpa_example directory. This directory contains:
24 |
25 | 1. example.properties - Configuration file for CPA (see section III).
26 | 2. MyTrainingSet.txt - Example training set file to be used in the Classifier (see section V).
27 | 3. images/ - Images from the screen used in the example.
28 | 4. per_image.csv - Comma Separated Values file for image data. This file was exported by CellProfiler’s ExportToDatabase module.
29 | 5. per_object.csv - Comma Separated Values file for object data. This file was exported by CellProfiler’s ExportToDatabase module.
30 | 6. example_SETUP.SQL - Used by CPA to create an internal database (SQLite). It can also be used to create a MySQL database. This file was exported by CellProfiler’s ExportToDatabase module.
31 |
32 | Run the CPAnalyst file created by the install process above. A dialog will appear asking you to select a properties file. Navigate to the cpa_example directory and select the example.properties file. You’re now ready to experiment with CellProfiler Analyst!
33 |
--------------------------------------------------------------------------------
/docs/source/4_cpa_interface.rst:
--------------------------------------------------------------------------------
1 | ======================================
2 | IV. The CellProfiler Analyst Interface
3 | ======================================
4 | To run CPA, double-click the CPAnalyst.exe file on Windows or CPAnalyst.app on Mac OS. Once you have selected a properties file to load, the following small window will appear.
5 |
6 | .. figure:: static/04_01.jpg
7 | :align: center
8 | .. figure:: static/04_02.jpg
9 | :align: center
10 |
11 | CellProfiler Analyst main window.
12 |
13 | This window provides a toolbar at the top with icons to launch each of CPA’s tools. The currently available tools are Image Gallery, Classifier, Plate Viewer, Scatter Plot, Histogram, Density Plot and Table Viewer. These tools can also be launched from the Tools menu. More tools will be added to this suite in the future.
14 |
15 | Below the toolbar is a logging console that all the tools will use to provide feedback on status, warnings, etc. This console can be configured to display messages at 5 levels of verbosity chosen from the Logging menu. In order of increasing verbosity, these are:
16 |
17 | - Critical: Virtually no messages. Will only report critical errors.
18 | - Errors: Only reports error messages.
19 | - Warnings: Only reports warnings and error messages.
20 | - Info: Reports general status information as well as any warnings and errors.
21 | - Debug: Reports technical information such as SQL queries in addition to all other messages listed above.
22 |
23 | You can also optionally disable logging of image loading events by using the "Log image loading" toggle in the logging menu.
24 |
25 | You can save the log to a file by selecting File > Save Log, or copied by selecting the text and using Ctrl+C (or your operating system default copy command).
26 |
27 | You will also find menu items to save and load workspaces under the File menu. See Section XIII for more on workspaces in CPA and how they can help you analyze new data more quickly.
28 |
29 |
30 |
31 | SQL query tool
32 | --------------
33 |
34 | The advanced menu provides a SQL query tool for writing SQL statements to query
35 | the DB
36 |
37 | .. figure:: static/04_03.jpg
38 | :align: center
39 |
40 | Querying for all unique genes in per_image table
41 |
42 | .. figure:: static/04_04.jpg
43 | :align: center
44 |
45 | Result of the query above for cpa_example dataset
46 |
47 |
48 |
--------------------------------------------------------------------------------
/docs/source/6_table_viewer.rst:
--------------------------------------------------------------------------------
1 | ================
2 | VI. Table Viewer
3 | ================
4 | Certain tools, such as Classifier, produce a table that will be opened in the Table Viewer. As well, any CSV file or database table can be viewed by using this tool.
5 |
6 | .. figure:: static/06_01.jpg
7 | :align: center
8 | .. figure:: static/06_02.jpg
9 | :align: center
10 |
11 | Table Viewer produced by Classifier, grouped by well number and gene (only positive Enrichment Score column).
12 |
13 | Features available in the Table Viewer
14 | --------------------------------------
15 |
16 | - **Sort**: Click on any column heading to sort the data based on that column. Click again to reverse the sort. To sort by more than one column (i.e., sort first by column X, then by column Y), click on the first heading of the first column you want to sort by, then hold shift and click on the next column heading. You can add any number of columns to a sorting in this way. Sorting order and direction is indicated in brackets at the end of the header name by a number and an arrow (^ or v). Clicking on any column header that is already part of a sorting will reverse the direction of the sort. Pressing shift+click on a column header that is already part of a sorting will remove that column from the sorting.
17 | - **Show images**: Double-click on a row header to show the image or images in that row’s group. Right-click to see a list of the image-keys in that row and click one to open it.
18 | - **View summary statistics**: Click anywhere within the table to select a column. A summary of statistical information about the selected column(s) is displayed in the status bar at the bottom of the window. You may select multiple columns by pressing ctrl+click (cmd+click on a Mac).
19 | - **Show/hide columns**: To select which columns are shown in the Table Viewer, select View > Show/hide columns and a dialog will appear with a list of columns. Check off the columns that you wish to show, and uncheck the column that you want hidden.
20 | - **Saving and loading CSV files**: CPA can read and write CSV (comma-separated value) files by selecting File > Load table from CSV or File > Save table to CSV. When saving a table it’s important to note that columns that were hidden (see above) will not be written to the CSV.
21 | - **Saving and Loading database tables**: Table Viewer can also load and save database tables. This means you can easily open a CSV file in Table Viewer and then store that table in your database for plotting and analysis in CPA. Conversely, you can load a database table into Table Viewer (such as your per-object table), and save it on your computer as a CSV. As with CSVs, saving and loading from the database can be done via File > Load table from database and File > Save table to database. Note, when saving a table to the database, you will be prompted whether to store the table permanently or "for this session only" – which means the table will be removed from the database when you close CPA.
22 |
23 | .. note::
24 | When saving a table to the database, you will be prompted whether to store the table permanently or "for this session only" – which means the table will be removed from the database when you close CPA.
25 |
--------------------------------------------------------------------------------
/docs/source/7_image_viewer.rst:
--------------------------------------------------------------------------------
1 | =================
2 | VII. Image Viewer
3 | =================
4 |
5 | Certain CPA tools, such as **Classifier**, display images in **Image Viewer**, and any image in the
6 | experiment can also be opened within CPA by choosing this tool from CPA’s **Tools** menu or by
7 | clicking the **Image Viewer** icon in the toolbar.
8 |
9 | .. figure:: static/07_01.jpg
10 | :align: center
11 | .. figure:: static/07_02.jpg
12 | :align: center
13 |
14 | The Image Viewer.
15 |
16 | When you open Image Viewer from CPA, it will prompt for the ID number of an image to show. If
17 | you also specified a ``table_id`` column in your properties file, then you will also be prompted for
18 | the table number. You can load additional images by selecting **File > Open Image (ctrl+O)**.
19 |
20 | If you specified ``plate_id`` and ``well_id`` in your properties file, then Image Viewer will display
21 | the plate and well in the title of the window along with the image-key, which is image 328 in the
22 | example above.
23 |
24 | The ``image_names`` that are specified in your properties file will appear in the menu bar. In the
25 | example above, the user has specified names for the **Actin**, **pH3**, and **DNA** channels. If you
26 | have not defined names for any channels, the menu bar will contain **channel-1**, **channel-2**, etc.
27 |
28 | Click on one of the channel names to see a dropdown list of available colors for each – clicking
29 | on a color will map that color onto the channel. If you specified ``image_channel_colors`` in
30 | your properties file, those colors specified there should appear under each channel menu by
31 | default.
32 |
33 | The Classifier menu provides an item that will let you classify the objects in the current image.
34 | This item is only enabled if Classifier is running and trained. For more
35 | on this feature see the **Score image** discussion in section III.C.6.
36 |
37 | - **Tip**: You can use keyboard shortcuts to toggle each channel on/off: Ctrl+1, +2, +3, … will toggle first, second, third, etc. color channels.
38 |
39 | Click **Show controls** (or press the space bar) to display the Image Viewer control panel, which
40 | controls brightness, contrast, and scale. This same control panel is available in Classifier by
41 | choosing **View > Image Controls** (see section III.C.1).
42 |
43 | .. figure:: static/07_03.jpg
44 | :align: center
45 |
46 | Image controls
47 |
48 | The upper slider controls brightness; the lower one rescales the size of the image or image tiles.
49 | The **Contrast Stretch** controls let you stretch the image contrast by rescaling the pixel
50 | intensities of each channel independently to fit the range 0-1 (where 0 is unsaturated and 1 is
51 | saturated).
52 |
53 | - **Linear** scales the image intensities linearly. For an image in the range 0-0.5, pixels at 0.5 intensity would be rescaled to 1.0, and pixels at 0.4 rescaled to 0.8; in short, all pixel intensities in the image would be doubled.
54 |
55 | - **Log** transform scales the image intensities logarithmically, which has the effect of scaling dimmer pixels by a greater factor than it scales brighter pixels.
56 |
57 | **Warning**: scaling in this way may yield misleading results. For example, if a channel of an
58 | image shows very little staining, the raw image may have intensities in a low, narrow range,
59 | e.g., from [0-0.01]. Stretching in this case would have the effect of raising the background
60 | intensity levels so that the image overall appears very bright.
61 |
--------------------------------------------------------------------------------
/docs/source/8_plate_viewer.rst:
--------------------------------------------------------------------------------
1 |
2 | ==================
3 | VIII. Plate Viewer
4 | ==================
5 |
6 | Plate Viewer is a tool for browsing image-based data laid out on multi-well plates common to
7 | high-throughput biological screens. Supported formats are:
8 |
9 | - **96 well plate** — 8 rows x 12 columns
10 | - **384 well plate** — 16 rows x 24 columns
11 | - **1536 well plate** — 32 rows x 48 columns
12 | - **5600 spot microarray** — 40 rows x 140 columns
13 |
14 | To launch this tool click the Plate Viewer icon in the CPA toolbar or select **Tools > Plate Viewer**
15 | from the CPA menu bar.
16 |
17 | .. figure:: static/08_01.jpg
18 | :align: center
19 |
20 | Sample Plate Viewer for a single 96-well plate, viewing the mean positive enrichment score output by Classifier. We can see that well D07 is very highly enriched for our "positive" cell phenotype.
21 |
22 | .. note::
23 | An **X** in one of the wells means there was no data in the database corresponding to that particular well. However, it may still contain images that can be viewed, as described below.
24 |
25 | In the colored plate display, right-clicking on a well will display a list of image-keys found in that
26 | well. Selecting one image-key will open that image in the **Image Viewer** (section V). Doubleclicking
27 | on a well will open all images from that well, each in its own Image Viewer.
28 |
29 | Above the plate is a menu that lets you specify the plate number to display. Holding the cursor
30 | over a particular well will display a tooltip showing the value pertaining to that well.
31 |
32 | The left-hand column contains many options for generating different views into your data.
33 |
34 | - **Data source**: Allows you to select a table for visualization. You cannot load a CSV directly into the Plate Viewer. You must open the CSV in Table Viewer first, save it to the database, and then open it in Plate Viewer.
35 | - **Measurement**: The column from the selected table that you would like to visualize.
36 | - **Aggregation Method**: Measurements must be aggregated to a single number for each well so that they can be represented by a color. Options are **mean**, **sum**, **median**, **standard deviation**, **cv%** (coefficient of variation), **minimum**, and **maximum**. If you’re viewing ``object_count`` from the image table, for example, you might select **sum** to visualize the sum of the object counts for all images that constitute a well.
37 |
38 | **Important**: Plate Viewer is agnostic with regard to the type of data it aggregates, so viewing columns from the image table will not cause the viewer to access any data from the object table. For example, a biological screen with 4 images (sites) per well may be analyzed in CellProfiler, and cell measurements may be aggregated to each image and output to the image table. One column grom the table, ``Image_Intensity_DNA_Mean_ Intensity``, could be visualized in Plate Viewer and aggregated from each image to each well by, say, the **maximum** option. This could be mistakenly thought to be reporting the maximum DNA intensity value of any cell from that well, when it is actually reporting the maximum of the mean per-image DNA intensity per-well.
39 |
40 | - **Color Map**: Each value computed by the Aggregation Method is mapped to a color via a color map. The currently selected color map is represented in a bar beneath the plate maps. More than 50 color maps are available.
41 | - **Well Shape**: Mostly for presentation purposes, you can select from different well shapes. Options are **square**, **rounded**, **circle**, and **image**.
42 |
43 | Important: The "*image*" feature is still under development. This will display a
44 | rescaled image from each well in the place of the well itself. This can take a very
45 | long time to refresh since full sized images must be loaded for every well in view. For
46 | it to be useful, viewing 1 plate at a time and maximizing the window is advised. Note:
47 | that the color map is irrelevant when using this view.
48 |
49 | - **Number of Plates**: Enter the number of plates you would like to view at once, and press the Enter or Return key.
50 |
51 | Here is a four-plate view of the same experiment shown in the previous example, in which the user has chosen to view the mean of the per-object measurement *Spindle_AreaShape_Area* in each well across 4 plates.
52 |
53 | .. figure:: static/08_y.jpg
54 | :align: center
55 |
56 | Viewing four 96-well plates at once in Plate Viewer. Here we are visualizing the mean Spindle_AreaShape_Area in each well. This makes it easy to visualize many thousands of object measurements in a meaningful way.
57 |
58 | .. figure:: static/08_z.jpg
59 | :align: center
60 |
61 | Viewing the sums of the per-object measurement tubulin_AreaShape_Area in each well of a single 384-well plate in Plate Viewer. Notice that while well C01 has the largest tubulin area (62406) in this plate, the color bar indicates that the largest value of this measurement in the experiment is 91617, which must be in some other plate.
62 |
63 | The color bar axis at the bottom of the window shows how the aggregated values of the selected measurement column map to colors:
64 |
65 | - The numbers at the far left and right of the axis represent the minimum and maximum values found in the entire experiment.
66 | - The value range of the current plate(s) extends to the point where the color bar stops and a thin black line begins.
67 |
68 | To assist in visualizing data, particularly when there are extreme outlier data points, you can
69 | **rescale** or **clip** the color bar by dragging the handles found at the far ends of the bar.
70 |
71 | - **Color rescaling**: This will rescale the full color map to fit within the minimum and maximum values at the handles. Values below the range are mapped to the minimum (leftmost) color, values above the range are mapped to the maximum (rightmost) color.
72 |
73 | - **Color clipping**: As with color rescaling, this will map values below the range to the minimum color, and values above the range to the maximum color. However, the full range of colors will not be rescaled to fit within the handles, it is cropped or “clipped.”
74 |
75 | To change the mode from rescaling to clipping, right click on the bar and select **Value
76 | bracketing: CLIP**, to change it back to rescaling, do the same and select **Value bracketing:
77 | RESCALE**. To set the sliders back at the global min and max, select **Reset sliders**.
78 |
79 | .. figure:: static/08_16.jpg
80 | :align: center
81 |
82 | Selecting Color Bar options.
83 |
--------------------------------------------------------------------------------
/docs/source/9_scatter_plot.rst:
--------------------------------------------------------------------------------
1 | ================
2 | IX. Scatter Plot
3 | ================
4 |
5 | Launch **Scatter Plot** from the main CPA interface by clicking the button in the toolbar. This tool
6 | will allow you to create scatter plots from the numeric columns in your tables.
7 |
8 | .. figure:: static/09_01.jpg
9 | :align: center
10 |
11 | Using Scatter Plot to visualize the relationship between the Image_Intensity_DNA_Mean_intensity and the Image_Intensity_pH3_Mean_intensity image measurements.
12 |
13 | To use the **Scatter Plot**, simply select the table whose columns you would like to plot from the
14 | table dropdown. Then select measurements from that table in the x-axis and y-axis dropdowns
15 | (only numeric columns will be available). To view an axis in the log scale, choose **log** from the
16 | x-scale or y-scale dropdown. The filter dropdown can be used to select filters defined in your
17 | properties file to limit the points being plotted. Finally, click the **Update Chart** button to view the
18 | plot.
19 |
20 | .. note::
21 | Update may take a long time or even fail for large databases. We are working to improve this performance in later releases.
22 |
23 | Once data is plotted, you can use the tools provided in the toolbar at the top of the window to
24 | 37
25 | explore the plot. Going backwards from right to left, the tools are as follows:
26 |
27 | - **Save**: Clicking this will give you choices for saving the plot as an image.
28 |
29 | * **Zoom-to-rect**: This tool may be toggled on and off. When it is on, you can use the mouse to click and drag a rectangle to zoom in on. The extents of the rectangle will become the new extents of the axes. Use the Back button (below) to zoom back out.
30 |
31 | - **Pan**: This tool may also be toggled. When on, you can use the mouse to pan the axes by clicking and dragging.
32 |
33 | * **Forward** and **Back**: These 2 buttons will redo and undo the zooming and panning actions that you make
34 |
35 | - **Home**: This will reset the view to the way it was after Update Chart was pressed
36 |
37 | **Selection**:
38 | When the pan and zoom tools are toggled off, the default action of the mouse is to draw a
39 | freeform selection. You can add to an existing selection by holding the shift key while drawing a
40 | new shape. Likewise, you can subtract from a selection by holding alt and drawing a selection
41 | around the points you wish to deselect.
42 |
43 | **Viewing Images**:
44 | You can view the images from a selection by right-clicking on the plot and selecting “Show
45 | images from selection” from the resultant popup menu. This will pop up a list of the selected
46 | image keys along with their plate and well information (if specified in your properties file).
47 | Double clicking on an image entry will launch that image in the **Image Viewer** tool.
48 |
--------------------------------------------------------------------------------
/docs/source/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/__init__.py
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. Sphinx RTD theme demo documentation master file, created by
2 | sphinx-quickstart on Sun Nov 3 11:56:36 2013.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | ==========
7 | Manual 3.0
8 | ==========
9 |
10 | .. image:: https://i.imgur.com/uaEp2md.png
11 |
12 | Table of Contents:
13 |
14 | .. toctree::
15 | :maxdepth: 1
16 |
17 | 0_introduction
18 | 1_preliminary_requirements
19 | 2_installation
20 | 3_properties_file
21 | 4_cpa_interface
22 | 5_classifier
23 | 6_table_viewer
24 | 7_image_viewer
25 | 8_plate_viewer
26 | 9_scatter_plot
27 | 10_histogram_plot
28 | 11_density_plot
29 | 12_boxplot
30 | 13_workspaces
31 | 14_image_gallery
32 | 15_normalization_tool
33 | 16_dimensionality_reduction
34 | 17_FAQ
35 |
--------------------------------------------------------------------------------
/docs/source/manual.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/manual.pdf
--------------------------------------------------------------------------------
/docs/source/static/01_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/01_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/01_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/01_02.jpg
--------------------------------------------------------------------------------
/docs/source/static/03_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/03_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/03_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/03_02.jpg
--------------------------------------------------------------------------------
/docs/source/static/04_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/04_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/04_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/04_02.jpg
--------------------------------------------------------------------------------
/docs/source/static/04_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/04_03.jpg
--------------------------------------------------------------------------------
/docs/source/static/04_04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/04_04.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_00.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_00.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_02.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_03.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_04.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_04b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_04b.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_05.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_05.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_06.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_06.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_06b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_06b.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_07.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_07.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_08.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_08.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_09.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_09.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_09a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_09a.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_09b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_09b.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_10.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_11.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_11b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_11b.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_12.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_13.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_14.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_15.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_16.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_16.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_17.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_17.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_18.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_18.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_19.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_19.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_20.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_20.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_a.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_b.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_e.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_e.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_f.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_f.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_y.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_y.jpg
--------------------------------------------------------------------------------
/docs/source/static/05_z.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/05_z.jpg
--------------------------------------------------------------------------------
/docs/source/static/06_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/06_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/06_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/06_02.jpg
--------------------------------------------------------------------------------
/docs/source/static/06_04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/06_04.jpg
--------------------------------------------------------------------------------
/docs/source/static/07_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/07_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/07_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/07_02.jpg
--------------------------------------------------------------------------------
/docs/source/static/07_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/07_03.jpg
--------------------------------------------------------------------------------
/docs/source/static/07_pic1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/07_pic1.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_00.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_00.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_001.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_001.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_02.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_03.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_04.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_05.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_05.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_06.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_06.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_08.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_08.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_09.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_09.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_10.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_11.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_13.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_14.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_15.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_16.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_16.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_x.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_x.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_y.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_y.jpg
--------------------------------------------------------------------------------
/docs/source/static/08_z.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/08_z.jpg
--------------------------------------------------------------------------------
/docs/source/static/09_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/09_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/09_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/09_02.jpg
--------------------------------------------------------------------------------
/docs/source/static/09_z.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/09_z.jpg
--------------------------------------------------------------------------------
/docs/source/static/10_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/10_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/11_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/11_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/12_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/12_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/14_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/14_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/15_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/15_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/16_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/16_01.jpg
--------------------------------------------------------------------------------
/docs/source/static/5_c.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/5_c.jpg
--------------------------------------------------------------------------------
/docs/source/static/5_d.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/docs/source/static/5_d.jpg
--------------------------------------------------------------------------------
/manual/cpa_manual.doc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CellProfiler/CellProfiler-Analyst/8a7f924052867192b425e4b7f89137fadbbd93fa/manual/cpa_manual.doc
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | boto3
2 | botocore
3 | imagecodecs
4 | imageio
5 | joblib
6 | matplotlib
7 | mock
8 | mysqlclient
9 | numpy
10 | pandas
11 | Pillow
12 | progressbar
13 | python-bioformats
14 | python-javabridge
15 | pytz
16 | requests
17 | scikit-learn
18 | scipy
19 | seaborn
20 | verlib
21 | wxPython
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import codecs
2 | import os
3 | import re
4 |
5 | import setuptools.dist
6 |
7 | import cpa.util.version
8 |
9 |
10 | def read(*directories):
11 | pathname = os.path.abspath(os.path.dirname(__file__))
12 |
13 | return codecs.open(os.path.join(pathname, *directories), "r").read()
14 |
15 |
16 | def find_version(*pathnames):
17 | data = read(*pathnames)
18 |
19 | matched = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", data, re.M)
20 |
21 | if matched:
22 | return matched.group(1)
23 |
24 | raise RuntimeError("Unable to find version string.")
25 |
26 |
27 | def package_data():
28 | resources = []
29 |
30 | for root, _, filenames in os.walk(os.path.join("cellprofiler", "data")):
31 | resources += [
32 | os.path.relpath(os.path.join(root, filename), "cellprofiler")
33 | for filename in filenames
34 | ]
35 |
36 | for root, _, filenames in os.walk(os.path.join("cellprofiler", "gui")):
37 | resources += [
38 | os.path.relpath(os.path.join(root, filename), "cellprofiler")
39 | for filename in filenames
40 | if ".html" in filename
41 | ]
42 |
43 | return {"cellprofiler": resources}
44 |
45 |
46 | setuptools.setup(
47 | app=['CellProfiler-Analyst.py'],
48 | author="Broad Institute",
49 | author_email="imagingadmin@broadinstitute.org",
50 | classifiers=[
51 | "Development Status :: 5 - Production/Stable",
52 | "Intended Audience :: Science/Research",
53 | "License :: OSI Approved :: BSD License",
54 | "Operating System :: OS Independent",
55 | "Programming Language :: Python :: 3",
56 | "Programming Language :: Python :: 3.8",
57 | "Topic :: Scientific/Engineering :: Bio-Informatics",
58 | "Topic :: Scientific/Engineering :: Image Recognition",
59 | "Topic :: Scientific/Engineering",
60 | ],
61 | # entry_points={"console_scripts": ["cellprofiler-analyst=CellProfiler-Analyst.__main__:main"]},
62 | extras_require={
63 | "build": ["pyinstaller"],
64 | },
65 | install_requires=[
66 | "boto3==1.17.15",
67 | "botocore==1.20.15",
68 | "imagecodecs>=2021.2.26",
69 | "imageio>=2.9.0",
70 | "joblib>=1.0.1",
71 | "matplotlib==3.3.4",
72 | "mock>=4.0.3",
73 | "mysqlclient>=2.0.3",
74 | "numpy>=1.20.1",
75 | "pandas>=1.2.2",
76 | "Pillow>=8.1.0",
77 | "progressbar>=2.5",
78 | "python-bioformats>=4.0.4",
79 | "python-javabridge>=4.0.3",
80 | "pytz>=2021.1",
81 | "requests>=2.25.1",
82 | "scikit-learn>=0.24.1",
83 | "scipy>=1.6.1",
84 | "seaborn>=0.11.1",
85 | "tifffile>=2021.3.31",
86 | "verlib==0.1",
87 | "wxPython==4.1.0",
88 | ],
89 | license="BSD",
90 | name="CellProfiler-Analyst",
91 | package_data=package_data(),
92 | include_package_data=True,
93 | packages=setuptools.find_packages(exclude=["tests*"]),
94 | python_requires=">=3.8",
95 | setup_requires=["pytest"],
96 | url="https://github.com/CellProfiler/CellProfiler-Analyst",
97 | version=cpa.util.version.__version__,
98 | windows=[{'script': 'CellProfiler-Analyst.py',
99 | 'icon_resources': [(1, '.\cpa\icons\cpa.ico')]}],
100 |
101 | )
102 |
--------------------------------------------------------------------------------